【问题标题】:R: Aggregating over several variables and observations (depending on values) and creating a new variableR:聚合多个变量和观察值(取决于值)并创建一个新变量
【发布时间】:2019-01-05 23:42:36
【问题描述】:

数据集具有如下结构

    Key         Date         Mat    Amount
     <int>     <date>       <chr>  <dbl>
1  1001056    2014-12-12    10025  0.10
2  1001056    2014-12-23    10025  0.20
3  1001056    2015-01-08    10025  0.10
4  1001056    2015-04-07    10025  0.20
5  1001056    2015-05-08    10025  0.20
6  1001076    2013-10-29    10026  3.00
7  1001140    2013-01-18    10026  0.72
8  1001140    2013-04-11    10026  2.40
9  1001140    2014-10-08    10026  0.24
10 1001237    2015-02-17    10025  2.40
11 1001237    2015-02-17    10026  3.40

Mat 采用 {10001,...,11000} 中的值,因此 A:=|Mat|=1000。

我想实现以下目标:

1)(中间步骤)对于每个关键日期组合,我想计算所有材料,这些材料在这种组合中可用(可能因钥匙而异),数量差异, 例如对于组合“1001237 2015-02-17”,这将适用于材料 10025 和 10026 2.40-3.40=-1(但可能是更多组合)。 (如何有效地存储这些值?) 这一步可能会被跳过。

2) 最后,我想构建一个维度为 A=1000 的新矩阵,其中每个条目 (i,j)(材料组合 i 和 j)包含上一步中计算的值的平均值。 更正式地说,条目 (i,j) 由

1/|所有包含 Mat i 和 Mat j 的关键日期组合| \sum_{所有包含 Mat i 和 Mat j 的关键日期组合} Amount_i - Amount_j

由于表相当大,计算效率很重要。

非常感谢您提前提供的帮助!

【问题讨论】:

    标签: r variables aggregation


    【解决方案1】:

    我可以使用tidyverse 中的列表列来做到这一点;诀窍是使用group_by 来获得KeyDate 的不同组合。代码如下:

    materials <- unique(x$Mat)
    n <- length(materials)
    
    x <- x %>% 
      group_by(Key, Date) %>% 
      nest() %>% 
      # Create a n by n matrix for each combination of Key and Date
      mutate(matrices = lapply(data, 
                           function(y) {
                             out <- matrix(nrow = n, ncol = n, 
                                           dimnames = list(materials, materials))
                             # Only fill in when the pair of materials is present
                             # for the date of interest
                             mat_present <- as.character(unique(y$Mat))
                             for (i in mat_present) {
                               for (j in mat_present) {
                                 # You may want to take an absolute value
                                 out[i,j] <- y$Amount[y$Mat == i] - y$Amount[y$Mat == j]
                               }
                             }
                             out
                           }))
    

    如果你真的想要速度,你可以用Rcpp实现lapply中的功能。您可以使用RcppParallel 进一步加快速度。现在数据框的一列是矩阵列表。然后,对于矩阵的每个元素,取平均值,同时忽略NAs:

    x_arr <- array(unlist(x$matrices), dim = c(2,2,10))
    results <- apply(x_arr, 2, rowMeans, na.rm = TRUE)
    

    我将矩阵列表堆叠成一个 3D 数组,发现行意味着逐个切片。对于性能,您也可以在RcppArmadillosum(x_arr, 2) 中执行此操作,但是当并非所有类型的材料都以KeyDate 的组合表示时,很难处理缺失值。

    【讨论】:

    • 感谢您的回复。我认为 i 和 j 的索引可能会调整(名称与行/列数)。在全数据集上运行代码,出现如下错误信息:Error in eval(substitute(expr), envir, enclos) : number of items to replace is not a multiple of replacement length
    • 我怀疑这是因为要分配给out[i,j] 的值的长度大于1。在编写代码时,我假设对于键和日期的每个组合,每个材料只出现一次。如果这不适用,您最终会尝试将向量分配给缩放器,这会导致错误。
    • 顺便说一句,为了提高效率,您可以将 for 循环修改为 for (j &lt; i),因为只需要一半的计算。如果不取绝对值,对角线上方的一半只是下半部分的负数。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-17
    • 2013-12-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-15
    相关资源
    最近更新 更多