根据每个senten的第一个单词,将dataframe列中的字符串列表拆分为新的列

2024-05-12 23:44:18 发布

您现在位置:Python中文网/ 问答频道 /正文

所以我有大约40000排的人和他们的抱怨。我试图将它们分类到各自的列中进行分析,并对其他分析师进行分析 在我的公司,使用其他工具的人可以使用这些数据。你知道吗

数据帧示例:

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           ║
╚═══╩════════╩══════════════════════════════════════════════════════════════════════════════════════════════════════════════════╩════════════════════════════════════════════════════════════════════════════════╩═══════════════════════╩═══════════════╝

我尝试过的事情/我的处境:

所以我至少可以用一个regex语句将它们分开,这个语句似乎可以处理我的真实数据。你知道吗

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                                                                           |
+---+-------+--------------------------------------------------------------------------------+

我是一个正则表达式初学者,所以我希望这可能会做得更好。我最初的regex模式是r'([^;]+)',但我试图排除分号后面的空格。你知道吗

所以我不知所措。我玩过:

df.problems.str.extractall(r"(\b(?!(?: \b))[\w\s.()',:/-]+)").unstack(),这与我的示例“有效”(不会出错)。你知道吗

但是用我的真实数据,我得到了一个错误:"ValueError: Index contains duplicate entries, cannot reshape"

即使它与我的真实数据一起工作,我仍然需要弄清楚如何将这些“类别”(身体、思想、灵魂)放入指定的列中。你知道吗

如果我能把这个问题说得更好的话,我的运气可能会更好。我想在这里真正自学,所以我会感谢任何线索,即使他们不是一个完整的解决方案。你知道吗

我嗅到了一条线索,也许我可以用groupby或者多索引的技术来实现。对编程来说有点陌生,所以我还是在黑暗中摸索。我会很感激任何人提供的任何提示或想法。谢谢您!你知道吗

编辑:我只想回来谈谈我在使用@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。你知道吗

我可以通过修改regex来解决这个问题,比如说匹配的开始必须是字符串的开始,或者前面有一个分号。你知道吗

splits = [r'(^)(.+?)[:]', r'(;)(.+?)[:]']
str.split('|'.join(splits)

在那之后,我不得不重新调整setu索引部分,以得到@WeNYoBen有用的解决方案,所以我将继续使用这个。你知道吗


Tags: middlebodybadproblemsbigmissingpainsoul
1条回答
网友
1楼 · 发布于 2024-05-12 23:44:18

虽然不优雅,但它能完成任务:

df['split'] = df.problems.str.split(';')
df['mind'] = df.split.apply(
    lambda x: ''.join([category for category in x if 'mind' in category]))
df['body'] = df.split.apply(
    lambda x: ''.join([category for category in x if 'body' in category]))
df['soul'] = df.split.apply(
    lambda x: ''.join([category for category in x if 'soul' in category]))
df.drop('split', inplace=True)

你可以把它包起来

df[cat] = df.split.apply(lambda x: ''.join([category for category in x if cat in category])) 

并在数据帧上为每个cat(例如cats=['mind', 'body', 'soul', 'whathaveyou', 'etc.'])运行它。你知道吗


编辑:

正如@ifly6所指出的,用户输入的字符串中可能有关键字的交叉点。为了安全起见,应该将函数改为

df[cat] = df.split.apply(lambda x: ''.join([category for category in x if category.startswith(cat)])) 

相关问题 更多 >