Сумма строк по диапазону дат для заданного идентификатора

Я просмотрел много постов с похожими, но я считаю, что менее сложные вопросы, и просто не могу найти ответ на этот вопрос.

У меня есть>1000000 строк данных, например, в этой форме:

date<-c("9/30/2012","10/31/2012","11/30/2012","12/31/2012","1/31/2013","2/28/2013","3/31/2013","10/31/2012","11/30/2012","12/31/2012","1/31/2013","2/28/2013","3/31/2013")
name<-c("a","a","a","a","a","a","a","b","b","b","b","b","b")
amount<-c(100,200,300,400,500,600,700,800,900,800,700,600,500)
data<-data.frame(name,date,amount)
View(data)

Что мне нужно, так это для записей с тем же именем суммировать сумму дат за январь-март, апрель-июнь, июль-сент, окт-декабрь в том же году.

Это мой идеальный выход:

date2<-c("9/30/2012","12/31/2012","3/31/2013","12/31/2012","3/13/2013")
name2<-c("a","a","a","b","b")
amount2<-c(100,900,1800,2500,1800)
data2<-data.frame(name2,date2,amount2)
View(data2)

Буду признателен за любой вклад, чтобы привести меня в правильном направлении. Большое спасибо!

2 ответа

Решение

1. Использование dplyr/zoo

Мы можем преобразовать класс 'date' из 'character' в 'Date', получить sum "количество" и last значение "date", сгруппированное по столбцам "name" и "Qtr" (от преобразования "date" в квартал года (as.yearqtr).

library(dplyr)
library(zoo)
 data %>%
     mutate(date=as.Date(date, format='%m/%d/%Y')) %>%
     group_by(name, Qtr=as.character(as.yearqtr(date))) %>% 
     summarise(amount= sum(amount), date=last(date))
 #  name     Qtr amount       date
 #1    a 2012 Q3    100 2012-09-30
 #2    a 2012 Q4    900 2012-12-31
 #3    a 2013 Q1   1800 2013-03-31
 #4    b 2012 Q4   2500 2012-12-31
 #5    b 2013 Q1   1800 2013-03-31

ПРИМЕЧАНИЕ: также добавлено предложение @docendo discimus для использования last и изменение класса столбца "дата". Qtr столбец "символ" как as.yearqtr класс не поддерживается dplyr (из ошибок). Столбец Qtr не был в ожидаемом наборе данных data2. Итак, я думаю, что не имеет значения, является ли это 'персонажем' или 'as.yearqtr'. Если мы не изменим столбец date на класс Date и сделаем изменение в group_by шаг, это даст тот же результат, что и "data2". Дополнительный столбец Qtr можно удалить.

2. Без использования зоопарка

 data %>%
     mutate(date1 = as.Date(date, format = '%m/%d/%Y')) %>% 
     group_by(name, Qtr= sprintf('%s %s', format(date1, '%Y'),
                                         quarters(date1))) %>%
     summarise(amount = sum(amount), date=last(date)) %>%
     ungroup() %>%
     select(-Qtr) %>% 
     as.data.frame()
 #  name amount       date
 #1    a    100  9/30/2012
 #2    a    900 12/31/2012
 #3    a   1800  3/31/2013
 #4    b   2500 12/31/2012
 #5    b   1800  3/31/2013

ПРИМЕЧАНИЕ 2. Добавлено решение без использования as.yearqtrсохранял тот же формат для "даты", что и в ожидаемом выводе "data2"

Вот несколько подходов:

1) совокупность и зоопарк

library(zoo)

aggregate(amount ~ name + yearqtr, 
          transform(data, yearqtr = as.yearqtr(date, "%m/%d/%Y")), 
          sum)

2) data.table & zoo

library(data.table)
library(zoo)

dt <- data.table(data, key = "name,date")
dt[, date := as.yearqtr(date, "%m/%d/%Y")][, list(sum = sum(amount)), by = "name,date"]

Обратите внимание, что оба эти решения преобразуют date к настоящему "yearqtr" объект, а не только символьная строка. Я не тестировал их, но обычно data.table очень быстрый. Вы можете создать data.table из data с помощью ссылки setDT за каждую большую производительность, но, возможно, предпочли бы держать их отдельно, поэтому мы оставили их здесь отдельно.

Другие вопросы по тегам