Python pandas 计算直到某列的值大于当前期间值的时间

4

我有一个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         

感谢您的提前帮助!

你如何计算第三列的值?这是问题的目的吗?还是你只想在现有的CSV文件中添加一列? - Jean-François Fabre
4个回答

3
upper_triangle     = np.triu(df.output.values < df.output.values[:, None])
df['datetime']     = pd.to_datetime(df['datetime'])
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] 通过广播创建成对比较矩阵([:, 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替换。


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

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

1
使用numpy的outer subtract函数获取差异矩阵。
然后使用numpy的triangle函数进行过滤,以确保我们只取未来时间的差异并避免过去。
使用numpy的where函数确保我们不会得到所有False值。
最后,计算时间差异。
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

计时

在小样本上,我的和Ayhan的表现似乎最佳

enter image description here

ayhan's is best over 10,000 rows

艾汉的表现在超过10000行时最佳。

enter image description here


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接