合并(rbind)数据帧并创建具有原始数据帧名称的列
我有几个要按行组合的数据帧。在生成的单个数据框中,我想创建一个新变量,标识观察来自哪个数据集合并(rbind)数据帧并创建具有原始数据帧名称的列,r,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
# 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
原始数据帧
df1我不确定这样的函数是否已经存在,但这似乎起到了作用:
bindAndSource <- function(df1, df2) {
df1$source <- as.character(match.call())[[2]]
df2$source <- as.character(match.call())[[3]]
rbind(df1, df2)
}
警告:这在类似于呼叫的
*aply
中不起作用。这并不完全是您要求的,但非常接近。将对象放入命名列表中,并使用do.call(rbind…)
请注意,行名称现在反映了源data.frame
s
更新:使用cbind
和rbind
另一个选项是创建如下所示的基本函数:
AppendMe <- function(dfNames) {
do.call(rbind, lapply(dfNames, function(x) {
cbind(get(x), source = x)
}))
}
更新2:使用“gdata”软件包中的组合
更新3:使用“数据表”中的rbindlist
现在可以使用的另一种方法是使用“data.table”中的rbindlist
及其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:使用“purrr”中的map_df
与rbindlist
类似,您也可以使用“purrr”中的map_df
和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
其他两个答案的混合:
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
df1另一个解决方法是在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
df1另一种使用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
df1尽管这里已经有一些很好的答案,但我只想添加我一直在使用的答案。它是baseR
,因此如果您想在包中使用它,它的限制可能更小,而且它比其他一些baseR
解决方案要快一点
dfs <- list(df1 = data.frame("x"=c(1,2), "y"=2),
df2 = data.frame("x"=c(2,4), "y"=4),
df3 = data.frame("x"=2, "y"=c(4,5,7)))
> microbenchmark(cbind(do.call(rbind,dfs),
rep(names(dfs), vapply(dfs, nrow, numeric(1)))), times = 1001)
Unit: microseconds
min lq mean median uq max neval
393.541 409.083 454.9913 433.422 453.657 6157.649 1001
我不是100%确定,但我相信速度的提高是因为只需调用一次cbind
,而不是每个数据帧调用一次。哦,我喜欢这种方法!我还不习惯使用match.call,但是我读的越多,它在创建函数方面就越重要!谢谢你,伙计@PaddyMaloney,使用匹配。谨慎地呼叫。)是的,这与我使用append函数时遇到的问题完全相同。从这里可以创建一个新变量=row.names,然后在句点之后解析所有内容。谢谢你的快速回复!对我来说,这为数据帧提供了一个数字(基于调用的顺序),而不是实际的数据帧名称:o
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
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
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
dfs <- list(df1 = data.frame("x"=c(1,2), "y"=2),
df2 = data.frame("x"=c(2,4), "y"=4),
df3 = data.frame("x"=2, "y"=c(4,5,7)))
> microbenchmark(cbind(do.call(rbind,dfs),
rep(names(dfs), vapply(dfs, nrow, numeric(1)))), times = 1001)
Unit: microseconds
min lq mean median uq max neval
393.541 409.083 454.9913 433.422 453.657 6157.649 1001
> microbenchmark(do.call(rbind,
lapply(names(dfs), function(x) cbind(dfs[[x]], source = x))),
times = 1001)
Unit: microseconds
min lq mean median uq max neval
844.558 870.071 1034.182 896.464 1210.533 8867.858 1001