R dplyr :: mutate,ifelse以全局变量为条件,从第一行开始循环

时间:2017-10-06 21:19:07

标签: r dplyr conditional vectorization mutate

我很好奇为什么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

1 个答案:

答案 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/yx-y作为yesno参数,因为checkVar == 1返回 TRUE (标量),ifelse返回(x/y)[1],即向量x/y的第一个元素,即 11 并被回收以填充新专栏z;

在第二种情况下,每行执行mutateifelse,因此评估五次次,每次都返回x/y的值那一行。

如果您的条件是标量,那么您不需要矢量化 ifelseif/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