将经度和纬度与 R 中的国家/地区匹配

Posted

技术标签:

【中文标题】将经度和纬度与 R 中的国家/地区匹配【英文标题】:Match Longitude and Latitude with countries in R 【发布时间】:2021-06-17 20:39:53 【问题描述】:

我想找到对应于两组不同坐标的国家。我的数据是这样设置的

lat_1 lon_1 lat_2 lon_2
40.71 74.00 51.50 0.127
37.77 122.4 48.85 2.352

我希望将结果存储在两个新列中。因此,对于第一行,一列会说美国,另一列会说英格兰。我曾尝试使用将坐标转换为国家/地区的函数,但是我必须一次将该函数应用于一组,我不确定它们是否匹配。同样使用该功能,它不会将其添加为额外的列。

到目前为止,我列出了以下内容。

library(sp)
library(rworldmap)
library(dplyr)


coords2country = function(points)
  
  countriesSP <- getMap(resolution='low')

  pointsSP = SpatialPoints(points, proj4string=CRS(proj4string(countriesSP)))  


  indices = over(pointsSP, countriesSP)


  indices$ADMIN  



 df <-read.csv("the_file",header=T, na.strings=c("","NA"))

 coords2country(df)

当我这样做时,我得到了我上面描述的,而不是我正在寻找的。​​p>

【问题讨论】:

如果您对基于 Shiny 的解决方案感兴趣,此软件包中包含的 Shiny 应用程序将满足您的需求:github.com/giocomai/latlon2map/这里是托管版本:latlon2map.europeandatajournalism.eu(抱歉,一次一组,但没有理由不匹配) @giocomai 谢谢你的建议。你能告诉我如何加载我的两组坐标吗? 【参考方案1】:

因此,这里是使用最新的 sf 包作为基础的完整代码,可以实现您正在寻找的内容。更多解释请参见代码中包含的 cmets。


coords_df <- tibble::tribble(
  ~lat_1, ~lon_1, ~lat_2, ~lon_2,
   40.71,     74,   51.5,  0.127,
   37.77,  122.4,  48.85,  2.352
  ) %>% 
  dplyr::mutate(id = dplyr::row_number()) # create id column for each observation to ensure matching


# transform coordinates into a geo object (here, an sf object)
coords_sf <- coords_df %>% 
  tidyr::pivot_longer(cols = 1:4,
                      names_to = "coord_type",
                      values_to = "coord_data") %>% 
  tidyr::separate(col = coord_type, into = c("coord_type", "set"), sep = "_") %>% 
  tidyr::pivot_wider(names_from = coord_type, values_from = coord_data) %>% 
  sf::st_as_sf(coords = c("lon", "lat"), crs = 4326)

coords_sf
#> Simple feature collection with 4 features and 2 fields
#> Geometry type: POINT
#> Dimension:     XY
#> Bounding box:  xmin: 0.127 ymin: 37.77 xmax: 122.4 ymax: 51.5
#> Geodetic CRS:  WGS 84
#> # A tibble: 4 x 3
#>      id set        geometry
#> * <int> <chr>   <POINT [°]>
#> 1     1 1        (74 40.71)
#> 2     1 2      (0.127 51.5)
#> 3     2 1     (122.4 37.77)
#> 4     2 2     (2.352 48.85)

# get low resolution world map
world <- rnaturalearth::ne_countries(returnclass = "sf") %>%
  dplyr::select(name) %>% # keep only country name
  sf::st_transform(crs = 4326) %>%
  st_make_valid() # useful as of 1.0 `sf` update, see https://github.com/r-spatial/sf/issues/1649


# join columns, if you want a country only if the point is within its borders
within_sf <- sf::st_join(x = coords_sf, 
            y = world,
            join = sf::st_within)

