【问题标题】:pandas - expressive method for counting based on occurrences of substringspandas - 根据子串的出现次数进行计数的表达方法
【发布时间】:2018-12-26 17:59:21
【问题描述】:

假设我有一个如下所示的 DataFrame:

df=pd.DataFrame({'name': ['john','jack','jill','al','zoe','jenn','ringo','paul','george','lisa'], 'how do you feel?': ['excited', 'not excited', 'excited and nervous', 'worried', 'really worried', 'excited', 'not that worried', 'not that excited', 'nervous', 'nervous']})

      how do you feel?    name
0              excited    john
1          not excited    jack
2  excited and nervous    jill
3              worried      al
4       really worried     zoe
5              excited    jenn
6     not that worried   ringo
7     not that excited    paul
8              nervous  george
9              nervous    lisa

我对计数感兴趣,但分为三类:“兴奋”、“担心”和“紧张”。

关键是“兴奋和紧张”应该与“兴奋”组合在一起。事实上,包含“excited”的字符串应该包含在一个组except中,用于诸如“not thatexcited”和“notexcited”之类的字符串。同样的逻辑也适用于“担心”和“紧张”。 (请注意,“兴奋和紧张”实际上属于“兴奋”和“紧张”组)

您可以看到,典型的 groupby 将不起作用,字符串搜索必须灵活。

我有一个解决方案,但想知道你们是否都可以找到更好的 Python 方法,和/或使用我可能不知道的更合适的方法。

这是我的解决方案:

定义一个函数以返回包含所需子字符串且不包含否定情绪的子字符串的行的计数

def get_perc(df, column_label, str_include, str_exclude):

    data=df[col_lab][(~df[col_lab].str.contains(str_exclude, case=False)) & \
    (df[col_lab].str.contains(str_include,  case=False))]

    num=data.count()

    return num

然后,在循环内调用此函数,传入各种“str.contains”参数,并将结果收集到另一个 DataFrame 中。

groups=['excited', 'worried', 'nervous']
column_label='How do you feel?'

data=pd.DataFrame([], columns=['group','num'])
for str_include in groups:
    num=get_perc(df, column_label, str_include, 'not|neither')
    tmp=pd.DataFrame([{'group': str_include,'num': num}])
    data=pd.concat([data, tmp])


data

      group    num
0   excited      3
1   worried      2
2   nervous      3

您能想到一种更简洁的方法吗?我确实在“str.contains”中尝试了一个正则表达式,以避免需要两个布尔系列和“&”。但是,如果没有捕获组,我就无法做到这一点,这意味着我必须使用“str.extract”,这似乎不允许我以相同的方式选择数据。

非常感谢任何帮助。

【问题讨论】:

  • "excited and nervous" 算作两者或只是excited ?
  • 两者都很好
  • 在这种情况下,您也可以编辑您的问题。
  • 我会推荐 NLTK

标签: python python-3.x pandas pandas-groupby


【解决方案1】:

您可以简单地提供映射,然后按映射产生的新系列进行分组。

map_dict = {'excited and nervous':'excited', 'not that excited':'not excited', 
            'really worried':'worried', 'not that worried':'not worried'}
df.groupby(df['how do you feel?'].replace(map_dict)).size()

输出:

how do you feel?
excited        3
nervous        2
not excited    2
not worried    1
worried        2
dtype: int64

【讨论】:

    【解决方案2】:

    你可以这样做:

    方法一

    1. 忽略not 行,然后
    2. 从指标字符串中获取相关的groups

    In [140]: col = 'how do you feel?'
    
    In [141]: groups = ['excited', 'worried', 'nervous']
    
    In [142]: df.loc[~df[col].str.contains('not '), col].str.get_dummies(sep=' ')[groups].sum()
    Out[142]:
    excited    3
    worried    2
    nervous    3
    dtype: int64
    

    方法二

    In [162]: dfs = df['how do you feel?'].str.get_dummies(sep=' ')
    
    In [163]: dfs.loc[~dfs['not'].astype(bool), groups].sum()
    Out[163]:
    excited    3
    worried    2
    nervous    3
    dtype: int64
    

    【讨论】:

    • 好,我正要发帖 dummies_df = df['你感觉怎么样?'].str.get_dummies(sep = ' ') dummies_df.loc[dummies_df['not'] ! = 1, ['兴奋', '担心', '紧张']].sum() 你打败了我 :)
    • @Zero 我真的很喜欢这个“get_dummies”的东西。我使用了str.contains,这样我仍然可以通过使用'excited' | pumped | thrilled | excited' 之类的正则表达式组将“兴奋”和“兴奋”之类的东西组合在一起。当然,这需要一些词形还原才能正确完成。 NLTK 与您的方法相结合可以很好地工作。
    猜你喜欢
    • 2014-06-12
    • 2012-10-29
    • 2020-02-22
    • 2014-06-19
    • 2013-02-26
    • 2019-08-17
    • 2021-10-24
    • 1970-01-01
    • 2021-08-02
    相关资源
    最近更新 更多