R: ggplot2 with geom_map returns "x and units must have length > 0" error despite values converted to factors

Konrad picture Konrad · Dec 9, 2014 · Viewed 8.6k times · Source

I'm working on a primitive shiny app that would map some data from the Open Data for Scotland project. I worked out the SPARQL queries that manufacture a data frame resembling the extract provided below

dz_label overall.quantiles
S010001 8
S010002 9

I have the fortified shapefiles and I'm trying to map them with use of the following code:

ggplot() + 
      geom_map(data = dta.simd, aes(map_id = dz_label, 
                                    fill = as.factor(dta.simd$overall.quantiles)), 
               map = shps.dzs2001) +
      geom_path(data = shps.dzs2001, aes(x=long, y=lat, group=group), 
                colour="black", size=0.25)

The code returns the error

Error: 'x' and 'units' must have length > 0

If I understand similar discussions (1, 2), the problem is associated with the value classes. However, my understanding is that the as.factor() should address this but, evidently this is not the case. The full code for the app is included below. Naturally, I'll be grateful for any help.

Server

# Libs
require(shiny); require(SPARQL); require(ggplot2); require(rgeos); require(maptools);
require(RCurl)

# Server function
shinyServer(function(input, output) {

  # Source the data

  ## Source the SPARQL data
  ### Define endpoint URL.
  endpoint <- "http://data.opendatascotland.org/sparql.csv"

  ### Create Query and download table for the SIMD rank
  query.simd <- "PREFIX stats: <http://statistics.data.gov.uk/id/statistical-geography/>
      PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
      PREFIX simd: <http://data.opendatascotland.org/def/simd/>
      PREFIX cube: <http://purl.org/linked-data/cube#>
      PREFIX stats_dim: <http://data.opendatascotland.org/def/statistical-dimensions/>
      PREFIX year: <http://reference.data.gov.uk/id/year/>

      SELECT DISTINCT
      ?dz_label
      ?overall_rank
      ?income_deprivation_rank
      ?employment_deprivation_rank
      ?health_deprivation_rank
      ?education_deprivation_rank
      ?access_deprivation_rank
      ?housing_deprivation_rank
      ?crime_deprivation_rank

      WHERE {

      GRAPH <http://data.opendatascotland.org/graph/simd/rank> {
      ?overall_rank_observation stats_dim:refArea ?dz .
      ?overall_rank_observation stats_dim:refPeriod year:2012 .
      ?overall_rank_observation simd:rank ?overall_rank .
      }

      GRAPH <http://data.opendatascotland.org/graph/simd/income-rank> {
      ?income_rank_observation stats_dim:refArea ?dz .
      ?income_rank_observation stats_dim:refPeriod year:2012 .
      ?income_rank_observation simd:incomeRank ?income_deprivation_rank .
      }

      GRAPH <http://data.opendatascotland.org/graph/simd/employment-rank> {
      ?employment_rank_observation stats_dim:refArea ?dz .
      ?employment_rank_observation stats_dim:refPeriod year:2012 .
      ?employment_rank_observation simd:employmentRank ?employment_deprivation_rank .
      }

      GRAPH <http://data.opendatascotland.org/graph/simd/health-rank> {
      ?health_rank_observation stats_dim:refArea ?dz .
      ?health_rank_observation stats_dim:refPeriod year:2012 .
      ?health_rank_observation simd:healthRank ?health_deprivation_rank .
      }

      GRAPH <http://data.opendatascotland.org/graph/simd/education-rank> {
      ?education_rank_observation stats_dim:refArea ?dz .
      ?education_rank_observation stats_dim:refPeriod year:2012 .
      ?education_rank_observation simd:educationRank ?education_deprivation_rank .
      }

      GRAPH <http://data.opendatascotland.org/graph/simd/geographic-access-rank> {
      ?access_rank_observation stats_dim:refArea ?dz .
      ?access_rank_observation stats_dim:refPeriod year:2012 .
      ?access_rank_observation simd:geographicAccessRank ?access_deprivation_rank .
      }

      GRAPH <http://data.opendatascotland.org/graph/simd/housing-rank> {
      ?housing_rank_observation stats_dim:refArea ?dz .
      ?housing_rank_observation stats_dim:refPeriod year:2012 .
      ?housing_rank_observation simd:housingRank ?housing_deprivation_rank .
      }

      GRAPH <http://data.opendatascotland.org/graph/simd/crime-rank> {
      ?crime_rank_observation stats_dim:refArea ?dz .
      ?crime_rank_observation stats_dim:refPeriod year:2012 .
      ?crime_rank_observation simd:crimeRank ?crime_deprivation_rank .
      }

    {
      SELECT ?dz ?dz_label WHERE
    {
      ?dz a <http://data.opendatascotland.org/def/geography/DataZone> .
      ?dz rdfs:label ?dz_label .
    }
    }
  }"

  ## Make the data table for SIMD
  dta.simd <- SPARQL(url = endpoint, query = query.simd, format = "csv")$results
  ### Clean the data frame
  dta.simd$dz_label <- gsub("Data Zone","", dta.simd$dz_label)

  # Readings shapefiles (pass only file that ends with shp)
  shps.dzs2001 <- readShapeSpatial("data/SG_DataZone_Bdry_2001.shp")

  ## Read shapefiles
  shps.dzs2001 <- fortify(shps.dzs2001, region= "DZ_CODE")

  # Switch on the gclibpermit
  gpclibPermit()

  # Make the plot
  output$distPlot <- renderPlot({

    ### Get the column index fumber
    col.ind <- match(input$firstvar, colnames(dta.simd))


    #### Calculate the breaks 
    ##### Take tha quantilies value from the UI
    ##### Obtain the breaks
    dta.simd$column <- as.numeric(as.character(dta.simd[,col.ind]))
    dta.simd$overall.quantiles <- ceiling(sapply(dta.simd$column,function(x) 
      sum(x-dta.simd$column>=0))/(length(dta.simd$column)/input$quannum))

    #### Graph the chart
    ggplot() + 
      geom_map(data = dta.simd, aes(map_id = dz_label, 
                                    fill = as.factor(dta.simd$overall.quantiles)), 
               map = shps.dzs2001) +
      geom_path(data = shps.dzs2001, aes(x=long, y=lat, group=group), 
                colour="black", size=0.25)

    ### Re-calculate summary stats
    summary.data <- head(dta.simd)

  })
  ### Do the summary tables
  output$summary.table <- renderDataTable({summary.data})
})

