在调用时使用dplyr mutate_中的多列函数

在调用时使用dplyr mutate_中的多列函数,r,dplyr,R,Dplyr,我想使用dplyr的mutate_at函数将一个函数应用于数据帧中的多个列,其中该函数输入它直接应用到的列以及数据帧中的另一列 作为一个具体的例子,我希望对以下数据帧进行变异 # Example input dataframe df <- data.frame( x = c(TRUE, TRUE, FALSE), y = c("Hello", "Hola", "Ciao"), z = c("World", "ao", "HaOlam") ) 返回如下所示的数据帧

我想使用dplyr的
mutate_at
函数将一个函数应用于数据帧中的多个列,其中该函数输入它直接应用到的列以及数据帧中的另一列

作为一个具体的例子,我希望对以下数据帧进行变异

# Example input dataframe
df <- data.frame(
    x = c(TRUE, TRUE, FALSE),
    y = c("Hello", "Hola", "Ciao"),
    z = c("World", "ao", "HaOlam")
)
返回如下所示的数据帧

# Desired output dataframe
df2 <- data.frame(x = c(TRUE, TRUE, FALSE),
                  y_1 = c("Hello", "Hola", NA),
                  z_1 = c("World", "ao", NA))
我知道这可以在BaseR中以多种方式实现,但为了可读性、与数据库接口等原因,我特别希望使用dplyr的
mutate_at
函数来实现这一目标

下面是关于stackoverflow的一些类似问题,这些问题没有解决我在这里提出的问题:


在@eipi10对这个问题的评论中,@eipi10回答了这个问题,但我写在这里是为了子孙后代

这里的解决方案是使用:

df %>%
   mutate_at(.vars = vars(y, z),
             .funs = list(~ ifelse(x, ., NA)))
您还可以将新的
cross()
函数与
mutate()
一起使用,如下所示:

df %>%
   mutate(across(c(y, z), ~ ifelse(x, ., NA)))
temp_fn <- function(input) ifelse(test = df[["x"]],
                                  yes = input,
                                  no = NA)

df %>%
   mutate_at(.vars = vars(y, z),
             .funs = temp_fn)
在这里使用公式运算符(如
~ifelse(…)
)表示
ifelse(x,,,NA)
是一个匿名函数,它是在调用
mutate_at()时定义的

这类似于在调用
mutate_at()
之外定义函数,如下所示:

df %>%
   mutate(across(c(y, z), ~ ifelse(x, ., NA)))
temp_fn <- function(input) ifelse(test = df[["x"]],
                                  yes = input,
                                  no = NA)

df %>%
   mutate_at(.vars = vars(y, z),
             .funs = temp_fn)
temp\u fn%
在(.vars=vars(y,z)处突变_,
.funs=温度(fn)

请注意dplyr中的语法更改:在dplyr版本0.8.0之前,您只需编写
.funs=funs(ifelse(x,,,NA))
,但
funs()
函数已被弃用,并将很快从dplyr中删除。

补充先前的响应,如果您希望
mutate_at()
添加新变量(而不是替换),如原始问题中的名称,如
z_1
y_1
,您只需:

  • dplyr>=1
    cross()
    :添加
    .names=“{.col}\u 1”
    ,或者使用
    列表('1'=~ifelse(x,,,NA)
    (反勾!)
  • dplyr[0.8,1[:使用
    list('1'=~ifelse(x,,,NA)
  • dplyr% 突变(跨越(c(y,z), 列表(~ifelse(x,NA)), .names=“{.col}_1”)) #>x y z y_1 z_1 #>1真正的你好世界你好世界 #>2真的好啊好啊好啊 #>3假乔浩林 ## 0.8 - % 在(.vars=vars(y,z)处突变_, .funs=list(`1`=~ifelse(x,,,NA))) #>x y z y_1 z_1 #>1真正的你好世界你好世界 #>2真的好啊好啊好啊 #>3假乔浩林 ##0.8之前 df%>% 在(.vars=vars(y,z)处突变_, .funs=funs(`1`=ifelse(x,NA))) #>警告:`funs()`从dplyr 0.8.0开始就不推荐使用。 #>请使用函数或lambda的列表: #> #>#简单命名列表: #>列表(平均值=平均值,中位数=中位数) #> #>#使用'tibble::lst()'自动命名: #>tibble::lst(平均值、中值) #> #>#使用lambdas #>列表(~平均值(,修剪=0.2),~中值(,na.rm=TRUE)) #>此警告每8小时显示一次。 #>调用`lifecycle::last_warnings()`查看此警告的生成位置。 #>x y z y_1 z_1 #>1真正的你好世界你好世界 #>2真的好啊好啊好啊 #>3假乔浩林
由(v0.3.0)于2020年10月3日创建


有关更多详细信息和技巧,请参阅:

df%>%mutate_at(vars(y,z),funs(ifelse(x,NA))
@eipi10啊,好的。因此,如果我在调用
funs()时实际包装了
ifelse(x,NA)
,上述代码就可以工作了
。谢谢!我已经检查了你的解决方案,效果非常好。你的解决方案正是我想要的!“这里使用funs()表示ifelse(x,,,NA)是一个匿名函数”——
funs()
与传统的匿名函数,
函数(x)有何不同
?根据我的经验,最值得注意的是,它需要更少的键入,并且可读性类似。但是,它还允许您提供匿名函数列表(例如
funs(avg=mean(.),total=sum(.,na.rm=TRUE))
。请参阅。