Python 3.x 如果数据至少每6小时存在一次,如何过滤时间序列?
我想验证每个ID是否至少每6小时有一次数据,并筛选出不符合此标准的ID 本质上是一个过滤器:“如果ID的数据不是至少每6小时一次,则从数据帧中删除ID” 我尝试使用相同的方法每天过滤一个,但在调整代码时遇到了问题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
# 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]GroupbyID
,然后整数除以小时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小时的样本数据吗?您能提供一些样本输入和输出吗?