平时对于一些不标准的数据,需要提取或者筛选其中的部分数据。本文主要分享一些常用的办法,同时也作为一个笔记的备份。
1. 正则表达式
正则表达式比较适合提取有明确类型的数据,比如字母,数字,汉字,日期等,同时也可以提取具有一定规律特征的数据。常见的用法如下:
import re
text = '2023-11-01,AAaa产品净值上涨1%,详细内容见《产品周报》'
# 提取数字
get_num = re.findall(r'\d+', text)
# 提取汉字
get_chinese = re.findall(r'[\u4e00-\u9fa5]+', text)
# 提取字母,不区分大小写
get_letter = re.findall(r'[a-zA-Z]', text)
# 提取日期
get_date = re.search(r'\d{4}-\d{2}-\d{2}', text)[0]
# 提取指定部分--使用'(.*?)?'表示需查找部分
find_str = '《(.*?)》'
get_part = re.findall(find_str, text)
2. 分割提取
分割提取是根据数据的某个标志,将数据切割为列表,然后载提取相关的数据,常见函数为split.
name = '20230101-举例asd基金(000001)-三级估值表.xlsx'
如上,name是一个基金的估值表文件,需要提取的字符为‘举例asd基金’,如果使用正则表达式也可以获取(先提取不同类型的数据,然后再进行拼接),但是步骤比较繁琐,同时泛化能力不强。因此,需要使用其他办法。
第一步,通过‘-’进行切割,可以得到一个列表(含三个元素):
first = name.split('-')
print(first)
对应的结果是:
接下来,取first里面的第二个元素,然后通过‘(’ ,进行切割,得到一个新列表,新列表的第一个元素就是所需字符。
second = first[1].split('(')[0]
print(second)
对应的结果为:
3.模糊匹配
可能出现相关数据与需求并非一对一的情形,可以考虑退求其次,使用模糊匹配来进行提取。
import pandas as pd
df = pd.DataFrame({'名称':['xx-举例如何1号基金','随意取名2号基金','举例随心1号基金','xx-随意命名1号基金']})
如上,需要筛选出名称里面含有‘举例’二字的基金。使用正则和分割均难以实现。因此考虑使用是否包含的思路(如果是单一字符串循环,则使用‘in’来判断):
new_df = df.loc[df['名称'].str.contains('举例')]
对应的结果:
还是上述的例子,如果需要匹配的字段为‘随心1号’,前文的办法就行不通了。这个情况下可以使用fuzz来匹配。
from fuzzywuzzy import fuzz
print(fuzz.ratio('举例随心1号基金','随心1号'))
fuzz.ratio输出两个字符串的相似度(按字符串顺序),上述代码对应结果为67,即'举例随心1号基金'和'随心1号'有67%的相似度。依照此方法,可以计算df['名称']的数据与‘随心1号’的相似度,取出满足相似度(大于50%)的数据:
for name in df['名称']:
rate = fuzz.ratio(name,'随心1号')
if rate>=50:
print('匹配字段为:{},相似度为{},符合条件!'.format(name,rate))
else:
print('匹配字段为:{},相似度为{},不符合条件!'.format(name,rate))
对应的结果为:
关于每种方式,还有许多功能,此处只分享一些常见功能,有需求者可进一步探索。
本期分享结束,有何问题欢迎交流。