【发布时间】:2021-01-03 11:35:35
【问题描述】:
我有两个数据框:
1)
S C V1
"d" "q" 2
...
C R V2
"u" "t" 5
...
我想实现这个:
B T V
"d" "q" 2
...
"u" "t" 5
...
我怎样才能有效地做到这一点?
【问题讨论】:
标签: r
我有两个数据框:
1)
S C V1
"d" "q" 2
...
C R V2
"u" "t" 5
...
我想实现这个:
B T V
"d" "q" 2
...
"u" "t" 5
...
我怎样才能有效地做到这一点?
【问题讨论】:
标签: r
您可以重命名两个具有相同名称的数据框以将它们组合在一起。
new_cols <- c('B','T', 'V')
names(df1) <- new_cols
names(df2) <- new_cols
result <- rbind(df1, df2)
【讨论】:
这是一个基本的 R 解决方案,它不依赖于您想要一起 rbind 的 data.frames 的数量。
dftmp <- Map(`names<-`, list(df1, df2), list(value = c("B", "T", "V")))
df_final <- do.call(rbind, dftmp)
df_final
# B T V
#1 d q 2
#2 u t 5
数据
df1 <- read.table(text = "
S C V1
d q 2
", header = TRUE)
df2 <- read.table(text = "
C R V2
u t 5
", header = TRUE)
【讨论】:
您不能 bind_rows 忽略列名。但是你可以创建一个函数来规避这个:
library(dplyr)
force_bind <- function(df1, df2, x_names) {
colnames(df2) <- colnames(df1) <- x_names
bind_rows(df1, df2)
}
force_bind(df1, df2, c("B", "T", "V"))
## B T V
## 1 d q 2
## 2 u t 5
``
【讨论】:
bind_rows,不是吗?也许我们应该提到额外的包。
对效率的明确要求和 jwarz 对此的评论让我简要比较了 3 个提议的解决方案
总结
bind_rows()approach 是最快的解决方案(如 jwarz 所述),缺点是依赖额外的包。Map() 方法具有灵活的优势,但速度较慢(比 dplyr 慢 35% 以上)。代码和结果
library(dplyr)
library(microbenchmark, quietly = TRUE)
df1 <- structure(list(S = "d", C = "q", V1 = 2L),
class = "data.frame", row.names = c(NA, -1L))
df2 <- structure(list(C = "u", R = "t", V2 = 5L),
class = "data.frame", row.names = c(NA, -1L))
new_cols <- c("B", "T", "V")
solution1 <- function(df1, df2, new_cols) {
names(df1) <- new_cols
names(df2) <- new_cols
return( rbind(df1, df2) )
}
solution2 <- function(df1, df2, new_cols) {
dftmp <- Map(`names<-`, list(df1, df2), list(value = new_cols))
return( do.call(rbind, dftmp) )
}
solution3 <- function(df1, df2, new_cols) {
colnames(df2) <- colnames(df1) <- new_cols
return( bind_rows(df1, df2) )
}
microbenchmark(
rbind = solution1(df1, df2, new_cols),
Map = solution2(df1, df2, new_cols),
dplyr = solution3(df1, df2, new_cols),
times = 1E4L
)
#> Unit: microseconds
#> expr min lq mean median uq max neval
#> rbind 70.8 78.4 87.57165 82.0 88.0 2613.2 10000
#> Map 81.3 88.9 99.86045 93.0 99.4 10521.7 10000
#> dplyr 53.3 62.8 70.44836 68.3 71.0 2362.6 10000
df1 <- structure(list(S = letters[sample(1:26, 999L, replace = TRUE)],
C = letters[sample(1:26, 999L, replace = TRUE)],
V1 = sample(1:26, 999L, replace = TRUE)),
class = "data.frame", row.names = 1:999)
df2 <- structure(list(C = letters[sample(1:26, 999L, replace = TRUE)],
R = letters[sample(1:26, 999L, replace = TRUE)],
V2 = sample(1:26, 999L, replace = TRUE)),
class = "data.frame", row.names = 1:999)
microbenchmark(
rbind = solution1(df1, df2, new_cols),
Map = solution2(df1, df2, new_cols),
dplyr = solution3(df1, df2, new_cols),
times = 1E4L
)
#> Unit: microseconds
#> expr min lq mean median uq max neval
#> rbind 119.5 130.1 140.10275 134.2 141.10 2751.9 10000
#> Map 130.4 141.4 153.46169 145.8 152.65 3978.6 10000
#> dplyr 58.3 70.8 78.97621 77.8 80.55 2289.1 10000
由reprex package (v0.3.0) 于 2021-01-03 创建
【讨论】: