在dplyr中使用case_when遇报错,请求解析原因
问题分析与解决
先看你给出的代码和报错:
x <- 1:5 dplyr::case_when( x == 1 ~ TRUE, x != 1 ~ print(x) )
执行后输出:
[1] 1 2 3 4 5
Error: must be a logical vector, not an integer vector
核心问题:case_when要求所有分支返回同类型的向量
dplyr::case_when的规则很明确:每个条件分支的返回值必须是长度匹配、类型一致的向量。这里你的两个分支返回值类型完全不兼容:
- 第一个分支
x == 1 ~ TRUE:返回的是和x长度相同的逻辑向量(只有第一个元素是TRUE,其余是FALSE) - 第二个分支
x != 1 ~ print(x):print(x)的副作用是打印出1:5,但它的返回值是输入的整数向量1:5本身(R中print函数会不可见地返回输入对象),这是整数类型,和第一个分支的逻辑类型冲突,直接触发报错。
另外还有个逻辑问题:print(x)是对整个向量操作,而case_when是逐元素判断条件,你其实是想对每个x !=1的元素执行打印?那当前写法也不符合逐元素处理的逻辑。
解决方案
根据你的需求分两种情况:
情况1:想标记x=1为逻辑值,其他返回对应数值(统一类型)
如果是要输出混合逻辑和数值,得先统一类型(比如都转成数值或字符):
x <- 1:5 # 统一为数值类型 dplyr::case_when( x == 1 ~ 1L, # 用整数1对应原来的TRUE x != 1 ~ x ) # 输出:[1] 1 2 3 4 5
情况2:想在x!=1时打印对应元素,同时返回逻辑向量
如果你的需求是满足x!=1时打印该元素,同时返回逻辑值(和第一个分支类型统一),可以用{}包裹代码块,让最后一个表达式返回逻辑值:
x <- 1:5 dplyr::case_when( x == 1 ~ TRUE, x != 1 ~ {print(.x); FALSE} # .x指代当前元素,逐元素打印 )
这里用.x可以访问当前的元素(dplyr 1.0.0+支持),执行后会逐元素打印2、3、4、5,同时返回逻辑向量[1] TRUE FALSE FALSE FALSE FALSE,完全符合case_when的类型要求。
内容的提问来源于stack exchange,提问作者pgcudahy
相关产品推荐
相关产品推荐

