熊猫检查时间序列连续性

时间:2019-01-04 12:33:33

标签: python pandas datetime

我有一个带有月度索引的DataFrame。我想检查时间指标在每月频率上是否连续,并且,如果可能的话,它会变得不连续,例如在其索引相邻的两个月之间有一定的“间隔月份”。

示例:以下时间序列数据

1964-07-31    100.00
1964-08-31     98.81
1964-09-30    101.21
1964-11-30    101.42
1964-12-31    101.45
1965-03-31     91.49
1965-04-30     90.33
1965-05-31     85.23
1965-06-30     86.10
1965-08-31     84.26
错过了1964 / 10,1965 / [1,2,7]。

3 个答案:

答案 0 :(得分:2)

按月使用asfreq来添加缺少的日期时间,将其过滤为新的Series,并在必要时使用创建月份列表的年份进行分组:

s = s.asfreq('m')
s1 = pd.Series(s[s.isnull()].index)
print (s1)
0   1964-10-31
1   1965-01-31
2   1965-02-28
3   1965-07-31
Name: 0, dtype: datetime64[ns]

out = s1.dt.month.groupby(s1.dt.year).apply(list)
print (out)
0
1964         [10]
1965    [1, 2, 7]
Name: 0, dtype: object

设置

s = pd.Series({pd.Timestamp('1964-07-31 00:00:00'): 100.0, 
               pd.Timestamp('1964-08-31 00:00:00'): 98.81, 
               pd.Timestamp('1964-09-30 00:00:00'): 101.21, 
               pd.Timestamp('1964-11-30 00:00:00'): 101.42, 
               pd.Timestamp('1964-12-31 00:00:00'): 101.45,
               pd.Timestamp('1965-03-31 00:00:00'): 91.49, 
               pd.Timestamp('1965-04-30 00:00:00'): 90.33, 
               pd.Timestamp('1965-05-31 00:00:00'): 85.23, 
               pd.Timestamp('1965-06-30 00:00:00'): 86.1, 
               pd.Timestamp('1965-08-31 00:00:00'): 84.26})

print (s)
1964-07-31    100.00
1964-08-31     98.81
1964-09-30    101.21
1964-11-30    101.42
1964-12-31    101.45
1965-03-31     91.49
1965-04-30     90.33
1965-05-31     85.23
1965-06-30     86.10
1965-08-31     84.26
dtype: float64

编辑:

如果日期时间并非总是月份的最后一天:

s = pd.Series({pd.Timestamp('1964-07-31 00:00:00'): 100.0, 
               pd.Timestamp('1964-08-31 00:00:00'): 98.81, 
               pd.Timestamp('1964-09-01 00:00:00'): 101.21, 
               pd.Timestamp('1964-11-02 00:00:00'): 101.42, 
               pd.Timestamp('1964-12-05 00:00:00'): 101.45,
               pd.Timestamp('1965-03-31 00:00:00'): 91.49, 
               pd.Timestamp('1965-04-30 00:00:00'): 90.33, 
               pd.Timestamp('1965-05-31 00:00:00'): 85.23, 
               pd.Timestamp('1965-06-30 00:00:00'): 86.1, 
               pd.Timestamp('1965-08-31 00:00:00'): 84.26})
print (s)
1964-07-31    100.00
1964-08-31     98.81
1964-09-01    101.21
1964-11-02    101.42
1964-12-05    101.45
1965-03-31     91.49
1965-04-30     90.33
1965-05-31     85.23
1965-06-30     86.10
1965-08-31     84.26
dtype: float64

#convert all months to first day
s.index = s.index.to_period('m').to_timestamp()
#MS is start month frequency
s = s.asfreq('MS')
s1 = pd.Series(s[s.isnull()].index)
print (s1)
0   1964-10-01
1   1965-01-01
2   1965-02-01
3   1965-07-01
dtype: datetime64[ns]

答案 1 :(得分:1)

假设输入中有一个数据框(第一列是日期),则可以执行以下操作:

all = pd.Series(data=pd.date_range(start=df[0].min(), end=df[0].max(), freq='M'))
mask = all.isin(df[0].values)
print(all[~mask])

输出

3    1964-10-31
6    1965-01-31
7    1965-02-28
12   1965-07-31
dtype: datetime64[ns]

这个想法是创建一个从每月第一个日期到最后一个日期的每月频率的日期范围,然后在第一列中检查这些值。

答案 2 :(得分:0)

我经常通过计算每个索引值之间的差距来做到这一点。

+-----+-----------------------|
| body_part  | body_part_name |  
------------------------------|
| 2,1,3         Chest,Abs,Neck|     
------------------------------|  

然后您可以绘制这些图形:

times_gaps = df.index - df.index.shift(1)

如果有差距,您会很快看到哪里。 如果没有间隙,您会看到一条水平线。

您还可以选择间隔时间:

times_gaps.plot()