我正在尝试使用
mutate
包中的 case_match
和 dplyr
创建一个函数,作为我的分析工作的一部分。但是,为了完全自动化该过程,我想包含一个额外的数据框(作为函数中的参数),其中包含文本字符串对,如果在包含数据的数据框中找到这些文本字符串对,这些文本字符串对将被更改。
没有 for 循环,这可以完美地工作:
dftest <- data.frame(old = c("ones","twos","fours","fives"), new = c("Humanoid",
"Hairy","Hairy","what"))
test1 <- data.frame(spp= c("ones", "twos", "threes"), log = c(5,61,36))
updnames <- function(df, col, names_df) {
require(dplyr)
if(ncol(names_df)>2)
{stop("More than 2 columns in names dataframe")}
if(sum(duplicated(names_df[1]))>0)
{stop("Duplicate old species names")}
else
{
names_df <- names_df %>% mutate_all(as.character)
df <- df %>%
mutate(updnames = case_match({{col}},
names_df[1,1] ~ names_df[1,2],
names_df[2,1] ~ names_df[2,2],
names_df[3,1] ~ names_df[3,2],
names_df[4,1] ~ names_df[4,2],
.default = {{col}}))}
return(df)
}
test2 <- updnames(test1, spp,dftest)
> test2 # Correct output
spp log updnames
1 ones 5 Humanoid
2 twos 61 Hairy
3 threes 36 threes
添加 for 循环不起作用。新列已按预期创建,但列值只是重复:
updnames <- function(df, col, names_df) {
require(dplyr)
if(ncol(names_df)>2)
{stop("More than 2 columns in names dataframe")}
if(sum(duplicated(names_df[1]))>0)
{stop("Duplicate old species names")}
else
{
names_df <- names_df %>% mutate_all(as.character)
for(i in 1:nrow(names_df)){
df <- df %>%
mutate(updnames = case_match({{col}},
names_df[i,1] ~ names_df[i,2],
.default = {{col}}))}
}
return(df)
}
test2 <- updnames(test1, spp, dftest)
> test2 # Wrong output
spp log updnames
1 ones 5 ones
2 twos 61 twos
3 threes 36 threes
我尝试查看 Stack Overflow 上的各种其他帖子并阅读相关文档,但我似乎无法弄清楚。
如果有人对我想要实现的目标有任何想法或替代解决方案,我将不胜感激。
使用
recode
。
test1 %>%
mutate(new_spp = recode(spp, !!!deframe(dftest)))
spp log new_spp
1 ones 5 Humanoid
2 twos 61 Hairy
3 threes 36 threes
以函数格式执行:
update_names <- function(df, col, new_names){
df %>% mutate(updnames = recode({{col}},!!!deframe(new_names)))
}
update_names(test1,spp, dftest)
spp log updnames
1 ones 5 Humanoid
2 twos 61 Hairy
3 threes 36 threes