Предположим следующую таблицу:

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» для каждого значения «client». Мне нужно вычислить новый столбец «сумма», который будет содержать сумму от добавления значений из «значение_1» и «значение_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(...)`.

Более того, как по мне, такой способ реализации несколько медленный. Мне интересно, есть ли какое-нибудь правильное и более оптимизированное решение этой проблемы.

Ценю твою помощь!

1
KarmaOfJesus 19 Янв 2021 в 15:33

2 ответа

Лучший ответ

Один из вариантов может быть:

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
1
tmfmnk 19 Янв 2021 в 12:50

Я думаю, что это ближе к тому, что вы хотите:

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
1
latlio 19 Янв 2021 в 12:38