【问题标题】:Create sf object from data frame with multiple coordinates | R sf从具有多个坐标的数据框创建 sf 对象 |顺丰
【发布时间】:2021-11-14 04:05:39
【问题描述】:

我想从一个数据框中创建一个 sf 对象,该数据框在每一行的不同列下包含多个坐标。在下面的 repex 中,每个 ID 都包含纬度和经度的开始和结束坐标。

dfr <- structure(list(ID = c("1001A", "1002A", "1003A", "1004A", "1005A", 
"1006A", "1007A", "1008A", "1009A", "1010A"), StartLat = c(33.53418, 
33.60399, 33.40693, 33.64672, 33.57127, 33.42848, 33.54936, 33.49554, 
33.5056, 33.61696), StartLong = c(-112.09114, -111.92731, -112.02982, 
-111.92548, -112.04899, -112.0998, -112.09123, -111.9687, -112.05629, 
-111.98657), EndLat = c(33.53488, 33.60401, 33.40687, 33.64776, 
33.57125, 33.42853, 33.54893, 33.49647, 33.5056, 33.61654), EndLong = c(-112.09114, 
-111.93097, -112.03429, -111.93031, -112.04807, -112.09929, -112.09122, 
-111.97105, -112.0541, -111.98657)), row.names = c(3028L, 8618L, 
6322L, 1171L, 691L, 6590L, 2008L, 4552L, 2894L, 1909L), class = "data.frame")

我尝试使用 sf 包的 st_as_sf 函数,但它会产生错误:

dfr_sf <- st_as_sf(dfr, coords = c(c("StartLong", "EndLong"), c("StartLat", "EndLat")),
                   crs = "+proj=longlat +datum=WGS84")
Error in points_rcpp(as.matrix(cc), dim) : 
  dim(pts)[2] == nchar(gdim) is not TRUE

每行的起点和终点坐标定义了一个路段。所有坐标都应位于最终 sf 对象中的几何列下方,以便将它们绘制为折线。

【问题讨论】:

    标签: r dataframe sf


    【解决方案1】:

    请使用 data.tablesf 库查找替代解决方案。我希望我没有错:这些线条出现在亚利桑那州。

    library(data.table)
    library(sf)
    library(dplyr)
    
    # Reshape the data.table 'dfr' into long format
    dfr2 <- melt(setDT(dfr), measure= patterns("Long", "Lat"), 
              value.name= c("Longitude", "Latitude"), na.rm=TRUE)[,variable:=NULL][]
    
    
    # function 'rename_geom_col' to rename the geometry column of the 'sf' object
    rename_geom_col <- function(x, new_name){
      current_name  <-  attr(x, "sf_column")
      names(x)[names(x)==current_name]  <- new_name
      st_geometry(x) <- new_name
      return(x)
    }
    
    # Convert the data.table 'dfr2' into the linestring 'sf' object 'results'
    results <- dfr2 %>% 
      split(., by = "ID", keep.by = FALSE) %>% 
      lapply(., as.matrix) %>% 
      lapply(.,st_linestring) %>%
      st_as_sfc() %>% 
      st_as_sf %>% 
      st_set_crs(4326) %>% 
      mutate(ID = dfr2[1:(nrow(dfr2)/2),"ID"]) %>% 
      relocate(x, .after = last_col()) %>% 
      rename_geom_col(., "geom")
    
    
    results
    #> Simple feature collection with 10 features and 1 field
    #> Geometry type: LINESTRING
    #> Dimension:     XY
    #> Bounding box:  xmin: -112.0998 ymin: 33.40687 xmax: -111.9255 ymax: 33.64776
    #> Geodetic CRS:  WGS 84
    #>       ID                           geom
    #> 1  1001A LINESTRING (-112.0911 33.53...
    #> 2  1002A LINESTRING (-111.9273 33.60...
    #> 3  1003A LINESTRING (-112.0298 33.40...
    #> 4  1004A LINESTRING (-111.9255 33.64...
    #> 5  1005A LINESTRING (-112.049 33.571...
    #> 6  1006A LINESTRING (-112.0998 33.42...
    #> 7  1007A LINESTRING (-112.0912 33.54...
    #> 8  1008A LINESTRING (-111.9687 33.49...
    #> 9  1009A LINESTRING (-112.0563 33.50...
    #> 10 1010A LINESTRING (-111.9866 33.61...
    

    reprex package (v2.0.1) 于 2021 年 11 月 16 日创建

    【讨论】:

      【解决方案2】:

      请查看dfr_line 是否是您想要的。我认为这个想法是我们需要先创建一个点 sf 对象,然后将其转换为线串。

      library(tidyverse)
      library(sf)
      
      dfr2 <- dfr %>%
        pivot_longer(-ID, names_to = c("Type", ".value"), names_pattern = "(^[A-Z][a-z]+)([A-Z][a-z]+$)")
      
      dfr_point <- dfr2 %>%
        st_as_sf(coords = c("Long", "Lat"), crs = "+proj=longlat +datum=WGS84")
      
      dfr_line <- dfr_point %>%
        group_by(ID) %>%
        summarize() %>%
        st_cast("LINESTRING")
      

      【讨论】:

      • 不值得我发布一个全新的答案,但tidyr::pivot_longer(-ID, names_to = c("endpoint", ".value"), names_pattern = "(^[A-Z][a-z]+)([A-Z][a-z]+$)") 可以代替您的pivot_longer - extract - pivot_wider 序列。你也不需要select 调用,因为当你总结时该列应该被删除
      • @camille 谢谢你的建议。我已经更新了我的答案。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-02-01
      • 2015-04-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多