首页 文章

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

提问于
浏览
0

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

1 回答

  • 3

    这与 dplyr::mutate 无关,但与 ifelse 如何工作有关,这是docs?ifelse:

    ifelse返回一个与test相同形状的值,该值填充了从yes或no中选择的元素,具体取决于test元素是TRUE还是FALSE . 用法ifelse(测试,是,否)

    例如:

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

    你的第一个案例是矢量化的, ifelsex/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
    

相关问题