【问题标题】:Moving window method to aggregate data移动窗口方法聚合数据
【发布时间】:2019-09-20 02:59:20
【问题描述】:

我有下面的矩阵:

 mat<- matrix(c(1,0,0,0,0,0,1,0,0,0,0,0,0,0,2,0,
       2,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,
       0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,
       0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,
       0,0,0,0,1,0,0,1,0,1,1,0,0,1,0,1,
       1,1,0,0,0,0,0,0,1,0,1,2,1,0,0,0), nrow=16, ncol=6)
 dimnames(mat)<- list(c("a", "c", "f", "h", "i", "j", "l", "m", "p", "q", "s", "t", "u", "v","x", "z"), 
              c("1", "2", "3", "4", "5", "6"))

我需要使用移动窗口方法聚合列。首先,窗口大小为 2,因此窗口由 2 列组成。对该聚合进行行总和。窗口将移动一步并再次进行行总和。对于提供的示例数据框,要聚合的第一列是第 1&2 列,第二个窗口将组合第 2&3 列,然后是 3&4,然后是 4&5 和 5&6。

这些结果(每个聚合的行总和)被放入一个矩阵中。在这个矩阵中,行是保守的,列现在代表每个聚合的结果。

接下来,移动窗口的大小将增加到 3。这样 3 列数据被合并(求和)。同样,窗口移动 1 步。对于提供的示例数据框,要聚合的第一列是第 1-2-3 列,第二个窗口将合并第 2-3-4 列,然后是 3-4-5、4-5-6。结果被放入一个单独的矩阵中。

移动窗口的大小会不断增加,直到窗口是所有列的大小。在本例中,最大的窗口结合了所有 6 个图。

下面是给定上面mat 的示例矩阵的窗口大小2 和3 的结果矩阵。列是根据添加的列命名的。

#Window length =2 
mat1<- matrix( c(3,0,0,0,1,0,1,0,0,0,0,0,0,0,2,0,
         2,0,1,1,2,0,0,0,0,0,0,0,0,0,1,0,
         0,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,
         0,1,0,0,1,1,0,1,0,1,1,0,0,1,0,1,
         1,1,0,0,1,0,0,1,1,1,2,2,1,1,0,1), nrow=16)
dimnames(mat1)<- list(c("a", "c", "f", "h", "i", "j", "l", "m", "p", "q", "s", "t", "u", "v","x", "z"), 
              c("1_2", "2_3", "3_4", "4_5", "5_6"))

 #Window length 3
 mat8<- matrix( c(3,0,1,1,2,0,1,0,0,0,0,0,0,0,3,0,
         2,1,1,1,2,1,0,0,0,0,0,0,0,0,1,0,
         0,1,1,1,2,1,0,1,0,1,1,0,0,1,0,1,
         1,2,0,0,1,1,0,1,1,1,2,2,1,1,0,1), nrow=16)
 dimnames(mat8)<- list(c("a", "c", "f", "h", "i", "j", "l", "m", "p", "q", "s", "t", "u", "v","x", "z"), 
              c("1_2_3", "2_3_4", "3_4_5", "4_5_6"))

在我的示例中,我有 6 列,因此总共会有 5 个结果矩阵。如果我有 600 列数据,我认为循环是迭代大型数据集的最有效方法。

【问题讨论】:

    标签: r loops aggregate


    【解决方案1】:

    这是基础 R 中的一种方式

    lapply(seq_len(ncol(mat) - 1), function(j) do.call(cbind, 
       lapply(seq_len(ncol(mat) - j), function(i) rowSums(mat[, i:(i + j)]))))
    
    
    #[[1]]
    #  [,1] [,2] [,3] [,4] [,5]
    #a    3    2    0    0    1
    #c    0    0    1    1    1
    #f    0    1    1    0    0
    #h    0    1    1    0    0
    #i    1    2    1    1    1
    #j    0    0    1    1    0
    #l    1    0    0    0    0
    #m    0    0    0    1    1
    #p    0    0    0    0    1
    #q    0    0    0    1    1
    #s    0    0    0    1    2
    #t    0    0    0    0    2
    #u    0    0    0    0    1
    #v    0    0    0    1    1
    #x    3    1    0    0    0
    #z    0    0    0    1    1
    
    #[[2]]
    #  [,1] [,2] [,3] [,4]
    #a    3    2    0    1
    #c    0    1    1    2
    #f    1    1    1    0
    #h    1    1    1    0
    #i    2    2    2    1
    #j    0    1    1    1
    #l    1    0    0    0
    #m    0    0    1    1
    #p    0    0    0    1
    #q    0    0    1    1
    #s    0    0    1    2
    #t    0    0    0    2
    #u    0    0    0    1
    #v    0    0    1    1
    #x    3    1    0    0
    #z    0    0    1    1
    #....
    

    由于这是滚动操作,我们也可以使用 zoo 中的 rollapply 和可变窗口宽度

    lapply(2:ncol(mat), function(j)
        t(zoo::rollapply(seq_len(ncol(mat)), j, function(x) rowSums(mat[,x]))))
    

    【讨论】:

    • 谢谢。与序列中的滑动窗口相比,如何将其修改为随机选择要聚合的列?
    • 这将需要对内部lapply 进行一些更改。我们需要使用sample 选择j 随机列,执行rowSums 并删除那些选择的j 列,以便在下一次迭代中不会重复这些列。
    • 有没有办法修改解决方案,使列名指定组合的列?例如,如果移动窗口结合了第 1 列和第 2 列,则列名将是“1_2”。同样,如果移动窗口结合了 3 列,如第 2,3 &4 列,则列名将指示“2_3_4”。
    • 我已经尝试了以下方法,请告诉我我的错误:lapply(seq_len(ncol(mat) - 1), function(j) do.call(cbind, lapply(sample(ncol(mat) - j), function(i) rowSums(mat[, i:(i - j)]))))
    • 我已经发布了与此请求帮助有关的第二个问题,使用不同的分箱技术,如果您也能提供帮助:stackoverflow.com/questions/58083701/…
    猜你喜欢
    • 2021-09-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-26
    • 1970-01-01
    • 1970-01-01
    • 2018-10-28
    • 1970-01-01
    相关资源
    最近更新 更多