I am trying to create a simple map using ggplotly
:
I want only the western european regions to be coloured in green, and to do this I have created the binary variable weur.
library(rnaturalearth)
library(plotly)
world <- ne_countries(returnclass = "sf")
w <- world[world$iso_a2_eh != -99, c("geometry", "name", "iso_a2_eh", "subregion")]
w$weur <- ifelse(w$subregion == "Western Europe", 1, 0)
Then I have created a text which should be shown when hovering on each of the countries with a very simple message specified in ggplot(aes(text = paste0(...))
:
fig <- ggplotly(
ggplot(data= w,
aes(text = paste0("country: ", name,
"\n country code: ", iso_a2_eh))) +
geom_sf(color= "white", aes(fill = as.character(weur)),
linewidth = 0.2, stat = "identity") +
theme(legend.position="none",
panel.background = element_rect(fill = "white"),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank()) +
coord_sf(xlim=c(-10,40), ylim=c(30,70), expand= FALSE, label_axes = "SW") +
scale_fill_manual(values = c("gray", "lightgreen"), na.value="#dadada", drop=F),
tooltip = "text"
)
fig
This works, but the text is shown only when you hover near to the borders of each country, while I would like to also see the text while hovering in the middle.
I thought that specifying the style
and hoveron
would have solved this issue
fig %>%
style(hoveron = "fills+points")
However, in this case if I hover in the middle of the map, only the "fill indicator" value (i.e. as.character(w$weur)
, which is 1 for germany in the image) is shown as text.
Is there any way to make ggplotly
show the same text both when hovering near to the border and in the middle of the area?
I found this trick that fixes the hovering behaviour. Or so I thought! Actually it turns out, that ggplotly transforms both weurs to two traces. Each trace can only have one text label. So this "fixer" only enforces this. But it actually does not fix it yet. Because then all green countries have the label "France" and all others have the label "Fiji". So I thought, however silly this might seem, you need to loop through all countries and add them specifically in one geom_sf-call, because only then these are created as seperated traces on the transformation :-/. Now, I know that the runtime is atrocious here, but since we are in buggy territories I thought I might share this insight.
library(rnaturalearth)
library(plotly)
library(ggplot2)
# Get world data and prepare it
world <- ne_countries(returnclass = "sf")
w <- world[world$iso_a2_eh != -99, c("geometry", "name", "iso_a2_eh", "subregion")]
w$weur <- ifelse(w$subregion == "Western Europe", 1, 0)
# or w$weur <- +w$subregion=='Western Europe'
w$color <- c("grey", "lightgreen")[1+w$weur] # pre calculate color
fig <- ggplotly(
ggplot(data = w) +
{ # Add each country as a seperate layer because plotly only accepts one label per data layer :/
lapply(seq_len(nrow(w)), \(i) {
country_data <- w[i, ]
geom_sf(data = country_data,
color = "white",
fill = country_data$color,
linewidth = 0.2,
aes(text = paste0("country: ", name, "\ncountry code: ", iso_a2_eh)))
})
} +
theme(legend.position="none",
panel.background = element_rect(fill = "white"),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank()) +
coord_sf(xlim=c(-10,40), ylim=c(30,70), expand= FALSE, label_axes = "SW")
) |> style(hoveron = "fills")
fig
giving
One could solve it by plotting directly within plotly sacraficing the layout, e.g.
plot_ly(
w,
split = ~ name,
color = ~ as.character(weur),
colors = c("gray", "lightgreen"),
stroke = I("white"),
text = ~ paste0("country: ", name, "<br>country code: ", iso_a2_eh),
hoverinfo = "text",
hoveron = "fills",
showlegend = FALSE
)