R tmap sf Ошибка: аргументы подразумевают различное количество строк при просмотре карты - PullRequest
0 голосов
/ 15 февраля 2020

Я пытаюсь создать карту всех школьных округов в каждом штате. Приведенный ниже код работает для всех штатов, кроме Флориды. Я получаю эту ошибку: Ошибка в data.frame (..., check.names = FALSE): аргументы подразумевают различное количество строк: 67, 121

require(dplyr)
require(sf)
library(tmap)
require(lwgeom)


  temp <- tempfile()  ### create a temporary file to download zip file to
  temp2 <- tempfile() ### create a temporary file to put unzipped files in
  download.file("https://s3.amazonaws.com/data.edbuild.org/public/Processed+Data/SD+shapes/2018/shapefile_1718.zip", temp) # downloading the data into the tempfile

  unzip(zipfile = temp, exdir = temp2) # unzipping the temp file and putting unzipped data in temp2

  filename <- list.files(temp2, full.names = TRUE) # getting the filename of the downloaded data

  shp_file <- filename %>%
    subset(grepl("*.shp$", filename)) ## selecting only the .shp file to read in 

  state_shape <- sf::st_read(shp_file) %>% ## reading in the downloaded data
    dplyr::mutate(GEOID = as.character(GEOID),
                  GEOID = stringr::str_pad(GEOID, width = 7, pad = "0")) %>% 
    filter(State == "Florida")

  url = "https://s3.amazonaws.com/data.edbuild.org/public/Processed+Data/Master/2017/full_data_17_geo_exc.csv"
  master <- read.csv(file = url, stringsAsFactors = FALSE) %>%
    dplyr::mutate(NCESID = as.character(NCESID),
                  NCESID = stringr::str_pad(NCESID, width = 7, pad = "0"),
                  year = "2017") %>%
    dplyr::select(-NAME, -State, -STATE_FIPS) ## removing variables that duplicate with shapes

  state_shape <- state_shape %>%
    dplyr::left_join(master, by = c("GEOID" = "NCESID")) %>% 
    select(GEOID, NAME, State, StPovRate)

  shape.clean <- lwgeom::st_make_valid(state_shape) # making all geometries valid

  povertyBlues <-  c('#dff3fe', '#92DCF0', '#49B4D6', '#2586a5', '#19596d')

  map <- tm_shape(shape.clean) + 
    tm_fill("StPovRate", breaks=c(0, .1, .2, .3, .4, 1), title = "Student Poverty",
            palette = povertyBlues, 
            legend.format=list(fun=function(x) paste0(formatC(x*100, digits=0, format="f"), " %"))) +
    tm_shape(shape.clean) +
    tm_borders(lwd=.25, col = "#e9e9e9", alpha = 1) +
    tm_layout(inner.margins = c(.05,.25,.1,.05)) 

  map  ### view the map

Длина tm_shape $ shp и state_shape равняется 67. Кто-нибудь знает, что может быть причиной «аргументов, подразумевающих различное количество строк: 67, 121»?

Спасибо !!

Ответы [ 2 ]

0 голосов
/ 29 апреля 2020

У меня только что была похожая проблема, и мне удалось ее устранить с помощью описанного здесь трюка https://www.r-spatial.org/r/2017/03/19/invalid.html

, а именно применения буфера 0.0 к недопустимым фигурам

p[which(st_is_valid(p)== FALSE),]= st_buffer(p[which(st_is_valid(p)== FALSE),], 0.0)

где p - рассматриваемый слой. Надеюсь, это поможет.

0 голосов
/ 19 февраля 2020

Мне не удалось заставить эти фигуры печатать с использованием tmap, но я смог вручную удалить проблемные точки и линии, чтобы они не вызывали ошибок в tmap. И во Флориде, и в штате Небраска были геометрические коллекции, поэтому я использовал следующий скрипт, чтобы удалить любые линии или точки и изменить геометрические коллекции на мультиполигоны. Я уверен, что есть лучший способ, и был бы рад услышать их, если у других есть более изящное решение. Это, по крайней мере, позволяет мне двигаться дальше!

### Create an st_is function that works for many types
st_is = function(x, type) UseMethod("st_is")

st_is.sf = function(x, type)
  st_is(st_geometry(x), type)

st_is.sfc = function(x, type)
  vapply(x, sf:::st_is.sfg, type, FUN.VALUE = logical(1))

st_is.sfg = function(x, type)
  class(x)[2L] %in% type

####### Correct Florida #########

#### import my florida file
  temp <- tempfile()  ### create a temporary file to download zip file to
  temp2 <- tempfile() ### create a temporary file to put unzipped files in
  download.file("https://s3.amazonaws.com/data.edbuild.org/public/Processed+Data/SD+shapes/2018/shapefile_1718.zip", temp) # downloading the data into the tempfile

  unzip(zipfile = temp, exdir = temp2) # unzipping the temp file and putting unzipped data in temp2

  filename <- list.files(temp2, full.names = TRUE) # getting the filename of the downloaded data

  shp_file <- filename %>%
    subset(grepl("*.shp$", filename)) ## selecting only the .shp file to read in 

  florida <- sf::st_read(shp_file) %>% ## reading in the downloaded data
    filter(State == "Florida")

#### extract polygon shapes from any geometry collection
solution <- for (i in florida) {
  for(j in seq_along(i)) {
    if (class(i[[j]]) != "character" & class(i[[j]]) != "double" & class(i[[j]]) != "numeric") {
      if (st_is.sf(i[[j]], c("GEOMETRYCOLLECTION"))) {
        i[[j]] <- st_collection_extract(i[[j]], type = c("POLYGON"))
      }
      else {
        next
      }
    }
    else {
      next
    }
  }
}

florida_clean <- florida
st_geometry(florida_clean) <- NULL #### remove geometry from original florida
sfc_geo <- sf::st_sfc(i)  #### define i as an sfc
florida_clean$geometry <- sfc_geo  #### attach i to florida
florida_clean <- sf::st_set_geometry( florida_clean, sfc_geo )  ### set florida's geometry as i, with the points and lines removed 
...