R dplyr::mutate with ifelse以全局变量为条件,从第一行回收结果

R dplyr::mutate with ifelse以全局变量为条件,从第一行回收结果,r,dplyr,conditional,vectorization,mutate,R,Dplyr,Conditional,Vectorization,Mutate,我很好奇为什么调用dplyr::mutate()中的ifelse()语句似乎只适用于数据帧的第一行。这将返回单个值,该值在整个列中循环使用。由于在ifelse()的任一情况下计算的表达式仅在我的数据帧的上下文中有效,因此我希望对列作为一个整体执行条件检查和结果表达式计算,而不仅仅是对它们的第一个元素 这里有一个例子:我在数据框外定义了一个变量,名为checkVar。根据checkVar的值,我想将不同的值添加到新列z中的数据框中,这些值是作为现有列的函数计算的 如果我这样做 checkVar &

我很好奇为什么调用
dplyr::mutate()
中的
ifelse()
语句似乎只适用于数据帧的第一行。这将返回单个值,该值在整个列中循环使用。由于在
ifelse()
的任一情况下计算的表达式仅在我的数据帧的上下文中有效,因此我希望对列作为一个整体执行条件检查和结果表达式计算,而不仅仅是对它们的第一个元素

这里有一个例子:我在数据框外定义了一个变量,名为
checkVar
。根据
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的商填充所有行

但是,如果指定
rowwise()
,则会得到所需的结果:

df <- df %>%
  dplyr::rowwise() %>%
  dplyr::mutate( z=ifelse(checkVar == 1, x/y, x-y) ) %>%
  dplyr::ungroup()
df
df%
dplyr::行方式()%>%
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
#一个tible:5 x 3
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

x
y
仅定义为我的数据帧的列时,为什么我必须显式指定
rowwise()

ifelse返回一个与填充的测试形状相同的值 从“是”或“否”中选择元素,具体取决于 测试元素是真是假

用法

ifelse(测试,是,否)

例如:

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


如果您的条件是标量,则不需要向量化的
If/else
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

checkVar
checkVar
的长度为
length
1。我相信,这只会导致使用第一行
x
y
。如果使用dplyr版本的
ifelse
,即
ifelse
,设置
checkVar,则会出现错误
“true是长度5而不是1或1。”
。最后一个示例非常有趣;我甚至不知道在调用
mutate
时,可以在赋值的右侧使用标准
if/else
构造。谢谢你的发帖;这是非常好的了解!备选方案:
mutate(z=case_when(checkVar==1~x/y,TRUE~as.numeric(x-y))
@bmosov01很高兴它有帮助@Marek
case\u当
仍会出现错误时。当
正常工作时,公式中最长的LHS应与
案例中最长的RHS具有相同的长度。@Psidom Strange,适用于R-3.4.2上的dplyr-0.7.3
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