vctrs icon indicating copy to clipboard operation
vctrs copied to clipboard

Unexpected size error in `vec_rbind` when combining tibbles with `survival::Surv()` columns and empty tibbles

Open dmphillippo opened this issue 2 years ago • 2 comments

When attempting to rbind a tibble that has a Surv column created using survival::Surv() with an empty tibble, an "unexpected size" error is thrown. This happens using dplyr::bind_rows() and vctrs::vec_rbind() directly.

A quick reprex:

library(dplyr)

x <- tibble(s = survival::Surv(1:3))

Binding Surv columns behaves as expected

bind_rows(x, x)
#> # A tibble: 6 × 1
#>        s
#>   <Surv>
#> 1      1
#> 2      2
#> 3      3
#> 4      1
#> 5      2
#> 6      3

But attempting to bind with an empty tibble returns this error

bind_rows(x, tibble())
#> Error in `vec_rbind()`:
#> ! `c()` method returned a vector of unexpected size 5 instead of 3.
#> ℹ In file 'c.c' at line 412.
#> ℹ This is an internal error that was detected in the vctrs package.
#>   Please report it at <https://github.com/r-lib/vctrs/issues> with a reprex (<https://https://tidyverse.org/help/>) and the full backtrace.

#> Backtrace:
#>     ▆
#>  1. ├─dplyr::bind_rows(x, tibble())
#>  2. │ └─vctrs::vec_rbind(!!!dots, .names_to = .id, .error_call = current_env())
#>  3. └─rlang:::stop_internal_c_lib(...)
#>  4.   └─rlang::abort(message, call = call, .internal = TRUE, .frame = frame)

Whereas I would expect this to return x unchanged.

If we convert the Surv column to a bare matrix column then bind_rows() behaves, but we lose the class and other attributes

x2 <- x
x2$s <- as.matrix(x2$s)

bind_rows(x2, tibble())
#> # A tibble: 3 × 1
#>   s[,1]  [,2]
#>   <dbl> <dbl>
#> 1     1     1
#> 2     2     1
#> 3     3     1

attributes(x2$s)
#> $dim
#> [1] 3 2
#> 
#> $dimnames
#> $dimnames[[1]]
#> NULL
#> 
#> $dimnames[[2]]
#> [1] "time"   "status"

attributes(x$s)
#> $dim
#> [1] 3 2
#> 
#> $dimnames
#> $dimnames[[1]]
#> NULL
#> 
#> $dimnames[[2]]
#> [1] "time"   "status"
#> 
#> 
#> $type
#> [1] "right"
#> 
#> $class
#> [1] "Surv"

Created on 2023-03-27 with reprex v2.0.2

dmphillippo avatar Mar 27 '23 11:03 dmphillippo

Possibly we need a can_fall_back() method for Surv objects that returns FALSE but I'm not entirely sure how all of that works, so this will take some investigation

DavisVaughan avatar Mar 27 '23 13:03 DavisVaughan

Probably also related to this existing issue: https://github.com/r-lib/vctrs/issues/1748

avsdev-cw avatar Aug 14 '23 10:08 avsdev-cw