R 对数据进行分组的有效方法。按年度列出结果
我正在寻求有关我是否有效使用R 对数据进行分组的有效方法。按年度列出结果,r,data.table,R,Data.table,我正在寻求有关我是否有效使用data.table的建议 我有一个描述事件的数据集,每个事件一行。每行我都有事件发生的日期。现在我只想统计一下每年有多少起事故。我使用下面的代码完成了这项工作,但感觉效率很低。如果您能就如何改进这一点提供任何建议,我将不胜感激。(数据集比下面显示的要大得多,我还需要做其他类似但更复杂的计算) 创建从2000年到2012年底的日期列表: dates <- seq(as.Date("1/1/2000", format="%d/%m/%Y"), as.Date
data.table
的建议
我有一个描述事件的数据集,每个事件一行。每行我都有事件发生的日期。现在我只想统计一下每年有多少起事故。我使用下面的代码完成了这项工作,但感觉效率很低。如果您能就如何改进这一点提供任何建议,我将不胜感激。(数据集比下面显示的要大得多,我还需要做其他类似但更复杂的计算)
创建从2000年到2012年底的日期列表:
dates <- seq(as.Date("1/1/2000", format="%d/%m/%Y"),
as.Date("31/12/2012", format="%d/%m/%Y"),
"day")
# Choose one million occurrences on various dates:
sampleDate <- sample(dates, 1000000, replace=TRUE)
# Create `data.table`, one line per incident:
library(data.table)
DT.dt <- data.table(Date=sampleDate, incident=1)
# Time how long it takes to count the number of indidents in each year:
system.time(result <- DT.dt[,count(format(Date,"%Y"))])
user system elapsed
11.83 0.10 11.95
result[1:3,]
x freq
2000 76930
2001 77101
2002 76666
日期当您使用数据进行聚合操作(分组)时。表
,尤其是对于大型数据集,您应该将分组依据的字段设置为键
(使用setkeyv(DT,“您的密钥字段”)
,等等)。此外,我不能就这个主题进行明确的讨论,但总体而言,我认为在数据中使用本机数据。table::
函数/操作会获得比使用其他包函数(例如plyr::count
时更好的性能。下面,我制作了一些数据.table
对象-第一个与您的示例相同;第二个添加了一列年份
(而不是在函数执行时计算格式(日期,“%Y”)
),但将日期
设置为键
;第三个与第二个相同,只是它使用Year
作为键。我还制作了一些函数(为了方便基准测试),它们以不同的方式进行分组
library(data.table)
library(plyr) # for 'count' function
library(microbenchmark)
##
dates <- seq.Date(
from=as.Date("2000-01-01"),
to=as.Date("2012-12-31"),
by="day")
##
set.seed(123)
sampleDate <- sample(
dates,
1e06,
replace=TRUE)
##
DT.dt <- data.table(
Date=sampleDate,
incident=1)
##
DT.dt2 <- copy(DT.dt)
DT.dt2[,Year:=format(Date,"%Y")]
setkeyv(DT.dt2,"Date")
##
DT.dt3 <- copy(DT.dt2)
setkeyv(DT.dt3,"Year")
##
> head(DT.dt,3)
Date incident
1: 2003-09-27 1
2: 2010-04-01 1
3: 2005-04-26 1
> head(DT.dt2,3)
Date incident Year
1: 2000-01-01 1 2000
2: 2000-01-01 1 2000
3: 2000-01-01 1 2000
> head(DT.dt3,3)
Date incident Year
1: 2000-01-01 1 2000
2: 2000-01-01 1 2000
3: 2000-01-01 1 2000
## your original method
f1 <- function(dt)
{
dt[,count(format(Date,"%Y"))]
}
## your method - using 'Year' column
f1.2 <- function(dt)
{
dt[,count(Year)]
}
## use 'Date' column; '.N' and
## 'by=' instead of 'count'
f2 <- function(dt)
{
dt[,.N,by=format(Date,"%Y")]
}
## use 'Year' and '.N','by='
f3 <- function(dt)
{
dt[,.N,by=Year]
}
##
Res <- microbenchmark(
f1(DT.dt),
f1.2(DT.dt2),
f1.2(DT.dt3),
f2(DT.dt2),
f3(DT.dt3))
##
> Res
Unit: milliseconds
expr min lq median uq max neval
f1(DT.dt) 478.941767 515.144253 557.428159 585.579862 706.8724 100
f1.2(DT.dt2) 98.722062 115.588034 126.332104 137.792116 223.4967 100
f1.2(DT.dt3) 97.475673 118.134788 125.836817 136.136156 238.2697 100
f2(DT.dt2) 352.767219 373.337958 387.759996 429.301164 542.1674 100
f3(DT.dt3) 7.912803 8.441159 8.736887 9.685267 76.9629 100
(我在上面调用了setkeyv(DT.dt3,cols=“Year”)
) 不确定函数count
来自何处。data.table
的方式是:DT.DT[,.N,by=format(Date,“%Y”)]
。我有一种感觉,这个Q可能是一个重复的,小音符。无需为聚合操作设置密钥。我们喜欢即兴表演。你的基准测试应该包括设置键的时间。我知道post规则说我不能说谢谢。但我没有名声,所以我甚至不能投票支持你的答案。但这是惊人的。谢谢
> DT.dt3[,list(Incidents=sum(incident)),by=Year]
Year Incidents
1: 2000 77214
2: 2001 77385
3: 2002 77080
4: 2003 76609
5: 2004 77197
6: 2005 76994
7: 2006 76560
8: 2007 76904
9: 2008 76786
10: 2009 76765
11: 2010 76675
12: 2011 76868
13: 2012 76963