好的,首先是一些代码来生成一些测试数据。这会产生 100 个随机 ID,并且每个 ID 从 2 年期间选择 20 个月以及随机值。然后将顺序打乱以获得额外的乐趣。
## Generate some IDs
ids <- sample(1000, 100)
## Generate the data
data <- do.call(rbind,
lapply(ids,
function(id)
data.frame(ID = id,
Date = sample(as.Date(paste(rep(c(2008:2009), each=12),
1:12, 1, sep="-")),
20),
Value = sample(1000, 20))))
## Shuffle
data <- data[sample(nrow(data), nrow(data)),]
这对我来说是这样的:
> head(data)
ID Date Value
1007 205 2008-07-01 235
1391 840 2008-12-01 509
918 278 2009-12-01 951
1213 945 2009-03-01 842
1369 766 2009-07-01 555
798 662 2008-12-01 531
好的,现在让我们遍历 ID 并找到每个 ID 的每个月的差异。在此之前,让我们将月份转换为数字,以便更容易计算差异(这有点不干净,有人知道对 Date 对象进行算术的更好方法吗?)。这样做只是year * 12 + month
为了使正常的算术起作用:
data$Month <- as.POSIXlt(data$Date)$mon + as.POSIXlt(data$Date)$year * 12
现在计算差异:
by.id <- by(data, data$ID, function(x) {
## Sort by month.
x <- x[order(x$Month),]
## Compute the month and value differences, taking care to pad the edge case.
data.frame(ID=x$ID,
Date = x$Date,
Month.diff=c(0, diff(x$Month)),
Value.diff=c(0,diff(x$Value)))
})
by.id <- do.call(rbind, by.id)
结果如下:
> head(by.id)
ID Date Month.diff Value.diff
4.1 4 2008-02-01 0 0
4.2 4 2008-03-01 1 123
4.3 4 2008-05-01 2 -94
4.4 4 2008-06-01 1 -243
4.5 4 2008-08-01 2 -327
4.6 4 2008-10-01 2 656
如果连续月份之间的差异大于 1,则月份不相邻,我们应该将它们的值设置为零。
by.id$Value.diff <- ifelse(by.id$Month.diff == 1,
by.id$Value.diff,
0)
最后,我们按月迭代并取顶部和底部的 N 个差异(我将在这里将 N 设置为 10 而不是 100,因为我的测试数据集相当小)。
by.month <- by(by.id, by.id$Date, function(x) {
## Sort the data in each month
x <- x[order(x$Value.diff),]
## Take the top and bottom and label them accordingly.
cbind(rbind(head(x, 10), tail(x, 10)),
type=rep(c("min", "max"), each=10))
})
我们终于得到它了。这是一个示例结果:
> by.month[[24]]
ID Date Month.diff Value.diff type
130.20 130 2009-12-01 1 -951 min
415.20 415 2009-12-01 1 -895 min
662.20 662 2009-12-01 1 -878 min
107.20 107 2009-12-01 1 -744 min
824.20 824 2009-12-01 1 -731 min
170.20 170 2009-12-01 1 -719 min
502.20 502 2009-12-01 1 -714 min
247.20 247 2009-12-01 1 -697 min
789.20 789 2009-12-01 1 -667 min
132.20 132 2009-12-01 1 -653 min
64.20 64 2009-12-01 1 622 max
82.20 82 2009-12-01 1 647 max
381.20 381 2009-12-01 1 698 max
303.20 303 2009-12-01 1 700 max
131.20 131 2009-12-01 1 751 max
221.20 221 2009-12-01 1 765 max
833.20 833 2009-12-01 1 791 max
806.20 806 2009-12-01 1 806 max
780.20 780 2009-12-01 1 843 max
912.20 912 2009-12-01 1 929 max