within_sf
#> Simple feature collection with 4 features and 3 fields
#> Geometry type: POINT
#> Dimension:     XY
#> Bounding box:  xmin: 0.127 ymin: 37.77 xmax: 122.4 ymax: 51.5
#> Geodetic CRS:  WGS 84
#> # A tibble: 4 x 4
#>      id set        geometry name          
#> * <int> <chr>   <POINT [°]> <chr>         
#> 1     1 1        (74 40.71) Kyrgyzstan    
#> 2     1 2      (0.127 51.5) United Kingdom
#> 3     2 1     (122.4 37.77) <NA>          
#> 4     2 2     (2.352 48.85) France

# join columns, if you want the country closest to the point
# (even if the point is not within the border of any country)
nearest_sf <- sf::st_join(x = coords_sf, 
            y = world,
            join = sf::st_nearest_feature)

nearest_sf
#> Simple feature collection with 4 features and 3 fields
#> Geometry type: POINT
#> Dimension:     XY
#> Bounding box:  xmin: 0.127 ymin: 37.77 xmax: 122.4 ymax: 51.5
#> Geodetic CRS:  WGS 84
#> # A tibble: 4 x 4
#>      id set        geometry name          
#> * <int> <chr>   <POINT [°]> <chr>         
#> 1     1 1        (74 40.71) Kyrgyzstan    
#> 2     1 2      (0.127 51.5) United Kingdom
#> 3     2 1     (122.4 37.77) China         
#> 4     2 2     (2.352 48.85) France

# now you have a country for each point.
# time to go back to your original format


# again a data frame, not any more an sf object
nearest_df <- dplyr::bind_cols(nearest_sf %>%
                                 sf::st_drop_geometry(),
                               nearest_sf %>% 
                                 sf::st_coordinates() %>% 
                                 tibble::as_tibble() %>% 
                                 dplyr::rename(lon = X, lat = Y)) 

nearest_df
#> # A tibble: 4 x 5
#>      id set   name               lon   lat
#>   <int> <chr> <chr>            <dbl> <dbl>
#> 1     1 1     Kyrgyzstan      74      40.7
#> 2     1 2     United Kingdom   0.127  51.5
#> 3     2 1     China          122.     37.8
#> 4     2 2     France           2.35   48.8

output_df <- dplyr::bind_cols(nearest_df %>% 
                   dplyr::filter(set == 1) %>% 
                   dplyr::transmute(lat_1 = lat, lon_1 = lon, name_1 = name),
                 nearest_df %>% 
                   dplyr::filter(set == 2) %>% 
                   dplyr::transmute(lat_2 = lat, lon_2 = lon, name_2 = name))


output_df
#> # A tibble: 2 x 6
#>   lat_1 lon_1 name_1     lat_2 lon_2 name_2        
#>   <dbl> <dbl> <chr>      <dbl> <dbl> <chr>         
#> 1  40.7   74  Kyrgyzstan  51.5 0.127 United Kingdom
#> 2  37.8  122. China       48.8 2.35  France

由reprex package (v2.0.0) 于 2021-06-18 创建

作为参考,我还将在此处留下一个基于闪亮解决方案的链接: https::github.com/giocomai/latlon2map / 如果您想快速浏览,这里有一个托管版本:latlon2map.europeandatajournalism.eu。有了这个,您可以加载您的 csv,选择您的第一组 lat lon,下载表格,使用另一组再次执行此操作,然后将结果合并到 R 或其他地方。

以上部分代码改编自同一个包的ll_match()函数。

【讨论】:

我喜欢包含最近的功能。我认为用领海代替最近的特征会更好(但我知道这不是这里的主要话题)。您到 github 存储库的链接也已损坏。 谢谢,链接已修复。是的,人们可能会用 st_buffers 近似领海,并且对于其中的任何内容都有一个剩余类别(或 NA),但这完全超出了所提出的问题。

以上是关于将经度和纬度与 R 中的国家/地区匹配的主要内容,如果未能解决你的问题,请参考以下文章

如何快速识别点(纬度和经度)是不是在一个国家/地区内?

在谷歌地图 api v3 中将地区、城市、州、国家/地区转换为纬度和经度?

如何使用pygeoip从国家、地区代码获取纬度、经度

给定经度和纬度,如何找到国家

在一个国家/地区生成随机纬度/经度多边形?

如何从android中的纬度和经度获取3位国家代码[重复]