จะระบุชื่อประเทศทั้งหมดที่กล่าวถึงในสตริงและแยกตามได้อย่างไร

ฉันมีสตริงที่มีชื่อประเทศและภูมิภาคอื่นๆ ฉันสนใจเฉพาะชื่อประเทศ และต้องการเพิ่มหลายคอลัมน์ โดยแต่ละคอลัมน์มีชื่อประเทศที่แสดงอยู่ในสตริง นี่คือโค้ดตัวอย่างสำหรับวิธีการตั้งค่า dataframe 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.citys อย่างไรก็ตาม ดูเหมือนว่าจะวนซ้ำผ่านสตริงจนกว่าจะไม่มีชื่อประเทศ ดูที่นี่:

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)

ฉันสงสัยว่าเป็นไปได้หรือไม่ที่จะใช้ช่องว่างเป็นตัวคั่น แต่กำหนดข้อยกเว้น (เช่นสหราชอาณาจักร) เห็นได้ชัดว่าอาจต้องอาศัยการทำงานด้วยตนเอง แต่ดูเหมือนจะเป็นวิธีแก้ปัญหาที่เป็นไปได้มากที่สุดสำหรับฉัน ไม่มีใครรู้วิธีกำหนดข้อยกเว้นดังกล่าวหรือไม่ แน่นอนว่าฉันยังเปิดกว้างและขอบคุณสำหรับวิธีแก้ปัญหาอื่น ๆ

อัปเดต:

ฉันพบวิธีแก้ปัญหาอื่นโดยใช้แพ็คเกจรหัสประเทศ:

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))

person Lisa    schedule 20.11.2020    source แหล่งที่มา
comment
เป็นไปได้ แต่คุณอาจมีหลายประเทศเช่นนั้น   -  person akrun    schedule 21.11.2020
comment
เฮ้ ขอบคุณสำหรับการตอบกลับอย่างรวดเร็ว คุณช่วยระบุได้ไหมว่าจะเป็นไปได้อย่างไร? ขอบคุณ!   -  person Lisa    schedule 21.11.2020
comment
ขึ้นอยู่กับว่าคุณมีรายชื่อประเทศที่มีหลายคำหรือไม่   -  person akrun    schedule 21.11.2020
comment
ดูเหมือนว่าในตัวอย่างในตอนต้นของคำถามของฉัน เช่น. แอฟริกาใต้ สหราชอาณาจักร แอฟริกา กลุ่มประเทศ BRICS   -  person Lisa    schedule 21.11.2020
comment
แล้วCote d'Ivoireล่ะ? มันเป็นประเทศ.   -  person akrun    schedule 21.11.2020
comment
@akrun ใช่ Cote d'Ivoire เป็นประเทศในแอฟริกา แอฟริกาตะวันตกให้ชัดเจน   -  person Onyambu    schedule 21.11.2020


คำตอบ (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"
person Onyambu    schedule 20.11.2020
comment
ขอบคุณมาก. มันใช้งานได้ดี หมายเหตุเล็กน้อยประการหนึ่ง มี=ขาด. จะต้องเป็น: stri_extract_all(df$country,regex = sprintf(r="(\b(%s)\b)",stri_c(vec,collapse = "|"))) - person Lisa; 21.11.2020
comment
ฉันเพิ่งค้นพบปัญหาหนึ่งในโซลูชันของคุณซึ่งฉันไม่สามารถแก้ไขได้ มีทั้งไนจีเรียและไนเจอร์ในสตริงข้อความ และสตริงไนจีเรียทั้งหมดลงเอยด้วยไนเจอร์ (ดูเหมือนว่าการจับคู่รายการแรกที่เป็นไปได้จะถูกแยกออกมา) มีแนวคิดใดบ้างที่จะแก้ไขปัญหานี้ - person Lisa; 23.11.2020
comment
@Lisa คุณเพิ่ม = พิเศษที่คุณควรทำตามที่โพสต์ไว้ข้างต้น ไม่มีขาด = จดบันทึกสิ่งนั้น - person Onyambu; 23.11.2020
comment
ขอบคุณสำหรับการตอบกลับของคุณ @Onyambu ถ้าฉันทำเช่นนั้น ฉันได้รับข้อความแสดงข้อผิดพลาดต่อไปนี้ใน R: Error: สตริงคงที่ที่ไม่คาดคิดใน stri_extract_all(df$country,regex = sprintf(r(\b(%s)\b).Mean While ฉันพบวิธีแก้ปัญหาโดยใช้แพ็คเกจรหัสประเทศ (ดูคำถามที่อัปเดต) - person Lisa; 23.11.2020
comment
@Lisa ดูเหมือนว่าคุณกำลังใช้ R เวอร์ชันเก่ากว่า เปลี่ยนเป็น sprintf('\\b(%s)\\b',.......) แทน จุดหมายถึงการบำรุงรักษาสิ่งอื่นๆ - person Onyambu; 23.11.2020
comment
ขอบคุณมาก! - person Lisa; 23.11.2020