大熊猫-一种基于子字符串出现的计数表达方法

时间:2018-07-18 18:04:00

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

假设我有一个看起来像这样的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

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

要注意的是,“激动和紧张”应该与“激动”分组。实际上,对于“不那么兴奋”和“不那么兴奋”之类的字符串,应将包含“激发”的字符串包含在组 中。相同的逻辑适用于“担心”和“紧张”。 (请注意,“兴奋和紧张”实际上属于“兴奋”和“紧张”组)

您会看到典型的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”,这似乎不允许我以相同的方式选择数据。

非常感谢您的帮助。

2 个答案:

答案 0 :(得分:4)

您可以这样做:

方法1

  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

方法2

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

答案 1 :(得分:3)

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

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