鉴于下表,仅给出了date
和number
列,我想推断avg_last_2m
列(计算最近两个月number
列的平均值),如下所示:
例如,
给定日期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.5
和avg_last_2m
计算列date
?效率在这里很重要,因为实际上我将有大约10万行数据。
这是数据框的代码
number
答案 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()
在这种情况下,您将使用最近的日期作为前两个月的方向,但可以轻松地进行调整。