Python 3.x 如果数据至少每6小时存在一次,如何过滤时间序列?

Python 3.x 如果数据至少每6小时存在一次,如何过滤时间序列?,python-3.x,pandas,datetime,filter,time-series,Python 3.x,Pandas,Datetime,Filter,Time Series,我想验证每个ID是否至少每6小时有一次数据,并筛选出不符合此标准的ID 本质上是一个过滤器:“如果ID的数据不是至少每6小时一次,则从数据帧中删除ID” 我尝试使用相同的方法每天过滤一个,但在调整代码时遇到了问题 # add day column from datetime index df['1D'] = df.index.day # reset index daily = df.reset_index() # count per ID per day. Result is per ID da

我想验证每个ID是否至少每6小时有一次数据,并筛选出不符合此标准的ID

本质上是一个过滤器:“如果ID的数据不是至少每6小时一次,则从数据帧中删除ID”

我尝试使用相同的方法每天过滤一个,但在调整代码时遇到了问题

# add day column from datetime index
df['1D'] = df.index.day
# reset index
daily = df.reset_index()
# count per ID per day. Result is per ID data of non-zero 
a = daily.groupby(['1D', 'id']).size()
# filter by right join 
filtered = a.merge(df, on = id", how = 'right')

我不知道如何将其适应于每天以下6小时的时段:00:01-06:00、06:01-12:00、12:01-18:00、18:01-24:00。

我建议使用pivot_表和重采样,允许更改为任意频率。更多解释请参见评论

# build test data. I need a dummy column to use pivot_table later. Any column with numerical values will suffice
data = [[datetime(2020, 1, 1, 1), 1, 1],
        [datetime(2020, 1, 1, 6), 1, 1],
        [datetime(2020, 1, 1, 12), 1, 1],
        [datetime(2020, 1, 1, 18), 1, 1],
        [datetime(2020, 1, 1, 1), 2, 1],

       ]

df = pd.DataFrame.from_records(data=data, columns=['date', 'id', 'dummy'])
df = df.set_index('date')

# We need a helper dataframe df_tmp.
# Transform id entries to columns. resample with 6h = 360 minutes = 360T. 
# Take mean() because it will produce nan values
# WARNING: It will only work if you have at least one id with observations for every 6h. 
df_tmp = pd.pivot_table(df, columns='id', index=df.index).resample('360T').mean()

# Drop MultiColumnHierarchy and drop all columns with NaN values
df_tmp.columns = df_tmp.columns.get_level_values(1)
df_tmp.dropna(axis=1, inplace=True)

# Filter values in original dataframe where 
mask_id = df.id.isin(df_tmp.columns.to_list())
df = df[mask_id]

我保留了您对时间戳的要求,但我相信您希望在我的解决方案中使用注释行

import pandas as pd

period = pd.to_datetime(['2020-01-01 00:01:00', '2020-01-01 06:00:00'])
# period = pd.to_datetime(['2020-01-01 00:00:00', '2020-01-01 06:00:00'])
shift = pd.to_timedelta(['6H', '6H'])

id_with_data = set(df['ID'])
for k in range(4): # for a day (00:01 --> 24:00)
  period_mask = (period[0] <= df.index) & (df.index <= period[1])
  # period_mask = (period[0] <= df.index) & (df.index < period[1]) 
  present_ids = set(df.loc[period_mask, 'ID'])
  id_with_data = id_with_data.intersection(present_ids)
  period += shift

df = df.loc[df['ID'].isin(list(id_with_data))]
将熊猫作为pd导入
期间=截止日期时间(['2020-01-01 00:01:00','2020-01-01 06:00:00'])
#期间=截止日期时间(['2020-01-01 00:00:00','2020-01-01 06:00:00']))
shift=pd.到_timedelta(['6H','6H'])
id_与_数据=set(df['id'])
对于范围(4)内的k:#一天(00:01-->24:00)

period_mask=(period[0]Groupby
ID
,然后整数除以小时
6
,得到唯一的计数。在您的情况下,它应该大于或等于
4
,因为24小时内有
4
-6个小时的箱子,每天有4个唯一的箱子,即

垃圾箱=4

00:01-06:00

06:01-12:00

12:01-18:00

18:01-24:00

代码

mask = df.groupby('id')['date'].transform(lambda x: (x.dt.hour // 6).nunique() >= 4)
df = df[mask]

这非常接近,但是,它删除了NaN的6个周期,这一点很重要。你的意思是在原始数据帧中有NaN值要保留吗?换句话说:你不关心一个观察值是否有意义的值;它有一个值就足够了,甚至NaN。很抱歉,混淆了。我关心的是观察值是否有意义作为一个有意义的(非NaN)值。按原样,df[mask_id]之后的结果df与输入df相同,因为有几天缺少数据,这是错误的。透视表排除了缺少的数据(过去18小时)关于您的原始数据框,我不理解其中的某些内容。我假设由于缺少天数,生成的数据框将是空的。您能发布过去18小时的样本数据吗?您能提供一些样本输入和输出吗?