Choropleth world map - convert k thousand numbers - r

When hovering over a country the numbers are shown as say 125.115k - I want to show it as 125,115
I tried using library(formattable) and something along the lines of z = comma(worldmap$Deaths,digits = 1)
My code is below
output$World_Map <- renderPlotly({
g <- list(
showframe = FALSE,
showcoastlines = FALSE,
projection = list(type = 'Mercator')
)
plot_ly(
worldmap,
type = 'choropleth',
locations = worldmap$COUNTRY_ALPHA_3_CODE,
z = worldmap$Deaths,
text = paste("Number of Deaths: ",worldmap$COUNTRY_SHORT_NAME,"\n",comma(worldmap$Cases, digits = 0),"\n","Number of Cases: ",worldmap$COUNTRY_SHORT_NAME),
colorscale = "Reds"
) %>% layout(title = "<b>Covid19 Global Pandemic .... Data Source: <a href='https://coronavirus.jhu.edu/'>Johns Hopkins University of Medicine</a><b>", geo = g)
})

For comma rendering numbers, I use prettyNum from base R, also comma function is available in scales package.
number_a <- 123456
prettyNum(number_a, big.mark = ",")
[1] "123,456"
Your question is about text tooltip in Plotly. You can do something like this, with hoverinfo/hovertemplate and text parameters.
Of course there are other manners to do it.
Because I don't have your data, I use an example from plotly website.
library(plotly)
# code for example
# https://plotly.com/r/choropleth-maps/#using-builtin-country-and-state-geometries
# doc for hovertemplate
# https://plotly-r.com/controlling-tooltips.html#tooltip-text
df <- read.csv('https://raw.githubusercontent.com/plotly/datasets/master/2014_world_gdp_with_codes.csv')
# light grey boundaries
l <- list(color = toRGB("grey"), width = 0.5)
# specify map projection/options
g <- list(
showframe = FALSE,
showcoastlines = FALSE,
projection = list(type = 'Mercator')
)
fig <- plot_geo(df)
fig <- fig %>% add_trace(
z = ~GDP..BILLIONS., color = ~GDP..BILLIONS., colors = 'Blues',
locations = ~CODE, marker = list(line = l),
hoverinfo = "text",
text = ~glue::glue("{COUNTRY} <b>{CODE}</b>"),
hovertemplate = "%{z:,0f}<extra>%{text}</extra>"
)
fig <- fig %>% colorbar(title = 'GDP Billions US$', tickformat = ",0f")
fig <- fig %>% layout(
title = '2014 Global GDP<br>Source:CIA World Factbook',
geo = g
)
fig
With this you can easily configure your hover info / tooltip.
See here for more examples :
https://plotly.com/r/choropleth-maps/#customize-choropleth-chart
For French number (space instead of comma), you can at the end config locale:
fig %>%
config(locale = 'fr')

Related

Plotly ignoring hoverinfo = 'skip'

