Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

linking between leaflet and d3scatter not working #47

Open
Myles12345 opened this issue Feb 26, 2018 · 21 comments
Open

linking between leaflet and d3scatter not working #47

Myles12345 opened this issue Feb 26, 2018 · 21 comments

Comments

@Myles12345
Copy link

Firstly, my apologies if this is an error on my part. I have been trying to work with the example provided on
http://rstudio-pubs-static.s3.amazonaws.com/209203_02f14fea3274448bbbf8d04c99c6051b.html

There seems to be some oddities with this code (perhaps it is older?) - the sd$transform(as.data.frame) does not seem to work as is. I created work around using:
sd_df <- SharedData$new(world@data, group = sd$groupName())

This may be the culprit or not. When I amend the code on the site above - and run. I am able to get linking between DT and d3scatter but not with leaflet map, as the version above shows. It seems like the SharedData is not being respected when used with leaflet?

Can others re-create the issue that I am experiencing? Does the native code posted on the website work for others? Again - if this is an oversight on my part I apologize

The code I am using is (knitted to flexdashboard:

`---
title: "Gapminder data using crosstalk"
output:
flexdashboard::flex_dashboard:
orientation: rows
theme: lumen

library(flexdashboard) ; library(crosstalk) ; library(dplyr) ; library(rgdal)
## This is the site works and where I have modified code from: http://rstudio-pubs-static.s3.amazonaws.com/209203_02f14fea3274448bbbf8d04c99c6051b.html
## These are the steps for creating (and writing) the SpatialPolygonsDataFrame using data from the gapminder package and the boundary vector layer supplied by www.naturalearthdata.com in the rworldmap package.

library(gapminder) ; library(countrycode)
df <- gapminder %>% filter(year == 2007) %>% mutate(ISO3 = countrycode(country, "country.name", "iso3c"), gdpPercap = round(gdpPercap, 0), lifeExp = round(lifeExp, 0))
# This removes a duplicate ISO3 ref (KOR) - save for a more robust solution. 
df<- df %>% filter(country != "Korea, Dem. Rep.")
###

### ### Run this code chunk for the first time

#library(rworldmap) ; library(spatialEco)
#data(countriesLow)
#world <- countriesLow
#world <- sp::merge(world, df, by.x = "ISO3", by.y = "ISO3", sort = FALSE)
#world <- world[, c("country", "continent.y",  "year", "lifeExp", "pop", "gdpPercap")] 
#world_NA <- world[is.na(world@data$country) ,]
#writeOGR(world_NA, ".", "world_NA", driver="ESRI Shapefile")
#world <- sp.na.omit(world, col.name = "country")
#writeOGR(world, ".", "world", driver="ESRI Shapefile")

### ### 

world <- readOGR(".", "world", verbose = FALSE)
world@data <- rename(world@data, continent = cntnnt_)
world_NA <- readOGR(".", "world_NA", verbose = FALSE)

sd <- SharedData$new(world)
#Added this to allow sharedDate to work ()
sd_df <- SharedData$new(world@data, group = sd$groupName())

Inputs {.sidebar}

#sd$transform(as.data.frame) does not work?  (throughout the replaced sd with sd_df)
filter_slider("lifeExp", "Life expectancy (years)", sd_df, ~lifeExp)
filter_slider("gdpPrcp", "Income per person ($)", sd_df, ~gdpPrcp)

This R Markdown document uses the experimental crosstalk R package to enable interactivity between different widgets that display the same Gapminder data.

Credits:
The following packages were used: flexdashboard, rgdal, dplyr, leaflet, d3scatter, DT, gapminder, countrycode,
rworldmap, and spatialEco.

Row {data-height=550}

library(leaflet)
pal <- colorFactor(c("#1f77b4", "#ff7f0e", "#2ca02c", "#d62728", "#9467bd"), domain = c("Africa", "Americas", "Asia", "Europe", "Oceania"), ordered = FALSE)
leaflet(sd_df) %>% 
setView(9.998176, 14.531777, zoom = 2) %>%
addProviderTiles("CartoDB.Positron") %>% 
addPolygons(data = world_NA, color = "#969696", weight = 1, fillColor = "#808080") %>% 
addPolygons(data = world, color = "#969696", weight = 2, fillColor = ~pal(continent), fillOpacity = 0.8, label = ~as.character(country))

Row {data-height=450}

library(d3scatter)
d3scatter(sd_df, x = ~gdpPrcp, y = ~lifeExp, color = ~continent, x_label = "Income per person", y_label = "Life expectancy")

library(DT)
datatable(sd_df, rownames = FALSE, extensions = 'Scroller', 
          options = list(scrollY = 200, scroller = TRUE, columnDefs = list(list(className = 'dt-left', targets = 0:3))))
@dmurdoch
Copy link
Contributor

dmurdoch commented Mar 8, 2018

Your source is really mangled. Is there a clean version online somewhere to try?

@Myles12345
Copy link
Author

@dmurdoch
Sorry - try this:

`---
title: "Gapminder data using crosstalk"
output:
flexdashboard::flex_dashboard:
orientation: rows
theme: lumen

library(flexdashboard) ; library(crosstalk) ; library(dplyr) ; library(rgdal)
## This is the site works and where I have modified code from: http://rstudio-pubs-static.s3.amazonaws.com/209203_02f14fea3274448bbbf8d04c99c6051b.html
## These are the steps for creating (and writing) the SpatialPolygonsDataFrame using data from the gapminder package and the boundary vector layer supplied by www.naturalearthdata.com in the rworldmap package.

library(gapminder) ; library(countrycode)
df <- gapminder %>% filter(year == 2007) %>% mutate(ISO3 = countrycode(country, "country.name", "iso3c"), gdpPercap = round(gdpPercap, 0), lifeExp = round(lifeExp, 0))
# This removes a duplicate ISO3 ref (KOR) - save for a more robust solution. 
df<- df %>% filter(country != "Korea, Dem. Rep.")
###

### ### Run this code chunk for the first time

library(rworldmap) ; library(spatialEco)
data(countriesLow)
world <- countriesLow
world <- sp::merge(world, df, by.x = "ISO3", by.y = "ISO3", sort = FALSE)
world <- world[, c("country", "continent.y",  "year", "lifeExp", "pop", "gdpPercap")] 
world_NA <- world[is.na(world@data$country) ,]
writeOGR(world_NA, ".", "world_NA",overwrite_layer=TRUE ,driver="ESRI Shapefile")
world <- sp.na.omit(world, col.name = "country")
writeOGR(world, ".", "world",overwrite_layer=TRUE ,driver="ESRI Shapefile")

### ### 

world <- readOGR(".", "world", verbose = FALSE)
world@data <- rename(world@data, continent = cntnnt_)
world_NA <- readOGR(".", "world_NA", verbose = FALSE)

sd <- SharedData$new(world)
#Added this to allow sharedDate to work ()
sd_df <- SharedData$new(world@data, group = sd$groupName())

Inputs {.sidebar}

Chart A

#sd$transform(as.data.frame) does not work?  (throughout the replaced sd with sd_df)
filter_slider("lifeExp", "Life expectancy (years)", sd_df, ~lifeExp)
filter_slider("gdpPrcp", "Income per person ($)", sd_df, ~gdpPrcp)

Row {data-height=550}

Chart B

library(leaflet)
pal <- colorFactor(c("#1f77b4", "#ff7f0e", "#2ca02c", "#d62728", "#9467bd"), domain = c("Africa", "Americas", "Asia", "Europe", "Oceania"), ordered = FALSE)
leaflet(sd_df) %>% 
setView(9.998176, 14.531777, zoom = 2) %>%
addProviderTiles("CartoDB.Positron") %>% 
addPolygons(data = world_NA, color = "#969696", weight = 1, fillColor = "#808080") %>% 
addPolygons(data = world, color = "#969696", weight = 2, fillColor = ~pal(continent), fillOpacity = 0.8, label = ~as.character(country))

Row {data-height=450}

library(d3scatter)
d3scatter(sd_df, x = ~gdpPrcp, y = ~lifeExp, color = ~continent, x_label = "Income per person", y_label = "Life expectancy")

library(DT)
datatable(sd_df, rownames = FALSE, extensions = 'Scroller', 
          options = list(scrollY = 200, scroller = TRUE, columnDefs = list(list(className = 'dt-left', targets = 0:3))))

@dmurdoch
Copy link
Contributor

dmurdoch commented Mar 9, 2018

That's got the same problem: Github is treating the chunk boundaries etc. as markup. You'll need to put the file online somewhere else and link to it.

@Myles12345
Copy link
Author

Myles12345 commented Mar 9, 2018

@dmurdoch
I'm such a Luddite - sorry! Try this
https://gist.github.com/Myles12345/c0fa26ac9572033a851d1f3d057db142

The previous link wasn't working - this one should work.

@dmurdoch
Copy link
Contributor

I took a look at your example. I think the issue is unrelated to d3scatter; it's something going wrong with crosstalk and leaflet when the shared data is not built from a regular dataframe, but from a SpatialPolygonsDataFrame. But exactly what is going wrong is beyond me.

Maybe you could simplify the example to only include a filter slider and some spatial polygons displayed in leaflet?

@jcheng5
Copy link
Member

jcheng5 commented Mar 13, 2018

First of all, sd_df <- SharedData$new(world@data, group = sd$groupName()) for now is the correct workaround. I forget now exactly what the problem was with transform but it was something really bad :)

