[英]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.