首页 > 解决方案 > 在绑定之前自动将一个数据框的所有列类型强制转换为另一个数据框的类型

问题描述

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

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
)

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

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

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

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

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

这是预期的结果:

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

标签: rdplyr

解决方案


我们可以使用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

什么type.convert是:

  1. 将最佳拟合类应用于ds_b(注意 %>% 在 内bind_rows)的数据。所以所有ds_b$x都是整数,因此 R 将类因子转换为 ds_b$x 中的类整数。
  2. 所有这些ds_b$y都是字符类,但本质上是整数,因此 R 将字符类转换为整数类。这可能会导致误解。但是,现在我们有ds_a$y双类和ds_b$y整数类 -> 但这对 R 来说没问题,bind_rows这里双类覆盖整数。
> # 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
  1. 将双精度类转换ds_b$p为整数类,因为数据本质上是整数。

解决方案:

library(dplyr)
bind_rows(ds_a, ds_b %>% type.convert(as.is=TRUE))

输出:

   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

推荐阅读