r-spatial / mapview

Interactive viewing of spatial data in R
https://r-spatial.github.io/mapview/
GNU General Public License v3.0
514 stars 91 forks source link

mapview mapview:::burstByRow on data.table #180

Open cstepper opened 5 years ago

cstepper commented 5 years ago

Hello, it seems like mapview isn't able to hande sf data.tables when applying burston a specific column.

Any ideas?

library('data.table')
library('sf')
#> Linking to GEOS 3.6.1, GDAL 2.2.3, proj.4 4.9.3
library('mapview')

# works on sf data.frame
brew_sf = breweries[1:5, ]

mapview(brew_sf, burst = "founded")


# crashes on sf data.table
brew_dt = as.data.table(breweries[1:5, ])
brew_dt = st_as_sf(brew_dt)

mapview(brew_dt, burst = "founded")
#> Error in `[.data.frame`(as.data.frame(x), , zcol): undefined columns selected

Created on 2018-09-11 by the reprex package (v0.2.0).

Session info ``` r devtools::session_info() #> Session info ------------------------------------------------------------- #> setting value #> version R version 3.5.1 (2018-07-02) #> system x86_64, mingw32 #> ui RTerm #> language (EN) #> collate English_United States.1252 #> tz Europe/Berlin #> date 2018-09-11 #> Packages ----------------------------------------------------------------- #> package * version date source #> backports 1.1.2 2017-12-13 CRAN (R 3.5.0) #> base * 3.5.1 2018-07-02 local #> base64enc 0.1-3 2015-07-28 CRAN (R 3.5.0) #> class 7.3-14 2015-08-30 CRAN (R 3.5.0) #> classInt 0.2-3 2018-04-16 CRAN (R 3.5.0) #> colorspace 1.3-2 2016-12-14 CRAN (R 3.5.0) #> compiler 3.5.1 2018-07-02 local #> crosstalk 1.0.0 2016-12-21 CRAN (R 3.5.1) #> curl 3.2 2018-03-28 CRAN (R 3.5.0) #> data.table * 1.11.4 2018-05-27 CRAN (R 3.5.1) #> datasets * 3.5.1 2018-07-02 local #> DBI 1.0.0 2018-05-02 CRAN (R 3.5.1) #> devtools 1.13.6 2018-06-27 CRAN (R 3.5.1) #> digest 0.6.15 2018-01-28 CRAN (R 3.5.0) #> e1071 1.7-0 2018-07-28 CRAN (R 3.5.1) #> evaluate 0.11 2018-07-17 CRAN (R 3.5.1) #> GIproxy 0.0.1 2018-07-10 local #> graphics * 3.5.1 2018-07-02 local #> grDevices * 3.5.1 2018-07-02 local #> grid 3.5.1 2018-07-02 local #> htmltools 0.3.6 2017-04-28 CRAN (R 3.5.0) #> htmlwidgets 1.2 2018-04-19 CRAN (R 3.5.1) #> httpuv 1.4.5 2018-07-19 CRAN (R 3.5.1) #> httr 1.3.1 2017-08-20 CRAN (R 3.5.1) #> jsonlite 1.5 2017-06-01 CRAN (R 3.5.1) #> knitr 1.20 2018-02-20 CRAN (R 3.5.1) #> later 0.7.3 2018-06-08 CRAN (R 3.5.0) #> lattice 0.20-35 2017-03-25 CRAN (R 3.5.0) #> leaflet 2.0.2 2018-08-27 CRAN (R 3.5.1) #> magrittr 1.5 2014-11-22 CRAN (R 3.5.1) #> mapview * 2.4.15 2018-08-08 Github (r-spatial/mapview@69be92e) #> memoise 1.1.0 2017-04-21 CRAN (R 3.5.0) #> methods * 3.5.1 2018-07-02 local #> mime 0.5 2016-07-07 CRAN (R 3.5.0) #> munsell 0.5.0 2018-06-12 CRAN (R 3.5.1) #> png 0.1-7 2013-12-03 CRAN (R 3.5.0) #> promises 1.0.1 2018-04-13 CRAN (R 3.5.0) #> R6 2.2.2 2017-06-17 CRAN (R 3.5.0) #> raster 2.6-7 2017-11-13 CRAN (R 3.5.0) #> RColorBrewer 1.1-2 2014-12-07 CRAN (R 3.5.0) #> Rcpp 0.12.18 2018-07-23 CRAN (R 3.5.1) #> rmarkdown 1.10 2018-06-11 CRAN (R 3.5.1) #> rprojroot 1.3-2 2018-01-03 CRAN (R 3.5.0) #> satellite 1.0.1 2017-10-18 CRAN (R 3.5.0) #> scales 1.0.0 2018-08-09 CRAN (R 3.5.1) #> sf * 0.6-4 2018-08-08 Github (r-spatial/sf@bafc5b5) #> shiny 1.1.0 2018-05-17 CRAN (R 3.5.1) #> sp 1.3-1 2018-06-05 CRAN (R 3.5.1) #> spData 0.2.9.3 2018-08-01 CRAN (R 3.5.1) #> stats * 3.5.1 2018-07-02 local #> stats4 3.5.1 2018-07-02 local #> stringi 1.2.4 2018-07-20 CRAN (R 3.5.1) #> stringr 1.3.1 2018-05-10 CRAN (R 3.5.1) #> tools 3.5.1 2018-07-02 local #> units 0.6-0 2018-06-09 CRAN (R 3.5.1) #> utils * 3.5.1 2018-07-02 local #> viridisLite 0.3.0 2018-02-01 CRAN (R 3.5.1) #> webshot 0.5.0 2017-11-29 CRAN (R 3.5.0) #> withr 2.1.2 2018-03-15 CRAN (R 3.5.1) #> xml2 1.2.0 2018-01-24 CRAN (R 3.5.0) #> xtable 1.8-2 2016-02-05 CRAN (R 3.5.0) #> yaml 2.2.0 2018-07-25 CRAN (R 3.5.1) ```
tim-salabim commented 5 years ago

