可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
Input file:
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
I want to apply an equation i.e. multiply row w to row x to get the pairwise value for w-x pair, as follows:
A B C D
w 0 0 1 1
X x 0 1 0 1
--------------
wx 0 0 0 1
to get row-wise analysis for w-x, w-y, w-y, w-z, x-y, x-z, y-z. and generate a new dataframe with 6 columns (two row names followed by the multiplied values).
That's
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
Thanksssssss.
回答1:
If you don't want the combo names in the resulting object, then we can combine elements of @DWin's and @Owen's Answers to provide a truly vectorised approach to the problem. (You can add the combination names as row names with one extra step at the end.)
First, the data:
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)
Take the combn()
idea from @DWin's Answer but use it on the row indices of dat
:
combs <- combn(seq_len(nrow(dat)), 2)
The rows of combs
now index the rows of dat
that we want to multiply together:
> combs
[,1] [,2] [,3] [,4] [,5] [,6]
[1,] 1 1 1 2 2 3
[2,] 2 3 4 3 4 4
Now we take the idea @Owen showed, namely dat[i, ] * dat[j, ]
with i
and j
being the first and second rows of combs
respectively. We convert to a matrix with data.matrix()
as this will be more efficient for large objects, but the code will work with dat
as a data frame too.
mat <- data.matrix(dat)
mat[combs[1,], ] * mat[combs[2,], ]
which produces:
> 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
To see how this works, note that mat[combs[k,], ]
produces a matrix with various rows repeated in the order specified by the combinations:
> 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
To get exactly what the OP posted, we can modify the rownames using a second combn()
call:
> 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
回答2:
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"
So the final solution:
t( apply(combos,2, function(x) c(x[1], x[2], unlist(dat[x[1],]*dat[x[2],]))) )
If you convert the combos to a dataframe you would also be able to cbindmatrix as type "numeric":
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
回答3:
If you want to multiply rows, I recommend converting to a matrix:
> m = as.matrix(df1)
> m["x", ] * m["y", ]
A B C D
0 0 0 1
The specific result you want you could get with 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,])
)
})
)
Sorry part of that looks a little magical -- data.frames aren't really meant to be "row like". The lines
do.call(data.frame,
c(list(a=a, b=b), m[i,] * m[j,])
)
pass in the 6 columns: a and b for the names, concatenated (with c
) to the multiplied row.
回答4:
A shorter way (I think) using the amazing plyr package
Your data.frame
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)
And your result :)
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],])
})