Python 过滤多索引分组数据帧
数据如下所示:Python 过滤多索引分组数据帧,python,pandas,dataframe,filter,multi-index,Python,Pandas,Dataframe,Filter,Multi Index,数据如下所示: id timestamp date value 1 2001-01-01 2001-05-01 0 1 2001-10-01 2001-05-01 1 2 2001-01-01 2001-05-01 0 2 2001-10-01 2001-05-01 0 如您所见,该表包含id、timestamp、date和value列。 具有相同id的每一行也具有相同的日期。 此外,date在时间上总是在每个id的第一个和最后一个时间戳之间
id timestamp date value
1 2001-01-01 2001-05-01 0
1 2001-10-01 2001-05-01 1
2 2001-01-01 2001-05-01 0
2 2001-10-01 2001-05-01 0
如您所见,该表包含id
、timestamp
、date
和value
列。
具有相同id
的每一行也具有相同的日期
。
此外,date
在时间上总是在每个id
的第一个和最后一个时间戳之间的某个位置
任务是以删除每个id
的方式过滤表,该id在其各自的日期
后的时间戳中至少不包含一个值>0
的条目
我实现它的方式是使用level0=id
和level1=date
对表进行多索引并对其排序。然后我将其按级别0
分组。接下来,我循环遍历每个组(id
),并分配一个新值,告诉我id
是否为“好”(布尔值)。最后,我过滤good为True的表
不幸的是,对于一个大的(>10M行)数据集来说,这个实现非常缓慢。
我正在寻找一种加速的方法。我的想法是使用groupby.apply(lambda g:something)
,但我没有让它发挥作用,我不知道这是否是最快的选择
工作代码示例:
import pandas as pd
df = pd.DataFrame({'id': [1, 1, 2, 2],
'timestamp': ['01-01-2001', '01-10-2001', '01-01-2001', '01-10-2001'],
'date': ['01-05-2001', '01-05-2001', '01-05-2001', '01-05-2001'],
'value': [0, 1, 0, 0]})
df['timestamp'] = pd.to_datetime(df['timestamp'])
df['date'] = pd.to_datetime(df['date'])
df = df.set_index(['id','timestamp']).sort_index()
grouped = df.groupby(level=0)
df['good'] = False
for i,(id,df_id) in enumerate(grouped):
index = df_id.index
df_id = df_id.droplevel(0)
df.good.loc[index] = any(df_id.value.loc[df_id.date[0]:] > 0)
df = df[df.good == True]
对于按值列中的1
获取所有id
s以及时间戳
更高,如date
创建两个掩码,按和按位链接,
,然后测试每组是否至少有一个True
,以及:
哇,谢谢!如果我想在日期中添加一些天作为“缓冲区”,比如import datetime any(df_id.value.loc[df_id.date[0]+datetime.timedelta(days=1):]>0
@gustavz-你认为像m=df['value'].gt(0)&df['timestamp'].gt(df['date']+pd.timedelta(days=1))吗
?如果我想知道,我将如何更改您的代码:为每个id
,提供date
之后从第一个大于0
的值开始的所有时间数据。因此,不仅是在某个日期之后大于零的所有数据,而且是从时间第一个大于零的值开始的日期之后的数据。@gustavz-N我不确定是否理解,您是否可以添加一些具有预期输出的示例数据,@gustavz-您现在可以检查吗?我认为您创建了新问题;),因为这里隐藏了3个问题;)
df['timestamp'] = pd.to_datetime(df['timestamp'])
df['date'] = pd.to_datetime(df['date'])
df = df.sort_values(['id','timestamp'])
m = df['value'].gt(0) & df['timestamp'].gt(df['date'])
df = df[m.groupby(df['id']).transform('any')]
print (df)
id timestamp date value
0 1 2001-01-01 2001-01-05 0
1 1 2001-01-10 2001-01-05 1