【问题标题】:dplyr use both rowwise and df-wise values in a mutatedplyr 在 mutate 中同时使用 rowwise 和 df-wise 值
【发布时间】:2018-08-06 06:42:15
【问题描述】:

您如何执行使用来自其他行的值的rowwise 操作(以 dplyr/tidy 样式)?假设我有这个 df:

df <- data_frame(value = c(5,6,7,3,4),
                 group = c(1,2,2,3,3),
                 group.to.use = c(2,3,3,1,1))

我想创建一个新变量 new.value,它等于每行的当前值加上“group”等于该行的“group.to.use”的行的最大值。所以对于第一行

new.value = 5 + (max(value[group === 2])) = 5 + 7 = 12

想要的输出:

# A tibble: 5 x 4
  value group group.to.use new.value
  <dbl> <dbl>        <dbl>     <dbl>
1    5.    1.           2.       12.
2    6.    2.           3.       10.
3    7.    2.           3.       11.
4    3.    3.           1.        8.
5    4.    3.           1.        9.

伪代码:

df %<>%
  mutate(new.value = value + max(value[group.to.use == <group.for.this.row>]))

【问题讨论】:

    标签: r dplyr


    【解决方案1】:

    在逐行操作中,您可以使用. 引用整个data.frame,并使用普通语法.$colname.[['col.name']] 引用data.frame 中的一整列:

    df %>%
        rowwise() %>%
        mutate(new.value = value + max(.$value[.$group == group.to.use])) %>%
        ungroup()
    
    # # A tibble: 5 x 4
    #   value group group.to.use new.value
    #   <dbl> <dbl>        <dbl>    <dbl>
    # 1     5     1            2       12
    # 2     6     2            3       10
    # 3     7     2            3       11
    # 4     3     3            1        8
    # 5     4     3            1        9
    

    或者,您可以预先计算每个组的最大值,然后进行左连接:

    df.max <- df %>% group_by(group) %>% summarise(max.value = max(value))
    
    df %>%
        left_join(df.max, by = c('group.to.use' = 'group')) %>%
        mutate(new.value = value + max.value) %>%
        select(-max.value)
    # # A tibble: 5 x 4
    #   value group group.to.use new.value
    #   <dbl> <dbl>        <dbl>     <dbl>
    # 1     5     1            2        12
    # 2     6     2            3        10
    # 3     7     2            3        11
    # 4     3     3            1         8
    # 5     4     3            1         9
    

    【讨论】:

    • df%&gt;%mutate(newcol = map_dbl(group.to.use,~max(value[.x==group]))+value) 是另一种解决方案
    • @Onyambu,不错。这个和我的第一个解决方案的副作用是重复计算同一组的最大值,这使得此类解决方案对于大型数据集效率低下。我个人更喜欢加入方式。
    • 为了避免joining你可以matchdf%&gt;%group_by(group)%&gt;%mutate(mx = max(value))%&gt;%ungroup()%&gt;%mutate(newcol = value+mx[match(group.to.use,group)],mx=NULL)
    • df%&gt;%mutate(newcol = ave(value,group,FUN=max)[match(group.to.use,group)]+value)也可以解决
    • 我发现逐行解决方案在语法上最简单,但我仍然习惯map
    【解决方案2】:

    使用基数 R,我们可以使用 ave,其中我们为每个 group 计算 max,并将它们与相应的 value match 相加。

    df$new.value <- with(df, value + 
                     ave(value, group, FUN = max)[match(group.to.use, group)])
    
    df
    #   A tibble: 5 x 4
    #   value group group.to.use new.value
    #  <dbl> <dbl>        <dbl>     <dbl>
    #1  5.00  1.00         2.00     12.0 
    #2  6.00  2.00         3.00     10.0 
    #3  7.00  2.00         3.00     11.0 
    #4  3.00  3.00         1.00      8.00
    #5  4.00  3.00         1.00      9.00
    

    【讨论】:

      【解决方案3】:

      这是base R的选项

      df$new.value <- with(df, value + vapply(group.to.use, function(x)
                                  max(value[group == x]), numeric(1)))
      df$new.value
      #[1] 12 10 11  8  9
      

      【讨论】:

        猜你喜欢
        • 2016-01-10
        • 1970-01-01
        • 2018-02-16
        • 1970-01-01
        • 2019-02-23
        • 2016-10-22
        • 1970-01-01
        • 1970-01-01
        • 2018-02-03
        相关资源
        最近更新 更多