如何解决在 Pandas MultiIndex 中重新采样会丢失值
我有一些从 2003 年到 2011 年的分层数据,它们最终变成了如下所示的时间序列数据:
polar_temp
Station_Number Date Value
417 CA002100805 20030101 -296
423 CA002202570 20030101 -269
425 CA002203058 20030101 -268
427 CA002300551 20030101 -23
428 CA002300902 20030101 -200
我在 Station_Number 和 Date 上设置了多索引:
polar_temp['Date'] = pd.to_datetime(polar_temp['Date'],format='%Y%m%d')#.dt.strftime("%Y-%m-%d")
polar_temp = polar_temp.set_index(['Station_Number',"Date"])
Value
Station_Number Date
CA002100805 2003-01-01 -296
CA002202570 2003-01-01 -269
CA002203058 2003-01-01 -268
CA002300551 2003-01-01 -23
CA002300902 2003-01-01 -200
现在我想通过使用以下方法计算每 8 天的 Value 平均值来对数据进行重新采样:
polar_temp8d = polar_temp.groupby([pd.Grouper(level='Station_Number'),pd.Grouper(level='Date',freq='8D')]).mean()
Value
Station_Number Date
CA002100805 2003-01-01 -300.285714
2003-01-09 -328.750000
2003-01-17 -325.500000
2003-01-25 -385.833333
2003-02-02 -194.428571
... ...
USW00027515 2005-06-23 76.625000
2005-07-01 42.375000
2005-07-09 94.500000
2005-07-17 66.500000
2005-07-25 56.285714
所以这里的问题是,pandas 只对 2003 年到 2005 年的年份进行重新采样,因此完全忽略了 2006 年到 2011 年的年份。现在我的问题是:我是否使用 Grouper 函数正确分析了时间序列数据,还是我遗漏了什么?
编辑 1:
通过运行:
print(polar_temp.loc['CA002300902'].sort_index(ascending=False))
Value
Date
2011-12-31 -288
2011-12-30 -299
2011-12-29 -347
2011-12-28 -310
2011-12-27 -239
可以看到重采样前的台站有到2011年的数据。
解决方法
我创建了合成数据来测试您的方法,并且效果很好。 然后我任意删除了数据点,以查看聚合是否会因缺少日期而失败,并跳过时间序列中的缺失值,如下面的输出所示。因此,我仍然不明白为什么您的输出在 2005 年停止。
没有重采样和插值的输出:
Value
Station_Number Date
CA002100805 2003-01-02 -195.545455
2003-01-10 -144.963636
2003-01-18 -158.045455
2003-01-26 -151.533333
2003-02-03 -196.300000
2003-04-08 -159.963636
2003-04-16 -157.115385
2003-04-24 -150.191489
2003-05-02 -146.113924
2003-05-10 -133.367347
请注意它如何完全跳过 2003 年 3 月的数据点。
您可以按以下方式对问题进行排序:
1. Adding missing dates to the DataFrame
2. 用 interpolate()
import pandas as pd
import numpy as np
# Sets random seed
np.random.seed(42)
# Sample size
size=10**5
station_numbers = ['CA002100805','CA002202570','CA002203058','CA002300551','CA002300902']
stations = [station_numbers[i] for i in
np.random.randint(low=0,high=len(station_numbers),size=size)]
values = np.random.randint(low=-400,high=100,size=size)
dates_list = pd.date_range(start='2003-01-01',end='2011-12-31')
###################################
#### TESTS with missing dates #####
###################################
# Removes dates from dates_list to test
percent_to_remove = 1/3
items_to_remove = len(dates_list) * percent_to_remove
# Index of items to remove
rem_idx = set()
while len(rem_idx) < items_to_remove:
# Thanks to Jon Kiparsky's answer on this thread
# https://stackoverflow.com/questions/28037158/how-to-not-repeat-randint-value
rem_idx.add(np.random.randint(0,len(dates_list)))
dates_list = dates_list.delete(list(rem_idx))
# Arbitratily removes dates in sequence to test
dates_list = dates_list.delete(range(20,60))
###################################
###################################
dates = [dates_list[i] for i in
np.random.randint(low=0,high=len(dates_list),size=size)]
# Creates DataFrame
data = (pd.DataFrame({'Station_Number': stations,'Date': dates,'Value': values})
.set_index('Date')
.sort_index())
# Creates one row per day
data = data.groupby('Station_Number').resample('D').mean()
# Fills NAs with standard interpolation strategy
data = data.interpolate()
# Calculates 8-day mean value
eight_day_mean = data.groupby([pd.Grouper(level='Station_Number'),pd.Grouper(level='Date',freq='8D')]).mean()
重采样和插值输出:
Value
Station_Number Date
CA002100805 2003-01-02 -178.138024
2003-01-10 -135.644524
2003-01-18 -147.253977
2003-01-26 -147.694712
2003-02-03 -200.642180
2003-02-11 -203.057708
2003-02-19 -192.821042
2003-02-27 -182.584375
2003-03-07 -172.347708
2003-03-15 -162.111042
2003-03-23 -151.874375
2003-03-31 -141.637708
2003-04-08 -154.028469
2003-04-16 -151.099405
2003-04-24 -156.152083
现在请注意它如何包含 2003 年 3 月的数据点,这些数据点介于 2003 年 2 月和 2003 年 4 月的值之间,因为采用了插值策略。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。