vctrs
vctrs copied to clipboard
Assigning to OOB locations directly adjacent to a vector
This is somewhat related to #1301 Discovered from looking at https://stackoverflow.com/questions/70794504/using-native-time-in-clock-package-and-having-error-with-rbind-error-levels-c
I have discovered that even with the levels.vctrs_vctr
fix, we still can't call rbind()
if we have a rcrd column.
library(vctrs)
x <- new_rcrd(list(a = 1L))
df <- data.frame(x = x)
rbind(df, df)
#> Error:
#> ! Can't assign to elements that don't exist.
#> x Location 2 doesn't exist.
#> ℹ There are only 1 element.
This boils down to the fact that rbind()
constructs the final result by using [<-
to "extend" each column, like this:
library(vctrs)
# Base R supports vector "extension" but we don't
y <- c("a", "b")
`[<-`(y, 3L, "c")
#> [1] "a" "b" "c"
try(vec_assign(y, 3L, "c"))
#> Error : Can't assign to elements that don't exist.
#> x Location 3 doesn't exist.
#> ℹ There are only 2 elements.
# Obviously base R also supports things we don't want too...
`[<-`(y, 4L, "c")
#> [1] "a" "b" NA "c"
Since [<-.vctrs_rcrd
uses vec_assign()
, we end up with the above error in rbind()
because of this
> vctrs:::`[<-.vctrs_rcrd`
function (x, i, value)
{
i <- maybe_missing(i, TRUE)
value <- vec_cast(value, x)
out <- vec_assign(vec_data(x), i, vec_data(value))
vec_restore(out, x)
}
I don't think that vec_assign()
should gain this ability directly (but I could be wrong), but the idea in general isn't completely crazy, since tibble seems to do it:
https://github.com/tidyverse/tibble/blob/64fefd56b12d7922a408b6b2505b8474dc1e470b/R/subsetting.R#L646
library(tibble)
df <- tibble(x = 1:2)
df[3,] <- tibble(x = 3)
df
#> # A tibble: 3 × 1
#> x
#> <int>
#> 1 1
#> 2 2
#> 3 3
the idea in general isn't completely crazy, since tibble seems to do it:
We've added num_as_location(oob = "extend")
for tibble. It might make sense to make vec_assign()
more flexible too.