【问题标题】:R dplyr::mutate with ifelse conditioned on a global variable recycles result from first rowR dplyr::mutate with ifelse 以全局变量为条件回收第一行的结果
【发布时间】:2018-03-18 18:01:49
【问题描述】:

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

返回

   x y  z
1 11 1 11
2 12 2 11
3 13 3 11
4 14 4 11
5 15 5 11

不是 z 是每行的 x 和 y 的商,而是所有行都使用数据框第一行的 x 和 y 的商填充。

但是,如果我指定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

xy 仅定义为我的数据框的列时,为什么我必须明确指定rowwise()

【问题讨论】:

  • checkVar 属于length 1。我相信,这只会导致第一行xy 被使用。如果你设置checkVar &lt;- rep(1,5),你会得到你想要的输出。如果您使用dplyrif_else,它会告诉您问题所在。此外,使用rowwise 可以使ifelse 中的所有内容的长度为1。
  • 如果你使用ifelse的dplyr版本,即if_else,那么你会得到错误"true is length 5 not 1 or 1."

标签: r conditional vectorization dplyr


【解决方案1】:

这与dplyr::mutate 无关,而是与ifelse 的工作原理有关,这是文档?ifelse

ifelse 返回一个与填充的 test 形状相同的值 元素从是或否中选择,具体取决于是否 测试元素是 TRUE 或 FALSE。

用法

ifelse(测试,是,否)

还有例子:

ifelse(T, c(1,2,3), c(2,3,4))
# [1] 1

您的第一个案例是向量化的,ifelse 将向量 x/yx-y 作为 yesno 参数,因为 checkVar == 1 返回 TRUE(标量),@987654330 @返回(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

【讨论】:

  • 你的最后一个例子很有趣;我什至不知道您可以在调用mutate 的赋值右侧使用标准if/else 构造。感谢发帖;很高兴知道这一点!
  • 替代:mutate(z = case_when(checkVar==1 ~ x/y, TRUE ~ as.numeric(x-y)))
  • @bmosov01 很高兴它有帮助!
  • @Marek case_when 仍然会出现错误。公式中最长的 LHS 应该具有与 case_when 中最长的 RHS 相同的长度才能正常工作。
  • @Psidom Strange,在 R-3.4.2 上为我工作 dplyr-0.7.3
猜你喜欢
  • 1970-01-01
  • 2018-06-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-24
  • 1970-01-01
  • 2020-07-25
  • 2017-02-23
相关资源
最近更新 更多