使用时间序列时,在 pandas rolling 中使用 center
Use center in pandas rolling when using a time-series
我正在尝试在 pandas 滚动函数中为时间序列设置 center=True:
import pandas as pd
series = pd.Series(1, index = pd.date_range('2014-01-01', '2014-04-01', freq = 'D'))
series.rolling('7D', min_periods=1, center=True, closed='left')
但输出是:
---------------------------------------------------------------------------
NotImplementedError Traceback (most recent call last)
<ipython-input-6-6b30c16a2d12> in <module>()
1 import pandas as pd
2 series = pd.Series(1, index = pd.date_range('2014-01-01', '2014-04-01', freq = 'D'))
----> 3 series.rolling('7D', min_periods=1, center=True, closed='left')
~\Anaconda3\lib\site-packages\pandas\core\generic.py in rolling(self, window, min_periods, freq, center, win_type, on, axis, closed)
6193 min_periods=min_periods, freq=freq,
6194 center=center, win_type=win_type,
-> 6195 on=on, axis=axis, closed=closed)
6196
6197 cls.rolling = rolling
~\Anaconda3\lib\site-packages\pandas\core\window.py in rolling(obj, win_type, **kwds)
2050 return Window(obj, win_type=win_type, **kwds)
2051
-> 2052 return Rolling(obj, **kwds)
2053
2054
~\Anaconda3\lib\site-packages\pandas\core\window.py in __init__(self, obj, window, min_periods, freq, center, win_type, axis, on, closed, **kwargs)
84 self.win_freq = None
85 self.axis = obj._get_axis_number(axis) if axis is not None else None
---> 86 self.validate()
87
88 @property
~\Anaconda3\lib\site-packages\pandas\core\window.py in validate(self)
1090 # we don't allow center
1091 if self.center:
-> 1092 raise NotImplementedError("center is not implemented "
1093 "for datetimelike and offset "
1094 "based windows")
NotImplementedError: center is not implemented for datetimelike and offset based windows
预期输出是由以下各项生成的:
import pandas as pd
series = pd.Series(1, index = pd.date_range('2014-01-01', '2014-04-01', freq = 'D'))
series.rolling(7, min_periods=1, center=True).sum().head(10)
2014-01-01 4.0
2014-01-02 5.0
2014-01-03 6.0
2014-01-04 7.0
2014-01-05 7.0
2014-01-06 7.0
2014-01-07 7.0
2014-01-08 7.0
2014-01-09 7.0
2014-01-10 7.0
Freq: D, dtype: float64
但是像偏移一样使用日期时间,因为它简化了我的其他代码的一部分(这里没有发布)。
是否有其他解决方案?
谢谢
尝试以下操作(使用 pandas==0.23.3
测试):
series.rolling('7D', min_periods=1, closed='left').sum().shift(-84, freq='h')
这将使您的滚动总和在 7 天 window 中居中(通过移动 -3.5 天),并允许您使用 'datetimelike' 字符串来定义 window尺寸。请注意 shift()
只接受一个整数,因此用小时定义。
这将产生您想要的输出:
series.rolling('7D', min_periods=1, closed='left').sum().shift(-84, freq='h')['2014-01-01':].head(10)
2014-01-01 12:00:00 4.0
2014-01-02 12:00:00 5.0
2014-01-03 12:00:00 6.0
2014-01-04 12:00:00 7.0
2014-01-05 12:00:00 7.0
2014-01-06 12:00:00 7.0
2014-01-07 12:00:00 7.0
2014-01-08 12:00:00 7.0
2014-01-09 12:00:00 7.0
2014-01-10 12:00:00 7.0
Freq: D, dtype: float64
请注意,滚动总和分配到 7 天的中心 windows(使用午夜到午夜时间戳),因此居中时间戳包括“12:00:00”。
另一个选项(如您在问题末尾显示的那样)是对数据重新采样以确保它具有均匀的日期时间频率,然后使用整数作为 window 大小(window = 7
)和 center=True
。但是,您声明代码的其他部分受益于使用 'datetimelike' 字符串定义 window
,因此此选项可能并不理想。
您可以尝试对 serie/dataframe 重新采样,以便将偏移量 window 转换为固定宽度 window。
# Parameters
window_timedelta = '7D'
resample_timedelta = '1D'
# Convert offset to window size
window_size = pd.Timedelta(structure_duration) // pd.Timedelta(resample_timedelta)
# Resample serie
series_res = series.resample(resample_timedelta, on='datetime').first()
# Perform the sum on the resampled serie
series_res['window_sum'] = series_res.rolling(window_size, center=True, min_periods=1).sum()
注意:重采样中的 first
hack 仅在您知道最多有 1 pt/day 时才有效。如果您有更多,您可以将其替换为 sum
或与您的数据相关的任何内容。
注2:为缺失日期引入NaN不会导致求和值为NaN,Pandas求和时忽略它们
从 pandas 版本 1.3 开始,这 * 可以直接使用 pandas。
* 或将是(the work is merged,但截至今天 1.3 尚未发布;我针对 pandas 主分支测试了以下行)。
import pandas as pd
series = pd.Series(1, index = pd.date_range('2014-01-01', '2014-04-01', freq = 'D'))
series.rolling(7, min_periods=1, center=True).sum().head(10)
输出符合预期:
2014-01-01 4.0
2014-01-02 5.0
2014-01-03 6.0
2014-01-04 7.0
2014-01-05 7.0
2014-01-06 7.0
2014-01-07 7.0
2014-01-08 7.0
2014-01-09 7.0
2014-01-10 7.0
Freq: D, dtype: float64
我正在尝试在 pandas 滚动函数中为时间序列设置 center=True:
import pandas as pd
series = pd.Series(1, index = pd.date_range('2014-01-01', '2014-04-01', freq = 'D'))
series.rolling('7D', min_periods=1, center=True, closed='left')
但输出是:
---------------------------------------------------------------------------
NotImplementedError Traceback (most recent call last)
<ipython-input-6-6b30c16a2d12> in <module>()
1 import pandas as pd
2 series = pd.Series(1, index = pd.date_range('2014-01-01', '2014-04-01', freq = 'D'))
----> 3 series.rolling('7D', min_periods=1, center=True, closed='left')
~\Anaconda3\lib\site-packages\pandas\core\generic.py in rolling(self, window, min_periods, freq, center, win_type, on, axis, closed)
6193 min_periods=min_periods, freq=freq,
6194 center=center, win_type=win_type,
-> 6195 on=on, axis=axis, closed=closed)
6196
6197 cls.rolling = rolling
~\Anaconda3\lib\site-packages\pandas\core\window.py in rolling(obj, win_type, **kwds)
2050 return Window(obj, win_type=win_type, **kwds)
2051
-> 2052 return Rolling(obj, **kwds)
2053
2054
~\Anaconda3\lib\site-packages\pandas\core\window.py in __init__(self, obj, window, min_periods, freq, center, win_type, axis, on, closed, **kwargs)
84 self.win_freq = None
85 self.axis = obj._get_axis_number(axis) if axis is not None else None
---> 86 self.validate()
87
88 @property
~\Anaconda3\lib\site-packages\pandas\core\window.py in validate(self)
1090 # we don't allow center
1091 if self.center:
-> 1092 raise NotImplementedError("center is not implemented "
1093 "for datetimelike and offset "
1094 "based windows")
NotImplementedError: center is not implemented for datetimelike and offset based windows
预期输出是由以下各项生成的:
import pandas as pd
series = pd.Series(1, index = pd.date_range('2014-01-01', '2014-04-01', freq = 'D'))
series.rolling(7, min_periods=1, center=True).sum().head(10)
2014-01-01 4.0
2014-01-02 5.0
2014-01-03 6.0
2014-01-04 7.0
2014-01-05 7.0
2014-01-06 7.0
2014-01-07 7.0
2014-01-08 7.0
2014-01-09 7.0
2014-01-10 7.0
Freq: D, dtype: float64
但是像偏移一样使用日期时间,因为它简化了我的其他代码的一部分(这里没有发布)。
是否有其他解决方案?
谢谢
尝试以下操作(使用 pandas==0.23.3
测试):
series.rolling('7D', min_periods=1, closed='left').sum().shift(-84, freq='h')
这将使您的滚动总和在 7 天 window 中居中(通过移动 -3.5 天),并允许您使用 'datetimelike' 字符串来定义 window尺寸。请注意 shift()
只接受一个整数,因此用小时定义。
这将产生您想要的输出:
series.rolling('7D', min_periods=1, closed='left').sum().shift(-84, freq='h')['2014-01-01':].head(10)
2014-01-01 12:00:00 4.0
2014-01-02 12:00:00 5.0
2014-01-03 12:00:00 6.0
2014-01-04 12:00:00 7.0
2014-01-05 12:00:00 7.0
2014-01-06 12:00:00 7.0
2014-01-07 12:00:00 7.0
2014-01-08 12:00:00 7.0
2014-01-09 12:00:00 7.0
2014-01-10 12:00:00 7.0
Freq: D, dtype: float64
请注意,滚动总和分配到 7 天的中心 windows(使用午夜到午夜时间戳),因此居中时间戳包括“12:00:00”。
另一个选项(如您在问题末尾显示的那样)是对数据重新采样以确保它具有均匀的日期时间频率,然后使用整数作为 window 大小(window = 7
)和 center=True
。但是,您声明代码的其他部分受益于使用 'datetimelike' 字符串定义 window
,因此此选项可能并不理想。
您可以尝试对 serie/dataframe 重新采样,以便将偏移量 window 转换为固定宽度 window。
# Parameters
window_timedelta = '7D'
resample_timedelta = '1D'
# Convert offset to window size
window_size = pd.Timedelta(structure_duration) // pd.Timedelta(resample_timedelta)
# Resample serie
series_res = series.resample(resample_timedelta, on='datetime').first()
# Perform the sum on the resampled serie
series_res['window_sum'] = series_res.rolling(window_size, center=True, min_periods=1).sum()
注意:重采样中的 first
hack 仅在您知道最多有 1 pt/day 时才有效。如果您有更多,您可以将其替换为 sum
或与您的数据相关的任何内容。
注2:为缺失日期引入NaN不会导致求和值为NaN,Pandas求和时忽略它们
从 pandas 版本 1.3 开始,这 * 可以直接使用 pandas。
* 或将是(the work is merged,但截至今天 1.3 尚未发布;我针对 pandas 主分支测试了以下行)。
import pandas as pd
series = pd.Series(1, index = pd.date_range('2014-01-01', '2014-04-01', freq = 'D'))
series.rolling(7, min_periods=1, center=True).sum().head(10)
输出符合预期:
2014-01-01 4.0
2014-01-02 5.0
2014-01-03 6.0
2014-01-04 7.0
2014-01-05 7.0
2014-01-06 7.0
2014-01-07 7.0
2014-01-08 7.0
2014-01-09 7.0
2014-01-10 7.0
Freq: D, dtype: float64