You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用dplyr的mutate_at结合case_when修改变量时遇问题求助

问题分析与解决

你遇到的问题核心是在mutate_at的funs()里错误地给新变量命名,导致原变量没有被修改,反而生成了一个新列。让我一步步帮你修正,顺便给你讲讲这类操作的正确姿势:

1. 原代码的问题所在

你写的:

mtcars %>% mutate_at( vars(starts_with("mpg")), funs(. = case_when( . == 21.0 ~ 5, TRUE ~ . )) )

这里的. =是告诉dplyr「生成一个以原变量名为基础、后缀加.的新变量」,所以运行后你会看到一个叫mpg.的新列,而原来的mpg列完全没变——这就是你觉得“无法成功”的原因!

2. 修正后的mutate_at写法

如果你坚持用mutate_at(适合dplyr 1.0.0之前的版本),只需要去掉funs()里的. =,直接写处理逻辑即可:

mtcars %>% 
  mutate_at(vars(starts_with("mpg")), 
            funs(case_when(. == 21.0 ~ 5, TRUE ~ .)))

或者更简洁的公式写法(推荐):

mtcars %>% 
  mutate_at(vars(starts_with("mpg")), 
            ~ case_when(. == 21.0 ~ 5, TRUE ~ .))

这样mutate_at就会用处理后的结果覆盖原变量,和你想要的mtcars$mpg[mtcars$mpg == 21.0] <- 5效果完全一致。

3. 更现代的写法:用across取代mutate_at

从dplyr 1.0.0版本开始,官方推荐用across()来替代mutate_at/mutate_all这类函数,语法更统一,灵活性也更高。对应你的需求,写法是:

mtcars %>% 
  mutate(across(starts_with("mpg"), 
                ~ case_when(. == 21.0 ~ 5, TRUE ~ .)))

across()的逻辑很清晰:第一个参数指定要操作的变量(这里用starts_with("mpg")匹配),第二个参数是要应用的函数/逻辑(这里用公式~ ...定义case_when规则)。

验证效果

运行上述代码后,你可以用filter(mtcars, mpg == 5)查看,会发现原来mpg为21.0的行(比如Mazda RX4、Mazda RX4 Wag)现在mpg都是5了,完全符合你的预期。


内容的提问来源于stack exchange,提问作者lost

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 07:57:43