过去2个月的平均值

时间:2019-10-07 14:38:11

标签: python python-3.x pandas

鉴于下表,仅给出了datenumber列,我想推断avg_last_2m列(计算最近两个月number列的平均值),如下所示:

enter image description here

例如, 给定日期20190909,最近2个月将从日期20190709到日期20190908,在此期间,我们有日期20190805(数字= {{1} }),因此最近2个月的平均时间为1

另一个示例是1/1=1.0,最近2个月将从日期20190930到日期20190730,我们有日期20190929(数字= 1)和日期20190805(数字= 0),因此最近2个月的平均值为20190909

我们如何基于列(1+0)/2=0.5avg_last_2m计算列date?效率在这里很重要,因为实际上我将有大约10万行数据。

这是数据框的代码

number

4 个答案:

答案 0 :(得分:3)

这里的问题是日历月份减法。它不是固定的窗口(天数),所以滚动并不简单(或可能吗?)。

可以通过完全合并来完成,但是如果您的DataFrame很长,那么很快就变得不切实际。对于10万行,我们最多可以有10B行DataFrame。并非没有,但一定会突破极限。可能会有更智能的算法可以执行此合并,而无需加入显然不在2个月内的行。

设置

import pandas as pd
df = pd.DataFrame({'date':['20190606','20190610','20190708','20190805','20190909','20190930'],
                   'number':[3,5,4,1,0,0]})

df['date'] = pd.to_datetime(df.date, format='%Y%m%d')
#df = df.sort_values('date').reset_index(drop=True)  # Logic below requires sorting

代码

m = df.reset_index().assign(k=1)
m = m.merge(m, on='k').query('index_x > index_y')  # Full merge, no double count

# Only take average of observations within 2 months. 
m = m[m.date_x < (m.date_y + pd.offsets.DateOffset(months=2))].groupby('date_x').number_y.mean()

df['avg_last_2m'] = df.date.map(m)
#        date  number  avg_last_2m
#0 2019-06-06       3          NaN
#1 2019-06-10       5          3.0
#2 2019-07-08       4          4.0
#3 2019-08-05       1          4.0
#4 2019-09-09       0          1.0
#5 2019-09-30       0          0.5

我们可以通过很慢的循环来换取时间。大概需要10分钟。

def prev_2m(date, df):
    m = (df.date < date) & (df.date > (date - pd.offsets.DateOffset(months=2)))
    return df.loc[m, 'number'].mean()

df['avg_last_2m'] = df.date.apply(prev_2m, df=df)

答案 1 :(得分:0)

我只是必须尝试一下,我真的不知道这是最快还是性能最好的方法,但是它可以工作。也许有人对优化有想法,甚至有完全不同的方法?

import datetime
d = {'date':['20190606','20190610','20190708','20190805','20190909','20190930'],'number':[3,5,4,1,0,0]}
memory_dict = {}
memory_counter = {}
number_out = []
for date, number in reversed(list(zip(d['date'],d['number']))):
    dt = datetime.datetime.strptime(date, '%Y%m%d')
    for mem in list(memory_dict):
        if((mem-dt).days < 60):
            memory_dict[mem] += number
            memory_counter[mem] += 1
        else:
            number_out.append(memory_dict[mem]/memory_counter[mem])
            del memory_dict[mem]
    dt = dt - datetime.timedelta(days=1)
    memory_dict[dt] = 0
    memory_counter[dt] = 0
for mem in memory_dict:
    if (memory_counter[mem] != 0):
        number_out.append(memory_dict[mem]/memory_counter[mem])
    else:
        number_out.append(-1)
number_out.reverse()
print(number_out)

我本来以为它可能适用于列表推导,但我想不出一种方法。这个问题使我很感兴趣,我不得不尝试一下。

答案 2 :(得分:0)

下面为我工作。

$(this).attr('hidden')

答案 3 :(得分:-1)

这应该可以解决问题

test_data=pd.DataFrame({'date':pd.to_datetime(['20190606','20190610','20190708','20190805','20190909','20190930']),'number':[3,5,4,1,0,0],\
                       'avg_last_2m':[None,3,4,4,1,0.5]})
offset =pd.offsets.DateOffset(months=2)

mean_k_months = test_data[test_data['date']>max(test_data['date'])-offset]['number'].mean() 

在这种情况下,您将使用最近的日期作为前两个月的方向,但可以轻松地进行调整。

相关问题