3

これに対する答えはどこかにあると確信していますが、正しい検索用語を使用しているとは思いません。

これが私の問題です。複数のマトリックス (ここでは単純化して 2 つだけにします) があり、各行は一意にラベル付けされた個人 (マトリックス間で共有されるものと共有されないものがあります) と、共有される共通の列見出しがあります。

例えば:

first<-matrix(rbinom(20,1,.5),4,5)
first[,1]=c(122,145,186,199)
colnames(first)<-c("ID",901,902,903,904)
first
      ID 901 902 903 904
[1,] 122   1   0   0   0
[2,] 145   0   0   0   1
[3,] 186   0   0   1   1
[4,] 199   1   0   0   0

second<-matrix(rbinom(30,1,.5),6,5)
second[,1]=c(122,133,142,151,186,199)
colnames(second)<-c("ID",901,902,903,904)
second
      ID 901 902 903 904
[1,] 122   0   1   1   1
[2,] 133   0   0   0   1
[3,] 142   1   1   0   1
[4,] 151   0   1   0   0
[5,] 186   1   0   1   1
[6,] 199   1   0   0   0

「ID」と列名に基づいて「最初」と「2番目」を一緒に追加したいと思います。これにより、7 行のマトリックスが生成されます (「最初の」マトリックスには 4 つの ID があり、「2 番目の」マトリックスには 3 つの新しい ID と 3 つの古い ID があるため、"122,133,142,145,151,186,199")、同じ数の列があります。

この例では、私が望む結果は次のようになります。

      ID 901 902 903 904
[1,] 122   1   1   1   1
[2,] 133   0   0   0   1
[3,] 142   1   1   0   1
[4,] 145   0   0   0   1
[5,] 151   0   1   0   0
[6,] 186   1   0   2   2
[7,] 199   2   0   0   0
4

3 に答える 3

2

元の答え

行名と列名を使用して行列を記述する @RYogi のアプローチに基づいて、次のことを提案します。

res <- rbind(first,second)
res <- tapply(res, expand.grid(dimnames(res)), sum)

行名が等しいすべての行が合計されます。

データフレームを使用する場合

入力が a の場合、 aには重複する行名があってはならないためdata.frame、上記は機能しません。data.frameそこでも機能する別のアプローチは次のとおりです。

rowsum(rbind(first, second), c(rownames(first), rownames(second)))

このアプローチは、マトリックスでも機能します。1行しかかからないので、もっと簡単だと思うかもしれません。よりも一般的ではないため、より効率的かもしれないと思いますtapply。識別子が別の列にある質問のデータ形式にこのソリューションを調整できます。

rowsum(rbind(first, second)[,-1], c(first[,1], second[,1]))

結果には、それらの名前を含む列ではなく、名前付きの行が含まれることに注意してください。

面白いことに、この問題のバージョンをかなり複雑な方法でrowsum探しているときに、偶然ここで読んだことがあります。私は幸運。rowSumsdata.frame

追加のヒント

Var1結果の名前とディメンションがわかりVar2にくい場合は、次を使用して削除できます

names(dimnames(res)) <- NULL

データが実際に記述した形式であり、最初のデータ列に行名がある場合は、次のコマンドを使用して適切な行名に変更できます。

rownames(first) <- first[,1]
first <- first[,-1]
于 2012-07-20T22:30:09.600 に答える
1

私はあなたの問題を少し異なって設定しました:

first <- matrix(rbinom(16,1,.5),4,4)
rownames(first) <- c(122,145,186,199)
colnames(first) <- c(901,902,903,904)

second <- matrix(rbinom(24,1,.5),6,4)
rownames(second) <- c(122,133,142,151,186,199)
colnames(second) <- c(901,902,903,904)

行列に名前付き行名が追加されました

> first
    901 902 903 904
122   1   0   0   1
145   1   0   0   0
186   0   0   1   1
199   1   0   1   1
> second
    901 902 903 904
122   1   1   0   0
133   0   0   1   1
142   1   0   1   0
151   1   0   1   1
186   0   1   0   1
199   0   0   0   0

これで、行名に対して集合演算を簡単に実行できます。

SumOnID <- function(A, B){
  rnA <- rownames(A)
  rnB <- rownames(B)

  ls.id <- list(ids = intersect(rnA, rnB), #shared indices
                idA = setdiff(rnA, rnB),   #only in A
                idB = setdiff(rnB, rnA))   #only in B

  do.call(rbind, 
    lapply(names(ls.id), function(x){
      if (x == "ids") return(A[x,, drop = F] + B[x,, drop = F])
      if (x == "idA") return(A[x,, drop = F])
      if (x == "idB") return(B[x,, drop = F])
    }))
}

試してみよう:

> SumOnID(first, second)
    901 902 903 904
122   2   1   1   1
186   1   1   0   1
199   2   1   1   0
145   1   1   0   1
133   1   0   1   1
142   1   0   1   0
151   1   1   1   1
于 2012-07-20T19:38:27.013 に答える
1

組み込み関数を使用した「for」ループのないソリューションを探していましたが、成功しませんでした。だからここに私のアプローチがあります

set.seed(1) # make it reproducible
first <- matrix(rbinom(20,1,.5),4,5)
first[ ,1] <- c(122, 145, 186, 199)
colnames(first) <- c("ID", 901, 902, 903, 904)

second <- matrix(rbinom(30, 1, .5), 6, 5)
second[ ,1] <- c(122, 133, 142, 151, 186, 199)
colnames(second) <- c("ID", 901, 902, 903, 904)

first

      ID 901 902 903 904
[1,] 122   0   1   1   1
[2,] 145   1   0   0   1
[3,] 186   1   0   1   0
[4,] 199   1   0   0   1

second
      ID 901 902 903 904
[1,] 122   0   0   1   1
[2,] 133   0   0   0   1
[3,] 142   1   1   1   0
[4,] 151   0   1   1   0
[5,] 186   0   1   1   1
[6,] 199   1   0   1   1

## stack them rowise
mat <- rbind(first, second)

ind <- unique(mat[,"ID"])

result <- matrix(nrow = length(ind), ncol = 5)
result[,1] <- ind

for (i in seq_along(ind)) {
    result[i,-1] <- colSums(mat[mat[ ,"ID"] == ind[i], -1, drop = FALSE])
}
colnames(result) <- colnames(mat)

result
      ID 901 902 903 904
[1,] 122   0   1   2   2
[2,] 145   1   0   0   1
[3,] 186   1   1   2   1
[4,] 199   2   0   1   2
[5,] 133   0   0   0   1
[6,] 142   1   1   1   0
[7,] 151   0   1   1   0
于 2012-07-20T19:41:40.713 に答える