我已经在这几个小时了,似乎无法找到解决方案。我有一个非常大的数据框(超过150万行),我想在其中进行相当具体的操作。首先,我的数据如下所示:
STATION DATE Precip
COOP 310 -7788 .24
COOP 310 -7788 .15
COOP 310 -6654 .59
COOP 310 -6654 .10
COOP 499 -7122 .64
COOP 499 -7122 .36
COOP 499 -7122 .14
COOP 499 -2350 .11
COOP 499 -2350 .85
我有一个weatehr station id(STATION),一个UNIX纪元形式的日期(DATE)和降水值(降雨时的15分钟数据间隔)。我一直在努力确定每站下雨的每日降雨量。所需的输出看起来像这样:
STATION DATE 24-hour_PRECIP
COOP 310 -7788 0.39
COOP 310 -6654 0.69
COOP 499 -7122 1.14
COOP 499 -2350 0.96
这实际上意味着,我做了两次SPLIT
操作,一次根据相同的STATION值拆分所有数据,然后再根据相同的DATE值。从理论上讲,此输出将通过SAPPLY
操作运行,将SUM
函数应用于每个唯一日期/工作站集中的数据集。我的方法(虽然错了):
数据框名称为“dfhour”:
sp1<-split(dfhour$Precip,dfhour$STATION)
我可以对这些数据做一个很好的sapply函数,但我想在使用sapply之前进一步拆分它。我知道那样做
sapply(split(split(dfhour$Precip, dfhour$STATION),dfhour$DATE),FUN=sum)
将无效,因为split
函数的输出是一个列表,而下一个split
函数将无法接受列表作为参数。有人对此问题有任何指导吗?还有哪些其他功能可以帮助我找到我需要去的地方?
答案 0 :(得分:2)
我认为你只是在寻找aggregate
。如果您的data.frame名为“mydf”:
> aggregate(Precip ~ ., mydf, sum)
STATION DATE Precip
1 COOP 310 -7788 0.39
2 COOP 499 -7122 1.14
3 COOP 310 -6654 0.69
4 COOP 499 -2350 0.96
但是,根据您的数据大小来判断,您可能希望使用data.table
代替:
> library(data.table)
data.table 1.8.8 For help type: help("data.table")
> DT <- data.table(mydf, key = "STATION,DATE")
> DT[, list(Precip = sum(Precip)), by = key(DT)]
STATION DATE Precip
1: COOP 310 -7788 0.39
2: COOP 310 -6654 0.69
3: COOP 499 -7122 1.14
4: COOP 499 -2350 0.96
想象一下您的数据如下(注意重复的日期,但在不同的站点):
mydf <- structure(list(STATION = c("COOP 310", "COOP 310", "COOP 310",
"COOP 310", "COOP 499", "COOP 499", "COOP 499", "COOP 499", "COOP 499",
"COOP 499", "COOP 499"), DATE = c(-7788L, -7788L, -6654L, -6654L,
-7122L, -7122L, -7122L, -2350L, -2350L, -7788L, -7788L), Precip = c(0.24,
0.15, 0.59, 0.1, 0.64, 0.36, 0.14, 0.11, 0.85, 0.35, 0.17)), .Names = c("STATION",
"DATE", "Precip"), row.names = c(NA, 11L), class = "data.frame")
mydf
# STATION DATE Precip
# 1 COOP 310 -7788 0.24
# 2 COOP 310 -7788 0.15
# 3 COOP 310 -6654 0.59
# 4 COOP 310 -6654 0.10
# 5 COOP 499 -7122 0.64
# 6 COOP 499 -7122 0.36
# 7 COOP 499 -7122 0.14
# 8 COOP 499 -2350 0.11
# 9 COOP 499 -2350 0.85
# 10 COOP 499 -7788 0.35
# 11 COOP 499 -7788 0.17
所提供的两种替代方案将生成“STATION”和“DATE”组合的总和。这是data.table
流程和结果:
DT <- data.table(mydf, key = "STATION,DATE")
DT[, list(Precip = sum(Precip)), by = key(DT)]
# STATION DATE Precip
# 1: COOP 310 -7788 0.39
# 2: COOP 310 -6654 0.69
# 3: COOP 499 -7788 0.52
# 4: COOP 499 -7122 1.14
# 5: COOP 499 -2350 0.96
答案 1 :(得分:1)
“超过150万行”与简单的split-apply-combine相结合,表明data.table
是解决问题的完美工具。
我想你想要的东西是:
DT[,sum(Precip),by="STATION,DATE"]
DT
是data.table
的{{1}}形式。
答案 2 :(得分:0)
您不需要嵌套的splits
。您只需要提供一个单独的“拆分”参数来捕获交叉级别,可能使用interaction
函数。
tapply( statfrm$Precip, interaction(statfrm$STATION, statfrm$DATE) , sum)
#----------------
COOP-310.-7788 COOP-499.-7788 COOP-310.-7122 COOP-499.-7122 COOP-310.-6654
0.39 NA NA 1.14 0.69
COOP-499.-6654 COOP-310.-2350 COOP-499.-2350
NA NA 0.96
你也可以使用分裂 - 乐观策略来获得类似的答案,在你的cas中,零值可能比你用tapply得到的NA更合适:
sapply(split(statfrm$Precip, interaction(statfrm$STATION, statfrm$DATE) ), sum)
#-------
COOP-310.-7788 COOP-499.-7788 COOP-310.-7122 COOP-499.-7122 COOP-310.-6654
0.39 0.00 0.00 1.14 0.69
COOP-499.-6654 COOP-310.-2350 COOP-499.-2350
0.00 0.00 0.96
就这个向量的显示而言,我有时会围绕向量包裹as.matrix以显示“向下”:
as.matrix(sapply(split(statfrm$Precip, interaction(statfrm$STATION, statfrm$DATE) ), sum))
#_________________
[,1]
COOP-310.-7788 0.39
COOP-499.-7788 0.00
COOP-310.-7122 0.00
COOP-499.-7122 1.14
COOP-310.-6654 0.69
COOP-499.-6654 0.00
COOP-310.-2350 0.00
COOP-499.-2350 0.96