我有一个带有n
列的数据框,并且想对每个 combination 列应用一个函数。这与cor()
函数将数据帧作为输入并生成相关矩阵作为输出的方式非常相似,例如:
X <- data.frame(A=rnorm(100), B=rnorm(100), C=rnorm(100))
cor(X)
将生成以下输出:
> cor(X)
A B C
A 1.00000000 -0.01199511 0.02337429
B -0.01199511 1.00000000 0.07918920
C 0.02337429 0.07918920 1.00000000
但是,我有一个自定义函数,需要将其应用于列的每种组合。我现在正在使用一个使用嵌套的循环的解决方案,该方法有效:
f <- function(x, y) sum((x+y)^2) # some placeholder function
out <- matrix(NA, ncol = ncol(X), nrow = ncol(X)) # pre-allocate
for(i in seq_along(X)) {
for(j in seq_along(X)) {
out[i, j] <- f(X[, i], X[, j]) # apply f() to each combination
}
}
哪个会产生:
> out
[,1] [,2] [,3]
[1,] 422.4447 207.0833 211.4198
[2,] 207.0833 409.1242 218.2430
[3,] 211.4198 218.2430 397.5321
我目前正在尝试过渡到tidyverse,并且希望避免使用for循环。 有人可以为我提供一种整洁解决方案吗?谢谢!
答案 0 :(得分:1)
你可以做
library(tidyverse)
f <- function(x, y) sum((x+y)^2)
X <- data.frame(A=rnorm(100), B=rnorm(100), C=rnorm(100))
as.list(X) %>%
expand.grid(., .) %>%
mutate(out = map2_dbl(Var1, Var2, f)) %>%
as_tibble()
答案 1 :(得分:0)
这不是tidyverse
解决方案,但可以避免使用for循环。我们使用RcppAlgos
(我是作者)来生成列的所有成对排列,并将您的自定义函数应用于每个列。之后,我们强制使用矩阵。
set.seed(42)
X <- data.frame(A=rnorm(100), B=rnorm(100), C=rnorm(100))
library(RcppAlgos)
matrix(permuteGeneral(ncol(X), 2, repetition = TRUE, FUN = function(y) {
sum((X[,y[1]] + X[,y[2]])^2)
}), ncol = ncol(X))
# [,1] [,2] [,3]
# [1,] 429.8549 194.4271 179.4449
# [2,] 194.4271 326.8032 197.2585
# [3,] 179.4449 197.2585 409.6313
答案 2 :(得分:0)
您可以使用基数R:
set.seed(42)
X <- data.frame(A=rnorm(100), B=rnorm(100), C=rnorm(100))
OUT = diag(colSums((X+X)^2))
OUT[lower.tri(OUT)] = combn(X, 2, function(x) sum(do.call('+', x)^2)) #combn(X,2,function(x)sum(rowSums(x)^2))
OUT[upper.tri(OUT)] = OUT[lower.tri(OUT)]
OUT
[,1] [,2] [,3]
[1,] 429.8549 194.4271 179.4449
[2,] 194.4271 326.8032 197.2585
[3,] 179.4449 197.2585 409.6313