Pandas按组扩展字符串发生次数

时间:2016-04-07 23:31:57

标签: python pandas

我试图按组创建一个字符串元组的扩展计数。

   index    category           group
2000-01-01  ('foo',)             a
2000-01-02  ('tito', 'puente')   a
2000-01-03  ('bar',)             a
2000-01-04  ('zip',)             b
2000-01-05  ('zorp',)            b
2000-01-03  ('feep',)            c

会变成:

   index    category           group   tuple_count
2000-01-01  ('foo',)             a        0
2000-01-02  ('tito', 'puente')   a        1
2000-01-03  ('bar',)             a        2
2000-01-04  ('zip',)             b        0
2000-01-05  ('zorp',)            b        0
2000-01-03  ('feep',)            c        1

我的想法是,我希望按照我感兴趣的类别出现次数的组创建一个展开窗口。在这种情况下,有趣的类别是[('tito', 'puente'), ('bar',), ('feep',)]。当出现新类别时,我想添加到计数中。

我使用以下代码并且无法弄清楚它为什么不起作用

from operator import or_

def count_categories(ser):

    categories_to_count = [('tito', 'puente'),
                           ('bar',),
                           ('feep',)]

    conditions = [ser == val for val in categories_to_count]
    mask = reduce(or_, conditions)
    return mask.sum()


def expanding_count_categories(s):
    return s.expanding().apply(count_categories)

df.groupby('group')['category'].apply(expanding_count_categories)

对于tuple_count列,我只返回类别列:

index              tuple_count
2000-01-01         ('foo',)
2000-01-02         ('tito', 'puente')
2000-01-03         ('bar',)
2000-01-04         ('zip',)
2000-01-05         ('zorp',)
2000-01-03         ('feep',)

编辑:

问题似乎是非数字目前not handled by expanding/window

2 个答案:

答案 0 :(得分:1)

不太确定您的扩展方法,但考虑在groupby应用函数中使用rank(),按组中的日期排序并使用isin()检查类别。唯一需要注意的是没有名为 index 的列与groupby系列中没有rank属性的 index 冲突。如果需要,请考虑在元组计数操作后设置和重命名索引:

df = pd.DataFrame({'datesix':['2000-01-01', '2000-01-02', '2000-01-03',
                             '2000-01-04', '2000-01-05', '2000-01-06'],
                   'category':[('foo',), ('tito', 'puente'), ('bar',),
                               ('zip',), ('zorp',), ('feep',)],                   
                   'group': ['a', 'a', 'a', 'b', 'b', 'c']})

df['datesix'] = pd.to_datetime(df['datesix'])

def count_categories(ser):
    categories_to_count = [('tito', 'puente'),
                           ('bar',),
                           ('feep',)]

    ser['tuple_count'] = ser.datesix[(ser.category.isin(categories_to_count))].rank()
    ser['tuple_count'] = ser['tuple_count'].fillna(0).astype(int)
    return ser

df = df.groupby('group').apply(count_categories)

#          category     datesix group  tuple_count
# 0          (foo,)  2000-01-01     a            0
# 1  (tito, puente)  2000-01-02     a            1
# 2          (bar,)  2000-01-03     a            2
# 3          (zip,)  2000-01-04     b            0
# 4         (zorp,)  2000-01-05     b            0
# 5         (feep,)  2000-01-06     c            1

答案 1 :(得分:0)

由于非数字目前不是由windows处理的,所以最好的方法是首先创建一个虚拟对象,然后对其进行运行求和。这也有利于滚动窗户的工作。

categories_to_count = [('tito', 'puente'),
                       ('bar',),
                       ('feep',)]

df['has_category'] = np.where(X['category'].isin(categories_to_count), 1, 0)

df.groupby('group')['has_category'].apply(lambda x: x.expanding().sum())