如何使用Python计算数据框中特定行值之间的时间差?

4

df 的样子如下所示:


Time                    A 

2019-05-18 01:15:28     7
2019-05-18 01:28:11     7
2019-05-18 01:36:36     12
2019-05-18 01:39:47     12
2019-05-18 01:53:32     12
2019-05-18 02:05:37     7

我知道如何计算连续行之间的时间差,但我想在A列中的值为7到12时计算时间差。

期望输出:


Time                    A   Time_difference

2019-05-18 01:15:28     7   0
2019-05-18 01:28:11     7   0
2019-05-18 01:36:36     12  00:21:08
2019-05-18 01:39:47     12  0
2019-05-18 01:53:32     12  0
2019-05-18 02:05:37     12  0


您需要进行特定的计算,还是有关要从哪些行中减去的规则?一般来说,有timedelta对象可用于时间计算。 - Aryerez
没有特定的规则,比如在A列出现7到12之间的时间窗口。 - hakuna_code
1
在“7”和“12”之间可能有多个“7”或“12”的值吗? - jezrael
1
你能否在 最小化、完整化和可验证示例 中添加更多的 712 值?我认为也可以添加更多连续的 712 或两者都有。 - jezrael
我做到了!谢谢。 - hakuna_code
显示剩余3条评论
3个回答

2
您可以使用loc来隔离数据框中的任何值。返回的是一个Series,可以像列表一样进行索引。使用[0]来获取Series中的第一个出现的值。
times = [
    '2019-05-18 01:15:28',
    '2019-05-18 01:28:11',
    '2019-05-18 01:36:36',
    '2019-05-18 01:39:47',
    '2019-05-18 01:53:32',
    '2019-05-18 02:05:37'
]

a = [9, 7, 7, 5, 12, 12]

df = pd.DataFrame({'times':times, 'a':a})
df.times = pd.to_datetime(df['times'])
pd.Timedelta(df.loc[df.a == 12, 'times'].values[0] - df.loc[df.a == 7, 'times'].values[0])

Timedelta('0 days 00:25:21')

或者为了更好的可读性,我们可以将代码拆分并在新变量上进行计算:

times = [
    '2019-05-18 01:15:28',
    '2019-05-18 01:28:11',
    '2019-05-18 01:36:36',
    '2019-05-18 01:39:47',
    '2019-05-18 01:53:32',
    '2019-05-18 02:05:37'
]

a = [9, 7, 7, 5, 12, 12]

df = pd.DataFrame({'times':times, 'a':a})
df.times = pd.to_datetime(df['times'])
end = df.loc[df.a == 12, 'times'].values[0]
start = df.loc[df.a == 7, 'times'].values[0]
pd.Timedelta(end - start)

时间差为0天00:25:21


谢谢!但是它没有遍历整个数据框来寻找另一个窗口(7到12)。就像我在期望输出中所指定的,无论何时数据框中有一个7到12的窗口,都应该计算差值。我将微调您的逻辑并进行检查... - hakuna_code
我认为你期望的输出并不是这样的。如果你想让它继续下去,难道不会有另一个时间差吗?在一条评论中,你明确表示想要第一次出现的情况。 - Ollie in PGH

1

解释:

  • (df["A"] == 7).cumsum() 将行分组为每7个一组
  • 对于每组7个,如果存在12,则将该组的第一行减去12的第一行
  • 如果没有,则将该组的第一行值传递到下一组,直到找到12

import pandas as pd
import numpy as np

np.random.seed(10)
date_range = pd.date_range("25-9-2019", "27-9-2019", freq="3H")
df = pd.DataFrame({'Time':date_range, 'A':np.random.choice([5,7,12], len(date_range))})

df["Seven"] = (df["A"] == 7).cumsum()

# display(df)
pass_to_next_group = {"val": None}
def diff(group):
    group["Diff"]=0
    loc = group.index[group["A"]==12]

    time_a = pass_to_next_group["val"] if pass_to_next_group["val"] else group["Time"].iloc[0]
    pass_to_next_group["val"] = None

    if group.name>0 and len(loc)>0:           
        group.loc[loc[0],"Diff"] =  time_a-group.loc[loc[0],"Time"]
    else:
        pass_to_next_group["val"] = time_a

    return group


df.groupby("Seven").apply(diff)


1
样例:
times = [
    '2019-05-18 01:15:28',
    '2019-05-18 01:28:11',
    '2019-05-18 01:36:36',
    '2019-05-18 01:39:47',
    '2019-05-18 01:53:32',
    '2019-05-18 02:05:37'
]

a = [7, 7, 12, 7, 12, 7]

df = pd.DataFrame({'times': pd.to_datetime(times), 'A':a})
print (df)
                times   A
0 2019-05-18 01:15:28   7
1 2019-05-18 01:28:11   7
2 2019-05-18 01:36:36  12
3 2019-05-18 01:39:47   7
4 2019-05-18 01:53:32  12
5 2019-05-18 02:05:37   7

首先创建默认索引,然后仅筛选 712 行:

df = df.reset_index(drop=True)
df1 = df[df['A'].isin([7, 12])]

然后与移位值比较,获取行中的第一个连续值:

df1 = df1[df1['A'].ne(df1['A'].shift())]
print (df1)
                times   A
0 2019-05-18 01:15:28   7
2 2019-05-18 01:36:36  12
3 2019-05-18 01:39:47   7
4 2019-05-18 01:53:32  12
5 2019-05-18 02:05:37   7

然后使用下面的 12 行过滤掉 7

m1 = df1['A'].eq(7) & df1['A'].shift(-1).eq(12)
m2 = df1['A'].eq(12) & df1['A'].shift().eq(7)

df2 = df1[m1 | m2]
print (df2)
                times   A
0 2019-05-18 01:15:28   7
2 2019-05-18 01:36:36  12
3 2019-05-18 01:39:47   7
4 2019-05-18 01:53:32  12

使用成对和不成对的行获取日期时间:

out7 = df2.iloc[::2]
out12 = df2.iloc[1::2]

并且最后减去:
df['Time_difference'] = out12['times'] - out7['times'].to_numpy()
df['Time_difference'] = df['Time_difference'].fillna(pd.Timedelta(0))
print (df)
                times   A Time_difference
0 2019-05-18 01:15:28   7        00:00:00
1 2019-05-18 01:28:11   7        00:00:00
2 2019-05-18 01:36:36  12        00:21:08
3 2019-05-18 01:39:47   7        00:00:00
4 2019-05-18 01:53:32  12        00:13:45
5 2019-05-18 02:05:37   7        00:00:00

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