Combining USA + Canada (specific province) with Plotly (plot_geo) or ggplot2

Dear all, I'm building a simple app for showing some results me and my research group obtained in the past few months. Data are from specific states of USA and provinces of Canada. I'd like to incorporate data from Alberta and Ontario provinces within the North America map but, when dealing with locationmode = in plot_geo function, I'm not able to combine them with the data from the USA states. Here are attached the developed app and an example of the data we have.

library(shiny)
library(DT)
library(ggplot2)
library(plotly)

data<-read.csv(file="data.csv",header=TRUE,sep=";")
head(data)
data$results <- with(data,paste("% of subjects",'<br>', "State:",data$States_Extended, 
                                '<br>', "Nr. of Samples:", data$Samples))
numbers <- paste("State:",data$States_Extended, '<br>',
                 "Nr. of Samples:", data$Samples)


ui1 <- fluidPage(
 titlePanel("Map of Positive Findings"),
  sidebarLayout(
    sidebarPanel(
      selectInput("variable", "Choose a target variable",
                  c("variable1" = "variable1",
                    "variable2" = "variable2")),
      radioButtons("maps", "Select type of data:",
                   c("Number of samples" = "samples",
                     "% of subjects" = "target"))),
  
    mainPanel(
     h3(textOutput("caption")),
      plotlyOutput("MapPlot"),
      fluidRow(
        DT::dataTableOutput("datatable")
      )
    )
  )
)




server1 <- function(input, output) {
  
  # Compute the formula text ----
  # This is in a reactive expression since it is shared by the
  # output$caption and output$mpgPlot functions
  formulaText <- reactive({
    paste("You chose: Map of", input$variable)
  })
  
  # Return the formula text for printing as a caption ----
  output$caption <- renderText({
    formulaText()
  })
  
  datasetInput <- reactive({
    switch(input$variable,
           "variable1" = data[,c("States_Extended","variable1")],
           "variable2" = data[,c("States_Extended","variable2")]
           )
  })
  output$datatable <- DT::renderDataTable({
    datasetInput()
  })
# Generate a plot of the requested variable against mpg ----
  # and only exclude outliers if requested
  output$MapPlot <- renderPlotly({
    # give state boundaries a border
    l <- list(color = toRGB("white"), width = 1)
    # specify some map projection/options
    g <- list(
      scope = 'north america',
      projection = list(type = 'albers'),
      showland = TRUE,
      landcolor = toRGB('grey'),
      showlakes = TRUE,
      lakecolor = toRGB('blue'),
      landcolor = toRGB("gray95"),
      subunitcolor = toRGB("gray85"),
      countrycolor = toRGB("gray85"),
      countrywidth = 0.5,
      subunitwidth = 0.5  
    )
    maps <- switch(input$maps,
                   samples = plot_geo(data, locationmode = 'USA-states',
                                      marker = list(line = l)) %>%
                     add_trace(
                       z = ~Samples, text = numbers, locations = ~States,
                       color = ~Samples, colors = 'Reds'
                     ) %>%
                     colorbar(title = paste('Number of <br>','analysis')) %>%
                     layout(
                       title = paste('Number of samples'),
                       geo = g
                     ),
                   target = plot_geo(data, locationmode = 'USA-states',
                                     marker = list(line = l)) %>%
                     add_trace(
                       z = ~data[,input$variable], text = ~results, locations = ~States,
                       color = ~data[,input$variable], colors = 'Oranges'
                     ) %>%
                     colorbar(title = paste(input$variable,'%')) %>%
                     layout(
                       title = paste('% of subjects  <br>', input$variable),
                       geo = g
                     )
    )
    
  })
  
}

# Run the application 
shinyApp(ui = ui1, server = server1)


And the related data:

States;States_Extended;Samples;variable1;variable2
AK;Alaska;1;0;0
AL;Alabama;2;50;0
AR;Arkansas;0;;
AZ;Arizona;14;64;0
CA;California;4;0;0
CO;Colorado;2;50;0
CT;Connecticut;1;100;0
DE;Delaware;2;50;0
FL;Florida;3;100;0
GA;Georgia;7;57;29
HI;Hawaii;0;;
IA;Iowa;2;50;0
ID;Idaho;0;;
IL;Illinois;0;;
IN;Indiana;6;100;17
KS;Kansas;0;;
KY;Kentucky;12;33;17
LA;Louisiana;2;50;0
MA;Massachusetts;0;;
MD;Maryland;0;;
ME;Maine;0;;
MI;Michigan;2;100;0
MN;Minnesota;4;50;0
MO;Missouri;4;50;0
MS;Mississippi;1;100;0
MT;Montana;2;100;0
NC;North Carolina;5;60;20
ND;North Dakota;0;;
NE;Nebraska;2;0;0
NH;New Hampshire;0;;
NJ;New Jersey;4;75;25
NM;New Mexico;4;75;25
NV;Nevada;1;100;0
NY;New York;25;72;8
OH;Ohio;3;100;0
OK;Oklahoma;4;50;0
OR;Oregon;0;;
PA;Pennsylvania;8;63;0
RI;Rhode Island;1;100;0
SC;South Carolina;6;50;17
SD;South Dakota;0;;
TN;Tennessee;4;50;0
TX;Texas;7;57;14
UT;Utah;4;75;0
VA;Virginia;5;100;40
VT;Vermont;0;;
WA;Washington;0;;
WI;Wisconsin;1;0;0
WV;West Virginia;0;;
WY;Wyoming;0;;
AB;Alberta;3;100;0
ON;Ontario;1;100;0

I attach here also an example of the current developed app:

I'd be very grateful if somebody could attend to this matter. I used plotly but ggplot2 functions would be great, too.

This type of visual is probably best handled through drawing the spatial polygons directly, rather than relying on plotly.js' "native" plotting support. The plotly R package has support for rendering sf data structures, so you could use a package like rnaturalearth to get at the actual spatial objects you desire, then plotly::add_sf() to render them. Compared to using plotly.js' native mapping support, this approach is more "heavy duty" since you're sending more data to the browser, but this gives you complete felxibility from the R side of things. Here's a choropleth of the regions you desire using a laea projection:

library(rnaturalearth)
library(sf)
library(dplyr)

# us laea projection as used in albersusa::us_laea_proj
us_laea <- "+proj=laea +lat_0=45 +lon_0=-100 +x_0=0 +y_0=0 +a=6370997 +b=6370997 +units=m +no_defs"

canada <- ne_states(country = "canada", returnclass = "sf") %>%
  st_transform(us_laea) %>%
  select(name, name_len)

usa <- ne_states(country = "united states of america", returnclass = "sf") %>%
  st_transform(us_laea) %>%
  select(name, name_len)

plot_ly(split = ~name, color = ~name_len, stroke = I("black"), span = I(1)) %>%
  add_sf(data = canada, color = I("gray90"), inherit = FALSE) %>%
  add_sf(data = usa) %>%
  add_sf(data = filter(canada, name %in% c("Ontario", "Alberta"))) %>%
  layout(showlegend = FALSE) %>%
  colorbar(title = "Length of<br>name")

14%20AM

1 Like

Dear @cpsievert, thank you so much for this!
It seems actually what I was looking for!
It helps a lot, thank you very much for your time and your willingness.

1 Like