R数据框中基于字符串格式适配正则提取字段的优化需求
解决R语言交易短信的字段精准提取问题
我明白你现在遇到的困扰:同一个数据框里的交易短信格式差异不小,前两条能用正则正常提取字段,但第三条因为结构特殊,好多信息都抽不出来。别担心,咱们可以先给每条短信做格式分类,再匹配对应的正则规则,就能精准提取出需要的六个字段了。
首先先看一下你的原始输入数据:
library(stringr) input = structure(list( `Sr. No.`=c("1", "2","3"), String=c( "ABCD, your Account XX1987 has been credited with EUR 22,500.00 on 30-Oct-17. Info: CAM*CASH DEPOSIT*ELISH SEC. The Available Balance is EUR 22,951.57.", "WXYZ, Your Ac XXXXXXXX1987 is debited with USD 5,000.00 on 14 May. Info. MMT*125485645*99999999. Your Net Available Balance is USD 20,531.38.", "INR 187,314.00 credited to your A/c No XXXXXXX1234 on 31/10/17 through NEFT with UTR )")), .Names=c("Sr. No.", "String"), row.names=1:3, class="data.frame")
问题分析
第三条短信的结构和前两条完全不一样:
- 交易金额和类型放在最开头,不是中间位置
- 日期用
/分隔,不是前两条的-或空格 - 没有明确的
Info标签,交易描述藏在through后面 - 完全没提可用余额,所以这个字段应该返回NA
所以咱们的核心思路是:先识别每条短信的格式类型,再针对不同类型用对应的正则提取字段。
解决方案代码
library(stringr) library(dplyr) # 第一步:给每条短信标记格式类型 input <- input %>% mutate( format_type = case_when( # 格式1:包含Info标签和Balance相关内容(对应前两条) str_detect(String, "Info\\.|Info:") & str_detect(String, "Available Balance|Net Available Balance") ~ "type1", # 格式2:包含"credited to your A/c No",无Info和Balance(对应第三条) str_detect(String, "credited to your A/c No") ~ "type2", # 其他格式默认type0,这里暂时不用处理 TRUE ~ "type0" ) ) # 第二步:针对不同格式提取目标字段 result <- input %>% mutate( # 提取交易类型:去除末尾的ed Type = case_when( format_type == "type1" ~ str_extract(String, "(credit|debit)ed") %>% str_remove("ed"), format_type == "type2" ~ str_extract(String, "(credit)ed") %>% str_remove("ed") ), # 提取账号:取字符串末尾的数字部分 Acc = case_when( format_type == "type1" ~ str_extract(String, "(?:Account|Ac|XX)[^0-9]*([0-9]+)") %>% str_extract("[0-9]+"), format_type == "type2" ~ str_extract(String, "A/c No XXXXXXX([0-9]+)") %>% str_remove("A/c No XXXXXXX") ), # 提取交易金额(含币种) Fig = case_when( format_type == "type1" ~ str_extract(String, "(?:EUR|USD|INR) [0-9,.]+"), format_type == "type2" ~ str_extract(String, "(?:INR) [0-9,.]+") ), # 提取交易日期:适配不同分隔符 Data = case_when( format_type == "type1" ~ str_extract(String, "on ([0-9]+[ -](?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)|[0-9]+[ -][0-9]+)") %>% str_remove("on "), format_type == "type2" ~ str_extract(String, "on ([0-9]+/[0-9]+/[0-9]+)") %>% str_remove("on ") ), # 提取交易描述:适配不同标签 Desc = case_when( format_type == "type1" ~ str_extract(String, "Info[:.] (.+)(?=\\. )"), format_type == "type2" ~ str_extract(String, "through (.+)") %>% str_remove("through ") %>% str_remove(" \\)$") ), # 提取可用余额:type2无相关内容,自动返回NA Balance = case_when( format_type == "type1" ~ str_extract(String, "(?:Available Balance|Net Available Balance) is ([A-Z]+ [0-9,.]+)") %>% str_remove("(?:Available Balance|Net Available Balance) is ") ) ) %>% # 保留并重命名需要的字段 select(Sr.No = `Sr. No.`, Type, Acc, Fig, Data, Desc, Balance) # 查看最终结果 print(result)
代码关键点说明
- 格式分类:用
case_when结合str_detect识别短信的特征,精准划分格式类型; - 字段适配:每个字段都针对不同格式调用专属正则,比如日期部分同时适配
-/空格和/两种分隔方式; - NA自动处理:第三条短信没有可用余额,
Balance字段会自动返回NA,完全符合预期。
最终输出结果
| Sr.No | Type | Acc | Fig | Data | Desc | Balance |
|---|---|---|---|---|---|---|
| 1 | credit | 1987 | EUR 22,500.00 | 30-Oct-17 | CAMCASH DEPOSITELISH SEC | EUR 22,951.57 |
| 2 | debit | 1987 | USD 5,000.00 | 14 May | MMT12548564599999999 | USD 20,531.38 |
| 3 | credit | 1234 | INR 187,314.00 | 31/10/17 | NEFT with UTR | NA |
内容的提问来源于stack exchange,提问作者Vector JX
相关产品推荐
相关产品推荐

