【发布时间】:2019-12-17 12:55:40
【问题描述】:
所以我有大约 40,000 行人员及其投诉。我正在尝试将它们分类到各自的列中进行分析,并为其他分析师 在我的公司,使用其他工具的人可以使用这些数据。
数据帧示例:
df = pd.DataFrame({"person": [1, 2, 3],
"problems": ["body: knee hurts(bad-pain), toes hurt(BIG/MIDDLE); mind: stressed, tired",
"soul: missing; mind: can't think; body: feels great(lifts weights), overweight(always bulking), missing a finger",
"none"]})
df
╔═══╦════════╦══════════════════════════════════════════════════════════════════════════════════════════════════════════════════╗
║ ║ person ║ problems ║
╠═══╬════════╬══════════════════════════════════════════════════════════════════════════════════════════════════════════════════╣
║ 0 ║ 1 ║ body: knee hurts(bad-pain), toes hurt(BIG/MIDDLE); mind: stressed, tired ║
║ 1 ║ 2 ║ soul: missing; mind: can't think; body: feels great(lifts weights), overweight(always bulking), missing a finger ║
║ 2 ║ 3 ║ none ║
╚═══╩════════╩══════════════════════════════════════════════════════════════════════════════════════════════════════════════════╝
期望的输出:
╔═══╦════════╦══════════════════════════════════════════════════════════════════════════════════════════════════════════════════╦════════════════════════════════════════════════════════════════════════════════╦═══════════════════════╦═══════════════╗
║ ║ person ║ problems ║ body ║ mind ║ soul ║
╠═══╬════════╬══════════════════════════════════════════════════════════════════════════════════════════════════════════════════╬════════════════════════════════════════════════════════════════════════════════╬═══════════════════════╬═══════════════╣
║ 0 ║ 1 ║ body: knee hurts(bad-pain), toes hurt(BIG/MIDDLE); mind: stressed, tired ║ body: knee hurts(bad-pain), toes hurt(BIG/MIDDLE) ║ mind: stressed, tired ║ NaN ║
║ 1 ║ 2 ║ soul: missing; mind: can't think; body: feels great(lifts weights), overweight(always bulking), missing a finger ║ body: feels great(lifts weights), overweight(always bulking), missing a finger ║ mind: can't think ║ soul: missing ║
║ 2 ║ 3 ║ none ║ NaN ║ NaN ║ NaN ║
╚═══╩════════╩══════════════════════════════════════════════════════════════════════════════════════════════════════════════════╩════════════════════════════════════════════════════════════════════════════════╩═══════════════════════╩═══════════════╝
我尝试过的事情/我现在所处的位置:
因此,我至少能够使用正则表达式语句将它们分开,该正则表达式语句似乎可以处理我的真实数据。
df.problems.str.extractall(r"(\b(?!(?: \b))[\w\s.()',:/-]+)")
+---+-------+--------------------------------------------------------------------------------+
| | | 0 |
+---+-------+--------------------------------------------------------------------------------+
| | match | |
| 0 | 0 | body: knee hurts(bad-pain), toes hurt(BIG/MIDDLE) |
| | 1 | mind: stressed, tired |
| 1 | 0 | soul: missing |
| | 1 | mind: can't think |
| | 2 | body: feels great(lifts weights), overweight(always bulking), missing a finger |
| 2 | 0 | none |
+---+-------+--------------------------------------------------------------------------------+
我是一个正则表达式初学者,所以我希望这可能会做得更好。我原来的正则表达式模式是r'([^;]+)',但我试图排除分号后的空格。
所以我很茫然。我玩过:
df.problems.str.extractall(r"(\b(?!(?: \b))[\w\s.()',:/-]+)").unstack(),在我的示例中“有效”(不会出错)。
但是用我的真实数据,我得到一个错误:"ValueError: Index contains duplicate entries, cannot reshape"
即使它适用于我的真实数据,我仍然需要弄清楚如何将这些“类别”(身体、思想、灵魂)放入指定的列中。
如果我能更好地表达这个问题,我可能会有更好的运气。我正在尝试在这里真正自学,因此即使它们不是完整的解决方案,我也会很感激任何线索。
我正在寻找一条线索,也许我可以通过 groupby 或 multiIndex 技术以某种方式做到这一点。对编程有点陌生,所以我仍然在黑暗中摸索。我将不胜感激任何人提供的任何提示或想法。谢谢!
编辑:我只想回过头来提一下我在使用@WeNYoBen 的解决方案时在我的真实数据"ValueError: Index contains duplicate entries, cannot reshape" 中遇到的错误:
(df.problems.str.extractall(r"(\b(?!(?: \b))[\w\s.()',:/-]+)")[0]
.str.split(':',expand=True)
.set_index(0,append=True)[1]
.unstack()
.groupby(level=0)
.first())
原来我有一些带有多个冒号的组。例如:
df = pd.DataFrame({"person": [1, 2, 3],
"problems": ["body: knee hurts(bad-pain), toes hurt(BIG/MIDDLE); mind: stressed, energy: tired",
"soul: missing; mind: can't think; body: feels great(lifts weights), overweight(always bulking), missing a finger",
"none"]})
╔═══╦════════╦══════════════════════════════════════════════════════════════════════════════════════════════════════════════════╗
║ ║ person ║ problems ║
╠═══╬════════╬══════════════════════════════════════════════════════════════════════════════════════════════════════════════════╣
║ 0 ║ 1 ║ body: knee hurts(bad-pain), toes hurt(BIG/MIDDLE); mind: stressed, energy: tired ║
║ 1 ║ 2 ║ soul: missing; mind: can't think; body: feels great(lifts weights), overweight(always bulking), missing a finger ║
║ 2 ║ 3 ║ none ║
╚═══╩════════╩══════════════════════════════════════════════════════════════════════════════════════════════════════════════════╝
查看第一行更新,反映我发现的边缘情况 ; mind: stressed, energy: tired。
我可以通过更改我的正则表达式来解决此问题,以说明匹配的开头必须是字符串的开头或以分号开头。
splits = [r'(^)(.+?)[:]', r'(;)(.+?)[:]']
str.split('|'.join(splits)
在那之后,我只需要重新调整 set_index 部分就可以让@WeNYoBen 的有用解决方案发挥作用,所以我会坚持使用这个。
【问题讨论】:
-
我应该补充一点,昨天我确实弄清楚了如何在我的真实数据中获取所有这些分组的完整列表,总共大约 10 个。
sorted(df.problems.str.extractall(r'(^|;)(.+?)[:]').reset_index()[1].str.strip().unique()) -
三个类别总是一样的吗?身体、思想、灵魂……
-
如果它们总是三个类别,那么您可能会尝试从
body ... ;匹配每个类别。 -
df.problems.str.extractall(r"(\b(?!(?: \b))[\w\s.()',:/-]+)")[0].str.split(':',expand=True).set_index(0,append=True)[1].unstack().groupby(level=0).first()你自己的函数抛光后比applt + lambda好 -
@sobek 我实际上将您的两种解决方案都用作垫脚石。试图解决另一个极端情况,我发现在一个短语中使用分号,在数万行中只出现了两次:/ 你们摇滚不过。这个周末学到了很多