R语言mutate函数用c()未批量修改全部值的问题咨询
问题与解决方案
问题详情
我想基于另一列的值批量修改数据,尝试在mutate里用c()作为条件列表时,只有部分值被修改,不是全部;但把每个条件单独写在mutate行里就能正常运行。示例数据和两种代码如下,请问有没有其他实现方式,还是必须分开写?
示例数据
Category <- c("Additional Fees", "Additional Fees", "None", "None", "Package", "None") Item <- c("20oz Upgrade", "Ice Cream", "20oz Upgrade", "Ice Cream", "Ice Cream", "20oz Upgrade") df <- data.frame(Category, Item)
可正常运行的多行代码
df2 <- df %>% mutate(Category = ifelse(Item == "20oz Upgrade", "Additional Fees", Category)) %>% mutate(Category = ifelse(Item == "Ice Cream", "Additional Fees", Category))
合并后部分值未修改的代码
df1 <- df %>% mutate(Category = ifelse(Item == c("20oz Upgrade", "Ice Cream"), "Additional Fees", Category))
原因分析
你用Item == c("20oz Upgrade", "Ice Cream")的写法是逐元素循环匹配,R会把短向量重复拉长到和Item同长度(即变成c("20oz Upgrade", "Ice Cream", "20oz Upgrade", "Ice Cream", "20oz Upgrade", "Ice Cream")),然后逐个位置对比。这就导致只有位置1、3、5的Item和第一个值匹配,位置2、4、6和第二个值匹配,而你的第5行Item是"Ice Cream",和循环后的第5个值"20oz Upgrade"不匹配,所以没被修改,这就是部分值失效的原因。
替代实现方法
不需要分开写,有几种更简洁的批量写法:
方法1:用%in%检查归属(最直接)
%in%会检查每个Item是否属于目标集合,完美解决批量匹配问题:
df3 <- df %>% mutate(Category = ifelse(Item %in% c("20oz Upgrade", "Ice Cream"), "Additional Fees", Category))
方法2:用case_when(适合多条件扩展)
如果之后需要添加更多不同的映射规则,case_when的可读性更强:
df4 <- df %>% mutate(Category = case_when( Item %in% c("20oz Upgrade", "Ice Cream") ~ "Additional Fees", TRUE ~ Category # 其他情况保持原Category不变 ))
方法3:用recode做固定映射
如果是明确的一对一/多对一映射,recode写法更紧凑:
df5 <- df %>% mutate(Category = recode(Item, "20oz Upgrade" = "Additional Fees", "Ice Cream" = "Additional Fees", .default = Category # 默认保留原值 ))
内容的提问来源于stack exchange,提问作者Kristen Williams
相关产品推荐
相关产品推荐

