使用 Python 从文本(在 CSV 文件中)中提取数据
Extracting data from text (in CSV file) with Python
我正在帮助一个狗救援组织分析他们收到的收养申请。所有申请都通过在线系统提交,每个申请都会获得一个自动生成的表格 ID。然后,申请将被分配给不同的志愿者处理。
大部分信息都很简单,我可以使用pandas轻松处理。部分分析是关于每个应用程序的处理时间。这意味着从申请创建之日起(表格状态为“已提交”)到狗被领养(表格状态为“已领养”)。当我导出表单数据时,状态发生变化,一般评论混合在一个名为“评论(内联)”的 header 下。
这里是一个应用程序 changes/comments 状态的简化示例。
文本遵循一些基本模式。
一般评论:
CURRENT_PERSON(名字)写于 DATE:文本
志愿者变化:
CURRENT_PERSON(名字)写于 DATE:已将表格分配给 NEW_PERSON(姓氏)
表单状态变化:
CURRENT_PERSON(名字)写于 DATE:状态从 CURRENT_STATUS 更改为 NEW_STATUS
我是 python 的新手(~3 个月)。首先想到的是使用 python 和正则表达式来解析文本,提取数据,并将它们分成两组(一组用于一般评论,一组用于状态更改)。这需要一些时间,因为我还在学习,但它似乎是可行的。最后的结果会是这样的。
同一状态可以分配多次,所以我需要给他们一个编号。然后我可以将处理时间计算为 Adopted-01 和 Submitted-01 之间的天数。
但是,从我目前了解到的情况来看,使用这种迭代(for 循环)似乎很慢,不推荐使用。到目前为止,我有大约 1500 个表格,而且这个数字只会增加。
我应该继续 python 并重新开始吗?还是有更好的方法来获得我所描述的内容?我坚信有更好的方法我只是还不够了解。
非常感谢您的建议。
更新
样本数据here in CSV file, here in XML file
您会在其中找到四个名字:
珍妮怀特,
罗斯伯克,
克里詹姆斯,
亨利·伍兹。
我意识到 CSV 文本文件并不像我想象的那么干净。评论或状态更改之间没有 space。尽管有模式,但并不总是一致的(仅名字与全名)。我更新了模式。导出为 CSV 后,您将看到以下内容
Henry 于 2020 年 9 月 22 日写道:分配给 Rose Burk 的表格
罗斯于 2020 年 9 月 22 日写道:已发送介绍电子邮件。
成为
Henry 于 2020 年 9 月 22 日写道:分配给 Rose 的表格 BurkRose 于 2020 年 9 月 22 日写道:已发送介绍电子邮件。
现在我还需要更多地关注清理数据。
感谢您的观看。
所以我想出了如何使用正则表达式来处理基于模式的评论。
下面这个可以获取所有不同的日期和所有状态,因为它们都有“状态更改自”部分,我可以将各个组与旧状态或新状态相匹配。
regex = r"(\d{1,2}\/\d{1,2}\/\d{4})\:\sChanged\sStatus\sfrom\s([A-Z][a-z]+(\s[a-z]+)?(\s[A-Z][a-z]+)?)\sto\s([A-Z][a-z]+(\s[a-z]+)?(\s[A-Z][a-z]+)?)"
如果我只关注已领养,这一个可以抓住我需要的日期。
regex = r"(\d{1,2}\/\d{1,2}\/\d{4})\:\sChanged\sStatus\sfrom\s([A-Z][a-z]+(\s[a-z]+)?(\s[A-Z][a-z]+)?)\sto\sAdopted(?!\sElsewhere)
此外,我不需要使用 for 循环。在关注采用日期的特定情况下,我可以使用以下内容将采用日期添加到我在 Jupyter notebook 中的数据框中。
df['Adopted']=df['Comments (inline)'].str.extract(r'(\d{1,2}\/\d{1,2}\/\d{4})\:\sChanged\sStatus\sfrom\s[A-Z][a-z]+(\s[a-z]+)?(\s[A-Z][a-z]+)?\sto\sAdopted(?!\sElsewhere)')
这也意味着我可以只使用原始 CSV 文件。
我正在帮助一个狗救援组织分析他们收到的收养申请。所有申请都通过在线系统提交,每个申请都会获得一个自动生成的表格 ID。然后,申请将被分配给不同的志愿者处理。
大部分信息都很简单,我可以使用pandas轻松处理。部分分析是关于每个应用程序的处理时间。这意味着从申请创建之日起(表格状态为“已提交”)到狗被领养(表格状态为“已领养”)。当我导出表单数据时,状态发生变化,一般评论混合在一个名为“评论(内联)”的 header 下。
这里是一个应用程序 changes/comments 状态的简化示例。
文本遵循一些基本模式。
一般评论: CURRENT_PERSON(名字)写于 DATE:文本
志愿者变化: CURRENT_PERSON(名字)写于 DATE:已将表格分配给 NEW_PERSON(姓氏)
表单状态变化: CURRENT_PERSON(名字)写于 DATE:状态从 CURRENT_STATUS 更改为 NEW_STATUS
我是 python 的新手(~3 个月)。首先想到的是使用 python 和正则表达式来解析文本,提取数据,并将它们分成两组(一组用于一般评论,一组用于状态更改)。这需要一些时间,因为我还在学习,但它似乎是可行的。最后的结果会是这样的。
同一状态可以分配多次,所以我需要给他们一个编号。然后我可以将处理时间计算为 Adopted-01 和 Submitted-01 之间的天数。
但是,从我目前了解到的情况来看,使用这种迭代(for 循环)似乎很慢,不推荐使用。到目前为止,我有大约 1500 个表格,而且这个数字只会增加。
我应该继续 python 并重新开始吗?还是有更好的方法来获得我所描述的内容?我坚信有更好的方法我只是还不够了解。
非常感谢您的建议。
更新
样本数据here in CSV file, here in XML file
您会在其中找到四个名字: 珍妮怀特, 罗斯伯克, 克里詹姆斯, 亨利·伍兹。
我意识到 CSV 文本文件并不像我想象的那么干净。评论或状态更改之间没有 space。尽管有模式,但并不总是一致的(仅名字与全名)。我更新了模式。导出为 CSV 后,您将看到以下内容
Henry 于 2020 年 9 月 22 日写道:分配给 Rose Burk 的表格 罗斯于 2020 年 9 月 22 日写道:已发送介绍电子邮件。
成为
Henry 于 2020 年 9 月 22 日写道:分配给 Rose 的表格 BurkRose 于 2020 年 9 月 22 日写道:已发送介绍电子邮件。
现在我还需要更多地关注清理数据。 感谢您的观看。
所以我想出了如何使用正则表达式来处理基于模式的评论。
下面这个可以获取所有不同的日期和所有状态,因为它们都有“状态更改自”部分,我可以将各个组与旧状态或新状态相匹配。
regex = r"(\d{1,2}\/\d{1,2}\/\d{4})\:\sChanged\sStatus\sfrom\s([A-Z][a-z]+(\s[a-z]+)?(\s[A-Z][a-z]+)?)\sto\s([A-Z][a-z]+(\s[a-z]+)?(\s[A-Z][a-z]+)?)"
如果我只关注已领养,这一个可以抓住我需要的日期。
regex = r"(\d{1,2}\/\d{1,2}\/\d{4})\:\sChanged\sStatus\sfrom\s([A-Z][a-z]+(\s[a-z]+)?(\s[A-Z][a-z]+)?)\sto\sAdopted(?!\sElsewhere)
此外,我不需要使用 for 循环。在关注采用日期的特定情况下,我可以使用以下内容将采用日期添加到我在 Jupyter notebook 中的数据框中。
df['Adopted']=df['Comments (inline)'].str.extract(r'(\d{1,2}\/\d{1,2}\/\d{4})\:\sChanged\sStatus\sfrom\s[A-Z][a-z]+(\s[a-z]+)?(\s[A-Z][a-z]+)?\sto\sAdopted(?!\sElsewhere)')
这也意味着我可以只使用原始 CSV 文件。