mutate_at 在某些情况下不创建变量后缀?
mutate_at does not create variable suffixes in some cases?
我一直在尝试 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
但是,我注意到当 vars
参数用于指向我的列 return 时只有一列而不是几列时,生成的新列会删除初始名称:它被命名为 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
我想了解为什么会发生这种行为,以及如何避免这种情况,因为我事先不知道 contains()
将 return.
有多少列
编辑:
新建的列必须继承原有列的名称,在末尾加上后缀'sqrt'
谢谢
我只是想出了一个(不太干净)的方法;
我向数据集添加了一个额外的虚拟变量,其名称确保它会被选中并且我们不会陷入 1 变量的情况,并且在计算之后我删除了 2 个虚拟变量,如下所示:
df %>% mutate(other_fake=NA) %>%
mutate_at(vars(contains("other")), .funs=funs('sqrt'=sqrt)) %>%
select(-contains("other_fake"))
#### var1 var2 other other_sqrt
#### 1 1 4 9 3
#### 2 2 5 9 3
这是另一个想法。我们可以在 mutate_at
调用之后添加 setNames(sub("^sqrt$", "other_sqrt", names(.)))
。这个想法是用 other_sqrt
替换列名 sqrt
。如果只有一个名为 other
的列,则模式 ^sqrt$
应仅匹配派生列 sqrt
,如示例 1 所示。如果有多个列 other
,如例2,setNames
不会改变列名。
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
或者我们可以设计一个函数,在操作数据框之前检查有多少列包含字符串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
我一直在尝试 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
但是,我注意到当 vars
参数用于指向我的列 return 时只有一列而不是几列时,生成的新列会删除初始名称:它被命名为 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
我想了解为什么会发生这种行为,以及如何避免这种情况,因为我事先不知道 contains()
将 return.
编辑: 新建的列必须继承原有列的名称,在末尾加上后缀'sqrt'
谢谢
我只是想出了一个(不太干净)的方法; 我向数据集添加了一个额外的虚拟变量,其名称确保它会被选中并且我们不会陷入 1 变量的情况,并且在计算之后我删除了 2 个虚拟变量,如下所示:
df %>% mutate(other_fake=NA) %>%
mutate_at(vars(contains("other")), .funs=funs('sqrt'=sqrt)) %>%
select(-contains("other_fake"))
#### var1 var2 other other_sqrt
#### 1 1 4 9 3
#### 2 2 5 9 3
这是另一个想法。我们可以在 mutate_at
调用之后添加 setNames(sub("^sqrt$", "other_sqrt", names(.)))
。这个想法是用 other_sqrt
替换列名 sqrt
。如果只有一个名为 other
的列,则模式 ^sqrt$
应仅匹配派生列 sqrt
,如示例 1 所示。如果有多个列 other
,如例2,setNames
不会改变列名。
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
或者我们可以设计一个函数,在操作数据框之前检查有多少列包含字符串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