mutate_at 在某些情况下不会创建变量后缀?

age*_*nis 5 r contains dplyr mutate

我一直在dplyr::mutate_at尝试通过对某些列应用相同的函数来创建新变量。当我在参数中命名我的函数.funs,mutate 调用会创建带有后缀的新列,而不是替换现有列,这是我在此线程中发现的一个很酷的选项。

df = data.frame(var1=1:2, var2=4:5, other=9)
df %>% mutate_at(vars(contains("var")), .funs=funs('sqrt'=sqrt))
####   var1 var2 other var1_sqrt var2_sqrt
#### 1    1    4     9  1.000000  2.000000
#### 2    2    5     9  1.414214  2.236068
Run Code Online (Sandbox Code Playgroud)

但是,我注意到当vars用于指向我的列的参数只返回一列而不是几列时,生成的新列会删除初始名称:它被命名sqrt而不是在other_sqrt这里:

df %>% mutate_at(vars(contains("other")), .funs=funs('sqrt'=sqrt))
####   var1 var2 other sqrt
#### 1    1    4     9    3
#### 2    2    5     9    3
Run Code Online (Sandbox Code Playgroud)

我想了解为什么会发生这种行为,以及如何避免它,因为我事先不知道contains()将返回多少列。

编辑:新创建的列必须继承原始列的原始名称,加上末尾的后缀“sqrt”。

谢谢

www*_*www 3

这是另一个想法。setNames(sub("^sqrt$", "other_sqrt", names(.)))我们可以在通话后添加mutate_at。这个想法是将列名称替换sqrtother_sqrt. 如果只有一列名为,则该模式^sqrt$应仅与派生列匹配,如示例 1 所示。如果有多个名为 的列(例如示例 2),则不会更改列名称。sqrtotherothersetNames

library(dplyr)

# Example 1
df <- data.frame(var1 = 1:2, var2 = 4:5, other = 9)

df %>% 
  mutate_at(vars(contains("other")), funs("sqrt" = sqrt(.))) %>%
  setNames(sub("^sqrt$", "other_sqrt", names(.)))
#   var1 var2 other other_sqrt
# 1    1    4     9          3
# 2    2    5     9          3

# Example 2
df2 <- data.frame(var1 = 1:2, var2 = 4:5, other1 = 9, other2 = 16)

df2 %>% 
  mutate_at(vars(contains("other")), funs("sqrt" = sqrt(.))) %>%
  setNames(sub("^sqrt$", "other_sqrt", names(.)))
#   var1 var2 other1 other2 other1_sqrt other2_sqrt
# 1    1    4      9     16           3           4
# 2    2    5      9     16           3           4
Run Code Online (Sandbox Code Playgroud)

other或者我们可以设计一个函数来在操作数据框之前检查有多少列包含该字符串。

mutate_sqrt <- function(df, string){
  string_col <- grep(string, names(df), value = TRUE)
  df2 <- df %>% mutate_at(vars(contains(string)), funs("sqrt" = sqrt(.)))
  if (length(string_col) == 1){
    df2 <- df2 %>%  setNames(sub("^sqrt$", paste(string_col, "sqrt", sep = "_"), names(.)))
  }
  return(df2)
}

mutate_sqrt(df, "other")
#   var1 var2 other other_sqrt
# 1    1    4     9          3
# 2    2    5     9          3

mutate_sqrt(df2, "other")
#   var1 var2 other1 other2 other1_sqrt other2_sqrt
# 1    1    4      9     16           3           4
# 2    2    5      9     16           3           4 
Run Code Online (Sandbox Code Playgroud)