列表理解和额外的步骤(将第一个元素与其自身进行比较,然后将第一个元素与第二个元素进行比较,将第二个元素与第三个元素进行比较,...)python
list comprehension with additional step (comparing first element to itself, then first with second, second with third,...) python
我有格式为 %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']))]
结果以第一个和第二个条目之间的时间差开始。但我希望列表理解从第一个条目与自身进行比较开始,因此我得到 00:00:00 作为第一个结果,然后开始将元素与连续元素进行比较(第一个与第二个,第二个与第三个,..)。有人知道如何解决这个问题吗?
你试了吗
# 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']))]
为此目的可读性更高
您可以使用 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
希望对您有所帮助!
一个非常 Pythonic 的方法是完全避免使用下标(切片),而只使用以下内容:
[0] + [time_diff(t1, t0) for (t1, t0) in zip(data[1:], data[:-1])]
- 已知第一个差值为 0 - 您是这样定义的。
- 对于其余的差异,我们
zip
两个子列表 - 一个从第二个元素元素开始,一直到最后,另一个从第一个元素开始,一直到最后一个元素。
- 然后,理解对的 zip(zip 是一个生成器对象,因此不会生成对列表),并使用差异来构造目标列表的第二个到最后一个元素。
您可以通过替换 data[:-1]
来提高性能和内存消耗。这将阻止创建临时列表 data[:-1]
,并且不会更改功能,因为 zip
仅在两个列表都未用完时才运行。不过,代码有点脏(恕我直言),因为您将长度不等的列表发送到 zip
.
您也可以跳过 data[1:]
临时列表的创建,方法是:
data_i = iter(data)
next(data_i)
diff = [0] + [time_diff(t1, t0) for (t1, t0) in zip(data_i, data)]
现在您正在使用 3 行代码,但没有创建任何临时列表,也没有访问列表签证随机访问(仅使用顺序访问)。
您可以使用 itertools.islice
进一步简化:
from itertools import islice
diff = [0] + [time_diff(t1, t0) for (t1, t0) in zip(islice(data, 1, None), data)]
我有格式为 %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']))]
结果以第一个和第二个条目之间的时间差开始。但我希望列表理解从第一个条目与自身进行比较开始,因此我得到 00:00:00 作为第一个结果,然后开始将元素与连续元素进行比较(第一个与第二个,第二个与第三个,..)。有人知道如何解决这个问题吗?
你试了吗
# 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']))]
为此目的可读性更高
您可以使用 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
希望对您有所帮助!
一个非常 Pythonic 的方法是完全避免使用下标(切片),而只使用以下内容:
[0] + [time_diff(t1, t0) for (t1, t0) in zip(data[1:], data[:-1])]
- 已知第一个差值为 0 - 您是这样定义的。
- 对于其余的差异,我们
zip
两个子列表 - 一个从第二个元素元素开始,一直到最后,另一个从第一个元素开始,一直到最后一个元素。 - 然后,理解对的 zip(zip 是一个生成器对象,因此不会生成对列表),并使用差异来构造目标列表的第二个到最后一个元素。
您可以通过替换 data[:-1]
来提高性能和内存消耗。这将阻止创建临时列表 data[:-1]
,并且不会更改功能,因为 zip
仅在两个列表都未用完时才运行。不过,代码有点脏(恕我直言),因为您将长度不等的列表发送到 zip
.
您也可以跳过 data[1:]
临时列表的创建,方法是:
data_i = iter(data)
next(data_i)
diff = [0] + [time_diff(t1, t0) for (t1, t0) in zip(data_i, data)]
现在您正在使用 3 行代码,但没有创建任何临时列表,也没有访问列表签证随机访问(仅使用顺序访问)。
您可以使用 itertools.islice
进一步简化:
from itertools import islice
diff = [0] + [time_diff(t1, t0) for (t1, t0) in zip(islice(data, 1, None), data)]