2011-09-04 12 views
3

輸入文件:乘一個數據幀一行一行地

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 

Thanksssssss。

回答

4

如果你不在結果對象中不需要組合名稱,那麼我們可以結合@Dinin's和@ Owen's Answers的元素來爲問題提供真正的矢量化方法。 (您可以在最後一個額外的步驟添加組合名稱爲行名。)

首先,數據:

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) 

採取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, ]ij分別爲的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()電話修改rownames:

> 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 
+0

感謝您的版本運行速度非常快。 – psiu

0

如果你想乘行,我建議轉化爲矩陣:

> 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)給該相乘的行。

4
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 
+0

哇哦,那是相當的簡潔。 – Owen

+0

+ combn()' –

0

較短的方式(我認爲)用驚人的plyr包

你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) 

的檢查結果:)

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],]) 
})