我有几个数据框,我想按行组合.在生成的单个数据框中,我想创建一个新变量,用于标识观察来自哪个数据集.
# 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.frame
s.
cbind
和rbind
另一种选择是制作如下基本功能:
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)
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)
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)
map_df
"purrr"与之类似rbindlist
,您也可以使用map_df
"purrr"和I
或c
作为函数应用于每个列表元素.
> 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)
我不确定这样的功能是否已经存在,但这似乎可以解决问题:
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
类似的调用中起作用
其他两个答案的混合:
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)
访问名称.