UI

require(shiny)

# Define list of options
choices.list <- list("Overall Rank" = "overall_rank", 
                     "Income" = "income_deprivation_rank",
                     "Employment" = "employment_deprivation_rank",
                     "Health" = "health_deprivation_rank",
                     "Education" = "education_deprivation_rank",
                     "Access to Services" = "access_deprivation_rank",
                     "Housing" = "housing_deprivation_rank",
                     "Crime" = "crime_deprivation_rank"
                     )

# Define UI for application that draws a histogram
shinyUI(fluidPage(

  # Application title
  titlePanel("Scottish Index of Multiple Deprivation 2012"),

  # Sidebar with a slider input for the number of bins
  sidebarLayout(
    sidebarPanel(
      selectInput(inputId = "firstvar", 
                  label = "Index domain to map",
                  choices = choices.list, 
                  selected = "income_deprivation_rank"),
      sliderInput("quannum", label = "Number of quantiles", 
                  min = 0, 
                  max = 100, 
                  value = 10)),

    # Show a plot of the generated distribution
    mainPanel(
      plotOutput("distPlot", height = "700px"),
      dataTableOutput("summary.data"),
      h5("Notes"),
      p("The data is sourced live from the Open Data for Scotland Project. The shapefiles are sourced from the Scottish Neighbourhood Statistics.")
    )
  )
))

Answer

Arsl&#225;n picture Arslán · Mar 2, 2015
fill=factor(overall.quantiles)

I was facing a similar problem and was able to fix it this way.