Как идентифицировать все названия стран, упомянутые в строке, и разделить соответственно?

#r #maps #stringr

#r #Карты #stringr

Вопрос:

У меня есть строка, которая содержит названия стран и других регионов. Меня интересуют только названия стран, и в идеале я хотел бы добавить несколько столбцов, каждый из которых содержит название страны, указанное в строке. Вот примерный код для настройки фрейма данных lis:

 df <- data.frame(id = c(1,2,3),
                 country = c("Cote d'Ivoire Africa Developing Economies West Africa",
                              "South Africa United Kingdom Africa BRICS Countries",
                             "Myanmar Gambia Bangladesh Netherlands Africa Asia"))
  

Если я разделяю строку только пробелом, те страны, которые содержат пробел, теряются (например, «Соединенное Королевство»). Смотрите здесь:

 df2 <- separate(df, country, paste0("C",3:8), sep=" ") 
  

Поэтому я попытался найти названия стран, используя набор данных world.cities. Однако, кажется, что это перебирает строку только до тех пор, пока не появится название, не относящееся к стране. Смотрите здесь:

 library(maps)
library(stringr)
all_countries <- str_c(unique(world.cities$country.etc), collapse = "|")
df$c1 <- sapply(str_extract_all(df$country, all_countries), toString)
  

Мне интересно, можно ли использовать пробел в качестве разделителя, но определять исключения (например, «Соединенное Королевство»). Очевидно, что это может потребовать некоторой ручной работы, но для меня это наиболее приемлемое решение. Кто-нибудь знает, как определить такие исключения? Я, конечно, также открыт и благодарен за любые другие решения.

Обновить:

Я нашел другое решение, используя пакет countrycode:

 library(countrycode)
countries <- data.frame(countryname_dict)
countries$continent <- countrycode(sourcevar = countries[["country.name.en"]],
                                   origin = "country.name.en",
                                   destination = "continent")

africa <- countries[ which(countries$continent=='Africa'), ]

library(stringr)
pat <- paste0("\b", paste(africa$country.name.en , collapse="\b|\b"), "\b")
df$country_list <- str_extract_all(df$country, regex(pat, ignore_case = TRUE))
  

Комментарии:

1. Это возможно, но у вас может быть несколько таких стран

2. Привет, спасибо за быстрый ответ. Не могли бы вы указать, как это было бы возможно? Спасибо!

3. Зависит от того, есть ли у вас список названий стран с несколькими словами

4. Это выглядит как в примере в начале моего вопроса; например, «Южная Африка, Великобритания, страны Африки БРИКС»

5. О чем Cote d'Ivoire ? Это страна

Ответ №1:

Вы могли бы сделать:

 library(stringi)
vec <- stri_trans_general(countrycode::codelist$country.name.en, id = "Latin-ASCII")
stri_extract_all(df$country,regex = sprintf(r"(b(%s)b)",stri_c(vec,collapse = "|")))
[[1]]
[1] "Cote d'Ivoire"

[[2]]
[1] "South Africa"   "United Kingdom"

[[3]]
[1] "Gambia"      "Bangladesh"  "Netherlands"
  

Комментарии:

1. Большое спасибо. Это работает хорошо. Одно незначительное замечание. Отсутствует «=». Это должно быть: stri_extract_all(df$country,regex = sprintf(r="(b(%s)b)",stri_c(vec,collapse = "|")))

2. Я только что обнаружил одну проблему в вашем решении, которую мне не удалось исправить. В текстовых строках есть как Нигерия, так и Нигер, и все строки Нигерии заканчиваются как Нигер (похоже, извлекается первое возможное совпадение). Есть идеи, как это исправить?

3. @Lisa, вы добавили дополнительное = , ВЫ ДОЛЖНЫ СДЕЛАТЬ ТОЧНО ТАК, КАК УКАЗАНО ВЫШЕ. пропущенных нет = . Обратите внимание на это

4. Спасибо за ваш ответ @Onyambu, если я это сделаю, я получу следующее сообщение об ошибке в R: Ошибка: неожиданная строковая константа в «stri_extract_all(df $ country,regex = sprintf (r»( b (% s) b)»». Тем временем я нашел решение, используя пакет countrycode (см. Обновленный вопрос)

5. @Lisa, похоже, вы используете более старую версию R. Измените ее на sprintf('\b(%s)\b',.......) вместо. Точки означают поддерживать все остальное