r — Сумма, основанная на различных значениях в другом столбце

#r #dplyr

Вопрос:

Я ищу решение tidyverse для суммирования столбца на основе уникальных значений столбца идентификаторов, при этом суммируя другие столбцы на основе всех значений.

Примеры данных:

    dat <- data.frame(
        manager = c("Adam", "Adam", "Adam", "Bill", "Bill", "Charlie", "Dan"),
        manager_age = c(30, 30, 30, 33, 33, 35, 35),
        sales = c(4, 12, 7, 4, 2, 15, 10))
   dat

  manager manager_age sales
1    Adam          30     4
2    Adam          30    12
3    Adam          30     7
4    Bill          33     4
5    Bill          33     2
6 Charlie          35    15
7     Dan          35    10
 

Я хочу суммировать все значения продаж, но суммировать только одно значение для каждого менеджера для manager_age.

Желаемый результат:

   unique_managers total_sales total_age
               4          54      133
 

Я почти нахожусь там, но мне нужна помощь с суммированным возрастом:

 results <- dat %>%summarize(unique_managers = n_distinct(manager), total_sales = sum(sales))
results
 

Заранее спасибо!

Изменить: Обновлены данные примера, чтобы включить двух менеджеров одного возраста.

Ответ №1:

Внимание: чтобы избежать случая, когда разные люди имеют одинаковый возраст, unique операция по возрасту должна быть в первую очередь в каждой личной группе.

 library(data.table)
dat <- data.frame(
    manager = c("Adam", "Adam", "Adam", "Bill", "Bill", "Charlie"),
    manager_age = c(30, 30, 30, 33, 33, 35),
    sales = c(4, 12, 7, 4, 2, 15))

setDT(dat)[,.(managers=.NGRP,
       sales = sum(sales),
       age=unique(manager_age)),
       by=manager][,.(unique_managers = unique(managers),
                      total_sales = sum(sales),
                      total_age = sum(age))]
#>    unique_managers total_sales total_age
#> 1:               3          44        98
 

Создано 2021-05-04 пакетом reprex (v2.0.0)

Ответ №2:

Это должно сделать это за вас:

 library(dplyr)   

results <- dat %>% 
  summarize(unique_managers = n_distinct(manager),
            total_sales = sum(sales)) %>% 
  cbind(dat %>% 
          select(manager, manager_age) %>% 
          group_by(manager) %>% 
          unique() %>% 
          ungroup() %>% 
          summarize(total_age = sum(manager_age)))
 

Что дает нам:

 > results
  unique_managers total_sales total_age
1               3          44        98
 

Редактировать:

Если у вас два менеджера одного возраста:

 dat <- data.frame(
  manager = c("Adam", "Adam", "Adam", "Bill", "Bill", "Charlie", "Dante"),
  manager_age = c(30, 30, 30, 33, 33, 35, 30),
  sales = c(4, 12, 7, 4, 2, 15, 14))
 

Дает нам:

   unique_managers total_sales total_age
1               4          58       128
 

Комментарии:

1. Я не думаю, что это сработает, если будет несколько менеджеров одного возраста. Рассмотрим четвертого менеджера, которому также исполнилось 30 лет. Желаемый total_age будет равен 128, но ваше решение даст 98.