【问题标题】:How to keep a dictionary of dictionaries (or something with similar functionality) in pandas?如何在熊猫中保存字典(或具有类似功能的东西)?
【发布时间】:2017-07-21 06:15:55
【问题描述】:

所以我有一个包含许多列的大型数据框。假设我感兴趣的两个主要列是消息和名称。每条消息都类似于个人身份,并附有此人的姓名。假设我有一个相当大的情感/感觉词库,但浓缩版可能看起来像 ['sad'、'happy'、'relieved'、'annoyed'、'angry'、'ecstatic'、'proud ', '失望的']。对于每个名称(并且名称可以重复,因为它们可能有多个消息),我想跟踪他们使用的情感词及其伴随的计数。例如(因为我有一个非常大的数据集,所以我做了这个):

Message                                      Name
I am really happy with my progress.          Alice
I was annoyed by his inconsideration.        John
I felt proud after seeing her performance.   Lisa
I am ecstatic after hearing the good news.   Alice
I felt disappointed by her dishonesty        Lisa

如果我想要一些基本上可以告诉我以下内容的东西(我不一定关心格式,只要它是干净的): {Alice: happy:1, ecstatic: 1;约翰:生气:1;丽莎:骄傲:1,失望:1}。

最好/最简单的方法是什么?字典是最好的方法吗?其次(这是一个额外的相关问题),在上面计算之后,如果我想为每个名字找到最常用的情感词怎么办。在这个例子中,所有的东西都几乎是 1,但想象一下计数是不一样的。

【问题讨论】:

  • 如果单行有两次message,你要算一还是二?
  • 例如,单行的消息有两次“快乐”?我真的没想到,但是两次就好了。

标签: python pandas dictionary dataframe


【解决方案1】:

如果您正在寻找一种非常简单的方式来完成您正在寻找的东西,我建议您将 pandas 的 groupby 功能与 collections utility 结合使用。

初始情况

df = pd.read_csv('messages.csv')
df['Emotion Words'] = df.Message.apply(extract_emotion_words)
print(df)

输出:

                                      Message   Name   Emotion Words
0         I am really happy with my progress.  Alice         [happy]
1      I am really happy with johns progress.  Alice         [happy]
2       I was annoyed by his inconsideration.   John       [annoyed]
3  I felt proud after seeing her performance.   Lisa         [proud]
4  I am ecstatic after hearing the good news.  Alice      [ecstatic]
5       I felt disappointed by her dishonesty   Lisa  [disappointed]

按名称分组并应用计数器

from collections import Counter
df.groupby('Name')['Emotion Words'].sum().apply(Counter)

输出:

Name
Alice        {'happy': 2, 'ecstatic': 1}
John                      {'annoyed': 1}
Lisa     {'disappointed': 1, 'proud': 1}
dtype: object

获取最常用的词

由于您还表示要获取最常见的情感词,您可以使用Counter.most_common(n) 函数,其中n 是要提取的最常见词的数量(在您的情况下为 1):

df.groupby('Name')['Emotion Words'].sum().apply(
   lambda words: Counter(words).most_common(1)
)

输出:

Name
Alice           [(happy, 2)]
John          [(annoyed, 1)]
Lisa     [(disappointed, 1)]
dtype: object

对于这个小例子,我使用以下函数来提取情感词。当然可能有更好的方法(也许你已经在使用nltk,如果没有,我建议你研究一下)。

import re

emotionWords = set(['sad', 'happy', 'relieved', 'annoyed', 'angry', 'ecstatic', 'proud', 'disappointed'])

def extract_emotion_words(message):
    tokenized = re.split(r'\W+', message.lower())
    return list(set(tokenized) & emotionWords)

【讨论】:

  • 这看起来很棒!谢谢!!如果您不介意提供更多帮助,您能否简单解释一下df.groupby('Name')['Emotion Words'].sum().apply(Counter) 行?我知道您正在按名称对情感词进行分组,但我有点不确定.sum().apply(Counter) 是如何工作的。另外,如果我想获得每个名字出现的最大情感词怎么办?再次感谢您的帮助!
  • @JaneSully 是的,当你对数据进行分组时,你必须提供一个聚合函数。如果将其与数值进行比较,您可能希望通过取中位数进行聚合。对于许多列表(我们的情感词),我们“求和”这意味着在这种情况下连接各个列表(所以['happy'] + ['proud'] 得到['happy', 'proud'])。之后我们将Counter 应用到它上面,从而得到这个“频率表”。
  • 这完全有道理。感谢您的明确解释。最后一个问题,如果您可以提供更多帮助。如果我想为每个名字找到最多出现的单词(想象快乐和失望的计数是两个),所以我想返回一些爱丽丝:快乐,约翰:烦恼,丽莎:失望,我会怎么做这样做?
  • @JaneSully 我刚刚添加了一个关于如何获取最常用词的示例
  • 谢谢。就是这么简单。你太有帮助了!
猜你喜欢
  • 1970-01-01
  • 2010-09-22
  • 1970-01-01
  • 2012-09-19
  • 1970-01-01
  • 2012-10-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多