Python pandas计算时间,直到列中的值大于当前时间段中的值

时间:2016-08-04 19:27:07

标签: python datetime pandas time

我在python中有一个pandas数据帧,有几列和一个日期时间戳。我想创建一个新列,用于计算输出小于当前时间段的时间。

我目前的表格如下:

 datetime               output
 2014-05-01 01:00:00    3
 2014-05-01 01:00:01    2
 2014-05-01 01:00:02    3
 2014-05-01 01:00:03    2
 2014-05-01 01:00:04    1

我正试图让我的桌子有一个额外的列,看起来像这样:

 datetime               output     secondsuntildecrease
 2014-05-01 01:00:00    3         1
 2014-05-01 01:00:01    2         3
 2014-05-01 01:00:02    3         1
 2014-05-01 01:00:03    2         1
 2014-05-01 01:00:04    1         

提前感谢!

4 个答案:

答案 0 :(得分:3)

upper_triangle = np.triu(df.output.values < df.output.values[:, None])
df['s_until_dec'] = df['datetime'][upper_triangle.argmax(axis=1)].values - df['datetime']
df.loc[~upper_triangle.any(axis=1), 's_until_dec'] = np.nan
df
             datetime  output           s_until_dec
0 2014-05-01 01:00:00       3              00:00:01
1 2014-05-01 01:00:01       2              00:00:03
2 2014-05-01 01:00:02       3              00:00:01
3 2014-05-01 01:00:03       2              00:00:01
4 2014-05-01 01:00:04       1                   NaT

以下是它的工作原理:

df.output.values < df.output.values[:, None]这会创建一个带有brodcasting的成对比较矩阵([:, None]创建一个新轴):

df.output.values < df.output.values[:, None]
Out: 
array([[False,  True, False,  True,  True],
       [False, False, False, False,  True],
       [False,  True, False,  True,  True],
       [False, False, False, False,  True],
       [False, False, False, False, False]], dtype=bool)

例如,output[0]小于output[1],因此(0,1)的矩阵元素为True。我们需要上三角形,所以我使用np.triu来获得该矩阵的上三角形。 argmax()将为我提供第一个True值的索引。如果我将其传递给iloc,我将得到相应的日期。当然除了最后一个。它包含所有False,因此我需要将其替换为np.nan.loc部分检查该案例的矩阵并替换为np.nan

答案 1 :(得分:2)

df = pd.DataFrame([3, 2, 3, 2, 1], index=pd.DatetimeIndex(start='2014-05-01 01:00:00', periods=5, freq='S'), columns=['output'])

def f(s):
    s = s[s & (s.index > s.name)]
    if s.empty:
        return np.nan
    else:
        return (s.index[0] - s.name).total_seconds()

df['secondsuntildecrease'] = df['output'].apply(lambda x: df['output'] < x).apply(f, axis=1)

df

输出

                     output  secondsuntildecrease
2014-05-01 01:00:00       3                   1.0
2014-05-01 01:00:01       2                   3.0
2014-05-01 01:00:02       3                   1.0
2014-05-01 01:00:03       2                   1.0
2014-05-01 01:00:04       1                   NaN

答案 2 :(得分:1)

这是一个单线

df['seconds_until'] = df.apply(lambda x: pd.to_datetime(df.loc[(df['output'] < x['output']) & (df['datetime'] > x['datetime']), 'datetime'].min()) - pd.to_datetime(x[
'datetime']), axis=1)

输出

              datetime  output  seconds_until
0  2014/05/01 01:00:00       3       00:00:01
1  2014/05/01 01:00:01       2       00:00:03
2  2014/05/01 01:00:02       3       00:00:01
3  2014/05/01 01:00:03       2       00:00:01
4  2014/05/01 01:00:04       1            NaT

答案 3 :(得分:1)

使用numpy的外部减法来获得差异矩阵。

然后使用numpy的三角函数进行过滤,以确保我们仅在未来的时间内采取差异并远离过去。

使用numpy的位置确保我们不会得到所有错误

最后,采取时间差异。

df = pd.DataFrame(
    dict(output=[3, 2, 3, 2, 1],
         datetime=pd.DatetimeIndex(start='2014-05-01 01:00:00', periods=5, freq='S'))
)

gt0 = np.triu(np.subtract.outer(df.output, df.output), 1) > 0
idx = np.where(gt0.any(1), gt0.argmax(1), np.nan)
-(df.datetime - df.loc[idx, 'datetime'].values).dt.total_seconds()

0    1.0
1    3.0
2    1.0
3    1.0
4    NaN
Name: datetime, dtype: float64

时序

Mine和ayhan似乎比小样本效果最好

enter image description here

ayhan最好超过10,000行

enter image description here