熊猫:日期时间的复杂情况

时间:2017-04-27 03:16:22

标签: python pandas datetime time-series

我有一个带有日期时间类型列和浮点类型列的数据框。

                     date  value
0     2010-01-01 01:23:00  21.2
1     2010-01-02 01:33:00  63.4
2     2010-01-03 06:02:00  80.6
3     2010-01-04 06:05:00  50.1
4     2010-01-05 06:20:00  346.5
5     2010-01-06 07:44:00  111.8
6     2010-01-07 08:00:00  113.1
7     2010-01-08 08:22:00  10.6
8     2010-01-09 09:00:00  287.2
9     2010-01-10 09:14:00  1652.6

我想创建一个新列来记录当前迭代行时间之前一小时的平均值。

[更新]示例

如果当前迭代为4 2010-01-05 06:20:00 346.5,我需要计算(50.1 + 80.6) / 2(范围2010-01-05 05:20:00~2010-01-05 06:20:00中的值并计算平均值)。

                     date  value  before_1hr_mean
4     2010-01-05 06:20:00  346.5  65.35

我使用iterrows()解决此问题,如下面的代码。但是这个方法非常慢,并且pandas中通常不建议使用函数iterrows(),这一行将变为

[UPDATE]

df['before_1hr_mean'] = np.nan
for index, row in df.iterrows():
   df.loc[index, 'before_1hr_mean'] = df[(df['date'] < row['date']) & \
       (df['date'] >= row['date'] - pd.Timedelta(hours=1))]['value'].mean()

有没有更好的方法来处理这种情况?

1 个答案:

答案 0 :(得分:3)

我冒昧地改变你的数据,以便在同一天完成。这是我理解你的问题的唯一方法。

df.join(
    df.set_index('date').value.rolling('H').mean().rename('before_1hr_mean'),
    on='date'
)

                 date   value  before_1hr_mean
0 2010-01-01 01:23:00    21.2        21.200000
1 2010-01-01 01:33:00    63.4        42.300000
2 2010-01-01 06:02:00    80.6        80.600000
3 2010-01-01 06:05:00    50.1        65.350000
4 2010-01-01 06:20:00   346.5       159.066667
5 2010-01-01 07:44:00   111.8       111.800000
6 2010-01-01 08:00:00   113.1       112.450000
7 2010-01-01 08:22:00    10.6        78.500000
8 2010-01-01 09:00:00   287.2       148.900000
9 2010-01-01 09:14:00  1652.6       650.133333

如果要排除当前行,则必须跟踪滚动小时的总和和计数,并在调整当前值后退出平均值。

s = df.set_index('date')
sagg = s.rolling('H').agg(['sum', 'count']).value.rename(columns=str.title)
agged = df.join(sagg, on='date')
agged

                 date   value     Sum  Count
0 2010-01-01 01:23:00    21.2    21.2    1.0
1 2010-01-01 01:33:00    63.4    84.6    2.0
2 2010-01-01 06:02:00    80.6    80.6    1.0
3 2010-01-01 06:05:00    50.1   130.7    2.0
4 2010-01-01 06:20:00   346.5   477.2    3.0
5 2010-01-01 07:44:00   111.8   111.8    1.0
6 2010-01-01 08:00:00   113.1   224.9    2.0
7 2010-01-01 08:22:00    10.6   235.5    3.0
8 2010-01-01 09:00:00   287.2   297.8    2.0
9 2010-01-01 09:14:00  1652.6  1950.4    3.0

然后做一些数学并分配一个新列

df.assign(before_1hr_mean=agged.eval('(Sum - value) / (Count - 1)'))

                 date   value  before_1hr_mean
0 2010-01-01 01:23:00    21.2              NaN
1 2010-01-01 01:33:00    63.4            21.20
2 2010-01-01 06:02:00    80.6              NaN
3 2010-01-01 06:05:00    50.1            80.60
4 2010-01-01 06:20:00   346.5            65.35
5 2010-01-01 07:44:00   111.8              NaN
6 2010-01-01 08:00:00   113.1           111.80
7 2010-01-01 08:22:00    10.6           112.45
8 2010-01-01 09:00:00   287.2            10.60
9 2010-01-01 09:14:00  1652.6           148.90

请注意,如果没有足够数小时的先前数据来计算,您将获得空值。