如何用正则表达式在Python中将半结构化数据转换为表格或DataFrame?
用正则表达式提取半结构化数据到DataFrame
先把待处理的原始文本列出来:
1.4 (iii) Imperial Energy Nord Limited Cyprus 100% 100% Audited 1.4 (iv) Biancus Holdings Limited Cyprus 100% 100% Audited 1.4 (v) Redcliffe Holdings Limited Cyprus 100% 100% Auditedd341 2 Mangalore Refinery and Petrochemicals Ltd. (MRPL) (Note no.4(a)&(d))India 80.94% 80.72% Audited
数据结构分析
这里的文本分两种格式:
- 完整行条目:序号(如
1.4)+ 罗马数字子项(如(iii))+ 公司全称 + 国家 + 两个持股比例 + 审计状态 - 跨行拆分条目:第一行是序号+公司全称(含括号备注),第二行是备注说明+国家+两个持股比例+审计状态
正则匹配方案
先把跨行的内容合并成完整条目,再用正则提取对应字段:
正则表达式说明
匹配带罗马子项的完整行:
^(\d+\.\d+) \((iii|iv|v)\) (.+?) (\w+) (\d+\.?\d*%) (\d+\.?\d*%) (\w+.*)$分组对应:序号、子项、公司名称、国家、持股比例1、持股比例2、审计状态
匹配跨行合并后的条目:
^(\d+) (.+?)\(Note no\.\d+\([a-d]\)&\([a-d]\)\)(\w+) (\d+\.?\d*%) (\d+\.?\d*%) (\w+)$分组对应:序号、公司名称、国家、持股比例1、持股比例2、审计状态
Python代码实现
import re import pandas as pd # 原始文本 raw_text = """1.4 (iii) Imperial Energy Nord Limited Cyprus 100% 100% Audited 1.4 (iv) Biancus Holdings Limited Cyprus 100% 100% Audited 1.4 (v) Redcliffe Holdings Limited Cyprus 100% 100% Auditedd341 2 Mangalore Refinery and Petrochemicals Ltd. (MRPL) (Note no.4(a)&(d))India 80.94% 80.72% Audited""" # 合并跨行的条目 lines = raw_text.split('\n') merged_lines = [] i = 0 while i < len(lines): if lines[i].startswith('(') and i > 0: merged_lines[-1] += lines[i] else: merged_lines.append(lines[i]) i += 1 # 定义正则模式和对应字段 patterns = [ (re.compile(r'^(\d+\.\d+) \((iii|iv|v)\) (.+?) (\w+) (\d+\.?\d*%) (\d+\.?\d*%) (\w+.*)$'), ['序号', '子项', '公司名称', '国家', '持股比例1', '持股比例2', '审计状态']), (re.compile(r'^(\d+) (.+?)\(Note no\.\d+\([a-d]\)&\([a-d]\)\)(\w+) (\d+\.?\d*%) (\d+\.?\d*%) (\w+)$'), ['序号', '公司名称', '国家', '持股比例1', '持股比例2', '审计状态']) ] # 提取数据 data = [] for line in merged_lines: matched = False for pattern, cols in patterns: match = pattern.match(line.strip()) if match: row = list(match.groups()) # 给跨行条目补全子项列,保持结构一致 if len(row) == 6: row.insert(1, None) data.append(row) matched = True break if not matched: print(f"未匹配到的行:{line}") # 转为DataFrame df = pd.DataFrame(data, columns=['序号', '子项', '公司名称', '国家', '持股比例1', '持股比例2', '审计状态']) print(df)
运行结果
输出的结构化DataFrame如下:
序号 子项 公司名称 国家 持股比例1 持股比例2 审计状态 0 1.4 iii Imperial Energy Nord Limited Cyprus 100% 100% Audited 1 1.4 iv Biancus Holdings Limited Cyprus 100% 100% Audited 2 1.4 v Redcliffe Holdings Limited Cyprus 100% 100% Auditedd341 3 2 None Mangalore Refinery and Petrochemicals Ltd. (MRPL) India 80.94% 80.72% Audited
补充说明
- 如果遇到
Auditedd341这类带冗余字符的审计状态,可以用df['审计状态'] = df['审计状态'].str.replace(r'(\w+)\d+', r'\1', regex=True)清理 - 若后续出现更多格式变体,只需扩展对应的正则模式即可
内容的提问来源于stack exchange,提问作者Abhishek Nimje
相关产品推荐
相关产品推荐

