使用滑动窗口对数据帧中的计数求和

时间:2016-01-27 13:57:57

标签: r dataframe sliding-window

我是R.的新手。我在R中有一个数据框,如下所示

df

对于每个ID,我想在每3个位置的滑动窗口中对“值”列中的计数求和。以下数据框是A1的摘录,其中仅包含与ID Values A1 10 A1 2 A1 4 A1 23 A1 10 A1 5 A1 20 A1 15 A1 13 A1 21 对应的记录:

Window_1

我想在时间和总和中输入3个条目,然后转到接下来的3个条目。当滑动窗口不能容纳3个条目时,我跳过这些值。

例如,10从第一个值(window_2)开始,而2从第二个值(4开始),window_3从第三个值开始({{1} }})。

 window_1 = [10+2+4] + [23+10+5] + [20+15+13] = 102 
 window_2 = [2+4+23] + [10+5+20] + [15+13+21] = 113
 window_3 = [4+23+10] + [5+20+15] = 77

并在以下数据框中报告:

ID  Window_1 Window_2 Window_3
A1   102       113      77

同样,我希望对数据框“df”中每个元素的Values列中的计数求和,并在data.frmae中报告如下:

ID    window_1   window_2   window_3
A1      102       113         77
A2      206       195         161
A3      198       163         175

我尝试了以下代码

sum_win_3=0
sum_win_2=0
sum_win_1=0
win_1_counts=0
win_2_counts=0
win_3_counts=0

for (i in seq(1,length(df$Values),3))
{

  if((i+i+1+i+2) %% 3 == 0)
  {
    win_1_counts=df$Values[i]+df$Values[i+1]+df$Values[i+2]
    win_1_counts[is.na(win_1_counts)]=0
    #print(win_1_counts)
  }
  sum_win_1=sum_win_1+win_1_counts
}
#print(sum_win_1)

for (j in seq(2,length(df$Values),3))
{
  if((j+j+1+j+2) %% 3 == 0)
  {
    win_2_counts=df$Values[j]+df$Values[j+1]+df$Values[j+2]
    win_2_counts[is.na(win_2_counts)]=0
    #print(win_2_counts)
  }
  sum_win_2=sum_win_2+win_2_counts
}
#print(sum_win_2)

for (k in seq(3,length(df$Values),3))
{
  if((k+k+1+k+2) %% 3 == 0)
  {
    win_3_counts=df$Values[k]+df$Values[k+1]+df$Values[k+2]
    win_3_counts[is.na(win_3_counts)]=0
    #print(win_3_counts)
  }
  #sum_win_3=sum_win_3+win_3_counts
}
print(sum_win_3)
output=data.frame(ID=df[1],Window_1=sum_win_1,Window_2=sum_win_2,Window_3=sum_win_3)

上面的代码将window_1,windows_2和window_3的计数相加,将所有ID放在一起,而不是分别处理每个ID。
请指导我以上述所需格式获得输出。 提前致谢

3 个答案:

答案 0 :(得分:8)

使用 data.table 包,我会按如下方式处理:

library(data.table)
setDT(df)[, .(w1 = sum(Values[1:(3*(.N%/%3))]),
              w2 = sum(Values[2:(3*((.N-1)%/%3)+1)]),
              w3 = sum(Values[3:(3*((.N-2)%/%3)+2)]))
          , by = ID]

给出:

   ID  w1  w2  w3
1: A1 102 113  77
2: A2 206 195 161
3: A3 198 163 175

或者为了避免重复(而不是@Cath):

setDT(df)[, lapply(1:3, function(i) {sum(Values[i:(3*((.N-i+1)%/%3)+(i-1))])})
          , by = ID]

如果要重命名V1,V2& V3变量,之后你可以这样做,但你也可以这样做:

cols <- c("w1","w2","w3")

setDT(df)[, (cols) := lapply(1:3, function(i) {sum(Values[i:(3*((.N-i+1)%/%3)+(i-1))])})
          , by = ID]

答案 1 :(得分:5)

这似乎有效:

library(zoo)
wins = function(x, w) 
  rollapply(x, width = w*((length(x)-seq(w)+1) %/% w), align = "left", sum)

aggregate(Values ~ ID, df, wins, 3)
#   ID Values.1 Values.2 Values.3
# 1 A1      102      113       77
# 2 A2      206      195      161
# 3 A3      198      163      175

到目前为止,这是唯一一个以滚动方式执行计算的答案,通常效率更高。

答案 2 :(得分:5)

可以使用sumf <- function(x1){ sum(tapply(x1, (seq_along(x1) -1) %/%3, function(x) ifelse(length(x) == 3, sum(x), 0))) } aggregate(Values ~ ID, data = df, FUN = function(y){ cbind(sumf(y), sumf(y[-1]), sumf(y[-c(1,2)])) }) # Group.1 x.1 x.2 x.3 #1 A1 102 113 77 #2 A2 206 195 161 #3 A3 198 163 175 filter

来完成
sum.filter <- function(z) tapply(head(tail(as.numeric(
    filter(z, c(1,1,1))),-1), -1), 
    0:(length(z)-3) %% 3 +1, sum)

aggregate(Values ~ ID, data = df, FUN = function(y){ cbind(sum.filter(y) )})

这也可以使用 Paraula tipo1; tipo1 = { Paraula.lletres[0] = 't'; Paraula.lletres[1]='1'; Paraula.llargaria = 2;

来完成
          Paraula tipo1 = new Paraula();
          tipo1.lletres[0] = 't';
          tipo1.lletres[1]='1';
          tipo1.llargaria = 2;