I am creating a plot with several time series, plotting the mean value and two quantiles in the process and highlighting the region between the quantiles. Then I have a unified hoverinfo showing me all points at one point in time. I do not want this hoverinfo to display the dummy trace that is only there for the highlighting. I tried both hoverinfo = skip and hoverinfo = none, but that only hides any text info, not the trace itself in the hoverinfo.
Here is the code I have (without most "beautification parameters" such as axis width and the likes...):
###creating dummy data
test_data <- data.frame(matrix(0,nrow = 27,ncol = 4))
colnames(test_data) <- c("x","y","value","date")
test_data$x <- c(-1,-1,-1,0,0,0,1,1,1,-1,-1,-1,0,0,0,1,1,1,-1,-1,-1,0,0,0,1,1,1)
test_data$y <- c(-1,0,1,-1,0,1,-1,0,1,-1,0,1,-1,0,1,-1,0,1,-1,0,1,-1,0,1,-1,0,1)
test_data$value <- rnorm(27,mean = 5,sd = 1)
date_vec <- c(rep(as.Date("2022-01-01"),9),rep(as.Date("2022-01-02"),9),rep(as.Date("2022-01-03"),9))
test_data$date <- date_vec
x_levels <- unique(test_data$x)
y_levels <- unique(test_data$y)
avg <- data.frame(matrix(0,nrow = 3,ncol = 1))
colnames(avg) <- c("value")
avg$date <- unique(date_vec)
Q75 <- data.frame(matrix(0,nrow = 3,ncol = 1))
colnames(Q75) <- c("value")
Q75$date <- unique(date_vec)
Q25 <- data.frame(matrix(0,nrow = 3,ncol = 1))
colnames(Q25) <- c("value")
Q25$date <- unique(date_vec)
for (i in 1:length(unique(date_vec))){
avg$value[i] <- mean(test_data$value[test_data$date == unique(date_vec)[i]])
Q75$value[i] <- quantile(test_data$value[test_data$date == unique(date_vec)[i]],0.75)
Q25$value[i] <- quantile(test_data$value[test_data$date == unique(date_vec)[i]],0.25)
}
##creating plot
fig <- plot_ly()
fig <- fig %>% layout(hovermode = 'x unified')
for(i in 1:length(x_levels)){
for(j in 1:length(y_levels)){
fig <- fig %>% add_trace(data = test_data, type = 'scatter', mode = 'lines+markers',
x = test_data$date[test_data$x == x_levels[i] & test_data$y == y_levels[j]],
y = test_data$value[test_data$x == x_levels[i] & test_data$y == y_levels[j]],
showlegend = FALSE, line = list(color = 'grey'), marker = list(color = 'grey'),
hoverinfo = 'text', text = paste0("some text dependent on x and y"))
}}
fig <- fig %>% add_trace(data = Q25, type = 'scatter', mode = 'lines', name = '25%-quantile', x = Q25$date,
y = Q25$value, showlegend = TRUE, line = list(color = 'darkred', dash = 'dot'),
hoverinfo = 'text', text = paste0("some text dependent on Q25"))
fig <- fig %>% add_trace(data = avg, type = 'scatter', mode = 'lines', name = 'mean value', x = avg$date,
y = avg$value, showlegend = TRUE, line = list(color = 'darkred', dahs = 'dash'),
hoverinfo = 'text', text = paste0("some text depenent on avg"))
fig <- fig %>% add_trace(data = Q75, type = 'scatter', mode = 'lines', name = '75%-quantile', x = Q75$date,
y = Q75$value, showlegend = TRUE, line = list(color = 'darkred', dash = 'dot'),
hoverinfo = 'text', text = paste0("some text dependent on Q75"))
#### This is the dummy trace in question:
fig <- fig %>% add_trace(x = Q25$date, y = Q25$value, type = 'scatter', mode = 'lines', fill = 'tonexty',
fillcolor = 'rgba(139,0,0,0.2)', line = list(color = 'darkred', width = 0.1), showlegend = FALSE,
hoverinfo = 'skip')
print(fig)
Is this a bug? Am I missing something obvious? Is there a better way to make the highlighting that does not create an additional hoverinfo? Thanks in advance!
Alright, this answer is not ideal—but it works.
There is good news, though. Plotly developers are already working on a solution. They're in the testing phase, which is where I got the idea for this answer. You can read about what Plotly's doing here.
First, I set a seed because you have random data. I used set.seed(3509). There were no changes to the data or fig.
When you hover over any point on your graph, your fill color will disappear. The tooltip does not show the trace that shouldn't be there anyway.
The fill color will return as soon as you move on or when the tooltip goes away.
This is the Javascript to call this hover event.
# the notation [12] is the curvenumber; it represnts a single trace
hoverer = "function(el, x) {
el.on('plotly_hover', function(d){
dt = {'fill': 'none'};
Plotly.restyle(el.id, dt, [12]);
});
el.on('plotly_unhover', function(d){
ft = {'fill':'tonexty'};
Plotly.restyle(el.id, ft, [12]);
});
}"
To visualize your plot with this event:
fig %>% htmlwidgets::onRender(hoverer)

Adding hover annotations to a Heatmap plotly R

