[英]How to use days as window for pandas rolling_apply function
我有一个不规则日期的熊猫数据帧。 有没有办法使用7天作为移动窗口来计算中位数绝对偏差 ,中位数等。? 我觉得我可以以某种方式使用pandas.rolling_apply
但它不会占用窗口参数的不规则间隔日期。 我发现了一个类似的帖子https://stackoverflow.com/a/30244019/3128336 ,我正在尝试创建我的自定义功能,但仍然无法弄清楚..任何人都可以帮忙吗?
import pandas as pd
from datetime import datetime
person = ['A','B','C','B','A','C','A','B','C','A',]
ts = [
datetime(2000, 1, 1),
datetime(2000, 1, 1),
datetime(2000, 1, 10),
datetime(2000, 1, 20),
datetime(2000, 1, 25),
datetime(2000, 1, 30),
datetime(2000, 2, 8),
datetime(2000, 2, 12),
datetime(2000, 2, 17),
datetime(2000, 2, 20),
]
score = [9,2,1,3,8,4,2,3,1,9]
df = pd.DataFrame({'ts': ts, 'person': person, 'score': score})
df看起来像这样
person score ts
0 A 9 2000-01-01
1 B 2 2000-01-01
2 C 1 2000-01-10
3 B 3 2000-01-20
4 A 8 2000-01-25
5 C 4 2000-01-30
6 A 2 2000-02-08
7 B 3 2000-02-12
8 C 1 2000-02-17
9 A 9 2000-02-20
您可以使用时间增量来选择窗口中的行,然后使用apply来遍历每一行并聚合:
>>> from datetime import timedelta
>>> delta = timedelta(days=7)
>>> df_score_mean = df.apply(lambda x: np.mean(df['score'][df['ts'] <= x['ts'] + delta]), axis=1)
0 5.500000
1 5.500000
2 4.000000
3 4.600000
4 4.500000
5 4.500000
6 4.555556
7 4.200000
8 4.200000
9 4.200000
我对滚动日期函数不太熟悉 - 所以我想知道添加缺失的数据(实际上是一个充满缺失数据的Dataframe)然后你的滚动窗口应该更容易实现。
from datetime import date
import pandas as pd
##############Your Initial DataFrame ##############
person = ['A','B','C','B','A','C','A','B','C','A',]
ts = [
datetime(2000, 1, 1),
datetime(2000, 1, 1),
datetime(2000, 1, 10),
datetime(2000, 1, 20),
datetime(2000, 1, 25),
datetime(2000, 1, 30),
datetime(2000, 2, 8),
datetime(2000, 2, 12),
datetime(2000, 2, 17),
datetime(2000, 2, 15),
]
score = [9,2,1,3,8,4,2,3,1,9]
df = pd.DataFrame({'ts': ts, 'person': person, 'score': score})
################## Blank DataFrame in Same Format ###############
#Create some dates
start = date(2000,1,1)
end = date(2000,3,1)
#We have 3 people
Eperson=['A','B','C']
#They Score 0
Escore=[0]
#Need a date range in Days
ets=pd.date_range(start, end, freq='D')
dfEmpty=pd.DataFrame([(c,b,0) for b in Eperson for c in ets])
dfEmpty.columns=['ts','person','score']
################# Now Join them
dfJoin=dfEmpty.merge(df,how='outer',on=['ts','person'])
dfJoin['score']=dfJoin.score_x+dfJoin.score_y
dfJoin.score.fillna(0,inplace=True)
del dfJoin['score_x']
del dfJoin['score_y']'
您现在拥有的数据框不会缺少每个人的日期 - 如果原始日期丢失,则人/分数将为0。
我很感激,如果您处理数百万条记录,这可能无效。
对非PEP类型评论道歉......它仍在进行中。
只是根据Brian Huey的建议发布我的解决方案。
from datetime import datetime, timedelta
import statsmodels.api as sm
delta = timedelta(days=7)
def calc_mad_mean(row):
start = row['ts']
end = start + delta
subset = df['score'][(start <= df['ts']) & (df['ts'] < end)]
return pd.Series({'mad': sm.robust.mad(subset), 'med': np.median(subset)})
first_wk = df.ts.iloc[0] + delta
results = df[first_wk < df.ts].apply(calc_mad_mean, axis=1)
df.join(results, how='outer')
结果
person score ts mad med
0 A 9 2000-01-01 NaN NaN
1 B 2 2000-01-01 NaN NaN
2 C 1 2000-01-10 0.000000 1.0
3 B 3 2000-01-20 3.706506 5.5
4 A 8 2000-01-25 2.965204 6.0
5 C 4 2000-01-30 0.000000 4.0
6 A 2 2000-02-08 0.741301 2.5
7 B 3 2000-02-12 1.482602 2.0
8 C 1 2000-02-17 5.930409 5.0
9 A 9 2000-02-20 0.000000 9.0
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.