3. Compatibility with tsibble and sf

library(cubble)
library(tsibble)
library(sf)

Analysts often have their preferred spatial or temporal data structure that they prefer to use for spatio-temporal analysis. For example, the tbl_ts class from the tsibble package (Wang, Cook, and Hyndman 2020) is commonly used in time series forecasting and the sf class (Pebesma 2018) is frequently used in spatial data science. In cubble, analysts have the flexibility to combine these two structures together by allowing the spatial component to be an sf object and the temporal component to also be a tsibble object.

Using a tsibble for the temporal component

The key and index arguments in a cubble object corresponds to the tsibble counterparts and they can be safely omitted, if the temporal component is a tsibble object, i.e. meteo_ts in the example below. The tsibble class from the input will be carried over to the cubble object:

ts_nested <- make_cubble(
  spatial = stations, temporal = meteo_ts, coords = c(long, lat))
(ts_long <- face_temporal(ts_nested))
#> # cubble:   key: id [3], index: date, long form, [tsibble]
#> # temporal: 2020-01-01 -- 2020-01-10 [1D], no gaps
#> # spatial:  long [dbl], lat [dbl], elev [dbl], name [chr], wmo_id [dbl]
#>    id          date        prcp  tmax  tmin
#>    <chr>       <date>     <dbl> <dbl> <dbl>
#>  1 ASN00086038 2020-01-01     0  26.8  11  
#>  2 ASN00086038 2020-01-02     0  26.3  12.2
#>  3 ASN00086038 2020-01-03     0  34.5  12.7
#>  4 ASN00086038 2020-01-04     0  29.3  18.8
#>  5 ASN00086038 2020-01-05    18  16.1  12.5
#>  6 ASN00086038 2020-01-06   104  17.5  11.1
#>  7 ASN00086038 2020-01-07    14  20.7  12.1
#>  8 ASN00086038 2020-01-08     0  26.4  16.4
#>  9 ASN00086038 2020-01-09     0  33.1  17.4
#> 10 ASN00086038 2020-01-10     0  34    19.6
#> # ℹ 20 more rows
class(ts_long)
#> [1] "temporal_cubble_df" "cubble_df"          "tbl_ts"            
#> [4] "tbl_df"             "tbl"                "data.frame"

The long cubble shows [tsibble] in the header to indicate the object also being in a tbl_ts class. Methods applies to the tbl_ts class can also be applied to the temporal cubble objects, for example, checking whether the data contain temporal gaps:

ts_long |> has_gaps()
#> # A tibble: 3 × 2
#>   id          .gaps
#>   <chr>       <lgl>
#> 1 ASN00086038 FALSE
#> 2 ASN00086077 FALSE
#> 3 ASN00086282 FALSE

An existing cubble object can promote its temporal component to a tsibble object by applying make_temporal_tsibble(). The promoted cubble object (ts_long2) will be the same as the one created with a tsibble component initially (ts_long):

ts_long2 <- make_cubble(
  stations, meteo, 
  key = id, index = date, coords = c(long, lat)) |> 
  face_temporal() |> 
  make_temporal_tsibble() 
identical(ts_long2, ts_long)
#> [1] TRUE

A spatial component with sf

Similarly, an sf object can be supplied as the spatial component to create a cubble object, with the coords argument being omitted. This opens up the possibility to represent fixed area with polygons or multipolygons and the coords argument will be calculated as the centroids of the (multi)polygons. The [sf] print in the cubble header suggest an spatial component being also a sf object:

(sf_nested <- make_cubble(
  spatial = stations_sf, temporal = meteo, 
  key = id, index = date))
#> # cubble:   key: id [3], index: date, nested form, [sf]
#> # spatial:  [144.83, -37.98, 145.1, -37.67], WGS 84
#> # temporal: date [date], prcp [dbl], tmax [dbl], tmin [dbl]
#>   id           elev name   wmo_id  long   lat            geometry ts      
#>   <chr>       <dbl> <chr>   <dbl> <dbl> <dbl>         <POINT [°]> <list>  
#> 1 ASN00086038  78.4 essen…  95866  145. -37.7 (144.9066 -37.7276) <tibble>
#> 2 ASN00086077  12.1 moora…  94870  145. -38.0   (145.0964 -37.98) <tibble>
#> 3 ASN00086282 113.  melbo…  94866  145. -37.7 (144.8321 -37.6655) <tibble>
class(sf_nested)
#> [1] "spatial_cubble_df" "cubble_df"         "sf"               
#> [4] "tbl_df"            "tbl"               "data.frame"

The following code shows how to perform coordinate transformation with st_transform on a cubble object:

sf_nested |> sf::st_transform(crs = "EPSG:3857")
#> # cubble:   key: id [3], index: date, nested form, [sf]
#> # spatial:  [16122635.62, -4576600.87, 16152057.36, -4532279.36], WGS 84 /
#> #   Pseudo-Mercator
#> # temporal: date [date], prcp [dbl], tmax [dbl], tmin [dbl]
#>   id           elev name   wmo_id  long   lat            geometry ts      
#>   <chr>       <dbl> <chr>   <dbl> <dbl> <dbl>         <POINT [m]> <list>  
#> 1 ASN00086038  78.4 essen…  95866  145. -37.7 (16130929 -4541016) <tibble>
#> 2 ASN00086077  12.1 moora…  94870  145. -38.0 (16152057 -4576601) <tibble>
#> 3 ASN00086282 113.  melbo…  94866  145. -37.7 (16122636 -4532279) <tibble>

The counterpart to promote the spatial component in an existing cubble to be an sf object is make_spatial_sf():

(sf_nested2 <- make_cubble(
  stations, meteo, 
  key = id, index = date, coords = c(long, lat)) |> 
  make_spatial_sf())
#> CRS missing: using OGC:CRS84 (WGS84) as default
#> # cubble:   key: id [3], index: date, nested form, [sf]
#> # spatial:  [144.83, -37.98, 145.1, -37.67], WGS 84
#> # temporal: date [date], prcp [dbl], tmax [dbl], tmin [dbl]
#>   id           long   lat  elev name   wmo_id ts                  geometry
#>   <chr>       <dbl> <dbl> <dbl> <chr>   <dbl> <list>           <POINT [°]>
#> 1 ASN00086038  145. -37.7  78.4 essen…  95866 <tibble> (144.9066 -37.7276)
#> 2 ASN00086077  145. -38.0  12.1 moora…  94870 <tibble>   (145.0964 -37.98)
#> 3 ASN00086282  145. -37.7 113.  melbo…  94866 <tibble> (144.8321 -37.6655)

Reference

Pebesma, Edzer. 2018. Simple Features for R: Standardized Support for Spatial Vector Data.” The R Journal 10 (1): 439–46. https://doi.org/10.32614/RJ-2018-009.
Wang, Earo, Dianne Cook, and Rob J Hyndman. 2020. “A New Tidy Data Structure to Support Exploration and Modeling of Temporal Data.” Journal of Computational and Graphical Statistics 29 (3): 466–78. https://doi.org/10.1080/10618600.2019.1695624.