Pandas 每月滚动 window
Pandas monthly rolling window
我希望对按类别分组的每日数据进行 'monthly' 滚动 window。下面的代码不能正常工作,它会导致以下错误:
ValueError: <DateOffset: months=1> is a non-fixed frequency
我知道我可以使用“30D”偏移量,但是这会随着时间的推移改变日期。
我正在寻找从一个月的第 x 天到第 J 个月的第 x 天的 window 的总和。例如。 J=1:7月4日至8月4日,7月5日至8月5日,7月6日至8月6日等
几天来我一直在努力解决这个问题。任何建议或提示都将非常 表示赞赏。新年快乐。
MRE:
import pandas as pd
from io import StringIO
data = StringIO(
"""\
date logret category
2014-03-25 -0.01 A
2014-04-05 -0.02 A
2014-04-15 -0.03 A
2014-04-25 0.01 B
2014-05-05 0.03 B
2014-05-15 -0.01 A
2014-05-25 0.04 B
"""
)
df = pd.read_csv(data,sep="\s+",parse_dates=True,index_col="date")
J=1
df.groupby(['category'])['logret'].rolling(pd.DateOffset(months=J),min_periods=J*20).sum()
def MonthRollAvg(df, offset, avgColumn):
#must have DateTimeIndex
df2 = df.copy()
df2.index = df2.index + pd.DateOffset(days = -offset)
return df2.groupby([df2.index.year, df2.index.month])[avgColumn].mean()
MonthRollAvg(df, 5, 'logret')
我能想到的最简单的方法是使用 pd.DateOffset 移动日期然后求平均值。因此,如果您想要从 6 号到 6 号,您可以使用 5 的偏移量来使该月的 6 号基本上成为该月的 1 号,然后找到每个月的平均值。这将使月份的长度保持原样。你只需要记录你在哪一天之间平均。
在中间步骤 'normalize' 你的时间戳,这样每个月都有 31 天,然后聚合,最后从你的结果中删除 'inserted' 行。
只要您的聚合具有中性元素,它就有效。
- 从原始 df 创建一个索引,所有时间戳都是字符串
- 使用表示时间戳的字符串创建另一个索引,其中所有月份都有 31 天
- 合并、聚合等
- select 来自原始 df
的索引聚合
- 向原始 df 添加新列
import pandas as pd
from io import StringIO
data = StringIO(
"""\
date logret category
2014-03-25 -0.01 A
2014-04-05 -0.02 A
2014-04-15 -0.03 A
2014-04-25 0.01 B
2014-05-05 0.03 B
2014-05-15 -0.01 A
2014-05-25 0.04 B
"""
)
df = pd.read_csv(data,sep="\s+",parse_dates=True,index_col="date")
idx = df.index.strftime('%Y-%m-%d')
y0 = df.index[0].year
y1 = df.index[-1].year
padded = pd.DataFrame(index=[f'{y}-{m:02}-{d:02}'
for y in range(y0,y1+1)
for m in range(1, 13)
for d in range(1, 32)])[idx[0]:idx[-1]]
# Note that the rolling interval is exclusive at start
df.assign(rolling_aggregate=padded.join(df.set_index(idx)).fillna(0).rolling(31).agg(sum).loc[idx])
产量:
logret category rolling_aggregate
date
2014-03-25 -0.01 A NaN
2014-04-05 -0.02 A NaN
2014-04-15 -0.03 A NaN
2014-04-25 0.01 B -0.04
2014-05-05 0.03 B 0.01
2014-05-15 -0.01 A 0.03
2014-05-25 0.04 B 0.06
我希望对按类别分组的每日数据进行 'monthly' 滚动 window。下面的代码不能正常工作,它会导致以下错误:
ValueError: <DateOffset: months=1> is a non-fixed frequency
我知道我可以使用“30D”偏移量,但是这会随着时间的推移改变日期。
我正在寻找从一个月的第 x 天到第 J 个月的第 x 天的 window 的总和。例如。 J=1:7月4日至8月4日,7月5日至8月5日,7月6日至8月6日等
几天来我一直在努力解决这个问题。任何建议或提示都将非常 表示赞赏。新年快乐。
MRE:
import pandas as pd
from io import StringIO
data = StringIO(
"""\
date logret category
2014-03-25 -0.01 A
2014-04-05 -0.02 A
2014-04-15 -0.03 A
2014-04-25 0.01 B
2014-05-05 0.03 B
2014-05-15 -0.01 A
2014-05-25 0.04 B
"""
)
df = pd.read_csv(data,sep="\s+",parse_dates=True,index_col="date")
J=1
df.groupby(['category'])['logret'].rolling(pd.DateOffset(months=J),min_periods=J*20).sum()
def MonthRollAvg(df, offset, avgColumn):
#must have DateTimeIndex
df2 = df.copy()
df2.index = df2.index + pd.DateOffset(days = -offset)
return df2.groupby([df2.index.year, df2.index.month])[avgColumn].mean()
MonthRollAvg(df, 5, 'logret')
我能想到的最简单的方法是使用 pd.DateOffset 移动日期然后求平均值。因此,如果您想要从 6 号到 6 号,您可以使用 5 的偏移量来使该月的 6 号基本上成为该月的 1 号,然后找到每个月的平均值。这将使月份的长度保持原样。你只需要记录你在哪一天之间平均。
在中间步骤 'normalize' 你的时间戳,这样每个月都有 31 天,然后聚合,最后从你的结果中删除 'inserted' 行。
只要您的聚合具有中性元素,它就有效。
- 从原始 df 创建一个索引,所有时间戳都是字符串
- 使用表示时间戳的字符串创建另一个索引,其中所有月份都有 31 天
- 合并、聚合等
- select 来自原始 df 的索引聚合
- 向原始 df 添加新列
import pandas as pd
from io import StringIO
data = StringIO(
"""\
date logret category
2014-03-25 -0.01 A
2014-04-05 -0.02 A
2014-04-15 -0.03 A
2014-04-25 0.01 B
2014-05-05 0.03 B
2014-05-15 -0.01 A
2014-05-25 0.04 B
"""
)
df = pd.read_csv(data,sep="\s+",parse_dates=True,index_col="date")
idx = df.index.strftime('%Y-%m-%d')
y0 = df.index[0].year
y1 = df.index[-1].year
padded = pd.DataFrame(index=[f'{y}-{m:02}-{d:02}'
for y in range(y0,y1+1)
for m in range(1, 13)
for d in range(1, 32)])[idx[0]:idx[-1]]
# Note that the rolling interval is exclusive at start
df.assign(rolling_aggregate=padded.join(df.set_index(idx)).fillna(0).rolling(31).agg(sum).loc[idx])
产量:
logret category rolling_aggregate
date
2014-03-25 -0.01 A NaN
2014-04-05 -0.02 A NaN
2014-04-15 -0.03 A NaN
2014-04-25 0.01 B -0.04
2014-05-05 0.03 B 0.01
2014-05-15 -0.01 A 0.03
2014-05-25 0.04 B 0.06