通过列位置将函数参数传递给mutate_at [英] Pass function arguments by column position to mutate_at

查看:72
本文介绍了通过列位置将函数参数传递给mutate_at的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试加强%>%管道工作流程,在该工作流程中,我需要将相同的函数应用于多个列,但每次都要更改一个参数。我觉得 purrr map invoke 函数应该



我的数据框包含预期寿命,贫困率和家庭收入中位数的列。我可以将所有这些列名传递给 mutate_at 中的 vars ,使用 round 作为要应用于每个函数的函数,还可以选择提供个数字自变量。但是我无法找出一种方法来传递与每个列相关的位数的不同值(如果存在)。我希望将预期寿命四舍五入为1,将贫困数舍入为2,将收入四舍五入。



我可以称 mutate 在每列上,但是考虑到我可能会有更多的列都接受相同的函数而只​​更改了一个附加参数,我想提供一些更简洁的信息。

  library(tidyverse)

df<-tibble :: tribble(
〜name,〜life_expectancy,〜poverty,〜household_income,
New Haven,78.0580437642378,0.264221051111753,42588.7592521085

在我的想象中,我可以做这样的事情:

  df%>%
mutate_at(vars(预期寿命,贫穷,家庭收入),
轮次,数字= c(1、2、0))

但是得到错误


mutate_impl(.data中的错误,点):
life_expectancy 的长度必须为1(行数),而不是3


使用 mutate_at 代替 mutate 只是为了拥有与理想情况相同的语法:

  df%>%
mutate_at(vars(life_expectancy),舍入,数字= 1)%> %
mutate_at(vars(贫困),整数,位数= 2)%>%
mutate_at(vars(household_income),圆形,位数= 0)
#> #小动作:1 x 4
#>名称life_expectancy贫穷family_income
#> < chr> < dbl> < dbl> < dbl>
#> 1纽黑文78.1 0.26 42589

映射数字将使用每个个数字 每个列的选项,而不是按位置,给了我三行,每行四舍五入为不同的数字。

  df%>%
mutate_at(vars(life_expectancy,贫穷,家庭收入),
函数(x)地图(x,圆形,数字= c(1、2、0)))%>%
unnest()
#> #小动作:3 x 4
#>名称life_expectancy贫穷family_income
#> < chr> < dbl> < dbl> < dbl>
#> 1纽黑文78.1 0.3 42589。 2纽黑文78.1 0.26 42589。 3纽黑文78 0 42589

reprex软件包(v0.2.1)

解决方案

2个解决方案






变异 !!!



调用是个好主意,但由于大多数 tidyverse 函数支持 !!!,因此您现在不需要它了!运算符,这是您可以做的事情:

 位数<-c(life_expectancy = 1,贫困= 2 ,family_income = 0)
df%>%mutate(!!! imap(digits,〜round(.. 3 [[。y]],.x),.))
##A tibble:1 x 4
#名称life_expectancy贫困家庭_收入
#< chr> < dbl> < dbl> < dbl>
#1纽黑文78.1 0.26 42589

.. 3 是初始数据帧,它通过调用末尾的点作为第三个参数传递给函数。



写得更明确:

  df%>%mutate(!!! imap(
digits,
function(digit,名称,数据)回合(数据[[[名称]],数字),
data =。))

如果您需要从旧界面开始(尽管我建议的界面会更灵活),请首先执行以下操作:

  digits<-setNames(c(1,2,0),c( life_expectancy, poverty, household_income))






mutate_at < -



在这里,我们有点避免避免<-,但可读性很重要,而且这真的很容易阅读。

 数字<-c( 1,2,0)
i<-0
df%&%;%
mutate_at(vars(life_expectancy,贫穷,家庭收入),〜round(。,digits [i<- i + 1]))
#小动作:1 x 4
#名称life_expectancy贫困家庭_收入
#< chr> < dbl> < dbl> < dbl>
#1纽黑文78.1 0.26 42589

(或仅 df %>%mutate_at(names(digits),〜round(。,digits [i<-i + 1]))(如果您在我的第一个解决方案中使用命名矢量)

I'm trying to tighten up a %>% piped workflow where I need to apply the same function to several columns but with one argument changed each time. I feel like purrr's map or invoke functions should help, but I can't wrap my head around it.

My data frame has columns for life expectancy, poverty rate, and median household income. I can pass all these column names to vars in mutate_at, use round as the function to apply to each, and optionally supply a digits argument. But I can't figure out a way, if one exists, to pass different values for digits associated with each column. I'd like life expectancy rounded to 1 digit, poverty rounded to 2, and income rounded to 0.

I can call mutate on each column, but given that I might have more columns all receiving the same function with only an additional argument changed, I'd like something more concise.

library(tidyverse)

df <- tibble::tribble(
        ~name, ~life_expectancy,          ~poverty, ~household_income,
  "New Haven", 78.0580437642378, 0.264221051111753,  42588.7592521085
  )

In my imagination, I could do something like this:

df %>%
  mutate_at(vars(life_expectancy, poverty, household_income), 
            round, digits = c(1, 2, 0))

But get the error

Error in mutate_impl(.data, dots) : Column life_expectancy must be length 1 (the number of rows), not 3

Using mutate_at instead of mutate just to have the same syntax as in my ideal case:

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

Mapping over the digits uses each of the digits options for each column, not by position, giving me 3 rows each rounded to a different number of digits.

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

Created on 2018-11-13 by the reprex package (v0.2.1)

解决方案

2 solutions


mutate with !!!

invoke was a good idea but you need it less now that most tidyverse functions support the !!! operator, here's what you can do :

digits <- c(life_expectancy = 1, poverty = 2, household_income = 0)  
df %>% mutate(!!!imap(digits, ~round(..3[[.y]], .x),.))
# # A tibble: 1 x 4
#          name life_expectancy poverty household_income
#         <chr>           <dbl>   <dbl>            <dbl>
#   1 New Haven            78.1    0.26            42589

..3 is the initial data frame, passed to the function as a third argument, through the dot at the end of the call.

Written more explicitly :

df %>% mutate(!!!imap(
  digits, 
  function(digit, name, data) round(data[[name]], digit),
  data = .))

If you need to start from your old interface (though the one I propose will be more flexible), first do:

digits <- setNames(c(1, 2, 0), c("life_expectancy", "poverty", "household_income"))


mutate_at and <<-

Here we bend a bit the good practice of avoiding <<- whenever possible, but readability matters and this one is really easy to read.

digits <- c(1, 2, 0)
i <- 0
df %>%
  mutate_at(vars(life_expectancy, poverty, household_income), ~round(., digits[i<<- i+1]))
# A tibble: 1 x 4
#     name      life_expectancy poverty household_income
#     <chr>               <dbl>   <dbl>            <dbl>
#   1 New Haven            78.1    0.26            42589

(or just df %>% mutate_at(names(digits), ~round(., digits[i<<- i+1])) if you use a named vector as in my first solution)

这篇关于通过列位置将函数参数传递给mutate_at的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