Secondly, in your example,

leaflet(sd_df) %>%
  addPolygons(data = world_NA, color = "#969696", weight = 1, fillColor = "#808080") %>% 
  addPolygons(data = world, color = "#969696", weight = 2, fillColor = ~pal(continent), fillOpacity = 0.8, label = ~as.character(country))

you're passing sd_df to leaflet(), but overriding that with world_NA and world in your two addPolygons calls. Because those addPolygons calls aren't using SharedData, they won't react to crosstalk. What happens if you at least replace world with sd?

@dmurdoch
Copy link
Contributor

That change didn't fix things for me. If I use the CRAN version of leaflet (1.1.0), it gives an error:

Error in UseMethod("metaData") : 
  no applicable method for 'metaData' applied to an object of class "c('SharedData', 'R6')"

If I update to the Github version of leaflet (rstudio/leaflet, 1.1.0.9000, 2017-02-17) the error goes away, but the map is unresponsive to changes to the other controls.

@Myles12345
Copy link
Author

The original - posted here:
https://rpubs.com/rcatlord/gapminder_crosstalk

seems to work as it should - I had to change to the SharedData() to get it to work at all when I tried it. I wonder if that is blocking something....?

@dmurdoch - here is a shortened version with just sliders, for testing...

https://gist.github.com/Myles12345/7f60bf44722d3ec5e555bbb968e9fa74

