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

为何dplyr的case_when函数兼容grepl却不兼容grep?

为啥grep在case_when里没效果,grepl却正常?

嘿,这个问题的关键其实是**grepl和grep返回的东西完全不一样**,而dplyr的case_when对条件格式有硬性要求——每个条件都得是和输入向量长度一致的逻辑向量(就是每个元素对应TRUE或者FALSE那种)。

先搞懂俩函数的核心区别

  • grepl("fizz", v):会返回一个和v长度一模一样的向量,每个位置告诉你这个元素里有没有匹配到目标模式。比如你的v是50个元素,它就给你50个TRUE/FALSE,刚好能让case_when逐个判断每个元素该走哪个分支。
  • grep("fizz", v):它返回的是那些匹配上的元素的位置编号,比如v里第5、10、15...个元素是"fizz",它就返回c(5,10,15,...),这个向量的长度是匹配到的元素个数,不是原向量的50个。case_when根本没法把这个短向量对应到每个元素的判断上,自然就“不生效”了。

拿你的代码举例子验证

能正常运行的写法(用grepl)

library(dplyr)
x <- 1:50
v <- case_when(
  x %% 35 == 0 ~ "fizz buzz",
  x %% 5 == 0 ~ "fizz",
  x %% 7 == 0 ~ "buzz",
  TRUE ~ as.character(x)
)

# 输出符合预期的结果
case_when(
  grepl("fizz", v) ~ "FFF",
  grepl("buzz", v) ~ "BZZ",
  TRUE ~ as.character(v)
)

为啥直接用grep不行?

如果换成grep,代码是这样的:

# 要么结果完全不符合预期,要么直接报错
case_when(
  grep("fizz", v) ~ "FFF",
  grep("buzz", v) ~ "BZZ",
  TRUE ~ as.character(v)
)

这里grep返回的是一堆位置数字,case_when会把这个短向量循环重复去匹配长向量的长度,这完全不是你想要的逐元素判断逻辑,所以看起来就像是没生效。

非要用grep的话怎么改?

可以把grep返回的索引转换成逻辑向量,用seq_along(v)生成原向量的位置序列,再用%in%判断每个位置是不是在匹配索引里:

case_when(
  seq_along(v) %in% grep("fizz", v) ~ "FFF",
  seq_along(v) %in% grep("buzz", v) ~ "BZZ",
  TRUE ~ as.character(v)
)

这样就能得到和v长度一致的逻辑向量,case_when就能正常工作了。不过说实话,直接用grepl要简洁得多,没必要多这一步~

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 09:04:36