列表理解,附加步骤(将第一个元素与自己比较,然后将第一个元素与第二个元素比较,第二个元素与第三个元素比较,...)python

问题描述 投票:0回答:2

我有一个格式为%H:%M:%S的时间戳。通过下面的函数,我得到了经过的时间。

# time diff func
def time_diff(t1, t2):
return datetime.strptime(t1, '%H:%M:%S') - datetime.strptime(t2, '%H:%M:%S')

# elapsed time since start
data['time'] = [time_diff(data['time'][i], data['time'][0]) for i in range(len(data['time']))]

我还想计算连续数据之间的时间间隔。因此,第一条和第二条之间的时间间隔,第二条和第三条之间的时间间隔,以此类推。下面的列表理解可以完成这个工作。

# get timedelta
timedeltas = [data['time'][i] - data['time'][i-1] for i in range(1 ,len(data['time']))]

结果从第一个和第二个条目之间的timedelta开始。但我希望列表理解从比较第一个条目开始,所以我得到的第一个结果是00:00:00,然后开始比较元素和连续的元素(第一个和第二个,第二个和第三个,...)。有人知道如何解决这个问题吗?

python list list-comprehension timedelta
2个回答
2
投票

一个非常Pythonic的方法是完全避免使用subsripting(分片),只用下面的方法。

[0] + [time_diff(t1, t0) for (t1, t0) in zip(data[1:], data[:-1])]
  • 第一个差值是已知的0--你是这样定义的。
  • 对于其余的差值,我们 zip 两个子列表--一个从第二个元素元素开始,一直到最后,另一个从第一个元素开始,一直到下一个或最后一个元素。
  • 然后,理解成对的zip(zip是一个生成器对象,所以不会生成成对的列表),并使用差异来构造目标列表的第二到最后一个元素。

你可以通过替换掉以下代码来提高性能和内存消耗 data[:-1]......这将防止创建一个临时列表 data[:-1],并且不会改变功能,因为 zip 只有在两个列表都没有用完的时候才会操作。这段代码有点脏,不过(IMHO),因为你把不等长的 list 发送给了 zip.

你也可以跳过创建 data[1:] 临时列表,通过做。

data_i = iter(data)
next(data_i)
diff = [0] + [time_diff(t1, t0) for (t1, t0) in zip(data_i, data)]

现在你只用了三行代码,但并没有创建任何临时列表,也没有随机访问列表(只使用顺序访问)。

你可以进一步简化使用 itertools.islice:

from itertools import islice
diff = [0] + [time_diff(t1, t0) for (t1, t0) in zip(islice(data, 1, None), data)]

1
投票

你试过了吗?

# get timedelta
timedeltas = [data['time'][i] - data['time'][i-1] if i > 0 else data['time'][i]-data['time'][i] for i in range(len(data['time']))]

虽然它很丑陋。我认为代码

timedeltas = [data['time'][0]-data['time'][0]] + [data['time'][i] - data['time'][i-1] for i in range(1 ,len(data['time']))]

更容易读懂


1
投票

你可以用 pandas:

import pandas as pd

# I suppose your data is a dictionary
data = {'time': ['12:13:11', '12:14:15', '13:20:31']}

df = pd.DataFrame(data=data)
df.time = pd.to_datetime(df.time)
df['timedeltas'] = df.time.diff() # Produces NaT to first index
df.timedeltas.fillna(pd.Timedelta(seconds=0), inplace=True) # Replaces NaT values with 0-second Timedelta

print(df)

>>> 
                 time timedeltas
0 2020-05-13 12:13:11   00:00:00
1 2020-05-13 12:14:15   00:01:04
2 2020-05-13 13:20:31   01:06:16

希望能帮到你

© www.soinside.com 2019 - 2024. All rights reserved.