我很好奇为什么ifelse()
调用中的dplyr::mutate()
语句似乎只适用于我数据框的第一行。这将返回单个值,该值将在整个列中循环使用。由于在ifelse()
的任何一种情况下评估的表达式仅在我的数据框的上下文中有效,我希望条件检查和结果表达式评估作为一个整体在列上执行,而不仅仅是它们的第一个元素
这是一个例子:我在数据框外定义了一个名为checkVar
的变量。根据{{1}}的值,我想在新列checkVar
中为我的数据框添加不同的值,这些值是根据现有列计算的。
如果我这样做
z
它返回
checkVar <- 1
df <- data.frame( x=11:15, y=1:5 ) %>%
dplyr::mutate( z=ifelse(checkVar == 1, x/y, x-y) )
df
而不是z是每行的x和y的商,所有行都填充了数据框第一行中x和y的商。
但是,如果我指定 x y z
1 11 1 11
2 12 2 11
3 13 3 11
4 14 4 11
5 15 5 11
,我会得到我想要的结果:
rowwise()
返回
df <- df %>%
dplyr::rowwise() %>%
dplyr::mutate( z=ifelse(checkVar == 1, x/y, x-y) ) %>%
dplyr::ungroup()
df
为什么在# A tibble: 5 x 3
x y z
<int> <int> <dbl>
1 11 1 11.000000
2 12 2 6.000000
3 13 3 4.333333
4 14 4 3.500000
5 15 5 3.000000
和rowwise()
仅定义为数据框的列时,我必须明确指定x
?
答案 0 :(得分:3)
这与dplyr::mutate
无关,但与ifelse
的工作原理无关,这里是文档?ifelse :
ifelse返回一个与填充的test相同形状的值 选择是或否的元素取决于是否 测试元素为TRUE或FALSE。
用法
ifelse(test,yes,no)
例如:
ifelse(T, c(1,2,3), c(2,3,4))
# [1] 1
您的第一个案例是向量化的,ifelse
将向量x/y
和x-y
作为yes
和no
参数,因为checkVar == 1
返回 TRUE (标量),ifelse
返回(x/y)[1]
,即向量x/y
的第一个元素,即 11 并被回收以填充新专栏z
;
在第二种情况下,每行执行mutate
和ifelse
,因此评估五次次,每次都返回x/y
的值那一行。
如果您的条件是标量,那么您不需要矢量化 ifelse
,if/else
更适合使用:
checkVar <- 1
mutate(df, z = if(checkVar == 1) x/y else x-y)
# x y z
#1 11 1 11.000000
#2 12 2 6.000000
#3 13 3 4.333333
#4 14 4 3.500000
#5 15 5 3.000000