【发布时间】:2019-04-16 16:55:18
【问题描述】:
我正在尝试收紧%>% 管道工作流,我需要将相同的函数应用于多个列,但每次都更改一个参数。我觉得 purrr 的 map 或 invoke 函数应该有所帮助,但我无法理解它。
我的数据框包含预期寿命、贫困率和家庭收入中位数列。我可以将所有这些列名传递给mutate_at 中的vars,使用round 作为应用于每个列的函数,并可选择提供digits 参数。但我想不出一种方法(如果存在)为与每一列关联的digits 传递不同的值。我希望预期寿命四舍五入为 1,贫困四舍五入为 2,收入四舍五入为 0。
我可以在每一列上调用mutate,但考虑到我可能有更多的列都接收相同的函数,只改变了一个额外的参数,我想要更简洁的东西。
library(tidyverse)
df <- tibble::tribble(
~name, ~life_expectancy, ~poverty, ~household_income,
"New Haven", 78.0580437642378, 0.264221051111753, 42588.7592521085
)
在我的想象中,我可以这样做:
df %>%
mutate_at(vars(life_expectancy, poverty, household_income),
round, digits = c(1, 2, 0))
但得到错误
mutate_impl(.data, dots) 中的错误: 列
life_expectancy的长度必须为 1(行数),而不是 3
使用mutate_at 而不是mutate 只是为了拥有与我理想情况下相同的语法:
df %>%
mutate_at(vars(life_expectancy), round, digits = 1) %>%
mutate_at(vars(poverty), round, digits = 2) %>%
mutate_at(vars(household_income), round, digits = 0)
#> # A tibble: 1 x 4
#> name life_expectancy poverty household_income
#> <chr> <dbl> <dbl> <dbl>
#> 1 New Haven 78.1 0.26 42589
对数字进行映射使用 each 列的每个 digits 选项,而不是按位置,给我 3 行,每行四舍五入到不同的位数。
df %>%
mutate_at(vars(life_expectancy, poverty, household_income),
function(x) map(x, round, digits = c(1, 2, 0))) %>%
unnest()
#> # A tibble: 3 x 4
#> name life_expectancy poverty household_income
#> <chr> <dbl> <dbl> <dbl>
#> 1 New Haven 78.1 0.3 42589.
#> 2 New Haven 78.1 0.26 42589.
#> 3 New Haven 78 0 42589
由reprex package (v0.2.1) 于 2018 年 11 月 13 日创建
【问题讨论】:
-
过去,当我遇到这个问题时,我最终收集了我的列,对它们进行分组,对它们进行变异,然后将它们散开。另见How do I sweep specific columns with dplyr?
-
@KonradRudolph 谢谢,我也在考虑这个问题,这是我以前使用过的一种方法,但我正在尝试找出是否可以实现超级简单的单行版本跨度>
-
@Henrik 您可能正在做某事。使用
map2_dfc可以工作,但这需要删除name列,然后可能重新加入。我试图想象一个map2_dfc/map_at混合 -
当您能够将函数列表传递给 summarise_at/mutate_at 时,似乎会更容易:github.com/tidyverse/dplyr/issues/3433。这似乎还行不通。
-
mutate支持!!!所以我认为最简单的方法是通过map2或(对我来说更干净)imap以编程方式重新创建详细的mutate调用(不是mutate_at)