【问题标题】:Selecting all possible combinations of variables [closed]选择所有可能的变量组合[关闭]
【发布时间】:2021-09-23 11:14:40
【问题描述】:

我有一个数据集,其中我们用 18 个项目和政治取向来衡量幸福感(我们暂时假设用一个项目来衡量政治取向)。

一个人的幸福感分数可以通过取所有 18 个项目的平均值来计算,也可以通过对每个可能的项目组合(例如,一个项目、两个项目的所有组合等)取平均值来计算,从而得到 @ 987654321@ 可能的组合。

我对幸福感和政治取向之间的相关系数如何根据幸福感的计算方式而变化感兴趣。也就是说,我有兴趣获得所有 18 (choose(18,1) = 18) 相关系数,如果幸福是用 18 个项目中的每一个进行评估,然后与政治取向相关,如果幸福是所有 153 个相关系数用 2 项的所有可能组合计算,然后与政治取向等相关联。所以最后我会寻找 262,144 个相关系数。

数据集看起来像这样(只有超过 10,000 名参与者),而 v19 是政治方向,v1 到 v18 是福利项目。

df <- as.data.frame(matrix(rnorm(190), ncol = 19)) 

本质上,我要问的是如何计算 2 个项目、3、...、17 个幸福项目的所有组合的平均值。我遇到了tidyrexpand() 函数,但这似乎是在做别的事情。

【问题讨论】:

  • 您提到了“幸福指数”和“政治方向”,之前您提到了 18 个项目,但您的样本数据是 10 行 19 列,未标记。请说明我们应该如何使用您对相关困境的描述来预测您的 rnorm 数据。
  • 每一列代表一个项目。第 1-18 列(即 v1 到 v18)代表 18 个福利项目,第 19 列政治方向(v19)。每行代表一个参与者的反应。现在清楚了吗?

标签: r combinations correlation


【解决方案1】:

以下是 (1) 计算 18 个因素组合的平均值的一些步骤;然后 (2) 将这些组合平均值中的每一个与第 19 列(政治方向)相关联。

set.seed(42)
df <- as.data.frame(matrix(rnorm(190), ncol = 19))
df[,1:3]
#          V1      V2      V3
# 1   1.37096  1.3049 -0.3066
# 2  -0.56470  2.2866 -1.7813
# 3   0.36313 -1.3889 -0.1719
# 4   0.63286 -0.2788  1.2147
# 5   0.40427 -0.1333  1.8952
# 6  -0.10612  0.6360 -0.4305
# 7   1.51152 -0.2843 -0.2573
# 8  -0.09466 -2.6565 -1.7632
# 9   2.01842 -2.4405  0.4601
# 10 -0.06271  1.3201 -0.6400
rowMeans(df[,c(1,2)])
#  [1]  1.3379  0.8610 -0.5129  0.1770  0.1355  0.2649  0.6136 -1.3756 -0.2110  0.6287
rowMeans(df[,c(1,3)])
#  [1]  0.53216 -1.17300  0.09561  0.92377  1.14973 -0.26830  0.62713 -0.92891  1.23926 -0.35135
rowMeans(df[,c(2,3)])
#  [1]  0.4991  0.2527 -0.7804  0.4679  0.8809  0.1027 -0.2708 -2.2098 -0.9902  0.3401

我展示了三个组合的行均值,因为我想验证下一步在哪里找到这些值。

means <- lapply(1:3, function(N) {
  do.call(cbind,
          lapply(asplit(combn(18, N), 2),
                 function(ind) rowMeans(df[, ind, drop = FALSE])))
})
str(means)
# List of 3
#  $ : num [1:10, 1:18] 1.371 -0.565 0.363 0.633 0.404 ...
#  $ : num [1:10, 1:153] 1.338 0.861 -0.513 0.177 0.135 ...
#  $ : num [1:10, 1:816] 0.7897 -0.0198 -0.3992 0.5229 0.722 ...

最后一步会生成一个means 对象,其中包含“1”(奇异列)、“2”(成对行平均值)和“3”深度组合平均值。请注意,choose(18,2) 是 153(means[[2]] 中的列数),choose(18,3) 是 816 (means[[3]])。每列代表各列组合的平均值。

我在此处包含1 (choose(18,1)) 只是为了将所有数据保持在相同的结构中,因为我们确实想测试单列的相关性;可以通过其他方法来实现这一点,我倾向于一致性和简单性。

为了验证我们的想法,我将从means[[2]] 中提取三列,它们对应于我上面基于直接访问df 显示的三个rowMeans 计算(检查将显示它们是匹配的):

