如何确定使用熊猫数据框捕获数据?
问题描述:
我正在处理由不完整时间序列组成的每小时监测数据,即一年中(或几年内)数小时的数据将从我的数据框中消失。如何确定使用熊猫数据框捕获数据?
我想确定数据捕获,即一个月,一个季节或一年中存在的值的百分比。
这适用于下面的代码(用于为月度重采样编写的演示) - 但是那段代码看起来效率不高,因为我需要创建第二个小时数据帧,并且需要重新采样两个数据帧。
有没有更优雅的解决方案呢?
import numpy as np
import pandas as pd
# create dummy series
t1 = pd.date_range(start="1997-01-01 05:00", end="1997-04-25 17:00", freq="H")
t2 = pd.date_range(start="1997-06-11 15:00", end="1997-06-15 12:00", freq="H")
t3 = pd.date_range(start="1997-06-18 00:00", end="1997-08-22 23:00", freq="H")
df1 = pd.DataFrame(np.random.randn(len(t1)), index=t1)
df2 = pd.DataFrame(np.random.randn(len(t2)), index=t2)
df3 = pd.DataFrame(np.random.randn(len(t3)), index=t3)
df = pd.concat((df1, df2, df3))
# create time index with complete hourly coverage over entire years
tstart = "%i-01-01 00:00"%(df.index.year[0])
tend = "%i-12-31 23:00"%(df.index.year[-1])
tref = pd.date_range(start=tstart, end=tend, freq="H")
dfref = pd.DataFrame(np.zeros(len(tref)), index=tref)
# count number of values in reference dataframe and actual dataframe
# Example: monthly resampling
cntref = dfref.resample("MS", "count")
cnt = df.resample("MS", "count").reindex(cntref.index).fillna(0)
for i in range(len(cnt.index)):
print cnt.index[i], cnt.values[i], cntref.values[i], cnt.values[i]/cntref.values[i]
答
由于没有进一步的建议,它看起来好像最初发布的解决方案是最有效的。
答
pandas
“Timedelta
将这样的伎俩:
# Time delta between rows of the df
df['index'] = df.index
pindex = df['index'].shift(1)
delta = df['index'] - pindex
# Any delta > 1H means a missing data period
missing_delta = delta[delta > pd.Timedelta('1H')]
# Sum of missing data periods divided by total period
ratio_missing = missing_delta.sum()/(df.index[-1] - df.index[0])
答
您可以使用TimeGrouper。
# Create an hourly index spanning the range of your data.
idx = pd.date_range(pd.Timestamp(df.index[0].strftime('%Y-%m-%d %H:00')),
pd.Timestamp(df.index[-1].strftime('%Y-%m-%d %H:00')),
freq='H')
# Use TimeGrouper to calculate the fraction of observations from `df` that are in the
# hourly time index.
>>> (df.groupby(pd.TimeGrouper('M')).size()/
pd.Series(idx).reindex(idx).groupby(pd.TimeGrouper('M')).size())
1997-01-31 1.000000
1997-02-28 1.000000
1997-03-31 1.000000
1997-04-30 0.825000
1997-05-31 0.000000
1997-06-30 0.563889
1997-07-31 1.000000
1997-08-31 1.000000
Freq: M, dtype: float64
+0
这有效(如果我在上面的示例中调整代码以计算idx为tref)。但是,在我的电脑上,它需要原始解决方案的两倍左右。分组看起来本质上很慢 - 如果分组或操作更复杂,它的优势可能会带来回报。 – maschu
这个解决方案很有趣也很快,但不幸的是我没有做我想做的事情,因为我需要每个月的数据捕获,而不仅仅是总分数。但是了解Timedelta很好。 – maschu