Converting from bind_rows to vec_rbind

I am looking for an example of how we could use vctrs::vec_rbind as a replacement for dplyr::bind_rows to allow conversion of non-matching column types.

I see the example provided here https://github.com/tidyverse/dplyr/issues/4281

library(dplyr, warn.conflicts = FALSE)
library(vctrs)

mtcars_char <- mtcars %>% mutate(mpg = as.character(mpg))

vec_rbind(mtcars, mtcars_char, .ptype = mtcars) %>% 
  as_tibble() # for printing
#> # A tibble: 64 x 11
#>      mpg   cyl  disp    hp  drat    wt  qsec    vs    am  gear  carb
#>    <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#>  1  21       6  160    110  3.9   2.62  16.5     0     1     4     4
#>  2  21       6  160    110  3.9   2.88  17.0     0     1     4     4
#>  3  22.8     4  108     93  3.85  2.32  18.6     1     1     4     1
#>  4  21.4     6  258    110  3.08  3.22  19.4     1     0     3     1
#>  5  18.7     8  360    175  3.15  3.44  17.0     0     0     3     2
#>  6  18.1     6  225    105  2.76  3.46  20.2     1     0     3     1
#>  7  14.3     8  360    245  3.21  3.57  15.8     0     0     3     4
#>  8  24.4     4  147.    62  3.69  3.19  20       1     0     4     2
#>  9  22.8     4  141.    95  3.92  3.15  22.9     1     0     4     2
#> 10  19.2     6  168.   123  3.92  3.44  18.3     1     0     4     4
#> # … with 54 more rows

But I still get an error:

mtcars_char <- mtcars %>% mutate(mpg = as.character(mpg))

vec_rbind(mtcars, mtcars_char, .ptype = mtcars) %>% 
  as_tibble() # for printing
"Error: Can't convert `$mpg` <character> to match type of `$mpg` <double>."

This is with R Version 3.5.0, dplyr: 1.0.2, vctrs: 0.3.4

Hoping to get this working as I have data sets that require some messy workarounds in order to use bind_rows()

I can reproduce the error, but I found a subsequent github issue that works. Not sure if it does what you need, though. Change is as.integer

library(dplyr, warn.conflicts = FALSE)
library(vctrs)
#> 
#> Attaching package: 'vctrs'
#> The following object is masked from 'package:dplyr':
#> 
#>     data_frame

mtcars_char <- mtcars %>% mutate(mpg = as.integer(mpg))

vec_rbind(mtcars, mtcars_char, .ptype = mtcars) %>% 
  as_tibble()
#> # A tibble: 64 x 11
#>      mpg   cyl  disp    hp  drat    wt  qsec    vs    am  gear  carb
#>    <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#>  1  21       6  160    110  3.9   2.62  16.5     0     1     4     4
#>  2  21       6  160    110  3.9   2.88  17.0     0     1     4     4
#>  3  22.8     4  108     93  3.85  2.32  18.6     1     1     4     1
#>  4  21.4     6  258    110  3.08  3.22  19.4     1     0     3     1
#>  5  18.7     8  360    175  3.15  3.44  17.0     0     0     3     2
#>  6  18.1     6  225    105  2.76  3.46  20.2     1     0     3     1
#>  7  14.3     8  360    245  3.21  3.57  15.8     0     0     3     4
#>  8  24.4     4  147.    62  3.69  3.19  20       1     0     4     2
#>  9  22.8     4  141.    95  3.92  3.15  22.9     1     0     4     2
#> 10  19.2     6  168.   123  3.92  3.44  18.3     1     0     4     4
#> # … with 54 more rows

Created on 2020-11-16 by the reprex package (v0.3.0.9001)

Character types are not coercible with numeric types by design. You need to explicitly parse them into numbers in a preliminary step. Same for date types, they are not coercible with numeric ones because they represent a different kind of data.

On the other hand character types are coercible to each other, for instance factor to character.

1 Like

There is some deep mojo to coercion that I don't have visibility into after reading the docs and the github material. It seems that it should be possible, but it feels like it requires some rolling your own constructors and can't be don't directly in vec_rbind. If @romain or @lionel see this, they will be able to provide better guidance than I ever could.

But mpg is a numeric type already. And therefore wouldn't actually be a good example of what vec_rbind is suppose to solve vs bind_rows.

It would be nice if something like ptype could be added to bind_rows since I assume using vec_rbind is going to require me to refactor code significantly.

1 Like

See https://vctrs.r-lib.org/reference/faq-compatibility-types.html for some information about coercibility. Feedback welcome :slight_smile:

2 Likes