不同数据类型的bind_rows

时间:2016-09-07 19:02:43

标签: r dplyr

我想堆叠一个data.frames列表,但有时列有不同的数据类型。我希望操作能够强制使用最小公分母(在我的情况下通常为character)。

此堆叠发生在package function内,几乎可以接受任何data.frames列表。它实际上不具备在ds_a$x之前强制bind_rows()到角色的能​​力。

ds_a <- data.frame(
  x = 1:6,
  stringsAsFactors = FALSE
)
ds_b <- data.frame(
  x = c("z1", "z2"),
  stringsAsFactors = FALSE
)

# These four implementations throw:
# Error: Can not automatically convert from integer to character in column "x".
ds_1 <- dplyr::bind_rows(ds_a, ds_b)
ds_2 <- dplyr::bind_rows(ds_b, ds_a)
ds_3 <- dplyr::bind_rows(list(ds_a, ds_b))
ds_4 <- dplyr::union_all(ds_a, ds_b)

我希望输出是一个带有单个字符向量的data.frame:

   x
1  1
2  2
3  3
4  4
5  5
6  6
7 z1
8 z2

我有一些长期计划使用来自(REDCap)数据库的元数据来影响强制,但我希望有一个短期的一般解决方案来进行堆叠操作。

2 个答案:

答案 0 :(得分:5)

我们可以使用rbindlist

中的data.table
library(data.table)
rbindlist(list(ds_a, ds_b))
#    x
#1:  1
#2:  2
#3:  3
#4:  4
#5:  5
#6:  6
#7: z1
#8: z2

答案 1 :(得分:0)

最近,我切换到一种方法,该方法最初是将所有列都保留为字符串(当从纯文本转换为data.frame时),然后进行堆栈,最后将converts the columns转换为适当的数据类型,做出决定的行(使用readr::type_convert())。

它模仿了这个例子。我没有做任何性能比较,但是没有明显的区别(互联网是真正的瓶颈)。另外,我有点喜欢减少数据类型转换次数的想法。

library(magrittr)
col_types <- readr::cols(.default = readr::col_character())
raw_a <- "x,y\n1,21\n2,22\n3,23\n4,24\n5,25\n6,26"
raw_b <- "x,y\nz1,31\nz2,32"
ds_a <- readr::read_csv(raw_a, col_types=col_types)
ds_b <- readr::read_csv(raw_b, col_types=col_types)

list(ds_a, ds_b) %>% 
  dplyr::bind_rows() %>% 
  readr::type_convert()
#> Parsed with column specification:
#> cols(
#>   x = col_character(),
#>   y = col_double()
#> )
#> # A tibble: 8 x 2
#>   x         y
#>   <chr> <dbl>
#> 1 1        21
#> 2 2        22
#> 3 3        23
#> 4 4        24
#> 5 5        25
#> 6 6        26
#> 7 z1       31
#> 8 z2       32

reprex package(v0.3.0)于2019-12-03创建