У меня есть набор данных, который содержит сокращения стран на основе кодов ISO-3, а также некоторые их значения.
library(dplyr)
# Create a dataframe with ISO-3 codes and random values
iso3 <- c("USA", "CAN", "GBR", "FRA", "GER")
random_values <- runif (5, min = 1, max = 100) # Generating random values between 1 and 100
# Combine ISO-3 codes and random values into a dataframe
country_data <- data.frame(ISO_3 = iso3, Random_Values = random_values)
Но теперь передо мной стоит новый вызов. Эта задача состоит в том, что я хочу сначала выбрать конкретную страну, а затем найти соседние с ней страны.
Может ли кто-нибудь помочь мне найти соседние страны уже выбранной страны?
@Edward Есть ли для этого какая-нибудь библиотека?





По предоставленным вами данным сделать это невозможно. Однако GeoDataSource предоставляет эти данные бесплатно со своей страницы «Загрузка» (прокрутите вниз до самого низа до «Границы страны»).
Вы можете легко прочитать эти данные в R, используя read.csv.
data <- read.csv("GEODATASOURCE-COUNTRY-BORDERS.CSV")
head(data)
country_code country_name country_border_code country_border_name
1 AD Andorra FR France
2 AD Andorra ES Spain
3 AE United Arab Emirates OM Oman
4 AE United Arab Emirates SA Saudi Arabia
5 AF Afghanistan CN China
6 AF Afghanistan IR Iran (Islamic Republic of)
Данные содержат только двухзначные коды ISO. Если вам нужны трехзначные коды ISO, вы можете связать эти данные с набором данных ISO_3166_1, предоставляемым пакетом ISOcodes.
library(ISOcodes)
data(ISO_3166_1)
head(ISO_3166_1)
Alpha_2 Alpha_3 Numeric Name Official_name Common_name
1 AW ABW 533 Aruba <NA> <NA>
2 AF AFG 004 Afghanistan Islamic Republic of Afghanistan <NA>
3 AO AGO 024 Angola Republic of Angola <NA>
4 AI AIA 660 Anguilla <NA> <NA>
5 AX ALA 248 Åland Islands <NA> <NA>
6 AL ALB 008 Albania Republic of Albania <NA>
library(dplyr)
data <- inner_join(data, select(ISO_3166_1, Alpha_2, Alpha_3),
by=c("country_code" = "Alpha_2"))
head(data)
country_code country_name country_border_code country_border_name Alpha_3
1 AD Andorra FR France AND
2 AD Andorra ES Spain AND
3 AE United Arab Emirates OM Oman ARE
4 AE United Arab Emirates SA Saudi Arabia ARE
5 AF Afghanistan CN China AFG
6 AF Afghanistan IR Iran (Islamic Republic of) AFG
Чтобы увидеть, в какой стране больше всего границ:
count(data, Alpha_3) |> slice_max(n)
Alpha_3 n
1 CHN 16
Выберите любую конкретную страну и покажите, какие страны являются ее соседями.
filter(data, Alpha_3= = "CHN")
country_code country_name country_border_code country_border_name Alpha_3
1 CN China AF Afghanistan CHN
2 CN China BT Bhutan CHN
3 CN China HK Hong Kong CHN
4 CN China IN India CHN
5 CN China KZ Kazakhstan CHN
6 CN China KP Korea (Democratic People's Republic of) CHN
7 CN China KG Kyrgyzstan CHN
8 CN China LA Lao People's Democratic Republic CHN
9 CN China MO Macao CHN
10 CN China MN Mongolia CHN
11 CN China MM Myanmar CHN
12 CN China NP Nepal CHN
13 CN China PK Pakistan CHN
14 CN China RU Russian Federation CHN
15 CN China TJ Tajikistan CHN
16 CN China VN Viet Nam CHN
Просто ради интереса вы можете построить это, используя различные пакеты R:
library("sf")
library("ggplot2")
library("rnaturalearth")
library("rnaturalearthdata")
world <- ne_countries(scale = "medium", returnclass = "sf")
China <- filter(data, Alpha_3= = "CHN") |>
mutate(country_border_name=case_when( # Fix some inconsistencies
country_border_name= = "Russian Federation"~"Russia",
country_border_name= = "Korea (Democratic People's Republic of)"~"North Korea",
country_border_name= = "Lao People's Democratic Republic"~"Laos",
country_border_name= = "Viet Nam"~"Vietnam",
TRUE~country_border_name))
China_map <- world %>%
mutate(value = factor(case_when(admin %in% "China"~"China",
admin %in% China$country_border_name~"Neighbour",
TRUE~"Other")))
ggplot(data = China_map) +
geom_sf(aes(fill=value)) +
labs(fill = "")
Таким образом, Лаос и Вьетнам не являются соседями Китая. Хорошо знать...
@MrUpsidown На самом деле, они есть в списке, как показано в выводе R, но не видны на карте, которую я быстро создал, из-за несоответствия их имен в двух наборах данных. Я отредактирую свой ответ. Спасибо, что взяли это на вооружение. ;)
Это действительно выглядит лучше!
Это довольно просто, если у вас есть набор пространственных данных: просто убедитесь, что вы имеете дело с простыми объектами объектов из {sf} и используйте, например. st_touches() чтобы определить функции (здесь: страны), которые совместно используют узлы с интересующей вас страной:
library(sf)
#> Linking to GEOS 3.12.1, GDAL 3.8.4, PROJ 9.3.1; sf_use_s2() is TRUE
library(rnaturalearth)
# get some admin data
world <- ne_countries(scale = "medium", returnclass = "sf") |>
dplyr::select(admin, adm0_a3)
# select a single country
country <- dplyr::filter(world, adm0_a3 == "DEU")
# identify adjacent countries
ind <- st_touches(country, world)
ind
#> Sparse geometry binary predicate list of length 1, where the predicate
#> was `touches'
#> 1: 48, 80, 97, 120, 161, 184, 185, 218, 225
# subset dataset by index of interest
neighbours <- world[unlist(ind), ]
neighbours
#> Simple feature collection with 9 features and 2 fields
#> Geometry type: MULTIPOLYGON
#> Dimension: XY
#> Bounding box: xmin: -68.37109 ymin: -21.36904 xmax: 55.83906 ymax: 57.73691
#> Geodetic CRS: WGS 84
#> admin adm0_a3 geometry
#> 48 Switzerland CHE MULTIPOLYGON (((9.524023 47...
#> 80 Poland POL MULTIPOLYGON (((23.60527 51...
#> 97 Netherlands NLD MULTIPOLYGON (((5.993945 50...
#> 120 Luxembourg LUX MULTIPOLYGON (((6.116504 50...
#> 161 France FRA MULTIPOLYGON (((9.480371 42...
#> 184 Denmark DNK MULTIPOLYGON (((12.56875 55...
#> 185 Czechia CZE MULTIPOLYGON (((18.83223 49...
#> 218 Belgium BEL MULTIPOLYGON (((4.226172 51...
#> 225 Austria AUT MULTIPOLYGON (((9.527539 47...
В случае отсутствия кодов ISO-3 вы сможете без особых усилий соединить их из другого набора данных, используя {dplyr}.
С текущими данными, которые у вас есть (country_data), вы ничего не сможете сделать. И какое отношение к этому имеют случайные_значения? Этот репозиторий GitHub: github.com/geodatasource/country-borders содержит данные по всем странам и их соседям, если это вам поможет.