means[[2]][,c(1,2,18)]
#          [,1]     [,2]    [,3]
#  [1,]  1.3379  0.53216  0.4991
#  [2,]  0.8610 -1.17300  0.2527
#  [3,] -0.5129  0.09561 -0.7804
#  [4,]  0.1770  0.92377  0.4679
#  [5,]  0.1355  1.14973  0.8809
#  [6,]  0.2649 -0.26830  0.1027
#  [7,]  0.6136  0.62713 -0.2708
#  [8,] -1.3756 -0.92891 -2.2098
#  [9,] -0.2110  1.23926 -0.9902
# [10,]  0.6287 -0.35135  0.3401

这意味着列的顺序为1,21,31,4、...、1,18,然后是2,3(第 18 列)、2,4 等,一直到17,18 (第 153 栏)。

从这里开始,将这些列中的每一个与V19 关联起来并不困难:

cors <- lapply(means, function(mn) apply(mn, 2, cor, df$V19))
str(cors)
# List of 3
#  $ : num [1:18] 0.2819 -0.3977 0.0426 0.2501 -0.063 ...
#  $ : num [1:153] -0.27 0.168 0.472 0.192 0.6 ...
#  $ : num [1:816] -0.1831 -0.063 -0.3355 0.0358 -0.3829 ...
cor(df$V1, df$V19)
# [1] 0.2819
cor(rowMeans(df[,c(1,2)]), df$V19)
# [1] -0.2702
cor(rowMeans(df[,c(1,3)]), df$V19)
# [1] 0.1677
cor(rowMeans(df[,c(1,2,3)]), df$V19)
# [1] -0.1831
cor(rowMeans(df[,c(1,2,4)]), df$V19)
# [1] -0.06303

由于已经完成的方式,应该直接将 3 的 N 更改为您可能需要的任何值...意识到 choose(18,9) 是 48620,生成这些组合平均值不是瞬时的,而是仍然很容易管理:

system.time({
  means18 <- lapply(1:18, function(N) {
    do.call(cbind,
            lapply(asplit(combn(18, N), 2),
                   function(ind) rowMeans(df[, ind, drop = FALSE])))
  })
})
#    user  system elapsed 
#   41.65    0.58   50.35 
str(means18)
# List of 18
#  $ : num [1:10, 1:18] 1.371 -0.565 0.363 0.633 0.404 ...
#  $ : num [1:10, 1:153] 1.338 0.861 -0.513 0.177 0.135 ...
#  $ : num [1:10, 1:816] 0.7897 -0.0198 -0.3992 0.5229 0.722 ...
#  $ : num [1:10, 1:3060] 0.7062 0.1614 -0.0406 0.24 0.6678 ...
#  $ : num [1:10, 1:8568] 0.6061 0.0569 0.1191 0.0466 0.2606 ...
#  $ : num [1:10, 1:18564] 0.5588 -0.0832 0.3619 0.146 0.2321 ...
#  $ : num [1:10, 1:31824] 0.4265 -0.0449 0.3933 0.3251 0.095 ...
#  $ : num [1:10, 1:43758] 0.2428 -0.0505 0.4221 0.1653 0.0153 ...
#  $ : num [1:10, 1:48620] 0.3839 -0.0163 0.385 0.1335 -0.1191 ...
#  $ : num [1:10, 1:43758] 0.4847 -0.0623 0.4115 0.2592 -0.2183 ...
#  $ : num [1:10, 1:31824] 0.5498 0.0384 0.2829 0.4037 -0.259 ...
#  $ : num [1:10, 1:18564] 0.5019 0.0442 0.2189 0.3281 -0.3759 ...
#  $ : num [1:10, 1:8568] 0.3484 -0.0723 0.2117 0.2262 -0.3471 ...
#  $ : num [1:10, 1:3060] 0.364 -0.102 0.197 0.29 -0.219 ...
#  $ : num [1:10, 1:816] 0.334 -0.155 0.154 0.269 -0.232 ...
#  $ : num [1:10, 1:153] 0.311 -0.242 0.217 0.235 -0.247 ...
#  $ : num [1:10, 1:18] 0.282 -0.291 0.214 0.2 -0.198 ...
#  $ : num [1:10, 1] 0.254 -0.228 0.105 0.283 -0.139 ...

其余的过程都可以用类似的方式完成。

【讨论】:

  • @Paul,这是否接近您的想法?如果是,请accept it(即使已关闭);如果没有,它将不会重新打开,除非您提供理由说明为什么这不起作用。 (如果你接受这个,请考虑回到你的previous questions,两者都有合理的答案。谢谢!)
  • 谢谢,您的模拟数据代码完全符合我的要求。使其适应实际数据存在一些问题,因此我长时间保持沉默,但现在它似乎正在工作。干杯!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-09-11
  • 1970-01-01
  • 1970-01-01
  • 2018-01-06
  • 1970-01-01
相关资源
最近更新 更多