合并(rbind)数据帧并使用原始数据帧的名称创建列

mal*_*atr 24 r

我有几个数据框,我想按行组合.在生成的单个数据框中,我想创建一个新变量,用于标识观察来自哪个数据集.

# 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
Run Code Online (Sandbox Code Playgroud)

我怎样才能做到这一点?提前致谢!

A5C*_*2T1 28

这不完全是你要求的,但它非常接近.将您的对象放在命名列表中并使用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
Run Code Online (Sandbox Code Playgroud)

请注意,行名称现在反映了源data.frames.

更新:使用cbindrbind

另一种选择是制作如下基本功能:

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

然后,此函数将获取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
Run Code Online (Sandbox Code Playgroud)

更新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
Run Code Online (Sandbox Code Playgroud)

更新3:使用rbindlist"data.table"

现在可以使用的另一种方法是使用rbindlist"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
Run Code Online (Sandbox Code Playgroud)

更新4:使用map_df"purrr"

与之类似rbindlist,您也可以使用map_df"purrr"和Ic作为函数应用于每个列表元素.

> 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
Run Code Online (Sandbox Code Playgroud)


chr*_*lle 16

另一种方法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
Run Code Online (Sandbox Code Playgroud)

  • 对我来说,这给出了数据帧的编号(基于调用的顺序)而不是实际的数据帧名称:o (3认同)

Ric*_*rta 7

我不确定这样的功能是否已经存在,但这似乎可以解决问题:

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

结果:

bindAndSource(df1, df2)

1 1 2    df1
2 3 4    df1
3 5 6    df2
4 7 8    df2
Run Code Online (Sandbox Code Playgroud)


警告:这不会在*aply类似的调用中起作用


jor*_*ran 6

其他两个答案的混合:

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
Run Code Online (Sandbox Code Playgroud)

如果您想避免match.call业务,您可以始终限制自己命名函数参数(即df1 = df1, df2 = df2)并使用names(args)访问名称.