[英]Multiply a data frame row-by-row
输入文件:
df1 <- data.frame(row.names=c("w","x","y","z"),
A=c(0,0,0,0),
B=c(0,1,0,0),
C=c(1,0,1,0),
D=c(1,1,1,1))
A B C D
w 0 0 1 1
x 0 1 0 1
y 0 0 1 1
z 0 0 0 1
我想应用一个方程,即行 w 乘以行 x 以获得 wx 对的成对值,如下所示:
A B C D
w 0 0 1 1
X x 0 1 0 1
--------------
wx 0 0 0 1
对 wx、wy、wy、wz、xy、xz、yz 进行逐行分析。 并生成一个具有 6 列的新数据框(两个行名称,后跟相乘值)。
那是
w x 0 0 0 1
w y 0 0 1 1
w z 0 0 0 1
x y 0 0 0 1
x z 0 0 0 1
y z 0 0 0 1
谢谢。
dat <- read.table(textConnection(" A B C D
+ w 0 0 1 1
+ x 0 1 0 1
+ y 0 0 1 1
+ z 0 0 0 1
+ "), header=TRUE)
> combos <- combn(rn,2)
> combos
[,1] [,2] [,3] [,4] [,5] [,6]
[1,] "w" "w" "w" "x" "x" "y"
[2,] "x" "y" "z" "y" "z" "z"
apply(combos,2, function(x) c(x[1], x[2], unlist(dat[x[1],]*dat[x[2],])))
[,1] [,2] [,3] [,4] [,5] [,6]
"w" "w" "w" "x" "x" "y"
"x" "y" "z" "y" "z" "z"
A "0" "0" "0" "0" "0" "0"
B "0" "0" "0" "0" "0" "0"
C "0" "1" "0" "0" "0" "0"
D "1" "1" "1" "1" "1" "1"
所以最终的解决方案:
t( apply(combos,2, function(x) c(x[1], x[2], unlist(dat[x[1],]*dat[x[2],]))) )
如果您将组合转换为数据帧,您还可以将 cbindmatrix 设为“数字”类型:
cbind( as.data.frame(t(combos)),
t( apply(combos,2, function(x)
unlist(dat[x[1],]*dat[x[2],]))) )
V1 V2 A B C D
1 w x 0 0 0 1
2 w y 0 0 1 1
3 w z 0 0 0 1
4 x y 0 0 0 1
5 x z 0 0 0 1
6 y z 0 0 0 1
如果您不想要结果对象中的组合名称,那么我们可以结合@DWin 和@Owen 的答案的元素来提供真正的矢量化方法来解决问题。 (您可以将组合名称添加为行名称,并在末尾添加一个额外步骤。)
一、数据:
dat <- read.table(con <- textConnection(" A B C D
w 0 0 1 1
x 0 1 0 1
y 0 0 1 1
z 0 0 0 1
"), header=TRUE)
close(con)
从@DWin's Answer 中获取combn()
想法,但在dat
的行索引上使用它:
combs <- combn(seq_len(nrow(dat)), 2)
combs
的行现在索引我们想要相乘的dat
行:
> combs
[,1] [,2] [,3] [,4] [,5] [,6]
[1,] 1 1 1 2 2 3
[2,] 2 3 4 3 4 4
现在我们采用@Owen 展示的想法,即dat[i, ] * dat[j, ]
其中i
和j
分别是combs
的第一行和第二行。 我们使用data.matrix()
转换为矩阵,因为这对于大型对象会更有效,但代码也将使用dat
作为数据框。
mat <- data.matrix(dat)
mat[combs[1,], ] * mat[combs[2,], ]
它产生:
> mat[combs[1,], ] * mat[combs[2,], ]
A B C D
w 0 0 0 1
w 0 0 1 1
w 0 0 0 1
x 0 0 0 1
x 0 0 0 1
y 0 0 0 1
要了解其工作原理,请注意mat[combs[k,], ]
生成一个矩阵,其中各行按组合指定的顺序重复:
> mat[combs[1,], ]
A B C D
w 0 0 1 1
w 0 0 1 1
w 0 0 1 1
x 0 1 0 1
x 0 1 0 1
y 0 0 1 1
> mat[combs[2,], ]
A B C D
x 0 1 0 1
y 0 0 1 1
z 0 0 0 1
y 0 0 1 1
z 0 0 0 1
z 0 0 0 1
为了准确获取 OP 发布的内容,我们可以使用第二个combn()
调用修改行名:
> out <- mat[combs[1,], ] * mat[combs[2,], ]
> rownames(out) <- apply(combn(rownames(dat), 2), 2, paste, collapse = "")
> out
A B C D
wx 0 0 0 1
wy 0 0 1 1
wz 0 0 0 1
xy 0 0 0 1
xz 0 0 0 1
yz 0 0 0 1
使用惊人的 plyr 包的更短方法(我认为)
你的数据框
df1 <- data.frame(row.names=c("w","x","y","z"), A=c(0,0,0,0), B=c(0,1,0,0), C=c(1,0,1,0), D=c(1,1,1,1))
YOUR_COMBS<-combn(rownames(df1),2)
你的结果:)
require(plyr) #(version 1.81...in version 1.82 you can take the annoying 'X1' index out... )
YOUR_RESULTS<-adply(YOUR_COMBS,2,function(x) {
tmp_row<-data.frame(Comb=paste0(x,collapse = ''),df1[x[1],]*df1[x[2],])
})
如果要乘以行,我建议转换为矩阵:
> m = as.matrix(df1)
> m["x", ] * m["y", ]
A B C D
0 0 0 1
您可以使用plyr
获得您想要的特定结果,
library(plyr)
ldply(1:(nrow(m)-1), function(i)
ldply((i+1):nrow(m), function(j) {
a = row.names(m)[[i]]
b = row.names(m)[[j]]
do.call(data.frame,
c(list(a=a, b=b), m[i,] * m[j,])
)
})
)
抱歉,这部分看起来有点神奇——data.frames 并不是真正意义上的“行状”。 线条
do.call(data.frame,
c(list(a=a, b=b), m[i,] * m[j,])
)
传入 6 列: a 和 b 作为名称,连接(与c
)到相乘的行。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.