如何将数据框中两个向量的括号内国家码拆分至新列
嘿,这个需求我刚好碰过类似的,咱们一步步来搞定它~
首先,你提到的dplyr::separate其实更适合有固定分隔符(比如逗号、空格)的场景,而你的情况是要匹配末尾带括号的国家码,用正则匹配类的工具会更灵活,比如tidyr::extract或者stringr系列函数,能轻松处理“有的条目有国家码、有的没有”“括号前可能有空格”这类情况。
先给你搭个示例数据集,方便对照理解:
library(dplyr) library(tidyr) library(stringr) # 模拟你的数据:有的条目带国家码,有的不带 df <- tibble( Athlete = c("Usain Bolt (JAM)", "Simone Biles", "Michael Phelps (USA)"), Nationality = c("Jamaica (JAM)", "United States", "United States of America (USA)") )
方法1:用tidyr::extract一键拆分+提取
这个函数可以通过正则表达式,把原字段拆分成“清理后的内容”和“国家码”两部分,非常适合你的需求:
# 先处理单个字段的示例 df_processed <- df %>% # 处理Athlete字段:拆分成清理后的运动员名和国家码 extract(Athlete, into = c("Athlete_clean", "cc_athlete"), regex = "^(.*?)\\s*\\(([A-Z]+)\\)$", # 正则匹配末尾的(XX) remove = FALSE, # 保留原Athlete字段方便对比 fill = "right") %>% # 没有国家码的条目填充NA # 再处理Nationality字段 extract(Nationality, into = c("Nationality_clean", "cc_nationality"), regex = "^(.*?)\\s*\\(([A-Z]+)\\)$", remove = FALSE, fill = "right") %>% # 合并两个来源的国家码(优先取非NA的那个) mutate(countrycode = coalesce(cc_athlete, cc_nationality)) %>% # 保留需要的字段 select(Athlete_clean, Nationality_clean, countrycode)
方法2:用stringr分步处理(更直观,适合新手)
如果觉得正则有点绕,可以用stringr的函数分步提取和清理,逻辑更清晰:
df_processed <- df %>% mutate( # 提取Athlete里的国家码,同时去掉括号 cc_athlete = str_extract(Athlete, "\\(([A-Z]+)\\)$") %>% str_remove_all("[()]"), # 清理Athlete字段:去掉末尾的(XX)部分 Athlete_clean = str_remove(Athlete, "\\s*\\([A-Z]+\\)$"), # 对Nationality做同样操作 cc_nationality = str_extract(Nationality, "\\(([A-Z]+)\\)$") %>% str_remove_all("[()]"), Nationality_clean = str_remove(Nationality, "\\s*\\([A-Z]+\\)$"), # 合并国家码 countrycode = coalesce(cc_athlete, cc_nationality) ) %>% select(Athlete_clean, Nationality_clean, countrycode)
关键细节解释
- 正则
\\s*\\(([A-Z]+)\\)$:\\s*:匹配0个或多个空格(兼容括号前有空格或没空格的情况)([A-Z]+):捕获大写字母组成的国家码(这部分就是我们要的内容)$:确保匹配的是字符串末尾的括号,避免误匹配中间的括号(如果有的话)
coalesce函数:如果两个字段的国家码都存在,取第一个;如果只有一个有,取那个;如果都没有,返回NA,完美处理各种情况。
两种方法都能得到你想要的结果,你可以根据自己的习惯选~
内容的提问来源于stack exchange,提问作者Nautica
相关产品推荐
相关产品推荐

