对于给定的标识符,按日期范围对行求和
Sum rows by date range, for a given identifier
我看了很多类似的帖子,但我认为问题不那么复杂,似乎无法找到答案。
我有 >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)
非常感谢任何意见,引导我朝着正确的方向前进。
非常感谢!
1.使用 dplyr/zoo
我们可以将'date'class从'character'转换为'Date',得到'amount'和[=13=的sum
] 按列 'name' 和 'Qtr' 分组的 'date' 的值(将 '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
并更改 'date' 列的 class。 Qtr
列是 'character',因为 as.yearqtr
class 不受 dplyr
支持(来自错误)。 'Qtr' 列不在预期的数据集 'data2' 中。所以,我猜是 'character' 还是 'as.yearqtr' 都没有关系。如果我们不将 'date' 列更改为 'Date' class,并在 group_by
步骤中进行更改,这将给出与 [=50= 相同的结果].可以删除多余的 '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
的解决方案,'date' 的格式与预期输出 'data2'
这里有一些方法:
1) 聚合 & 动物园
library(zoo)
aggregate(amount ~ name + yearqtr,
transform(data, yearqtr = as.yearqtr(date, "%m/%d/%Y")),
sum)
2) data.table & 动物园
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 非常快。您可以使用 setDT
通过引用从 data
创建 data.table 以获得更好的性能,但可能更愿意将它们分开,因此我们将它们分开放置在这里。
我看了很多类似的帖子,但我认为问题不那么复杂,似乎无法找到答案。
我有 >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)
非常感谢任何意见,引导我朝着正确的方向前进。 非常感谢!
1.使用 dplyr/zoo
我们可以将'date'class从'character'转换为'Date',得到'amount'和[=13=的sum
] 按列 'name' 和 'Qtr' 分组的 'date' 的值(将 '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
并更改 'date' 列的 class。 Qtr
列是 'character',因为 as.yearqtr
class 不受 dplyr
支持(来自错误)。 'Qtr' 列不在预期的数据集 'data2' 中。所以,我猜是 'character' 还是 'as.yearqtr' 都没有关系。如果我们不将 'date' 列更改为 'Date' class,并在 group_by
步骤中进行更改,这将给出与 [=50= 相同的结果].可以删除多余的 '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
的解决方案,'date' 的格式与预期输出 'data2'
这里有一些方法:
1) 聚合 & 动物园
library(zoo)
aggregate(amount ~ name + yearqtr,
transform(data, yearqtr = as.yearqtr(date, "%m/%d/%Y")),
sum)
2) data.table & 动物园
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 非常快。您可以使用 setDT
通过引用从 data
创建 data.table 以获得更好的性能,但可能更愿意将它们分开,因此我们将它们分开放置在这里。