我正在尝试比较两个DataFrames,我希望有效地使用pandas (or numpy)
,而不是嵌套的for循环,其中包含if语句来解决特定问题。下面是我的程序的一小部分。
spindleload = {'time': ['2020-02-03 00:18:07', '2020-02-03 00:18:08', '2020-02-03 00:18:09', '2020-02-03 00:18:10', '2020-02-03 00:18:11', '2020-02-03 00:18:12', '2020-02-03 00:18:13', '2020-02-03 00:18:14', '2020-02-03 00:18:15', '2020-02-03 00:18:16', '2020-02-03 00:18:17'],
'value': [17,25,14,14,22,22,22,22,22,12,19]}
df1 = pd.DataFrame(data=spindleload)
cycletime = {'newtimestart': ['2020-02-03 00:18:08','2020-02-03 00:18:13'], 'newtimeend': ['2020-02-03 00:18:11', '2020-02-03 00:18:15']}
df2 = pd.DataFrame(data=cycletime)
现在,我希望循环它,以获得df1中的时间和值,用于df2的newtimestart与newtimeend之间的相应值。下面是代码。
output_graph_time = []
output_graph_value = []
for i in range(len(df2)):
for j in range(len(df1)):
if df1['time'][j] >= df2['newtimestart'][i]:
output_graph_time.append(df1['time'][j])
output_graph_value.append(df1['value'][j])
if df1['time'][j] == df2['newtimeend'][i]:
break
print(output_graph_time)
print(output_graph_value)
现在,代码运行良好,但当它读取数百万行数据时,它无法执行,我也尝试实现Numba
,但内核无法处理,需要重新启动。因此,我请求使用Numpy或Pandas矢量化方法来解决此问题。
除此之外,当我尝试应用矢量化方法时,我发现在每次执行后都很难打破if条件。
您可以在日期范围内转换df2并进行分解,然后使用isin
过滤器df1。
从字符串转换为日期时间(忽略此步骤是因为值已经是日期时间(
df1['time'] = pd.to_datetime(df1['time'])
df2 = df2.apply(pd.to_datetime)
映射为pd.date_range
和explode
,然后使用isin
进行过滤
out = (df1[df1['time'].isin(df2.agg(tuple,1).map(lambda x:
pd.date_range(*x,freq='s')).explode())])
print(out)
time value
1 2020-02-03 00:18:08 25
2 2020-02-03 00:18:09 14
3 2020-02-03 00:18:10 14
4 2020-02-03 00:18:11 22
6 2020-02-03 00:18:13 22
7 2020-02-03 00:18:14 22
8 2020-02-03 00:18:15 22
这与您的输出类似:
print(output_graph_time)
print(output_graph_value)
['2020-02-03 00:18:08', '2020-02-03 00:18:09', '2020-02-03 00:18:10',
'2020-02-03 00:18:11', '2020-02-03 00:18:13', '2020-02-03 00:18:14',
'2020-02-03 00:18:15']
[25, 14, 14, 22, 22, 22, 22]
我知道df1
是数百万行。如果你的df2
不是很大,你可以进行交叉合并:
(df1.assign(dummy=1)
.merge(df2.assign(dummy=1), on='dummy')
.query('newtimestart<=time<=newtimeend')
)
输出:
time value
2 2020-02-03 00:18:08 25
4 2020-02-03 00:18:09 14
6 2020-02-03 00:18:10 14
8 2020-02-03 00:18:11 22
13 2020-02-03 00:18:13 22
15 2020-02-03 00:18:14 22
17 2020-02-03 00:18:15 22