繁体   English   中英

如何使用days作为pandas rolling_apply函数的窗口

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM