如何用R的tidyverse将数据集中两列国家缩写替换为全称?
问题描述
需借助R的tidyverse工具,将数据集df2中的MA Nation和PR Nation两列国家缩写,对照主数据集df1的国家列表替换为完整国名。使用ifelse语句尝试后得到异常结果,求可行解决方案。
数据集
# 对照字典df1 df1 <- structure(list(CountryCode = c("BF", "BG", "BM", "BR", "CA", "CE", "CH", "GH", "GM", "HA", "IC", "IN", "IR", "IT", "IZ", "JO", "KE", "KS", "LE", "MX", "NI", "NL", "NP", "PK", "QA", "SA", "SF", "SP", "TC", "TD", "TU", "TW", "UK", "US", "VM", "JA", "EI"), CountryName = c("BAHAMAS, THE", "BANGLADESH", "MYANMAR", "BRAZIL", "CANADA", "SRI LANKA", "CHINA", "GHANA", "GERMANY", "HAITI", "ICELAND", "INDIA", "IRAN", "ITALY", "SYRIA", "JORDAN", "KENYA", "KOREA, REPUBLIC OF (SOUTH )", "LEBANON", "MEXICO", "NIGERIA", "NETHERLANDS, THE", "NEPAL", "PAKISTAN", "QATAR", "SAUDI ARABIA", "SOUTH AFRICA", "SPAIN", "UNITED ARAB EMIRATES", "TRINIDAD AND TOBAGO", "TURKEY", "CHINA (TAIWAN)", "UNITED KINGDOM", "UNITED STATES", "VIETNAM", "JAPAN", "IRELAND")), row.names = c(NA, -37L), class = c("tbl_df", "tbl", "data.frame")) # 待处理数据集df2(已去除NA行) df2 <- structure(list(ID = c("E23531197", "Q07441087", "U79148472", "Y43292349", "A40257720", "Y64624318", "B97628594", "T06694322", "J67643839", "B11219391", "V72937405", "C22564030", "B90485180", "B56635832", "J44870077", "Y05510846", "X82045887", "V14380989", "J87108024", "X61041595", "A60573885", "Y23860927", "T74687928", "G60127163", "P45475749", "D40096957", "F73581752", "M76164536", "X57076671", "K30511805", "B41693626", "E50532024", "H47908538" ), `MA Nation` = c(NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, "IN", NA, NA, "CA", NA, NA, NA, NA), `PR Nation` = c("PK", "BG", "MX", "PK", "IN", "CH", "JA", "EI", "UK", "CH", "UK", "IN", "TU", "BG", "IN", "CA", "CA", "PK", "CH", "BG", "LE", "IN", "IN", "TW", "BG", "IN", "CH", "BG", "CA", "BF", "CH", "CH", "CH")), class = c("tbl_df", "tbl", "data.frame"), row.names = c(NA, -33L))
可行解决方案
方法1:left_join结合数据重塑(推荐)
适合多列匹配场景,代码简洁易维护,避免重复逻辑:
library(tidyverse) # 将df2转为长格式,统一处理匹配逻辑 df2_long <- df2 %>% pivot_longer( cols = c(`MA Nation`, `PR Nation`), names_to = "nation_type", values_to = "country_code" ) # 匹配完整国名后转回宽格式 df2_updated <- df2_long %>% left_join(df1, by = c("country_code" = "CountryCode")) %>% pivot_wider( id_cols = ID, names_from = nation_type, values_from = c(country_code, CountryName), names_sep = "_" ) %>% # 重命名列以贴合原数据结构 rename( `MA Nation` = country_code_MA Nation, `MA Nation Full` = CountryName_MA Nation, `PR Nation` = country_code_PR Nation, `PR Nation Full` = CountryName_PR Nation ) # 查看处理结果 head(df2_updated)
方法2:直接用命名向量替换(适合少量列场景)
借助deframe将df1转为缩写-国名的命名向量,直接在原数据上替换:
library(tidyverse) # 从df1生成缩写对应国名的命名向量 country_map <- deframe(df1) # 为原数据添加完整国名列 df2_updated <- df2 %>% mutate( `MA Nation Full` = country_map[`MA Nation`], `PR Nation Full` = country_map[`PR Nation`] ) # 查看结果 head(df2_updated)
为什么ifelse会失效?
ifelse仅适用于单条件或极少量条件判断,当需要匹配30+个国家缩写时,手动嵌套ifelse会出现以下问题:
- 代码冗余繁琐,极易出现拼写错误或漏写条件
- 对NA值的处理逻辑容易出错
- 可读性极差,后期难以维护
因此不推荐用ifelse完成这类批量匹配任务。
内容的提问来源于stack exchange,提问作者asokol
相关产品推荐
相关产品推荐