Thanks @cstepper, this seems to be an edge case. The problem is with the split method of data.table and trips here.

The following presents a hacky workaround:

library(mapview)
library(data.table)

# no problem
tst_dt = data.table::data.table(franconia)
split(tst_dt, f = tst_dt[["district"]])

# causes problem
tst_dt_sf = sf::st_as_sf(tst_dt)
split(tst_dt_sf, f = tst_dt_sf[["district"]])

# dirty hacky workaround - push class "data.table" to the end
dt_last = function(x) {
  cls = class(x)
  dtcls = grep("data.table", cls)

  if (length(dtcls) == 0) return(x)

  class(x) = c(cls[-dtcls], "data.table")
  return(x)
}

class(tst_dt_sf)
class(dt_last(tst_dt_sf))

# now it works
split(dt_last(tst_dtsf), f = tst_dtsf[["district"]])
mapview(dt_last(tst_dtsf), zcol = "district", burst = TRUE)

While we could (and with regard to its scope should) implement such a workaround in mapview, I'd like to hear @edzer 's opinion on this one as he may have a more clever workaround? I am just not that familiar with all the details of class handling in R...

tim-salabim commented 5 years ago

@edzer do you have any input here, regarding that this may well trip sf users outside of mapview too?

edzer commented 5 years ago

Would a split method for sf objects resolve this?

tim-salabim commented 5 years ago

I think so, given that the class order is sf data.table data.frame

edzer commented 5 years ago

So this method should remove the sf and data.table classes, then call NextMethod()? Feels hacky, but if it works, it works.

tim-salabim commented 5 years ago

Yeah, I don't see a better solution without importing data.table. even then it would involve some hacks.

Doing as.data.frame > split > st_as_sf doesn't feel too hacky IMO. Fwiw we do such things all the time when working with sf and data.table.

edzer commented 5 years ago

That would also drop tbl_dfs.

tim-salabim commented 5 years ago

Good point. This means that we need to re-assign classes after the operation, right?

edzer commented 5 years ago

We do that all the time, see for an example here.