Сумма строк по диапазону дат для заданного идентификатора
Я просмотрел много постов с похожими, но я считаю, что менее сложные вопросы, и просто не могу найти ответ на этот вопрос.
У меня есть>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
за каждую большую производительность, но, возможно, предпочли бы держать их отдельно, поэтому мы оставили их здесь отдельно.