使用 R 中列之间的成对计算创建矩阵
Create matrix using pairwise calculations between columns in R
R 的新手,让我头疼!
我正在尝试编写结合以下步骤的代码:
a) 找出两列之间每行的最小值
b) 对找到的最小值求和
c) 在许多列中执行此操作并构建结果的成对矩阵
步骤 a 和 b 对于一次两列来说足够简单。像这样:
column1 = c(0.08, 0.20, 0.09, 0.19, 0.25, 0.20, 0.00)
column2 = c(0.07, 0.19, 0.09, 0.21, 0.25, 0.19, 0.00)
ps = data.frame(column1, column2)
sum(pmin(ps$column1,ps$column2))
但是对于步骤 c,我很难编写代码来对由 7 行和 32 列组成的数据帧中的每个成对列比较执行此操作。这是我到目前为止想出的:
d <- replicate(32, rnorm(7))
c <- combn(seq_len(ncol(d)),2)
mat1 <- matrix(0,ncol=32,nrow=32,dimnames=list(colnames(d),colnames(d)))
v1 <- unlist(lapply(seq_len(ncol(c)),function(i) {d1<-d[,c[,i]]; length(which(d1[,1]!=0 & d1[,2]!=0)) }))
mat1[lower.tri(mat1)]<-v1
我很确定我的问题出在与 "v1" 关联的 "function" 命令中。但我很难过,真的需要一点帮助!
同样,我的目标是在每个成对列比较之间获得一个 32x32 的求和最小值矩阵。
这有意义吗?
非常感谢。
我想你可以尝试以下方法(我不得不承认这是一种简单的方法):
column1 = c(0.08, 0.20, 0.09, 0.19, 0.25, 0.20, 0.00)
column2 = c(0.07, 0.19, 0.09, 0.21, 0.25, 0.19, 0.00)
column3 = c(0.05, 0.49, 0.39, 0.1, 0.5, 0.11, 0.01)
ps = data.frame(column1, column2, column3)
res <-matrix(nrow = ncol(ps), ncol = ncol(ps))
for (i in (1:ncol(ps))) {
for (j in (i:ncol(ps))){
res[i,j] <- sum(pmin(ps[,i],ps[,j]))
}
}
为了利用矩阵对称的事实,你可以这样做:
res[lower.tri(res)] <- t(res)[lower.tri(res)]
(需要注意的一件事是,我也从@Aaron 那里了解到,他的评论是 res[lower.tri(res)] <- res[upper.tri(res)]
不起作用,因为 R 正在按列填充值)
或者(再次感谢亚伦)你可以这样做(并跳过最后一步):
for (i in (1:ncol(ps))) {
for (j in (i:ncol(ps))){
res[i,j] <- res[j,i] <- sum(pmin(ps[,i],ps[,j]))
}
}
outer
函数会执行此操作并为您跟踪簿记,但您必须向其传递矢量化函数。
summin <- Vectorize(function(i, j) sum(pmin(ps[[i]], ps[[j]])))
outer(seq_len(ncol(ps)), seq_len(ncol(ps)), FUN=summin)
## [,1] [,2]
## [1,] 1.01 0.98
## [2,] 0.98 1.00
我不知道你的 v1
代码中应该发生什么,看起来你不再对最小值求和了。
如果我要循环自己,我会使用 expand.grid
而不是 combn,因为这样我就得到了对角线,而不必弄清楚如何填充矩阵的两侧,尽管以两次执行所有计算为代价。 (无论如何,计算机可以比我弄清楚如何让它只做一次快两倍。)我也只是把它作为一个向量,然后再转换成一个矩阵。
cc <- expand.grid(seq_len(ncol(d)), seq_len(ncol(d)))
out <- sapply(seq_len(nrow(cc)), function(k) {
i <- cc[k,1]
j <- cc[k,2]
sum(pmin(d[[i]],d[[j]]))
})
out <- matrix(out, ncol=ncol(d))
R 的新手,让我头疼!
我正在尝试编写结合以下步骤的代码:
a) 找出两列之间每行的最小值
b) 对找到的最小值求和
c) 在许多列中执行此操作并构建结果的成对矩阵
步骤 a 和 b 对于一次两列来说足够简单。像这样:
column1 = c(0.08, 0.20, 0.09, 0.19, 0.25, 0.20, 0.00)
column2 = c(0.07, 0.19, 0.09, 0.21, 0.25, 0.19, 0.00)
ps = data.frame(column1, column2)
sum(pmin(ps$column1,ps$column2))
但是对于步骤 c,我很难编写代码来对由 7 行和 32 列组成的数据帧中的每个成对列比较执行此操作。这是我到目前为止想出的:
d <- replicate(32, rnorm(7))
c <- combn(seq_len(ncol(d)),2)
mat1 <- matrix(0,ncol=32,nrow=32,dimnames=list(colnames(d),colnames(d)))
v1 <- unlist(lapply(seq_len(ncol(c)),function(i) {d1<-d[,c[,i]]; length(which(d1[,1]!=0 & d1[,2]!=0)) }))
mat1[lower.tri(mat1)]<-v1
我很确定我的问题出在与 "v1" 关联的 "function" 命令中。但我很难过,真的需要一点帮助!
同样,我的目标是在每个成对列比较之间获得一个 32x32 的求和最小值矩阵。
这有意义吗?
非常感谢。
我想你可以尝试以下方法(我不得不承认这是一种简单的方法):
column1 = c(0.08, 0.20, 0.09, 0.19, 0.25, 0.20, 0.00)
column2 = c(0.07, 0.19, 0.09, 0.21, 0.25, 0.19, 0.00)
column3 = c(0.05, 0.49, 0.39, 0.1, 0.5, 0.11, 0.01)
ps = data.frame(column1, column2, column3)
res <-matrix(nrow = ncol(ps), ncol = ncol(ps))
for (i in (1:ncol(ps))) {
for (j in (i:ncol(ps))){
res[i,j] <- sum(pmin(ps[,i],ps[,j]))
}
}
为了利用矩阵对称的事实,你可以这样做:
res[lower.tri(res)] <- t(res)[lower.tri(res)]
(需要注意的一件事是,我也从@Aaron 那里了解到,他的评论是 res[lower.tri(res)] <- res[upper.tri(res)]
不起作用,因为 R 正在按列填充值)
或者(再次感谢亚伦)你可以这样做(并跳过最后一步):
for (i in (1:ncol(ps))) {
for (j in (i:ncol(ps))){
res[i,j] <- res[j,i] <- sum(pmin(ps[,i],ps[,j]))
}
}
outer
函数会执行此操作并为您跟踪簿记,但您必须向其传递矢量化函数。
summin <- Vectorize(function(i, j) sum(pmin(ps[[i]], ps[[j]])))
outer(seq_len(ncol(ps)), seq_len(ncol(ps)), FUN=summin)
## [,1] [,2]
## [1,] 1.01 0.98
## [2,] 0.98 1.00
我不知道你的 v1
代码中应该发生什么,看起来你不再对最小值求和了。
如果我要循环自己,我会使用 expand.grid
而不是 combn,因为这样我就得到了对角线,而不必弄清楚如何填充矩阵的两侧,尽管以两次执行所有计算为代价。 (无论如何,计算机可以比我弄清楚如何让它只做一次快两倍。)我也只是把它作为一个向量,然后再转换成一个矩阵。
cc <- expand.grid(seq_len(ncol(d)), seq_len(ncol(d)))
out <- sapply(seq_len(nrow(cc)), function(k) {
i <- cc[k,1]
j <- cc[k,2]
sum(pmin(d[[i]],d[[j]]))
})
out <- matrix(out, ncol=ncol(d))