7

それぞれ異なるサイズの 5 つのマトリックスを含むリストがあり、行名を使用してそれらすべてをマージしたいと考えています。

これは私のリストの再現可能な例です (私は R バージョン 3.0.1 で igraph_0.6.5-2 を使用しています):

x <- list(    
as.matrix(c(1,4)),
as.matrix(c(3,19,11)),
as.matrix(c(3,9,8,5)),
as.matrix(c(3,10,8,87,38,92)),
as.matrix(c(87,8,8,87,38,92))  
)   

colnames(x[[1]]) <- c("P1")  
colnames(x[[2]]) <- c("P2")  
colnames(x[[3]]) <- c("P3")  
colnames(x[[4]]) <- c("P4")  
colnames(x[[5]]) <- c("P5")  
rownames(x[[1]]) <- c("A","B")   
rownames(x[[2]]) <- c("B","C","D")  
rownames(x[[3]]) <- c("A","B", "E", "F")  
rownames(x[[4]]) <- c("A","F","G","H","I","J" )  
rownames(x[[5]]) <- c("B", "H","I","J", "K","L")  

次のリストが表示されます。

> x
[[1]]
  P1
A  1
B  4
[[2]]
  P2
B  3
C 19
D 11
[[3]]
  P3
A  3
B  9
E  8
F  5
[[4]]
  P4
A  3
F 10
G  8
H 87
I 38
J 92
[[5]]
  P5
B 87
H  8
I  8
J 87
K 38
L 92

私はこのようなものを取得したいと思います:

>   P1  P2  P3  P4  P5 
A    1  na   3   3  na 
B    4   3   9  na  87 
C   na  19  na  na  na 
D   na  11  na  na  na 
E   na  na   8  na  na 
F   na  na   5  10  na 
G   na  na  na   8  na 
H   na  na  na  87  na 
I   na  na  na  38   8 
J   na  na  na  92  87 
K   na  na  na  na  38 
L   na  na  na  na  92 

do.call関数を使用してそれらをマージします。

y <- do.call(merge,c(x, by="row.names",all=TRUE))

次のエラーが表示されます。

Error in fix.by(by.x, x) : 'by' must match numbers of columns

どんな助けでも大歓迎です。ありがとう!

4

1 に答える 1

7

あなたrow.names()を a の列に移動し、あなたのすべてのs にdata.frame使用Reduce()するヘルパー関数を作成します。merge()data.framelist

rownames2col <- function(inDF, RowName = ".rownames") {
  temp <- data.frame(rownames(inDF), inDF, row.names = NULL)
  names(temp)[1] <- RowName
  temp
}

Reduce(function(x, y) merge(x, y, by = ".rownames", all = TRUE), 
       lapply(x, rownames2col))
#    .rownames P1 P2 P3 P4 P5
# 1          A  1 NA  3  3 NA
# 2          B  4  3  9 NA 87
# 3          C NA 19 NA NA NA
# 4          D NA 11 NA NA NA
# 5          E NA NA  8 NA NA
# 6          F NA NA  5 10 NA
# 7          G NA NA NA  8 NA
# 8          H NA NA NA 87  8
# 9          I NA NA NA 38  8
# 10         J NA NA NA 92 87
# 11         K NA NA NA NA 38
# 12         L NA NA NA NA 92

rownames()in を列として追加するステップが追加された理由は、による結合によって最初のinでrow.names呼び出される列が作成され、後続の項目を簡単に結合できないためです。Row.namesmerge()Reduce()list()

> Reduce(function(x, y) merge(x, y, by = "row.names", all = TRUE), x[1:2])
  Row.names P1 P2
1         A  1 NA
2         B  4  3
3         C NA 19
4         D NA 11

更新:data.tableアプローチ

引数を " " に設定し、結果の列に " " をdata.table設定することで、非常によく似た概念を使用できます。keep.rownamesTRUEkeyrn

library(data.table)
Reduce(function(x, y) merge(x, y, all = TRUE), 
       lapply(x, function(y) data.table(y, keep.rownames=TRUE, key = "rn")))
#     rn P1 P2 P3 P4 P5
#  1:  A  1 NA  3  3 NA
#  2:  B  4  3  9 NA 87
#  3:  C NA 19 NA NA NA
#  4:  D NA 11 NA NA NA
#  5:  E NA NA  8 NA NA
#  6:  F NA NA  5 10 NA
#  7:  G NA NA NA  8 NA
#  8:  H NA NA NA 87  8
#  9:  I NA NA NA 38  8
# 10:  J NA NA NA 92 87
# 11:  K NA NA NA NA 38
# 12:  L NA NA NA NA 92

更新 2:「手動」アプローチ

もちろん、forループによって支援される手動のアプローチもあります。これはmerge、基本的なサブセット化に比べてかなり遅いため、実際には上記よりも高速である可能性があります。速度に関するもう 1 つの利点は、結果のオブジェクトが でありmatrix、多くのmatrix操作が操作よりも高速であることdata.frameです。

## Identify the unique "rownames" for all list items
Rows <- unique(unlist(lapply(x, rownames)))

## Create a matrix of NA values 
##   with appropriate dimensions and dimnames
myMat <- matrix(NA, nrow = length(Rows), ncol = length(x), 
                dimnames = list(Rows, sapply(x, colnames)))


## Use your `for` loop to fill it in
##   with the appropriate values from your list
for (i in seq_along(x)) {
  myMat[rownames(x[[i]]), i] <- x[[i]]
}
myMat
#   P1 P2 P3 P4 P5
# A  1 NA  3  3 NA
# B  4  3  9 NA 87
# C NA 19 NA NA NA
# D NA 11 NA NA NA
# E NA NA  8 NA NA
# F NA NA  5 10 NA
# G NA NA NA  8 NA
# H NA NA NA 87  8
# I NA NA NA 38  8
# J NA NA NA 92 87
# K NA NA NA NA 38
# L NA NA NA NA 92
于 2013-08-01T16:53:58.020 に答える