在绑定之前自动将一个数据框的所有列类型强制为另一个数据框的类型

Par*_*gue 12 r dplyr

假设我有两个要绑定的数据框:

ds_a <- data.frame(
  x = 1:6,
  y = 5,
  z = "4",
  l = 2,
  stringsAsFactors = FALSE
)

ds_b <- data.frame(
  x = as.factor(1:6),
  y = "5",
  p = 2,
  stringsAsFactors = FALSE
)
Run Code Online (Sandbox Code Playgroud)

当我尝试绑定它们时,出现以下错误:

> bind_rows(ds_a, ds_b)
Error: Can't combine `..1$x` <integer> and `..2$x` <factor<4c79c>>.
Run Code Online (Sandbox Code Playgroud)

通常,我解决这个问题的方法是将两个数据框中的所有列都转换为字符,绑定两个数据框,然后手动将所有列重新转换回其原始类型。

有没有一种方法可以通过自动转换 的列来简单地强制ds_a和之间的所有类型冲突以匹配ds_bds_bds_a(假设它们的名称相同)

更一般地说,我想要一个解决方案来自动将所有列转换为列名称匹配ds_b的类型。如果并且不共享所有相同的列,ds_a则该解决方案应该有效(当一个列中不存在但在另一个中存在列时,只需填充 NA )。ds_bds_a

这是预期的结果:

