计算数据框中所有列组合的均值
我有这个数据框:
structure(list(ffw0 = c(8.60799803435064, 8.34185836453619, 8.07471159730671,
7.82091460501107, 7.56772724986936), ffw1 = c(8.4937475524497,
7.99877773077364, 7.40230840036861, 6.72275626701698, 5.96367684510491
), ffw2 = c(8.80102997756335, 8.73105190900452, 8.65977919061515,
8.60566795392347, 8.55234042159471)), row.names = c(NA, -5L), class = "data.frame")
comb
ffw0 ffw1 ffw2 year arima210 arima211 com
1 8.607998 8.493748 8.801030 2026 8.005053 7.841940 7.923496
2 8.341858 7.998778 8.731052 2027 7.692402 7.189011 7.440706
3 8.074712 7.402308 8.659779 2028 7.583277 6.761488 7.172382
4 7.820915 6.722756 8.605668 2029 7.545043 6.480838 7.012941
5 7.567727 5.963677 8.552340 2030 7.531630 6.296588 6.914109
我想对这些列的所有组合取均值。也就是说,例如取所有列的两两组合(x、y),对每一对按行计算其均值。然后取所有三元组合(x、y、z),对每个组合按行计算其均值,依此类推。
我在这个旧线程里看到了这个链接 link,似乎有些组合会产生非常大的均值,无法解释。
我可以用dplyr做到吗?还是有其他方法?
解决方案
Here's a base-R method.
comb2 <- combn(names(comb), 2, simplify = FALSE)
names(comb2) <- sapply(comb2, function(z) paste0("(", paste(z, collapse = ","), ")"))
res2 <- lapply(comb2, function(nm) rowMeans(subset(comb, select = nm)))
str(res2)
# List of 3
# $ (ffw0,ffw1): Named num [1:5] 8.55 8.17 7.74 7.27 6.77
# ..- attr(*, "names")= chr [1:5] "1" "2" "3" "4" ...
# $ (ffw0,ffw2): Named num [1:5] 8.7 8.54 8.37 8.21 8.06
# ..- attr(*, "names")= chr [1:5] "1" "2" "3" "4" ...
# $ (ffw1,ffw2): Named num [1:5] 8.65 8.36 8.03 7.66 7.26
# ..- attr(*, "names")= chr [1:5] "1" "2" "3" "4" ...
For a 3-way, we just change 2 to a 3:
comb3 <- combn(names(comb), 3, simplify = FALSE)
names(comb3) <- sapply(comb3, function(z) paste0("(", paste(z, collapse = ","), ")"))
res3 <- lapply(comb3, function(nm) rowMeans(subset(comb, select = nm)))
With those two, we can convert the lists to frames and then cbind them.
cbind(list2DF(res2), list2DF(res3))
# (ffw0,ffw1) (ffw0,ffw2) (ffw1,ffw2) (ffw0,ffw1,ffw2)
# 1 8.550873 8.704514 8.647389 8.634259
# 2 8.170318 8.536455 8.364915 8.357229
# 3 7.738510 8.367245 8.031044 8.045600
# 4 7.271835 8.213291 7.664212 7.716446
# 5 6.765702 8.060034 7.258009 7.361248
Confirmation of one column (the second):
with(comb, (ffw0 + ffw2) / 2)
# [1] 8.704514 8.536455 8.367245 8.213291 8.060034
Note that part of the reason I combn(names(comb), ...) instead of combn(comb, ...) is that I want to form the names suggested in the question, e.g., (ffw0,ffw1). If you are less concerned about the naming, then using Friede's suggestion of combn(comb, ...) will certainly be shorter code and more direct, only requiring an additional naming step afterwards.
As a further example, if we want to create our own function that calls rowMeans and names the returned columns appropriately, we might do something like:
rowMeans2 <- function(x, sep = ",") {
out <- list(rowMeans(x))
names(out) <- paste(names(x), collapse = sep)
list2DF(out)
}
combn(comb, 2, simplify = FALSE) |>
lapply(rowMeans2) |>
do.call(cbind, args = _)
# ffw0,ffw1 ffw0,ffw2 ffw1,ffw2
# 1 8.550873 8.704514 8.647389
# 2 8.170318 8.536455 8.364915
# 3 7.738510 8.367245 8.031044
# 4 7.271835 8.213291 7.664212
# 5 6.765702 8.060034 7.258009
That's rather succinct, and easily extended for combn(comb, 3, ...) and on.