【问题标题】:Convert json object to spatial lines data frame将 json 对象转换为空间线数据框
【发布时间】:2021-12-29 17:44:39
【问题描述】:

我从 EnergyData 下载了伊拉克电网的 geojson 文件。您可以自己下载文件here 并访问网页here

我尝试使用geojsonio::geojson_read 将文件读入R,但它抛出了错误。另一位用户热心地指出,Energy Data 网站提供的文件格式不正确,不符合 geojson 格式,因此文件名具有误导性。所以他们建议我使用jsonlite::read_json。虽然该函数确实将文件读入 R,但它不是空间对象。这是一个多级列表。我也试过sf::st_read,但对象是一个凌乱的数据框。我需要我的最终对象是一个空间线数据框,所以我可以将它与另一个空间线对象合并和裁剪,并写出生成的 shapefile。但是当我尝试sp::SpatialLinesDataFrame 时,我无法正确索引到对象以正确顺序连接线。我需要 R 中的对象看起来像网页上的图片,而不是一团糟。

这是我的代码:

library(geojsonio)
library(jsonlite)
library(sf)
library(sp)

Iraq_electric_json <- jsonlite::read_json("Filepath/electric-network-iraq.geojson")

Iraq_electric_df <- sf::st_read("Filepath/electric-network-iraq.geojson")

# ERRORS HERE
Sldf <- SpatialLinesDataFrame(data = Iraq_electric_df$geometry)

我在这里发布了我的问题的第一部分(如何读取 geojson 文件):

geojsonio::geojson_read error for a geojson file "conversion from feature type sfc_GEOMETRY to sp is not supported"

但由于问题的第 2 部分(更改对象格式)与第 1 部分有很大不同,我决定发布一个全新的问题。

【问题讨论】:

    标签: r json geospatial geojson shapefile


    【解决方案1】:

    这很长,因为解决方案主要是挖掘并弄清楚您希望如何使用此文件。这里有一些潜在的问题:

    • 就像我在您的第一篇文章中提到的那样,就 GeoJSON 文件的结构而言,该文件可能格式不正确。一些阅读方法会发出最后一行不完整的警告;结尾的空行是 json 文件中预期结构的一部分。
    • nodesinterconnection 属性是数组,我认为 R 函数不知道如何处理它们; sf 函数知道将这些读取为列表列,但对于 geojsonio 可能不可用。
    • 有多种几何类型。

    最后一点很重要,因为它会阻止您使用sp::Spatial* 类——这些仅适用于单一几何类型(SpatialGridSpatialPolygons 等)。该文件将点和线混合在一起,因此您需要像 sf 这样可以容纳混合几何类型的文件。

    我尝试阅读本文的几种方法,其中一些返回列表可以进一步挖掘,一些返回 sf 对象:

    library(dplyr)
    library(sf)
    
    path <- "https://development-data-hub-s3-public.s3.amazonaws.com/ddhfiles/145188/electric-network-iraq.geojson"
    
    # sf
    iraq1 <- st_read(path, drivers = "GeoJSON")
    #> options:        GeoJSON 
    #> Reading layer `electric-network-iraq' from data source 
    #>   `https://development-data-hub-s3-public.s3.amazonaws.com/ddhfiles/145188/electric-network-iraq.geojson' 
    #>   using driver `GeoJSON'
    #> Simple feature collection with 48 features and 6 fields
    #> Geometry type: GEOMETRY
    #> Dimension:     XY
    #> Bounding box:  xmin: 40.99849 ymin: 30.50785 xmax: 47.85893 ymax: 37.88342
    #> Geodetic CRS:  WGS 84
    
    # list
    iraq2 <- jsonlite::read_json(path)
    str(iraq2, max.level = 1)
    #> List of 2
    #>  $ type    : chr "FeatureCollection"
    #>  $ features:List of 48
    
    # list
    iraq3 <- readLines(path) %>%
      geojson::to_geojson() %>%
      jsonlite::fromJSON()
    #> Warning in readLines(path): incomplete final line found on 'https://development-
    #> data-hub-s3-public.s3.amazonaws.com/ddhfiles/145188/electric-network-
    #> iraq.geojson'
    #> Registered S3 method overwritten by 'geojsonlint':
    #>   method         from 
    #>   print.location dplyr
    
    # sf, same warning about incomplete final line
    iraq4 <- suppressWarnings(geojsonsf::geojson_sf(path))
    #> Registered S3 method overwritten by 'geojsonsf':
    #>   method        from   
    #>   print.geojson geojson
    

    我将继续使用第一个,一个具有混合几何类型的sf 对象(只是通用的GEOMETRY)。注意这里有些是线,有些是点,还有两列是字符串列表。

    head(iraq1)
    #> Simple feature collection with 6 features and 6 fields
    #> Geometry type: GEOMETRY
    #> Dimension:     XY
    #> Bounding box:  xmin: 41.12771 ymin: 36.34583 xmax: 43.12683 ymax: 37.88342
    #> Geodetic CRS:  WGS 84
    #>   transmissionPower lineType      name nodeType            nodes
    #> 1               400   single      <NA>     <NA>    Batman, Zakho
    #> 2                NA     <NA>     Zakho     city                 
    #> 3               400   single      <NA>     <NA> Mosul Dam, Zakho
    #> 4                NA     <NA> Mosul Dam      dam                 
    #> 5               400   double      <NA>     <NA> Mosul, Mosul Dam
    #> 6                NA     <NA>     Mosul     city                 
    #>   interconnection                       geometry
    #> 1   Syria, Turkey LINESTRING (41.12771 37.883...
    #> 2                      POINT (42.68304 37.14215)
    #> 3                 LINESTRING (42.68304 37.142...
    #> 4                      POINT (42.83355 36.62586)
    #> 5                 LINESTRING (42.83355 36.625...
    #> 6                      POINT (43.12683 36.34583)
    
    plot(iraq1["geometry"])
    

    如果您真的需要sp::Spatial 对象,则必须将点和线分开。我根据维数(点数为 0,线数为 1)拆分它们并写出现在可读的 GeoJSON 文件,然后将它们读回。最后你得到一个 SpatialPointsDataFrame 和一个 SpatialLinesDataFrame .您不必将它们写入文件;您可以将每个数据帧传递给 sf::as_Spatial 并获得相同的 sp 类。

    iraq1 %>%
      mutate(dimension = st_dimension(geometry)) %>%
      split(.$dimension) %>%
      purrr::iwalk(~geojsonio::geojson_write(.x, file = sprintf("iraq_repaired_dim%s.geojson", .y)))
    
    iraq_pts <- geojsonio::geojson_read("iraq_repaired_dim0.geojson", what = "sp")
    iraq_lines <- geojsonio::geojson_read("iraq_repaired_dim1.geojson", what = "sp")
    
    class(iraq_pts)
    #> [1] "SpatialPointsDataFrame"
    #> attr(,"package")
    #> [1] "sp"
    class(iraq_lines)
    #> [1] "SpatialLinesDataFrame"
    #> attr(,"package")
    #> [1] "sp"
    

    【讨论】:

      猜你喜欢
      • 2021-11-18
      • 2020-01-11
      • 2021-06-20
      • 2015-05-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多