首页 > 解决方案 > 如何在python中增加样本日期

问题描述

我想用相同 ID 的前一个和下一个之间的平均值对日期进行上采样。我无法将滚动应用于日期时间类型。插值也不能像我预期的那样工作,事实上它重复了前一个日期,我不能做到这一点。所以我使用了一个 for 循环来执行此操作,但它在第一个循环时停止。你能解决这个问题吗?或者你知道另一种更快的方法吗?

这是我为构建数据框而编写的代码:

Values = [4.5, 4.2, 3.7, 4.8, 4.4, 4.6, 3.3, 5.3, 3.8 ,2.6, 2.4, 5.9, 4.9, 5.1, 5.1, 5.4, 2.7,4.9, 4.7, 5.5]
ID = [2002070, 2002070,2002070, 2002070, 2002070, 2002070, 2002070, 2002070, 2002070, 2002740,2002740,2002740,2002740,2002740,2002740,2002740,2002740,2003010,2003010,2003010]
date = ['2005-12-07', '2008-05-14', '2008-10-27', '2009-04-20', '2012-03-01', '2013-11-28','2012-08-13', '2011-07-27', '2011-11-02', '2012-06-29', '2014-02-13', '2014-06-16', '2014-09-12','2011-01-10', '2011-04-05', '2012-11-02', '2013-02-07', '2013-08-15', '2013-11-15', '2014-01-23']
date=pd.to_datetime(date)
df=pd.DataFrame({'ID': ID, 'Values': Values, 'Date': date})

         ID  Values       Date
0   2002070     4.5 2005-12-07
1   2002070     4.2 2008-05-14
2   2002070     3.7 2008-10-27
3   2002070     4.8 2009-04-20
4   2002070     4.4 2012-03-01
5   2002070     4.6 2013-11-28
6   2002070     3.3 2012-08-13
7   2002070     5.3 2011-07-27
8   2002070     3.8 2011-11-02
9   2002740     2.6 2012-06-29
10  2002740     2.4 2014-02-13
11  2002740     5.9 2014-06-16
12  2002740     4.9 2014-09-12
13  2002740     5.1 2011-01-10
14  2002740     5.1 2011-04-05
15  2002740     5.4 2012-11-02
16  2002740     2.7 2013-02-07
17  2003010     4.9 2013-08-15
18  2003010     4.7 2013-11-15
19  2003010     5.5 2014-01-23

低于“值”列的平均值计算。如您所见,我获得了日期的 NaT,我想用相同 ID 的前一个和下一个日期的平均值替换

df1 = pd.concat(
    [
        df.groupby('ID')['Values'].rolling(2).mean()
            .dropna().reset_index('ID'),
        df
    ], sort=True
).sort_index().reset_index(drop=True)

         Date       ID  Values
0  2005-12-07  2002070    4.50
1         NaT  2002070    4.35
2  2008-05-14  2002070    4.20
3  2008-10-27  2002070    3.70
4         NaT  2002070    3.95
5  2009-04-20  2002070    4.80
6         NaT  2002070    4.25
7  2012-03-01  2002070    4.40
8         NaT  2002070    4.60
9  2013-11-28  2002070    4.60
10        NaT  2002070    4.50
11 2012-08-13  2002070    3.30
12        NaT  2002070    3.95
13 2011-07-27  2002070    5.30
14        NaT  2002070    4.30
15 2011-11-02  2002070    3.80
16        NaT  2002070    4.55
17 2012-06-29  2002740    2.60
18 2014-02-13  2002740    2.40
19        NaT  2002740    2.50
20 2014-06-16  2002740    5.90
21        NaT  2002740    4.15
22        NaT  2002740    5.40
23 2014-09-12  2002740    4.90
24        NaT  2002740    5.00
25 2011-01-10  2002740    5.10
26        NaT  2002740    5.10
27 2011-04-05  2002740    5.10
28        NaT  2002740    5.25
29 2012-11-02  2002740    5.40
30        NaT  2002740    4.05
31 2013-02-07  2002740    2.70
32 2013-08-15  2003010    4.90
33        NaT  2003010    4.80
34 2013-11-15  2003010    4.70
35        NaT  2003010    5.10
36 2014-01-23  2003010    5.50

下一个代码用于计算 df(不是 df1)上日期的平均值,然后我将把平均值系列与 df 连接起来。但它不起作用。

mean = pd.Series(np.zeros(len(df)), name='mid', index=df.index)
val=[0,0]
previous = next_ = None
l = len(df)
for index, obj in enumerate(df):
    if obj == 'Date':
        if index > 0:
            previous = df[obj][index - 1]
            
            
        if index < (l - 1):
            next_ = df[obj][index + 1]
            
        val=[previous, next_]
        mean[index] = (np.array(val, dtype='datetime64[s]').view('i8').mean().astype('datetime64[s]'))

标签: pythonpandas

解决方案


如果您想用 2 个有效日期之间的“中位数”日期替换NaT,我会将日期转换为int并进行插值。

将此列添加到您的数据框

import numpy as np
df['Date_'] = df['Date'].astype(np.int64)

然后在df1上:

df1['Date'] = pd.to_datetime(df1['Date_'].interpolate()).dt.normalize()
df1.head(5)
 Date         Date_       ID  Values
0 2005-12-07  1.133914e+18  2002070    4.50
1 2007-02-24           NaN  2002070    4.35
2 2008-05-14  1.210723e+18  2002070    4.20
3 2008-10-27  1.225066e+18  2002070    3.70
4 2009-01-22           NaN  2002070    3.95


推荐阅读