2017-04-27 37 views
4

我有一个数据帧与日期时间类型列和浮点类型列。熊猫:日期时间的复杂条件

 
        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 

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

[UPDATE]实施例

如果当前迭代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()来解决这个问题,如下面的代码。但这种方法很慢,通常不是在大熊猫推荐功能iterrows()和该行将会变得

[更新]

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() 

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

+0

您是否意识到您的示例会在几天内递增......这意味着结果与原始数据完全相同。在这个例子中,我们采用了一行的平均值。 – piRSquared

+0

此外,你的代码表示'df ['date'] <= row ['date']'意味着你想在当前行的值中包含当前行的值。但是您的示例计算中,您排除了当前行的值。这也意味着你的第一行的计算将为空。 – piRSquared

+0

对不起,我的错误代码。我把等号放在错误的位置上。从你的代码中学到很多东西,在这种情况下,null或者Nan是可以的。 – zue

回答

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 

发现得到空当没有值得以前的数据来计算一个多小时。

+1

我并不完全相信我知道OP所要求的内容,但是“before_1hr_mean”列与值列完全一样是不是有点奇怪? – DSM

+0

这很奇怪......我甚至没有注意到这一点。那么现在呢,这会让一堆蠕虫变得模糊不清。 OP需要一个更好的例子,或者我可以破译他们的代码正在做什么。顺便说一句,他们的代码产生同样的事情。 – piRSquared

+0

是的,我认为OP需要指定为什么每行是不同的_date_,尽管我们正在谈论“1小时前”。 – DSM