基于正则表达式在R中填充列:葡萄酒评论数据处理优化求助
从葡萄酒评论标题里精准提取年份这个需求,我太懂了——既要抓准不遗漏,又不想写一堆绕来绕去的代码。既然你已经有能用的方案,那我分享几个更优雅、更符合R现代编程风格的写法,不管你是用tidyverse还是data.table都能适配~
方法1:Tidyverse + Stringr 极简向量化写法
葡萄酒年份基本都是19xx或20xx的4位数字,用stringr的str_extract配合精准正则就能一步到位,还能避免把其他4位数字(比如批次号)误判为年份:
library(tidyverse) # 假设你的数据集是wine_reviews wine_reviews <- wine_reviews %>% mutate(year = str_extract(title, "\\b(19|20)\\d{2}\\b"))
这里的\\b是单词边界,确保我们匹配的是完整的年份数字,不会出现把“20230”里的“2023”或者标题里的其他数字片段误提的情况。如果遇到标题里有多个年份(比如“2018 vs 2020 赤霞珠对比”),可以换成str_extract_all,再用paste合并成字符串,根据你的需求调整就行。
方法2:处理无年份的健壮版
如果有些评论标题没有年份,或者用“NV”(Non-Vintage,无年份)标记,我们可以让代码更健壮,给这些情况一个清晰的标记:
wine_reviews <- wine_reviews %>% mutate(year = case_when( # 先匹配NV标记 str_detect(title, "\\bNV\\b") ~ "Non-Vintage", # 再提取常规年份 TRUE ~ str_extract(title, "\\b(19|20)\\d{2}\\b") %>% str_replace_na(replacement = "Unknown") ))
这样不管标题里是有明确年份、标了NV,还是完全没年份,结果列都会有清晰的取值,后续分析也更方便。
方法3:Data.table 用户的高效写法
如果你用data.table处理大规模数据集,这种写法既简洁又高效,完全利用data.table的向量化操作:
library(data.table) # 转换为data.table并新增year列 setDT(wine_reviews)[, year := str_extract(title, "\\b(19|20)\\d{2}\\b")] # 同样可以扩展处理无年份的情况 setDT(wine_reviews)[, year := fifelse( is.na(str_extract(title, "\\b(19|20)\\d{2}\\b")), "Unknown", str_extract(title, "\\b(19|20)\\d{2}\\b") )]
正则的小优化(应对特殊标题)
如果你的数据里有一些特殊格式的标题,比如带“Vintage”字样(比如“Vintage 2019 Pinot Noir”),可以调整正则来精准匹配并清理:
wine_reviews <- wine_reviews %>% mutate(year = str_extract(title, "\\b(?:Vintage\\s+)?(19|20)\\d{2}\\b") %>% str_remove_all("Vintage\\s+"))
这个正则会匹配“Vintage 2019”或者直接“2019”的情况,然后自动去掉多余的“Vintage”字样,得到干净的年份数字。
这些方法都比循环分割、复杂条件判断要简洁得多,而且都是R里的向量化操作,处理大数据集的速度也更快,希望能帮到你~
内容的提问来源于stack exchange,提问作者Kier

