重采样是时间序列分析中处理时间序列数据的一项基本技术。它是将时间序列数据从一种频率转换为另一种频率,可以改变数据的时间间隔,通过上采样增加粒度,或者通过下采样减少粒度。在本文中,我们将深入探讨 Pandas 中重采样的关键问题。
时间序列数据通常带有可能与所需分析间隔不匹配的时间戳。例如,数据以不规则的时间间隔收集,但需要以一致的频率进行建模或分析。
将 pandas 导入为 pd # 创建样本时间序列数据框 数据 = {'日期': www.sychzs.cn_range(start='2023-01-01', end='2023-12-31', freq='D'), “值”:范围(365)} df = pd.DataFrame(数据) # 将日期列设置为索引 df.set_index('日期', inplace=True) # 使用resample()方法重新采样 # 将日数据转换为月数据并计算月总和 Monthly_data = df['value'].resample('M').sum() # 将月度数据转换为季度数据,并计算每个季度的平均值 每季度数据 = 每月数据.resample('Q').mean() # 将季度数据转换为年度数据,并计算每年的最大值 年度数据 = 季度数据.resample('Y').max() 打印(每月数据) 打印(季度数据)print(annual_data)
在上面的例子中,我们首先创建了一个样本时间序列数据框,并使用 resample() 方法将其转换为不同的时间频率(每月、每季度、每年)并应用不同的聚合函数(sum、平均值、最大值)。
Resample()方法参数:
默认情况下,Pandas 的 resample() 方法使用 Dataframe 或 Series 的索引,并且这些索引应该是时间类型。但是,如果您希望根据特定列重新采样,则可以使用 on 参数。这允许您选择特定列进行重采样,即使它不是索引。
df.reset_index(drop=False, inplace=True)
df.resample('W', notallow='index')['C_0'].sum().head()
在此代码中,使用 resample() 方法对 'index' 列执行每周重新采样采样,计算每周“C_0”列的总和。
关闭参数允许控制重采样期间的打开和关闭间隔。默认情况下,某些频率如“M”、“A”、“Q”、“BM”、“BA”、“BQ”和“W”是右闭的,这意味着包含右边界,而其他频率则为右闭。左闭合,包括左边框。转换数据频率时,如果需要,可以手动设置关闭间隔。
df =generate_sample_data_datetime()
pd.concat([df.resample('W', close='left')['C_0'].sum().to_frame(name='left_close'),
df.resample('W', close='right')['C_0'].sum().to_frame(name='right_close')],
axis=1).head(5)
在这段代码中,我们演示了将每日频率转换为每周频率时左闭区间和右闭区间之间的差异。
label参数可以控制重采样时输出结果的标签。默认情况下,某些频率使用组内的右边界作为输出标签,而其他频率则使用左边界。转换数据频率时,您可以指定是使用左边界还是右边界作为输出标签。
df =generate_sample_data_datetime()
df.resample('W', label='left')['C_0'].sum().to_frame(name='left_boundary').head(5)
df.resample('W', label='right')['C_0'].sum().to_frame(name='right_boundary').head(5)
在此代码中,输出标签基于它会改变标签参数中指定的“左”或“右”。建议在实际应用中明确指定,以减少混乱。
重采样可以进行汇总统计,类似于使用groupby。使用 sum、mean、min、max 等聚合方法来汇总重采样间隔内的数据。这些聚合方法与可用于 groupby 操作的方法类似。
df.resample('D').sum()
df.resample('W').mean()
df.resample('M').min()
df.resample('Q').max()
df.resample('Y').count()
df.resample('W').std()
df.resample('M').var()
df.resample('D').median()
df.resample('M').quantile([0.25, 0.5, 0.75])
custom_agg = lambda x: x.max() - x.min()
df.resample('W').apply(custom_agg)
在时间序列数据分析中,上采样和下采样是用于操纵数据观察频率的技术。这些技术对于调整时间序列数据的粒度以满足分析需求非常有价值。
我们先生成一些数据
导入 pandas 作为 pd
将 numpy 导入为 np
defgenerate_sample_data_datetime():
np.随机.种子(123)
行数 = 365 * 2
列数 = 5
start_date = '2023-09-15' # 如果需要,您可以更改开始日期
列 = ["C_0"、"C_1"、"C_2"、"C_3"、"C_4"]
df = pd.DataFrame(np.random.randint(1, 100, 大小=(行数, 列数)), 列=列)
df.index = www.sychzs.cn_range(start=start_date, period=number_of_rows)
返回df
df =generate_sample_data_datetime()
上采样涉及增加数据的粒度,这意味着将数据从较低频率转换为较高频率。
假设您有上面生成的每日数据,并希望将其转换为 12 小时频率并计算每个间隔中“C_0”的总和:
df.resample('12H')['C_0'].sum().head(10)
代码将数据重新采样为 12 小时间隔,并在每个间隔 Sum 聚合中应用 'C_0'。该 .head(10) 用于显示结果的前 10 行。
在上采样过程中,特别是从较低频率转换为较高频率时,您将遇到由于新频率引入的间隙而丢失数据点的情况。因此,需要填补数据缺口。一般采用以下方法进行填充:
前向填充 - 用之前的可用值填充缺失值。可以使用 limit 参数限制前向填充量。
df.resample('8H')['C_0'].ffill(limit=1)
Backfill - 用下一个可用值填充缺失值。
df.resample('8H')['C_0'].bfill(limit=1)
最后填充 - 使用最接近的可用值填充缺失数据,可以向前或向后。
df.resample('8H')['C_0'].nearest(limit=1)
Fillna — 结合了前面三种方法的功能。您可以指定方法(例如“pad”/“fill”、“bfill”、“nearest”)并使用 limit 参数进行数量控制。
df.resample('8H')['C_0'].fillna(method='pad', limit=1)
Asfreq - 指定一个固定值来填充所有缺失的部分一次。例如,您可以使用 -999 来填充缺失值。
df.resample('8H')['C_0'].asfreq(-999)
插值方法 - 可以应用各种插值算法。
df.resample('8H').interpolate(method='linear').applymap(lambda x: round(x, 2))
result = df.resample('W').agg(
{
'C_0': ['总和', '平均值'],'C_1': lambda x: np.std(x, ddof=1)
}
).head()
使用聚合方法将每日时间序列数据重新采样为每周频率。并为不同的列指定不同的聚合函数。对于“C_0”,计算总和和平均值,而对于“C_1”,计算标准差。
def custom_agg(x):
聚合结果 = {
'C_0_mean': round(x['C_0'].mean(), 2),
'C_1_sum': x['C_1'].sum(),
'C_2_max': x['C_2'].max(),
'C_3_mean_plus1': round(x['C_3'].mean() + 1, 2)
}
返回 pd.Series(agg_result)
result = df.resample('W').apply(custom_agg).head()
定义了一个名为 custom_agg 的自定义聚合函数,它将 DataFrame x 作为输入并计算不同列上的各种聚合。使用 apply 方法将数据重新采样到每周频率并应用自定义聚合函数。
df['C_0_cumsum'] = df.resample('W')['C_0'].transform('cumsum')
df['C_0_rank'] = df.resample('W')['C_0'].transform('rank')
result = df.head(10)
使用transform方法计算'C_0'变量在周组中的累积和排名。 DF原有索引结构保持不变。
result = df.resample('W')['C_0', 'C_1'] \
.pipe(lambda x: x.cumsum()) \
.pipe(lambda x: x['C_1'] - x['C_0'])result = result.head(10)
使用管道方法链接下采样的“C_0”和“C_1”变量。 cumsum 函数计算累积和,第二个管道操作计算每个组的“C_1”和“C_0”之间的差。像管道一样执行顺序操作。
时间序列的重采样是将时间序列数据从一种时间频率(如每天)转换为另一种时间频率(如每月或每年),通常伴随着对数据的聚合操作。重采样是时间序列数据处理中的关键操作。通过重采样,您可以更好地了解数据的趋势和模式。
在Python中,可以使用Pandas库的resample()方法来进行时间序列重采样。