python-3.x - Python - 使用名称列表在自由文本熊猫列中查找完全匹配
问题描述
我有一个 Excel 文件,其中包含一个自由格式的文本列(有时其结构类似于电子邮件),我需要在其中找到所有名字和姓氏、电话号码和电子邮件,并在这些字段中添加额外的列 TRUE/FALSE。我不需要提取匹配的数据(即在相邻列中记下它),尽管这可能是一个优势。
注意:我不知道需要查找的姓名、电话或电子邮件,因此纯属猜测。我有一个包含 40k+ 个条目的注册名字列表,以及一个包含另外几百个条目的最常见姓氏列表。对于电话号码和电子邮件,我使用了 regex。电话的结构可以像(但永远不会以 0 开头):
- +45 0000 0000
- +45 00000000
- 00 00 00 00
- 0000 0000
- 00000000
- 0000-0000
到目前为止,我设法从 ~20000 行文件中过滤掉了大约 10000 行,尽管我的解决方案包含很多误报。Fx 我的正则表达式提取了很多样本/项目编号(例如 D03121110002 或 I08133100006 或 835-2019-8066115 或 835-2019-80745616)。项目编号总是以 D 或 I 开头,后跟 0.... 有没有办法过滤掉以 0 开头的数字?而样本号码中至少包含 2 个“-”(电话号码应该只有 1 个“-”,每边分隔 4 位数字)。
更重要的是,一些标记为 TRUE 的列行包含像“ Det er OK. ”这样的文本,其中 Python(我假设)将整个文本组合在一起,并从列表中提取任何匹配的替换名称,在这种情况下,我猜测可能是“ t er O ”或“ r OK ”,因为我的列表有名称“ Tero ”和“ Rok ”(尽管大小写不匹配,它结合了来自 2/3 个单独单词的字母,这不是我想要)...奇怪的是,对于以小写字母书写且末尾没有“ . ”的相同文本,这不是正确的,即“ det er ok",这被标记为 FALSE!PS 不幸的是,电子邮件中很少有名字是用小写字母写的,而不是应该是句子大小写......
电子邮件示例(姓名为 Thomas、Lars、Ole、Per):
Hej Thomas,
De 24 timer var en af mange sager som vi havde med til møde med Lars og Ole. De har godkendt den under dette møde.
Mvh. Per
下面是我的代码。
# Import datasets and create lists/variables
import pandas as pd
import re
from pandas import ExcelWriter
namesdf = pd.read_excel('names.xlsx', sheet_name='Alle Navne')
names = list(namesdf['Names'])
lastnamesdf = pd.read_excel('names.xlsx', sheet_name='Frie Efternavne')
lastnames = list(lastnamesdf['Frie Efternavne'])
reg = re.compile("\d{2}[\s]??\d{2}[-\s]??\d{2}[\s]??\d{2}|\(\d{2}\)\s*\d{2}[-\s]??\d{2}[\s]??\d{2}|[\W?\w+]@[\w.-]+")
# Import dataset and drop NULLS
df = pd.read_excel(r'Entreprise Beskeder.xlsx', sheet_name='dataark')
df["Besked"].dropna(inplace = True)
# Compare dataset to the created lists/variables to match names, phone numbers and emails
df["Navner"] = df["Besked"].str.contains("|".join(names)) # Creates new column and adds TRUE/FALSE for first names
df["Efternavner"] = df["Besked"].str.contains("|".join(lastnames)) # Creates new column and adds TRUE/FALSE for last names
df["Mobil|Email"] = df["Besked"].str.contains(reg) # Creates new column and adds TRUE/FALSE for phones/emails
# Save the result
writer = ExcelWriter('PythonExport.xlsx')
df.to_excel(writer)
writer.save()
我将不胜感激任何可能改进我的代码并减少过滤掉我发现的所有这些误报单元格所需的手动工作的建议!谢谢 :)
解决方案
关于正则表达式部分,我建议以下(^|\s|\+45)\s?((\d{2})([\-\s])(\d{2})\4(\d{2})\4(\d{2})|\d{4}[\s\-]?\d{4})
演示:https ://regex101.com/r/unz6Ke/9
Matching strings
================
plop +45 00 00 00 00 some words
plop +45 0000 0000 some words
plop +45 00000000 some words
plop +4500000000 some words
plop 00 00 00 00 some words
plop 0000 0000 some words
plop 0000-0000 some words
plop 00000000 some words
plop 00-00-00-00 some words
Unwanted strings
================
plop 15.10.2019 some words
plop 04-10-2017 some words
plop 27/9-18 some words
plop D03121110002 some words
plop 835-2019-8066115 some words
一些细节:
(^|\s|\+45)
匹配行首、空格或 +45
(\d{2})([\-\s])(\d{2})\4(\d{2})\4(\d{2})
匹配由(空格)分隔的 4 对 2 位数字或-
\d{4}[\s\-]?\d{4}
匹配 2 组 4 位数字,由 a
(空格)分隔或-
编辑:改进正则表达式以捕获文本中的电话号码并删除字符类的无用用法。
推荐阅读
- javascript - AppendChild 和 insertAdjacentHtml 的区别?
- networking - 如何解决此错误:输入必须是向量,而不是 NULL。?
- ubuntu - 当我使用anaconda的环境时,我无法在Ubuntu系统中打开spyder。这是怎么发生的?我应该怎么办?
- c++ - 如何根据 C++ 中的条件返回两个不同的 lambda 函数?
- git - 为什么 VSCode 不识别 git?
- wordpress - 显示登录页面,但我无法登录 wordpress
- node.js - 测试库忽略的节点环境变量
- react-native - 使用 Redux 在屏幕之间共享状态的问题 - React native
- python - razorpay.errors.BadRequestError:金额必须是整数
- angular - 如何观察 ngForm 的变化并根据变化的值进行计算