Search code examples
rshinyr-leaflet

NAs not permitted in row index in Shiny app (leaflet map)


I receive a strange error NAs not permitted in row index

My error is traditionally is somewhere between subseting/reactivity/outputting

Sample data is here

Shapefile is here

# Load packages
library(shiny)
library(rgdal)
library(raster)
library(leaflet)
library(sp)
library(geojsonio)
library(RColorBrewer)
library(jsonlite)
library(shinythemes)

# Global code

# Read file on a local machine
data_pg <- read.csv("pg.csv", header = TRUE, stringsAsFactors = FALSE)

# Read a shapefile
countries <- readOGR(".","ne_50m_admin_0_countries")

# Merge data
data_pg_df <- merge(countries, data_pg, by.x = "NAME", by.y = "Country", duplicateGeoms = TRUE)


# Color palette
pal <- colorFactor(
palette = 'Dark2',
domain = data_pg_df$Region
)

# UI code

ui <- fluidPage(theme = shinytheme("united"),
            titlePanel("PG Map"),
            sidebarLayout(
              sidebarPanel(
                selectInput("regionInput", "Region",
                            choices = c("Choose region", 
                                        "Africa",
                                        "Asia",
                                        "Latin America",
                                        "North America",
                                        "Europe"),
                            selected = "Choose region"),
                selectInput("pgInput", "Select PG",
                            choices = c("Choose PG", 
                                        "PG 1",
                                        "PG 2",
                                        "PG 3"),
                            selected = "Choose PG")
              ),

              mainPanel(
                
                # Output
                tabsetPanel(type = "tabs",
                            tabPanel("Map", leafletOutput(outputId = 'map', height = 700)) #,
                            # tabPanel("Chart",  plotOutput("chart")),
                            # tabPanel("Table",  tableOutput("table"))
   )
  )
 )
)

#  Server
server <- function(input, output) {

selectedRegion <- reactive({
  data_pg_df[data_pg_df$Region == input$regionInput, ] 
})

output$map <- renderLeaflet({
  leaflet(data_pg_df) %>%
    addProviderTiles(providers$Stamen.Toner) %>%
    addPolygons(stroke = FALSE, 
                fillOpacity = 0.75, 
                color = pal(selectedRegion()), weight = 1) 

})



}

shinyApp(ui = ui, server = server)

So, either I subset in a wrong way. Or mess up with reactivity. Or my output is wrong.

I updated the code, but the error continues with NAs

# Global code

# Read file on a local machine
data_pg <- read.csv("pg.csv", header = TRUE, stringsAsFactors = FALSE)

# Read a shapefile
countries <- readOGR(".","ne_50m_admin_0_countries")

# Merge data
data_pg_df <- merge(countries, data_pg, by.x = "name", by.y = "Country", 
duplicateGeoms = TRUE)


# UI code

ui <- fluidPage(theme = shinytheme("united"),
            titlePanel("PG Map"),
            sidebarLayout(
              sidebarPanel(
                selectInput("regionInput", "Region",
                            choices = c("Choose region", 
                                        "Africa",
                                        "Asia",
                                        "Latin America",
                                        "North America",
                                        "Europe"),
                            selected = "Choose region"),
                selectInput("pgInput", "Select PG",
                            choices = c("Choose PG", 
                                        "PG 1",
                                        "PG 2",
                                        "PG 3"),
                            selected = "Choose PG")
              ),

              mainPanel(
                
                # Output
                tabsetPanel(type = "tabs",
                            tabPanel("Map", leafletOutput(outputId = 'map', height = 700)) #,
                            # tabPanel("Chart",  plotOutput("chart")),
                            # tabPanel("Table",  tableOutput("table"))
  )
  )
  )
  )

#  Server
server <- function(input, output) {

output$map <- renderLeaflet({
leaflet(data_pg_df) %>% 
  addProviderTiles(providers$Stamen.TonerLite) %>% 
  setView(11.0670977,0.912484, zoom = 4) 

})  

selectedRegion <- reactive({
data_pg_df[data_pg_df$Region == input$regionInput, ] 
})

observe({
state_popup <- paste0("<strong>Region: </strong>", 
                      selectedRegion()$Region, 
                      "<br><strong> Client name: </strong>", 
                      selectedRegion()$Client.name,
                      "<br><strong> Country: </strong>", 
                      selectedRegion()$Country,
                      "<br><strong> PG: </strong>", 
                      selectedRegion()$PG)


 leafletProxy("map", data = selectedRegion()) %>%
  clearShapes() %>%
  addPolygons(fillColor =  "blue",
              popup = state_popup,
              color = "#BDBDC3",
              fillOpacity = 0.5,
              weight = 1 
  )
 })

}

shinyApp(ui = ui, server = server)

Also updated shapefiles


Solution

  • Resolved with a help of R community perfectly. enter image description here

    Treating NAs was a key:

    "If you look at data_pg_df$Region, you'll see it has many NAs:

    > data_pg_df$Region
    [1] NA              NA              NA              NA              NA             
    [6] NA              NA              NA              "Latin America" NA             
    [11] NA              NA              NA              NA              NA             
    [16] NA              NA              NA              NA              NA             
    [21] NA              NA              NA              NA              NA             
    [26] NA              NA              NA              NA              NA             
    [31] NA              NA              NA              NA              NA             
    [36] NA              NA              NA              "North America" NA             
    [41] NA              "Asia"          NA              NA              NA             
    [46] NA              NA              NA              NA              NA             
    [51] NA              NA              NA              NA              NA             
    [56] NA              NA              "Europe"        NA              NA             
    [61] NA              NA              NA              NA              NA          
    ...   
    

    With data_pg_df$Region == input$regionInput, you're comparing it to a value, like "Asia". In R, if you compare a value to NA, you get NA.

    > data_pg_df$Region == "Asia"
    [1]    NA    NA    NA    NA    NA    NA    NA    NA FALSE    NA    NA    NA    NA    
    NA    NA
    [16]    NA    NA    NA    NA    NA    NA    NA    NA    NA    NA    NA    NA    NA    
    NA    NA
    [31]    NA    NA    NA    NA    NA    NA    NA    NA FALSE    NA    NA  TRUE    NA    
    NA    NA
    [46]    NA    NA    NA    NA    NA    NA    NA    NA    NA    NA    NA    NA FALSE    
    NA    NA
    [61]    NA    NA    NA    NA    NA    NA    NA    NA    NA    NA    NA    NA    NA    
    NA    NA
    ...
    

    And you can't index into data_pg_df object using NA.

    You'll need to handle the NAs somehow. I don't know for sure what's appropriate for your data set, but it looks like you might want to keep only the rows where == resolves to TRUE, and drop the rows which would result in NA and FALSE. To do this, you can add in a check with is.na():

    !is.na(data_pg_df$Region) & data_pg_df$Region == "Asia"
    [1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE 
    FALSE FALSE
    [16] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE 
    FALSE FALSE
    [31] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE  TRUE FALSE 
    FALSE FALSE
    [46] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE 
    FALSE FALSE
    [61] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE 
    FALSE FALSE
    ...
    

    So then you'd have:

    selectedRegion <- reactive({
    data_pg_df[!is.na(data_pg_df$Region) & data_pg_df$Region == input$regionInput, ]
    })