web-dev-qa-db-ja.com

異なる長さの2つのデータフレームを結合する

2つのデータフレームがあります。
最初の列は1列10行のみです。
2つ目は3列50行です。

cbindを使用してこれを結合しようとすると、次のエラーが発生します。

Data.frame(...、check.names = FALSE)のエラー:

誰でもこれを行う別の機能を提案できますか?
P.Sリストを使用してこれを試しましたが、同じエラーが発生します。

3列で構成されるデータフレームはCSVファイルの最初の3列である必要がありますが、1列のデータフレームは、write.table 関数。最初の3列は50行で、4列目は最初の10行を占める必要があります。

31
Matt

plyrパッケージには、data.framesをマージし、空のセルにNAを導入するrbind.fill関数があります。

library(plyr)
combined <- rbind.fill(mtcars[c("mpg", "wt")], mtcars[c("wt", "cyl")])
combined[25:40, ]

    mpg    wt cyl
25 19.2 3.845  NA
26 27.3 1.935  NA
27 26.0 2.140  NA
28 30.4 1.513  NA
29 15.8 3.170  NA
30 19.7 2.770  NA
31 15.0 3.570  NA
32 21.4 2.780  NA
33   NA 2.620   6
34   NA 2.875   6
35   NA 2.320   4
34
Andrie

フォローアップのコメントを考えると、OPが実際に何をしているのかはまったくわかりません。彼らが実際にデータをファイルに書き込む方法を探している可能性があります。

しかし、異なる長さの複数のデータフレームをcbindする方法を本当に求めていると仮定しましょう。

cbindは最終的にdata.frameを呼び出しますが、そのヘルプファイルには次のように記述されています。

Data.frameに渡されるオブジェクトの行数は同じである必要がありますが、必要に応じて、Iで保護されているアトミックベクトル、ファクター、および文字ベクトルは、R 2.9.0以降のリスト引数の要素を含め、整数回リサイクルされます。

したがって、OPの実際の例では、Rは短いベクトルを長さ50にリサイクルする必要があるため、はエラーではありません。私は次を実行します:

set.seed(1)
a <- runif(50)
b <- 1:50
c <- rep(LETTERS[1:5],length.out = 50)
dat1 <- data.frame(a,b,c)
dat2 <- data.frame(d = runif(10),e = runif(10))
cbind(dat1,dat2)

エラーは発生せず、短いデータフレームは期待どおりにリサイクルされます。ただし、これを実行すると:

set.seed(1)
a <- runif(50)
b <- 1:50
c <- rep(LETTERS[1:5],length.out = 50)
dat1 <- data.frame(a,b,c)
dat2 <- data.frame(d = runif(9), e = runif(9))
cbind(dat1,dat2)

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

Error in data.frame(..., check.names = FALSE) : 
  arguments imply differing number of rows: 50, 9

しかし、Rの素晴らしい点は、たとえそうするべきではない場合でも、ほぼすべてのことをRで実行できることです。たとえば、次は、不均一な長さのcbindデータフレームを自動的にNAsで埋める単純な関数です。

cbindPad <- function(...){
args <- list(...)
n <- sapply(args,nrow)
mx <- max(n)
pad <- function(x, mx){
    if (nrow(x) < mx){
        nms <- colnames(x)
        padTemp <- matrix(NA, mx - nrow(x), ncol(x))
        colnames(padTemp) <- nms
        if (ncol(x)==0) {
          return(padTemp)
        } else {
        return(rbind(x,padTemp))
          }
    }
    else{
        return(x)
    }
}
rs <- lapply(args,pad,mx)
return(do.call(cbind,rs))
}

次のように使用できます。

set.seed(1)
a <- runif(50)
b <- 1:50
c <- rep(LETTERS[1:5],length.out = 50)
dat1 <- data.frame(a,b,c)
dat2 <- data.frame(d = runif(10),e = runif(10))
dat3 <- data.frame(d = runif(9), e = runif(9))
cbindPad(dat1,dat2,dat3)

この機能がすべての場合に機能することを保証しません。これは単なる例です。

[〜#〜] edit [〜#〜]

主な目標がcsvまたはテキストファイルを作成することである場合、あなたがする必要があるのは、NAではなく""を使用してパディングする関数を変更し、次のようなことをすることです:

dat <- cbindPad(dat1,dat2,dat3)
rs <- as.data.frame(apply(dat,1,function(x){paste(as.character(x),collapse=",")}))

rswrite.tableを使用します。

20
joran

アンドリーの答えを参照して、plyr::rbind.fill()を使用することを提案します:t()と組み合わせると、cbind.fill()plyrの一部ではない)のようなものがあります。同一のケース番号を考慮してデータフレームを構築します。

1
søren