#r #optimization #dplyr
#r #оптимизация #dplyr
Вопрос:
Предположим, что следующая таблица:
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’. Мне нужно вычислить новый столбец ‘sum’, который будет содержать сумму от добавления значений из ‘value_1’ и ‘value_2’, но только для тех строк, где ‘prod_type’ == ‘max_prod_type’ для каждого значения ‘client’.
Я попробовал следующий код:
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:
Одним из вариантов может быть:
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
Комментарии:
1. Прошу прощения за то, что пропустил информацию, приведенную в первой версии вопроса. Я внес в нее некоторые изменения. На самом деле, если у клиента есть 2 строки с максимальным типом продукта, нам нужно обработать желаемое вычисление для двух строк, пожалуйста, смотрите Мое обновление