@dmurdoch
Copy link
Contributor

This is kind of weird. The rpubs.com example isn't using the leaflet package from CRAN or the current master branch on github. You can see this if you debug it: the Javascript for leaflet on that page has crosstalk code in the methods.addPolygons function, whereas the mainstream ones don't. I don't know Henry Partridge (@rcatlord); if you do, maybe you could contact him to ask about it.

But the reason yours doesn't work is because you aren't using this customized version of leaflet.

@dmurdoch
Copy link
Contributor

dmurdoch commented Mar 15, 2018

Okay, adding crosstalk support to addPolygons is actually kind of easy. You can install a version of leaflet with that change using devtools::install_github("dmurdoch/leaflet@crosstalk4"). But you'll also need to make the change that Joe mentioned, i.e. use data = sd instead of data = world where you want the display to be linked.

@Myles12345
Copy link
Author

That's amazing - I found that it was crosstalk4 that seemed to be the relevant branch? I also (as you noted) removed -
sd_df <- SharedData$new(world@data, group = sd$groupName()) in view of the original - sd <- SharedData$new(world) - that seems to work now.

Here is a working version:
https://gist.github.com/Myles12345/7f60bf44722d3ec5e555bbb968e9fa74

Thank you so much for your support and fantastic work!

@dmurdoch
Copy link
Contributor

Yes, crosstalk4. I've fixed the comment.

@dmaupin12
Copy link

I've been using this package version to filter polygons and its worked perfectly, however I noticed that polygons are now not filtering again. I reinstalled the leaflet version using devtools::install_github("dmurdoch/leaflet@crosstalk4") to no avail. Is there something else I should do? Anyone else having this problem?

Thanks

@dmaupin12
Copy link

dmaupin12 commented Apr 25, 2018

I figured out the problem. For anyone working on a Dell laptop with OneDrive, I would recommend saving the library folder in the c drive instead of the OneDrive location. After changing the location of my packages and re-downloading the leaflet version it is now working.

@dmurdoch
Copy link
Contributor

Generally speaking R and R packages shouldn't care about where they are stored, but it is easy to have several versions of a package in different library locations, and then sometimes a little surprising which one R chooses. So I would recommend checking that you really only have one copy of each package installed, or this problem might arise again.

@rcatlord
Copy link

Hi all - I've updated the code for the gapminder / crosstalk app. It takes into the workarounds mentioned here and the code is more concise.

http://rpubs.com/rcatlord/gapminder_crosstalk_updated

@JacobBraslaw22
Copy link

Hi,
I've come across version issues with leaflet. leaflet crosstalk4 is built on leaflet version 1.1.0.9000 and works with adding polygons.
However, for this dashboard I need to add raster imagery as well using leafem::addRasterRGB. leafem is built on leaflet version 2.1 and breaks crosstalk4 for addPolygons when I update the package.
Are there any workarounds?

@dmurdoch
Copy link
Contributor

@JacobBraslaw22: The issue you're commenting on was posted 4 years ago. I don't know about the others, but I've long forgotten the context. Could you post a new issue, with minimal reproducible code in it?

@hmeeks
Copy link

hmeeks commented Jun 7, 2022

@dmurdoch I'm having the same problem as @JacobBraslaw22. I'm trying to replicate creating the following app (http://rpubs.com/rcatlord/gapminder_crosstalk_updated). The source code works for leaflet version 1.1.0.9000 but not for the leaflet version 2.1. It seems like crosstalk4 doesn't work for addPolygons- the filter_slide works as it should for everything else (plots & map with addMarker). Do you have a workaround this? Thank you!

@dmurdoch
Copy link
Contributor

dmurdoch commented Jun 7, 2022

@hmeeks: No, I haven't looked at that code in 4 years.

@jdlom
Copy link

jdlom commented Dec 16, 2022

@hmeeks have you opened an issue on rstudio/leaflet repository ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants