【问题标题】:Weighted difference of observation relative to all other observation in a group (R)观察相对于组中所有其他观察的加权差异 (R)
【发布时间】:2019-06-15 01:30:22
【问题描述】:

我有以下示例数据。共有 X、Y 和 Z 三组,观测值 1 到 9 分为这些组。对于每个观察,我观察变量 A 和 B。所以:

test <- data.frame(
  id = 1:9,
  group = c(rep("X", 3), rep("Y", 3), rep("Z", 3)),
  A = seq(from = 0.15, to = 0.55, by = 0.05),
  B = 5:13
)

这给了

  id group    A  B
1  1     X 0.15  5
2  2     X 0.20  6
3  3     X 0.25  7
4  4     Y 0.30  8
5  5     Y 0.35  9
6  6     Y 0.40 10
7  7     Z 0.45 11
8  8     Z 0.50 12
9  9     Z 0.55 13

我很长一段时间以来一直在努力实现的是:对于每个观察值 1 到 9,将该观察值的 A 值相对于该观察值组的所有其他观察值的 A 值的加权差求和。因此,对于观察 1 到 4(作为示例),它应该如下所示:

id 1: (0.15 - 0.15) * 5 + (0.15 - 0.20) * 6 + (0.15 - 0.25) * 7 = -1
id 2: (0.20 - 0.15) * 5 + (0.20 - 0.20) * 6 + (0.20 - 0.25) * 7 = -0.1
id 3: (0.25 - 0.15) * 5 + (0.25 - 0.20) * 6 + (0.25 - 0.25) * 7 = 0.8
id 4: (0.30 - 0.30) * 8 + (0.30 - 0.35) * 9 + (0.30 - 0.40) * 10 = -1.45

例如,对于观察 3,这转化为单词:

第 1 步:0.25 是观察 3 在 A 上的值,该值与观察 1 在 A 上的值(即 0.15)进行比较,这个 0.10 的差异按 5 加权(观察 1 在 B 上的值)

第 2 步:将 0.25(观察 3 在 A 上的值)与观察 2 在 A 上的值 (0.20) 进行比较,并将 0.05 的差异加权 6(观察 2 在 B 上的值)

第 3 步:将 0.25(A 上的观测值 3 的值)与 A 上的(它自己的)值进行比较,并且这个 0 的差异被加权 7(它自己在 B 上的值)(我看到这一步没有必要给出0的差异;为了完整性而添加)。

步骤 4:步骤 1-3 的总和

是否有可行的方法在 R 中实现这一点?我一直在尝试使用mutategroup_by,但到目前为止都没有成功。非常感谢任何帮助。

【问题讨论】:

    标签: r dplyr


    【解决方案1】:

    您可以使用group_by() 和一点线性代数来做到这一点:

    library(dplyr)
    
    test <- data.frame(
      id = 1:9,
      group = c(rep("X", 3), rep("Y", 3), rep("Z", 3)),
      A = seq(from = 0.15, to = 0.55, by = 0.05),
      B = 5:13
    )
    
    test %>% group_by(group) %>%
      mutate(res = A*sum(B) - c(A%*%B))
    #> # A tibble: 9 x 5
    #> # Groups:   group [3]
    #>      id group     A     B    res
    #>   <int> <fct> <dbl> <int>  <dbl>
    #> 1     1 X      0.15     5 -1.   
    #> 2     2 X      0.2      6 -0.1  
    #> 3     3 X      0.25     7  0.800
    #> 4     4 Y      0.3      8 -1.45 
    #> 5     5 Y      0.35     9 -0.1  
    #> 6     6 Y      0.4     10  1.25 
    #> 7     7 Z      0.45    11 -1.90 
    #> 8     8 Z      0.5     12 -0.1  
    #> 9     9 Z      0.55    13  1.70
    

    reprex package (v0.2.1) 于 2019-01-21 创建

    【讨论】:

    • 谢谢,这就是我要找的。​​span>
    【解决方案2】:

    你可以试试data.table:

    > test[, out := colSums(sapply(A, function(x) (x - A) * B)), by = "group"]
    > test
       id group    A  B   out
    1:  1     X 0.15  5 -1.00
    2:  2     X 0.20  6 -0.10
    3:  3     X 0.25  7  0.80
    4:  4     Y 0.30  8 -1.45
    5:  5     Y 0.35  9 -0.10
    6:  6     Y 0.40 10  1.25
    7:  7     Z 0.45 11 -1.90
    8:  8     Z 0.50 12 -0.10
    9:  9     Z 0.55 13  1.70
    

    我所做的是:我将自定义函数function(x) (x - A) * B) 应用于列A 的每个元素,这给了我一个(A[i] - A[j]) * B[j] 元素的矩阵。然后我对列求和,得到结果向量。

    【讨论】:

    • 看起来你没有得到想要的输出
    • 太棒了,几乎可以完成这项工作。有没有办法按组(在我的示例中为 X、Y、Z)限制您的功能?在您的示例中,对所有 9 个观察结果进行求和,但我需要将其限制在 X(观察 1-3)、Y(观察 4-6)和 Z(观察 7-9)内。我希望我足够具体。
    • 一开始没有意识到OP需要分组。使用data.table 更正了答案,因为@gfgm 已经提供了dplyr ;)
    • 谢谢,这有帮助!
    猜你喜欢
    • 2019-06-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-17
    • 2016-12-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多