1

我在 TSV 中有一个时间序列数据,如下所示:

ID \t Date \t Value
-------------------------------
1234567 \t 2009-01-01T00:00:00.000Z \t 121
12131 \t 2009-06-01T00:00:00.000Z \t 151
12131 \t 2009-07-01T00:00:00.000Z \t 15153
...

它很容易放入 RAM,但对于 Excel 来说太大了。

每个 ID 每月有一个值,但并非所有 ID 都有所有 12 个月的条目。

数据跨越 12 个月,但并非所有 ID 都有 12 个月。我想查看每个 ID 的数据,如果有上个月的条目,则将当前月份减去上个月并将其存储在新列中以获得增量。如果上个月没有条目,则返回 0。然后,对于每个月,我想要这些增量的前 100 个正数和负数,以及 ID。

我想在 R 中执行此操作,因为它在 Excel 中很难并且不断崩溃。我已经安装了 R、Rattle 等,并且我已经完成了基本示例,但是......学习曲线很陡峭。我真的很感激一些帮助:)

4

3 回答 3

7

首先添加所有缺失的月份:

all_combs <- expand.grid(
  ID = unique(data$ID),
  Date = unique(data$Date))

data <- merge(data, all_combs, by = c("ID", "Date"), all = T)
# Ensure data ordered by date
data <- data[with(data, order(ID, Date)), ]

然后添加一列deltas(用diff计算)

library(plyr)
data <- ddply(data, "ID", transform, delta = c(NA, diff(Value)))

最后,删除缺失的增量,按它们的值排序并提取每组中的前 10 个和后 10 个。

changed <- subset(data, !is.na(delta))
changed <- changed[with(changed, order(ID, delta)), ]

# Select top 100 for each
top10 <- ddply(changed, "ID", function(df) {
 rbind(head(df, 10), tail(df, 10))
})
于 2009-12-23T08:49:22.173 回答
4

好的,首先是一些代码来生成一些测试数据。这会产生 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
于 2009-12-23T06:04:15.517 回答
1

伪代码开始:

For Each ID
  If Previous month data Exists 
    compute Diff
  Else diff = 0
return diff

For Each Month
  Max 100 (Positive)
  Min 100 (Negative)

#Realish Code
dataset$diff <- lappply(dataset,function(ID,month,value){IF dataset[month-1] = TRUE{value-(value[month-1]})})
#This gets tricky since you need to know the month and what the previous month is in a format you can test
于 2009-12-23T04:25:36.307 回答