gpt4 book ai didi

python - 使用日期索引从 pandas DataFrame 计算 3 个月的滚动中位数

转载 作者:行者123 更新时间:2023-11-28 18:32:27 57 4
gpt4 key购买 nike

我从一个输入 DataFrame 开始,看起来像:

df = pd.DataFrame({"created_on":[datetime(2015, 1, 3),
datetime(2015 , 1, 5),
datetime(2015, 2, 24),
datetime(2015, 3, 6),
datetime(2015, 3, 17),
datetime(2015, 5, 31),
datetime(2015, 6, 3)],
"value":[3, 2, 1, 1, 3, 2, 2]
}
)

  created_on  value
0 2015-01-03 3
1 2015-01-05 2
2 2015-02-24 1
3 2015-03-06 1
4 2015-03-17 3
5 2015-05-31 2
6 2015-06-03 2

我想为每个月获取 created_on 在当前月份或从当前月份开始的过去 2 个月内的观察值的中值。

上述输入数据的预期输出是:

month        median_value
2015-01-01 2.5
2015-02-01 2
2015-03-01 2
2015-04-01 1
2015-05-01 2
2015-06-01 2

即对于“2015-01-01”,仅使用观察值“2015-01-03”和“2015-01-05”,对于月份“2015-02-01”,我采用“2015-01- 03”、“2015-01-05”、“2015-02-24”等。

我想从日期列中提取月份,然后像这样使用 groupby:

 df['created_on_month'] = df['created_on'].apply(
lambda dt: datetime(dt.year, dt.month, 1)
)
df.groupby('created_on_month').median()

但我不知道如何在 groupby 中对 3 个月内进行聚合,以一行可以属于多个组的方式。此解决方案的另一个问题是空月份(上例中的“2015-04-01”)不会出现在结果中。

我也尝试过使用 pandas 提供的 rolling_median 可以完成这项工作,但它与 resample 一起使用,在计算观察次数时效果很好,但中位数中位数是不一样的。

最后,我还可以使用一个简单的循环,例如:

months = pd.date_range('2015-01-01', '2015-06-01', freq='MS')
output = pd.DataFrame(index=months, columns=("month", "median_value"))

for m in months:
tmp = df [ (df.created_on >= (m - pd.DateOffset(months=2)))
& (df.created_on <= m+pd.DateOffset(months=1))]
res = {"month":m, "median_value":tmp["value"].median()}
output.loc[m] = res

print output

产生:

                          month median_value
2015-01-01 2015-01-01 00:00:00 2.5
2015-02-01 2015-02-01 00:00:00 2
2015-03-01 2015-03-01 00:00:00 2
2015-04-01 2015-04-01 00:00:00 1
2015-05-01 2015-05-01 00:00:00 2
2015-06-01 2015-06-01 00:00:00 2

但如果存在更优雅的解决方案,我会很乐意学习它。

最佳答案

好的,这应该很接近了。我使用的是 90 天的窗口 b/c 我不确定我是否可以使用 3 个月的窗口。否则,它似乎工作得很好。

df2 = pd.rolling_apply( df.set_index('created_on')['value'], window=90, 
func=np.nanmedian, freq='d', min_periods=1 )

df2[ (df2.index.day == 1)[1:] ] # [1:] is a kludge to get end of month
# rather than beginning, probably a
# better way to do that...

created_on
2015-01-31 2.5
2015-02-28 2.0
2015-03-31 2.0
2015-04-30 1.0
2015-05-31 2.0

请注意,因为我的方法与您的不同,它会在月末而不是月初标记出来,但这不会以任何方式影响结果,而且我认为月末实际上更准确。

我不确定打印出 2015 年 6 月结果的最佳方法,但它已正确存储在 6 月 3 日的 df2 中:

df2.tail(1)

created_on
2015-06-03 2

所以这只是如何最好地提取和显示信息的问题。我想用 6 月 30 日的缺失值填充原始数据框是一种方法。

关于python - 使用日期索引从 pandas DataFrame 计算 3 个月的滚动中位数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35624859/

57 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com