【问题标题】:Optimize computation in dplyr mutate function优化 dplyr mutate 函数中的计算
【发布时间】:2021-04-23 18:12:22
【问题描述】:

假设下表:

library(dplyr)
library(tibble)
library(purrr)

df = tibble(
  client = c(1,1,1,1,2,2,2,2),
  prod_type = c(1,1,2,2,1,1,2,2),
  max_prod_type = c(2,2,2,2,2,2,2,2),
  value_1 = c(10,20,30,30,100,200,300,300),
  value_2 = c(1,2,3,3,1,2,3,3),
)
# A tibble: 8 x 5
  client prod_type max_prod_type value_1 value_2
   <dbl>     <dbl>         <dbl>   <dbl>   <dbl>
1      1         1             2      10       1
2      1         1             2      20       2
3      1         2             2      30       3
4      1         2             2      30       3
5      2         1             2     100       1
6      2         1             2     200       2
7      2         2             2     300       3
8      2         2             2     300       3

此处的“max_prod_type”列表示每个“客户”值的“prod_type”列的最大值。我需要计算新列“sum”,其中包含将“value_1”和“value_2”中的值相加得到的总和,但仅限于那些行,其中每个“客户”值的“prod_type”==“max_prod_type”。

我尝试了以下代码:

df %>%
  mutate(
    sum = 
      map2_dbl(
        client, max_prod_type,
        ~case_when(
          prod_type == .y~
            filter(df, client == .x, prod_type == .y) %>%
            mutate(sum = value_1 + value_2) %>%
            select(sum) %>%
            sum(),
          T~NA_real_
        )
      )
  )

所需的输出如下:

 # A tibble: 8 x 6
  client prod_type max_prod_type value_1 value_2   sum
   <dbl>     <dbl>         <dbl>   <dbl>   <dbl> <dbl>
1      1         1             2      10       1    NA
2      1         1             2      20       2    NA
3      1         2             2      30       3    66
4      1         2             2      30       3    66
5      2         1             2     100       1   NA
6      2         1             2     200       2   NA
7      2         2             2     300       3   606
8      2         2             2     300       3   606

但是它会抛出一个错误:

Error: Problem with `mutate()` input `sum`.
x Result 1 must be a single double, not a double vector of length 6
i Input `sum` is `map2_dbl(...)`.

此外,就我而言,这种实现方式有点慢。我想知道这个问题是否有任何正确和更优化的解决方案。

感谢您的帮助!

【问题讨论】:

    标签: r optimization dplyr


    【解决方案1】:

    一个选项可能是:

    df %>%
     group_by(client) %>%
     mutate(res = row_number() == which(value_1 == max(value_1)),
            res = if_else(res, sum(value_1[res]) + sum(value_2[res]), NA_real_))
    
      client prod_type max_prod_type value_1 value_2   res
       <dbl>     <dbl>         <dbl>   <dbl>   <dbl> <dbl>
    1      1         1             2      10       1    NA
    2      1         1             2      20       2    NA
    3      1         2             2      30       3    66
    4      1         2             2      30       3    66
    5      2         1             2     100       1    NA
    6      2         1             2     200       2    NA
    7      2         2             2     300       3   606
    8      2         2             2     300       3   606
    

    【讨论】:

      【解决方案2】:

      我认为这更接近你想要的:

      df %>%
        mutate(sum = case_when(prod_type == max_prod_type ~ value_1 + value_2,
                               TRUE ~ NA_real_))
      
      # A tibble: 6 x 6
        client prod_type max_prod_type value_1 value_2   sum
         <dbl>     <dbl>         <dbl>   <dbl>   <dbl> <dbl>
      1      1         1             2      10       1    NA
      2      1         1             2      20       2    NA
      3      1         2             2      30       3    33
      4      2         1             2     100       1    NA
      5      2         1             2     200       2    NA
      6      2         2             2     300       3   303
      

      【讨论】:

      • 对于第一版问题中提供的误导性信息,我深表歉意。我对它做了一些修改。实际上,如果客户有 2 行具有最大产品类型,我们需要为两行处理所需的计算,请参阅我的更新
      猜你喜欢
      • 2015-02-05
      • 2021-02-04
      • 1970-01-01
      • 2022-11-20
      • 1970-01-01
      • 1970-01-01
      • 2022-01-22
      • 2015-06-17
      • 1970-01-01
      相关资源
      最近更新 更多