【问题标题】:Pandas: complex condition on datetime熊猫:日期时间的复杂条件
【发布时间】:2017-09-24 16:11:18
【问题描述】:

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

日期值 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 并计算平均值)。

before_1hr_mean 之前的日期值 4 2010-01-05 06:20:00 346.5 65.35

我使用iterrows() 来解决这个问题,如下面的代码。但是这种方法真的很慢,而且函数iterrows()在pandas中通常不推荐使用,这行会变成as

[更新]

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

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

【问题讨论】:

  • 您是否意识到您的示例按天递增...这意味着结果与您的原始数据相同。在这个例子中,我们取一行的平均值。
  • 另外,您的代码显示df['date'] &lt;= row['date'] 暗示您希望将当前行的值包含在平均值中。但是您的示例计算排除了当前行的值。这也意味着您的第一行的计算将为空。
  • 对不起我的错误代码。我把等号放在错误的位置。从您的代码中学到很多东西,在这种情况下 null 或 Nan 是可以的。

标签: python pandas datetime time-series


【解决方案1】:

我冒昧地更改了您的数据,以便在同一天完成。只有这样我才能理解你的问题。

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

请注意,如果没有一小时的先前数据可以计算,您会得到空值。

【讨论】:

  • 我不完全确定我知道 OP 要求什么,但“before_1hr_mean”列与 value 列完全相同是不是有点奇怪?
  • 这很奇怪......我什至没有注意到这一点。好吧,现在这打开了一罐蠕虫的歧义。 OP 需要一个更好的例子,或者我可以破译他们的代码在做什么。顺便说一句,他们的代码产生同样的东西。
  • 是的,我认为 OP 需要说明为什么每一行都是不同的 日期,尽管我们谈论的是“1 小时之前”。
  • @DSM 如果您认为这有道理,请告诉我
  • 感谢您的回答!
猜你喜欢
  • 2018-11-15
  • 1970-01-01
  • 1970-01-01
  • 2021-11-01
  • 2016-07-05
  • 2019-07-19
  • 2022-10-12
  • 2017-02-23
  • 2016-11-09
相关资源
最近更新 更多