R:更快的period.apply替代品

时间:2015-05-20 16:23:35

标签: r time-series apply

我准备了以下数据

Timestamp   Weighted Value  SumVal  Group
1           1600            800     1
2           1000            1000    2
3           1000            1000    2
4           1000            1000    2
5           800             500     3
6           400             500     3
7           2000            800     4
8           1200            1000    4

我想计算每个组的总和(Weighted_Value)/ sum(SumVal),所以例如对于组3,结果将是1.2。

我正在使用period.apply来做到这一点:

period.apply(x4, intervalIndex, function(z) sum(z[,4])/sum(z[,2]))

但是对我的应用程序来说太慢了,所以我想问一下是否有人知道更快的替代方案?我已经尝试过了,但它似乎更慢了。

我的目标是btw。计算时间加权平均值,将不规则时间序列转换为等距时间间隔的时间序列。

谢谢!

4 个答案:

答案 0 :(得分:3)

library(data.table)
setDT(df)[, sum(Weighted_Value) / sum(SumVal), by = Group]

但我没有看到你所指的时间序列。 看看图书馆(动物园)。

答案 1 :(得分:3)

使用rowsum似乎比data.table方法更快(至少对于这个小示例数据集):

sgibb <- function(datframe) {
  data.frame(Group = unique(df$Group),
             Avg = rowsum(df$Weighted_Value, df$Group)/rowsum(df$SumVal, df$Group))
}

rowsum方法添加到@ platfort的基准:

library(microbenchmark)
library(dplyr)
library(data.table)

microbenchmark(
  Nader   = df %>%
              group_by(Group) %>%
              summarise(res = sum(Weighted_Value) / sum(SumVal)),
  Henk    = setDT(df)[, sum(Weighted_Value) / sum(SumVal), by = Group],
  plafort = weight.avg(df),
  sgibb = sgibb(df)
)
# Unit: microseconds
#     expr      min       lq      mean    median        uq      max neval
#    Nader 2179.890 2280.462 2583.8798 2399.0885 2497.6000 6647.236   100
#     Henk  648.191  693.519  788.1421  726.0940  751.0810 2386.260   100
#  plafort 2638.967 2740.541 2935.4756 2785.7425 2909.4640 5000.652   100
#    sgibb  347.125  384.830  442.6447  409.2815  441.8935 2039.563   100

答案 2 :(得分:2)

尝试使用dplyr它应该比基础R

更快
library(dplyr)

df <- read.table(text = "Timestamp   Weighted_Value  SumVal  Group
1           1600            800     1
2           1000            1000    2
3           1000            1000    2
4           1000            1000    2
5           800             500     3
6           400             500     3
7           2000            800     4
8           1200            1000    4" , header = T)


df %>%
  group_by(Group) %>%
  summarise(res = sum(Weighted_Value) / sum(SumVal))

答案 3 :(得分:2)

这是一个基础R解决方案。它对于较大的(500k +)数据集来说不是最快的,但是你可以看到可能发生的事情&#34;引擎盖下#34;在其他功能。

weight.avg <- function(datframe) {
  s <- split(datframe, datframe$Group)
  avg <- sapply(s, function(x) sum(x[ ,2]) / sum(x[ ,3]))
  data.frame(Group = names(avg), Avg = avg)
}

weight.avg(df)
  Group      Avg
1     1 2.000000
2     2 1.000000
3     3 1.200000
4     4 1.777778

该函数的第一行按组拆分数据框。第二个将公式应用于每个组。最后一个创建了一个新的数据框。

数据

df <- read.table(text = "Timestamp   Weighted_Value  SumVal  Group
                 1           1600            800     1
                 2           1000            1000    2
                 3           1000            1000    2
                 4           1000            1000    2
                 5           800             500     3
                 6           400             500     3
                 7           2000            800     4
                 8           1200            1000    4" , header = T)

最快时间

library(microbenchmark)
library(dplyr)
library(data.table)

microbenchmark(
  Nader   = df %>%
              group_by(Group) %>%
              summarise(res = sum(Weighted_Value) / sum(SumVal)),
  Henk    = setDT(df)[, sum(Weighted_Value) / sum(SumVal), by = Group],
  plafort = weight.avg(df)
)
Unit: microseconds
    expr      min        lq      mean   median       uq      max
   Nader 2619.174 2827.0100 3094.5570 2949.976 3107.481 7980.684
    Henk  783.186  833.7155  932.5883  888.783  944.640 3275.646
 plafort 3550.787 3772.4395 4085.2323 3853.561 3995.869 7595.801