使用布尔掩码的python pandas .filter()方法

时间:2015-04-16 21:10:51

标签: python pandas filter time-series

我有一个如下所示的数据框(z):

timestamp                   source  price
2004-01-05 14:55:09+00:00   Bank1   420.975
2004-01-05 14:55:10+00:00   Bank2   421.0
2004-01-05 14:55:22+00:00   Bank1   421.075
2004-01-05 14:55:34+00:00   Bank1   420.975
2004-01-05 14:55:39+00:00   Bank1   421.175
2004-01-05 14:55:45+00:00   Bank1   421.075
2004-01-05 14:55:52+00:00   Bank1   421.175
2004-01-05 14:56:12+00:00   Bank2   421.1
2004-01-05 14:56:33+00:00   Bank1   421.275

有时,银行2只提交1个报价的时间窗口 - 我需要抛弃这样的所有日子,因为银行需要2个或更多报价。如果Bank 2出现1次或更少次,那就扔掉那一天。

我通过创建一个布尔掩码来完成此操作,我计划从中筛选出符合条件的所有日子:

r = z.groupby([z.index.date, z['source']]).size() > 1 
    # return boolean for each day/source if it appears at least once
r = r.groupby(level=0).all() == True 
    # ie. if the datetime 0th-level index contains all True, return True, otherwise False (meaning one source failed the criteria)

这会产生:

2004-01-05  True
2004-01-06  True
2004-01-07  True
2004-01-08  False
2004-01-09  True

完美。现在我只需要从原始数据帧z中过滤它,同时保持原始结构(即第二级频率,而不是每天)。这意味着使用df.filter()方法。

我的原始数据框架具有相同的结构(并且它们的.shape [0]相同):

2004-01-05  94
2004-01-06  24
2004-01-07  62
2004-01-08  30
2004-01-09  36

这里我感到困惑。我跑:

t = y.groupby(y.index.date).filter(lambda x: [x for x in r])

接收TypeError: filter function returned a list, but expected a scalar bool

  • 基本上,我需要lambda函数只返回r中的每个x(布尔值)。

我在一个非常复杂的情况下解决了这个问题(只是把我之前解决的所有事情都解决了,并且不要把它扔进r变量,而是让它成为lambda函数的一部分)。

t = y.groupby(y.index.date).filter(lambda x: (x.groupby([x.index.date, x['source']]).size() > 1).groupby(level=0).all() == True) # ie. the datetime 0th-level index

这非常凌乱,必须有一个基本的说法,这里是我的数据框z,然后是groupby('z.index.date'),然后基于布尔掩码.filter() r

编辑:这是我从大熊猫教程中找到的,但我出于某种原因,.between_time()部分不起作用。它会过滤掉长度为< = 1的所有内容,而不仅仅是当.between_time()条件为真时。

t = y.groupby([y.index.date, y['source']]).filter(lambda x: len(x.between_time('14:00','15:00') > 1)

2 个答案:

答案 0 :(得分:0)

您建议的原始方法是正确的,但您必须在群组上使用transformdatesource)而不是applytransform使用与原始数据框相同的结构返回组信息。

grp = z.groupby([z.index.date,z.source])
counts = grp.transform('count')  #counts the records for each group and index the information with the same structure of z

filtered_z = z[counts > 1] #final filtering

答案 1 :(得分:0)

我想我想出了这个日期:

仅在数据框z

中为日期创建新列
z['date'] = z.index.date

然后保留布尔系列r

中的日期
z[z['date'].isin(r.index)]