使用列的循环值对R中的时间序列数据进行分组
我有一个每日数据集,需要根据一列的循环值进行分组。我希望添加另一列,其中包含分组标识符。例如,我有这组数据使用列的循环值对R中的时间序列数据进行分组,r,data.table,grouping,R,Data.table,Grouping,我有一个每日数据集,需要根据一列的循环值进行分组。我希望添加另一列,其中包含分组标识符。例如,我有这组数据 YEAR = c(1900, 1900, 1900, 1901,1901, 1901, 1901, 1902, 1902, 1902, 1903) CS = c("SUM", "SUM", "SUM", "SUM", "SPR", "SPR", "SPR", "SPR", "SPR", "SPR", "SPR") DAS = c(1, 2, 3, 4, 1, 2, 3,1, 2, 3,
YEAR = c(1900, 1900, 1900, 1901,1901, 1901, 1901, 1902, 1902, 1902, 1903)
CS = c("SUM", "SUM", "SUM", "SUM", "SPR", "SPR", "SPR", "SPR", "SPR", "SPR", "SPR")
DAS = c(1, 2, 3, 4, 1, 2, 3,1, 2, 3, 4)
mydt <- data.table (YEAR, CS, DAS)
YEAR CS DAS
1: 1900 SUM 1
2: 1900 SUM 2
3: 1900 SUM 3
4: 1901 SUM 4
5: 1901 SPR 1
6: 1901 SPR 2
7: 1901 SPR 3
8: 1902 SPR 1
9: 1902 SPR 2
10: 1902 SPR 3
11: 1903 SPR 4
显然,GRP只是年份和CS的串联,尽管任何标识符(如组号)都可以。分组基于DAS的值何时返回1。我用了一个for循环来做这个,它工作得很好
group <- function(df) {
for (i in 1: nrow(df)) {
if (df$DAS[i]== 1) {
nval<- paste0(df$YEAR[i], df$CS[i])
}
df$GRP[i] <- nval
}
df
}
我的问题是,当它与数百万行一起使用时,速度非常慢。有没有办法更快地实现这一目标
更新
正如colemand77所指出的,分组并不完全基于年份和CS的组合,而是基于DAS值何时返回1。有些情况下,年份和CS的值不同,但它们仍然属于DAS的同一个周期,因此属于一个组。因此,请强调Arun的答案:
mydt[, GRP := .GRP, by=c("YEAR", "CS")]
但也要指出,你在上面的GRP并不是你所说的年份和CS的串联。。。如果这只是一个印刷错误,那么阿伦的评论是正确的。如果不是,那么你可能需要重申,因为阿伦的回答会带来意想不到的结果
尝试以下操作,但尚未计时。ifelse可能不会尽可能快,但以最快的方式,我可以做到最好。如果速度很慢,请告诉我,我们将重新计算:
mydt[DAS == 1,GRP := .GRP, by = DAS][,GRP2 := cumsum(ifelse(is.na(GRP),0,GRP))]
数据表不会自动变得更快。请仔细阅读介绍和参考语义学案例。您要查找的是mydt[,GRP:=.GRP,by=cYEAR,CS]-.GRP是一个特殊的内置变量。根据您更新的注释。。。是否有任何逻辑日期等来确定组何时更改,或者只是DAS返回到1?DAS总是相同的序列吗?例如,始终是1:4,或者有时是1:5,等等?DAS始终是从1到n的正整数序列。因此,n可以是任何正整数。在我的数据中,一个周期对应于一种作物——从播种到收获。DAS实际上计算播种后的天数,从1次播种开始,到作物死亡或收获结束。不幸的是,作物可能在12月开始种植,次年5月收获。几年的每日数据被转储在一个长时间序列中。也就是说,年份和种植季节不是一个好的分组变量。在我看来,将数据分组的唯一方法是当DAS返回到1时。感谢Arun和colemand77的回复。例如,当DAS为1时,GRP的值是Year和CS的值的串联。不管YEAR和CS的值是多少,分组应该对应于DAS从1开始到DAS再次值为1之前的行。啊!这是一个有趣的问题。我以前从未遇到过这种情况,所以让我考虑一下,然后再与您联系。@User9999-查看上面的内容,如果您的性能有任何改进,请告诉我。谢谢colemand77,它工作得很好。使用7000行数据执行不到一秒钟,比for循环花费25秒要好得多。谢谢你的帮助,非常感谢。太棒了。看看另一个世界性的伟大,那就是数据表。
mydt[DAS == 1,GRP := .GRP, by = DAS][,GRP2 := cumsum(ifelse(is.na(GRP),0,GRP))]