I am getting errors when trying to unnest a tibble column that has lubridate objects in it. I came across this issue after unnesting some columns that I had just nested. Here is a toy example that shows the error:
library(tidyverse)
library(lubridate)
#>
#> Attaching package: 'lubridate'
#> The following object is masked from 'package:base':
#>
#> date
test <- tibble(A=1:5, B=hours(1:5))
test
#> # A tibble: 5 x 2
#> A B
#> <int> <Period>
#> 1 1 1H 0M 0S
#> 2 2 2H 0M 0S
#> 3 3 3H 0M 0S
#> 4 4 4H 0M 0S
#> 5 5 5H 0M 0S
nested <- test %>% nest(B2=B)
nested
#> # A tibble: 5 x 2
#> A B2
#> <int> <list>
#> 1 1 <tibble [1 Γ 1]>
#> 2 2 <tibble [1 Γ 1]>
#> 3 3 <tibble [1 Γ 1]>
#> 4 4 <tibble [1 Γ 1]>
#> 5 5 <tibble [1 Γ 1]>
unnested <- nested %>% unnest(cols=B2)
#> Error: No common type for `..1$B2$B` <Period> and `..2$B2$B` <Period>.
I wonder whether this is because Period objects have multiple slots -- unnesting seems to work fine with Duration objects (as well as Date and datetime objects).
Interval class objects have two slots: .Data, a numeric object equal to the number of seconds in the interval; and start, a POSIXct object that specifies the time when the interval starts.
So Interval objects have multiple slots, like Period objects. I tried to chase down the issue with debug(), and got as far as identifying vctrs::vector_rbind() as the function the raises the error, but I can't tell why. (vector_rbind() seems to invoke a hidden -- at least to me -- vctrs_rbind method, and I could get any further.)
and when I inspected the x and y values passed in line 13, their slots -- although named identically -- are not interpreted as identical attributes so failed the compatibility test. (Note the .Data slot did not show as an attribute, so didn't seem involved -- I think this is the only slot in the other data types.)
Not sure where this goes, but thought I'd share it in case someone else can pick up the trail.
Part of the issue is that unnest() and unchop() eventually call vctrs:::has_same_type() to compare list elements, and will lead to a raised error if it returns false:
library(lubridate)
#>
#> Attaching package: 'lubridate'
#> The following object is masked from 'package:base':
#>
#> date
vctrs:::has_same_type(hours(0), hours(1))
#> [1] FALSE
The only solution I can come up with is converting Period and Interval objects to duration objects before unnest() (which calls unchop()) is called, and then convert back afterwards. The downside is that conversion is not straightforward for Period objects, which are ambiguous lengths of time: for example, months(1) can represent 28, 29, 30, or 31 days, depending on the date it's applied to.