ds_merged =read.table(text = 'x y z l p 
1 1 5 4 2 NA
2 2 5 4 2 NA
3 3 5 4 2 NA
4 4 5 4 2 NA
5 5 5 4 2 NA
6 6 5 4 2 NA
7 1 5 NA NA 2
8 2 5 NA NA 2
9 3 5 NA NA 2
10 4 5 NA NA 2
11 5 5 NA NA 2
12 6 5 NA NA 2', header = TRUE, row.names = NULL)

> ds_merged

   row.names x y  z  l  p
1          1 1 5  4  2 NA
2          2 2 5  4  2 NA
3          3 3 5  4  2 NA
4          4 4 5  4  2 NA
5          5 5 5  4  2 NA
6          6 6 5  4  2 NA
7          7 1 5 NA NA  2
8          8 2 5 NA NA  2
9          9 3 5 NA NA  2
10        10 4 5 NA NA  2
11        11 5 5 NA NA  2
12        12 6 5 NA NA  2
Run Code Online (Sandbox Code Playgroud)

Ron*_*hah 8

您可以根据另一个数据帧更改一个数据帧的类,并对数据集进行行绑定。

library(dplyr)
library(purrr)

bind_rows(ds_a, map2_df(ds_b, map(ds_a, class), ~{class(.x) <- .y;.x}))

#   x y
#1  1 5
#2  2 5
#3  3 5
#4  4 5
#5  5 5
#6  6 5
#7  1 5
#8  2 5
#9  3 5
#10 4 5
#11 5 5
#12 6 5
Run Code Online (Sandbox Code Playgroud)

map2_df用于更改ds_b数据类别,其中

.x- 传递 的列值ds_b

.y-map(ds_a, class)获取class每列的ds_a

在函数中,它更改了值的类.x.y绑定它们。然后我们bind_rowsds_a数据框一起使用。


如果列数不相等,您可以仅更改常见列的类并绑定行。

new_bind <- function(a, b) {
  common_cols <- intersect(names(a), names(b))
  b[common_cols] <- map2_df(b[common_cols], 
               map(a[common_cols], class), ~{class(.x) <- .y;.x})
  bind_rows(a, b)  
}
new_bind(ds_a, ds_b) 

#   x y    z  l  p
#1  1 5    4  2 NA
#2  2 5    4  2 NA
#3  3 5    4  2 NA
#4  4 5    4  2 NA
#5  5 5    4  2 NA
#6  6 5    4  2 NA
#7  1 5 <NA> NA  2
#8  2 5 <NA> NA  2
#9  3 5 <NA> NA  2
#10 4 5 <NA> NA  2
#11 5 5 <NA> NA  2
#12 6 5 <NA> NA  2            
Run Code Online (Sandbox Code Playgroud)


Tar*_*Jae 8

我们可以使用type.convert()

说明:OP评论后:

type_convert不考虑ds_a(您可以检查是否glimpse(ds_a)glimpse结果数据帧进行比较:

请注意 的列ds_a与 中的列具有相同的类result

> # compare classes
> glimpse(ds_a)
Rows: 6
Columns: 4
$ x <int> 1, 2, 3, 4, 5, 6
$ y <dbl> 5, 5, 5, 5, 5, 5
$ z <chr> "4", "4", "4", "4", "4", "4"
$ l <dbl> 2, 2, 2, 2, 2, 2
> glimpse(ds_b)
Rows: 6
Columns: 3
$ x <fct> 1, 2, 3, 4, 5, 6
$ y <chr> "5", "5", "5", "5", "5", "5"
$ p <dbl> 2, 2, 2, 2, 2, 2
> glimpse(result)
Rows: 12
Columns: 5
$ x <int> 1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6
$ y <dbl> 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5
$ z <chr> "4", "4", "4", "4", "4", "4", NA, NA, NA, NA, NA, NA
$ l <dbl> 2, 2, 2, 2, 2, 2, NA, NA, NA, NA, NA, NA
$ p <int> NA, NA, NA, NA, NA, NA, 2, 2, 2, 2, 2, 2
Run Code Online (Sandbox Code Playgroud)

所做type.convert的是:

  1. 将最佳拟合类应用于 的数据ds_b(请注意 %>% 在 内bind_rows)。所以所有都是ds_b$x整数,因此 R 将类因子转换为 ds_b$x 中的类整数。
  2. 所有这些ds_b$y都是字符类,但本质上都是整数,因此R将字符类转换为整数类。这可能会造成误解。但是,现在我们有ds_a$ydouble 类和ds_b$y整数类 -> 但这对于 R 来说没有问题,bind_rows这里 double 类覆盖了整数。
> # showing what type.convert does to ds_b
> ds_b$x <- as.integer(ds_b$x)
> ds_b$y <- as.integer(ds_b$y)
> ds_b %>% 
+   as_tibble()
# A tibble: 6 x 3
      x     y     p
  <int> <int> <dbl>
1     1     5     2
2     2     5     2
3     3     5     2
4     4     5     2
5     5     5     2
6     6     5     2
> ds_b %>% 
+   as_tibble()
# A tibble: 6 x 3
      x     y     p
  <int> <int> <dbl>
1     1     5     2
2     2     5     2
3     3     5     2
4     4     5     2
5     5     5     2
6     6     5     2
> bind_rows(ds_a, ds_b) %>% 
+   as_tibble()
# A tibble: 12 x 5
       x     y z         l     p
   <int> <dbl> <chr> <dbl> <dbl>
 1     1     5 4         2    NA
 2     2     5 4         2    NA
 3     3     5 4         2    NA
 4     4     5 4         2    NA
 5     5     5 4         2    NA
 6     6     5 4         2    NA
 7     1     5 NA       NA     2
 8     2     5 NA       NA     2
 9     3     5 NA       NA     2
10     4     5 NA       NA     2
11     5     5 NA       NA     2
12     6     5 NA       NA     2
Run Code Online (Sandbox Code Playgroud)
  1. 将 double 类转换ds_b$p为整型,因为数据本质上是整数。

解决方案:

library(dplyr)
bind_rows(ds_a, ds_b %>% type.convert(as.is=TRUE))
Run Code Online (Sandbox Code Playgroud)

输出:

   x y    z  l  p
1  1 5    4  2 NA
2  2 5    4  2 NA
3  3 5    4  2 NA
4  4 5    4  2 NA
5  5 5    4  2 NA
6  6 5    4  2 NA
7  1 5 <NA> NA  2
8  2 5 <NA> NA  2
9  3 5 <NA> NA  2
10 4 5 <NA> NA  2
11 5 5 <NA> NA  2
12 6 5 <NA> NA  2
Run Code Online (Sandbox Code Playgroud)