37

行ごとに結合したいデータフレームがいくつかあります。結果の単一のデータ フレームで、観測がどのデータ セットから来たかを識別する新しい変数を作成したいと考えています。

# original data frames
df1 <- data.frame(x = c(1, 3), y = c(2, 4))
df2 <- data.frame(x = c(5, 7), y = c(6, 8))

# desired, combined data frame
df3  <- data.frame(x = c(1, 3, 5, 7), y = c(2, 4, 6, 8),
                   source = c("df1", "df1", "df2", "df2")
# x y source
# 1 2    df1
# 3 4    df1
# 5 6    df2
# 7 8    df2

どうすればこれを達成できますか?前もって感謝します!

4

7 に答える 7

44

それはまさにあなたが求めたものではありませんが、かなり近いものです。オブジェクトを名前付きリストに入れて使用しますdo.call(rbind...)

> do.call(rbind, list(df1 = df1, df2 = df2))
      x y
df1.1 1 2
df1.2 3 4
df2.1 5 6
df2.2 7 8

行名が source を反映するようになったことに注意してくださいdata.frame

更新:使用cbindしてrbind

別のオプションは、次のような基本的な関数を作成することです。

AppendMe <- function(dfNames) {
  do.call(rbind, lapply(dfNames, function(x) {
    cbind(get(x), source = x)
  }))
}

次に、この関数は、次のように、"スタック" する名前の文字ベクトルを受け取りdata.frameます。

> AppendMe(c("df1", "df2"))
  x y source
1 1 2    df1
2 3 4    df1
3 5 6    df2
4 7 8    df2

更新 2: combine「gdata」パッケージから使用する

> library(gdata)
> combine(df1, df2)
  x y source
1 1 2    df1
2 3 4    df1
3 5 6    df2
4 7 8    df2

更新 3: rbindlist「data.table」から使用

現在使用できる別のアプローチは、rbindlistfrom "data.table" とそのidcol引数を使用することです。それにより、アプローチは次のようになります。

> rbindlist(mget(ls(pattern = "df\\d+")), idcol = TRUE)
   .id x y
1: df1 1 2
2: df1 3 4
3: df2 5 6
4: df2 7 8

更新 4: map_df「purrr」から使用

と同様に、各リスト要素に適用する関数とともに、または関数としてfrom "purrr" をrbindlist使用することもできます。map_dfIc

> mget(ls(pattern = "df\\d+")) %>% map_df(I, .id = "src")
Source: local data frame [4 x 3]

    src     x     y
  (chr) (int) (int)
1   df1     1     2
2   df1     3     4
3   df2     5     6
4   df2     7     8
于 2013-03-01T16:32:45.900 に答える
27

を使用した別のアプローチdplyr

df1 <- data.frame(x = c(1,3), y = c(2,4))
df2 <- data.frame(x = c(5,7), y = c(6,8))

df3 <- dplyr::bind_rows(list(df1=df1, df2=df2), .id = 'source')

df3
Source: local data frame [4 x 3]

  source     x     y
   (chr) (dbl) (dbl)
1    df1     1     2
2    df1     3     4
3    df2     5     6
4    df2     7     8
于 2016-04-17T10:55:31.403 に答える
7

そのような関数が既に存在するかどうかはわかりませんが、これはうまくいくようです:

bindAndSource <-  function(df1, df2) { 
  df1$source <- as.character(match.call())[[2]]
  df2$source <- as.character(match.call())[[3]]
  rbind(df1, df2)
}

結果:

bindAndSource(df1, df2)

1 1 2    df1
2 3 4    df1
3 5 6    df2
4 7 8    df2


警告: これは - の*aplyような呼び出しでは機能しません

于 2013-03-01T16:28:39.617 に答える
6

他の2つの答えのブレンド:

df1 <- data.frame(x = 1:3,y = 1:3)
df2 <- data.frame(x = 4:6,y = 4:6)

> foo <- function(...){
    args <- list(...)
    result <- do.call(rbind,args)
    result$source <- rep(as.character(match.call()[-1]),times = sapply(args,nrow))
    result
 }

> foo(df1,df2,df1)
  x y source
1 1 1    df1
2 2 2    df1
3 3 3    df1
4 4 4    df2
5 5 5    df2
6 6 6    df2
7 1 1    df1
8 2 2    df1
9 3 3    df1

ビジネスを避けたい場合はmatch.call、関数の引数の名前付け (つまりdf1 = df1, df2 = df2) と を使用names(args)して名前にアクセスすることにいつでも制限できます。

于 2013-03-01T16:33:33.163 に答える
2

これに対する別の回避策は、plyrパッケージでldplyを使用することです...

df1 <- data.frame(x = c(1,3), y = c(2,4))
df2 <- data.frame(x = c(5,7), y = c(6,8))
list = list(df1 = df1, df2 = df2)
df3 <- ldply(list)

df3
  .id x y
  df1 1 2
  df1 3 4
  df2 5 6
  df2 7 8
于 2013-03-06T14:36:28.133 に答える