I'm currently using plotly's heatmap to make a risk matrix (if anyone knows a more efficient way to do it I'd be open to suggestions). Currently I add information about the different risks with annotations but I would like that instead of annotations it was a marker that contains the information when hovering over it, as in the image that I attached below.
Below I attach the code and an image of how I would like it to be.
I'll appreciate any suggestion, advice, etc. Thanks!
df.risk <- data.frame(
Risk = paste0("R",1:5),
Prob = runif(5),
Cons = runif(5,1,5))
m <- c(rep(0.1,4),0.5,rep(0.1,2),rep(0.5,3),0.1,rep(0.5,3),0.9,0.1,rep(0.5,2),rep(0.9,2),rep(0.5,2),rep(0.9,3))
scale <- matrix(m, nrow = 5, ncol = 5)
pal <- c("#1A9641",
"#EFE90F",
"#F44336")
fig <- plot_ly(
x = seq(1,16,by = 4),
y = seq(0,1,by = 0.2),
z = scale,
type = "heatmap",
colors = colorRamp(pal))
fig <- fig %>%
layout(xaxis = list(title = 'Cons'),
yaxis = list(title = 'Prob'))
fig %>%
add_annotations(y = df.risk$Prob,
x = df.risk$Cons,
text = df.risk$Risk,
showarrow = FALSE) %>% hide_colorbar()
Let me know if this is what you were looking for. I changed your data in df.risk, so that the template was a bit more obvious. Other than that the content leading up to the plot_ly object remained as you presented it in your question.
The data changes first
df.risk <- data.frame(
Risk = rep(c("Product rendered obsolete",
"Strict legal requirements",
"Sufficient human resources",
"Sufficient material resources",
"Sufficient manufacturing equipment",
"Sufficient sales",
"Reliable suppliers",
"Unknown/unintended costs exceeding ROI",
"Evidence technology will work",
"Sufficient market share long term"), 3),
Prob = runif(10),
Cons = runif(10,1,5))
Then the initial creation of the plot_ly object.
fig <- plot_ly(
x = seq(1,16,by = 4),
y = seq(0,1,by = 0.2),
z = scale,
hoverinfo = "none",
type = "heatmap",
colors = colorRamp(pal)) %>%
add_markers(
inherit = F,
x = ~Cons, y = ~Prob,
data = df.risk,
showlegend = F,
text = ~Risk,
color = I("white"), # I("transparent") or whatever color you prefer
hovertemplate = paste0("%{text}<br><br>", # risks
"Probability: %{y:.0%}<br>", # prob % rounded
"Severity: %{x:.2f}", # severity, rounded
"<extra></extra>")) # no trace info
fig %>%
layout(xaxis = list(title = 'Consequences/Severity'),
yaxis = list(title = 'Probability')) %>% hide_colorbar()
This is what it looks like.

Font not in bold

In my code below (which works just fine) I would like all the fonts when I hover over country on world map to be either bold or non bold. What is happening is as per the following example - say I hover over USA then I get .
562,079 Deaths United States USA
Cases: 30,211,178
Population: 320,635,163
Deaths % by Population:v0.0097%
The "Deaths United Sates" is not bold.
Code
output$World_Map <- renderPlotly({
l <- list(color = toRGB("grey"), width = 0.5)
g <- list(
showframe = FALSE,
showcoastlines = FALSE,
projection = list(type = "kavrayskiy7")
)
fig <- plot_geo(worldmap)
fig <- fig %>% add_trace(
z = ~ worldmap$Deaths,
color = ~ worldmap$Deaths,
colors = 'Reds',
locations = ~ worldmap$Country_Alpha_Code,
marker = list(line = l),
hoverinfo = "text",
text = ~ glue::glue(
"Deaths: {Country.x} <b>{Country_Alpha_Code}<b>\nCases: {comma(Cases,digits=0)}<b>\nPopulation: {comma(Population,digits=0)}<b>\nDeaths % by Population: {comma(Deaths_Perc_Pop,digits=4)}%</b>"
),
hovertemplate = "%{z:,0f}<extra>%{text}</extra>"
)
fig <-
fig %>% colorbar(title = 'Deaths - Positive Cases Gradient', tickformat = ",0f")
fig <-
fig %>% layout(title = 'Covid19 Global Pandemic .... <br>Data Source:Johns Hopkins University of Medicine',
geo = g)
fig
})
Regards

Plotly animated map not showing countries with NA values

I posted this in the plotly community forum but got absolutely no activity! Hope you can help here:
I have map time-series data, some countries don’t have data and plotly does not plot them at all. I can have them outlined and they look different but it appears nowhere that the data is missing there (i.e. I want a legend entry). How can I achieve this? Here is a reprex:
library(plotly)
library(dplyr)
data = read.csv('https://github.com/lc5415/COVID19/raw/master/data.csv')
l <- list(color = toRGB("grey"), width = 0.5)
g <- list(
scope = 'world',
countrycolor = toRGB('grey'),
showframe = T,
showcoastlines = TRUE,
projection = list(type = 'natural earth')
)
map.time = data %>%
plot_geo() %>%
add_trace(z = ~Confirmed, color = ~Confirmed, frame = ~Date, colors = 'Blues',
text = ~Country, locations = ~Alpha.3.code, marker = list(line = l)) %>%
colorbar(title = 'Confirmed') %>%
layout(
title = 'Number of confirmed cases over time',
geo = g
) %>%
animation_opts(redraw = F) %>%
animation_slider(
currentvalue = list(
prefix = paste0("Days from ",
format(StartDate, "%B %dnd"),": "))) %>%
plotly_build()
map.time
Note that the countries with missing data (e.g. Russia) have as many data points as all other countries, the issue is not that they do not appear in the dtaframe passed to plotly.
The obvious way to handle this is to create a separate labels column for the tooltip that reads "No data" for NA values (with the actual value otherwise), then make your actual NA values 0. This will give a uniform appearance to all the countries but correctly tells you when a country has no data.
map.time = data %>%
mutate_if(is.numeric, function(x) {x[is.na(x)] <- -1; x}) %>%
plot_geo() %>%
add_trace(z = ~Confirmed, color = ~Confirmed, frame = ~Date, colors = 'Blues',
text = ~Country, locations = ~Alpha.3.code,
marker = list(line = l)) %>%
colorbar(title = 'Confirmed') %>%
layout(
title = 'Number of confirmed cases over time',
geo = g
) %>%
animation_opts(redraw = F) %>%
animation_slider(
currentvalue = list(
prefix = paste0("Days from ",
format(StartDate, "%B %dnd"),": "))) %>%
plotly_build()
Which gives:

R - plotly - combine bubble and chorpleth map

I would like to combine two types of maps within one map in plotly, namely bubble and choropleth map. The objective is to show population size on a country level (choropleth) as well as on a city level (bubble) by hovering with the mouse over the map.
The plotly example code for a choropleth map is as follows:
library(plotly)
df <- read.csv('https://raw.githubusercontent.com/plotly/datasets/master/2014_world_gdp_with_codes.csv')
# light grey boundaries
l <- list(color = toRGB("grey"), width = 0.5)
# specify map projection/options
g <- list(
showframe = FALSE,
showcoastlines = FALSE,
projection = list(type = 'Mercator')
)
plot_ly(df, z = GDP..BILLIONS., text = COUNTRY, locations = CODE, type = 'choropleth',
color = GDP..BILLIONS., colors = 'Blues', marker = list(line = l),
colorbar = list(tickprefix = '$', title = 'GDP Billions US$'),
filename="r-docs/world-choropleth") %>%
layout(title = '2014 Global GDP<br>Source:CIA World Factbook',
geo = g)
The plotly example code for a bubble map is as follows:
library(plotly)
df <- read.csv('https://raw.githubusercontent.com/plotly/datasets/master/2014_us_cities.csv')
df$hover <- paste(df$name, "Population", df$pop/1e6, " million")
df$q <- with(df, cut(pop, quantile(pop)))
levels(df$q) <- paste(c("1st", "2nd", "3rd", "4th", "5th"), "Quantile")
df$q <- as.ordered(df$q)
g <- list(
scope = 'usa',
projection = list(type = 'albers usa'),
showland = TRUE,
landcolor = toRGB("gray85"),
subunitwidth = 1,
countrywidth = 1,
subunitcolor = toRGB("white"),
countrycolor = toRGB("white")
)
plot_ly(df, lon = lon, lat = lat, text = hover,
marker = list(size = sqrt(pop/10000) + 1),
color = q, type = 'scattergeo', locationmode = 'USA-states',
filename="r-docs/bubble-map") %>%
layout(title = '2014 US city populations<br>(Click legend to toggle)', geo = g)
How could one possibly merge the two types of maps into one?
Great question! Here's a simple example. Note:
Use add_trace to add another chart type layer on top of the plot
the layout of the plot is shared across all traces. layout keys describe things like the map's scope, axes, title, etc. See more layout keys.
Simple bubble chart map
lon = c(-73.9865812, -118.2427266, -87.6244212, -95.3676974)
pop = c(8287238, 3826423, 2705627, 2129784)
df_cities = data.frame(cities, lat, lon, pop)
plot_ly(df_cities, lon=lon, lat=lat,
text=paste0(df_cities$cities,'<br>Population: ', df_cities$pop),
marker= list(size = sqrt(pop/10000) + 1), type="scattergeo",
filename="stackoverflow/simple-scattergeo") %>%
layout(geo = list(scope="usa"))
Interactive version
Simple choropleth chart
state_codes = c("NY", "CA", "IL", "TX")
pop = c(19746227.0, 38802500.0, 12880580.0, 26956958.0)
df_states = data.frame(state_codes, pop)
plot_ly(df_states, z=pop, locations=state_codes, text=paste0(df_states$state_codes, '<br>Population: ', df_states$pop),
type="choropleth", locationmode="USA-states", colors = 'Purples', filename="stackoverflow/simple-choropleth") %>%
layout(geo = list(scope="usa"))
Interactive version
Combined choropleth and bubble chart
plot_ly(df_cities, lon=lon, lat=lat,
text=paste0(df_cities$cities,'<br>Population: ', df_cities$pop),
marker= list(size = sqrt(pop/10000) + 1), type="scattergeo",
filename="stackoverflow/choropleth+scattergeo") %>%
add_trace(z=df_states$pop,
locations=df_states$state_codes,
text=paste0(df_states$state_codes, '<br>Population: ', df_states$pop),
type="choropleth",
colors = 'Purples',
locationmode="USA-states") %>%
layout(geo = list(scope="usa"))
Interactive version with hover text
Note that z and locations columns in the second trace are explicitly from the df_states dataframe. If they were from the same dataframe as the first trace (df_cities declared in plot_ly) then we could've just written z=state_codes instead of z=df_states$state_codes (as in the second example).

Resources