M H*_*ley 3 python numpy vectorization pandas
我希望有效地使用pandas(或numpy) 而不是for带有if语句的嵌套循环来解决特定问题。这是一个玩具版本:
假设我有以下两个 DataFrame
import pandas as pd
import numpy as np
dict1 = {'vals': [100,200], 'in': [0,1], 'out' :[1,3]}
df1 = pd.DataFrame(data=dict1)
dict2 = {'vals': [500,800,300,200], 'in': [0.1,0.5,2,4], 'out' :[0.5,2,4,5]}
df2 = pd.DataFrame(data=dict2)
Run Code Online (Sandbox Code Playgroud)
现在我希望循环遍历每个数据帧的每一行,并在满足特定条件时将值相乘。这段代码适用于我想要的
ans = []
for i in range(len(df1)):
for j in range(len(df2)):
if (df1['in'][i] <= df2['out'][j] and df1['out'][i] >= df2['in'][j]):
ans.append(df1['vals'][i]*df2['vals'][j])
np.sum(ans)
Run Code Online (Sandbox Code Playgroud)
然而,显然这是非常低效的,实际上我的 DataFrame 可能有数百万个条目,这使得它无法使用。我也不是在创造pandas或numpy高效的向量实现。有谁知道如何有效地矢量化这个嵌套循环?
我觉得这段代码类似于矩阵乘法,所以可以利用它取得进展outer吗?这是if我发现很难融入的情况,因为if逻辑需要将 中的每个条目df1与 中的所有条目进行比较df2。
您还可以使用 Numba 等编译器来完成这项工作。这也将优于矢量化解决方案,并且不需要临时数组。
例子
import numba as nb
import numpy as np
import pandas as pd
import time
@nb.njit(fastmath=True,parallel=True,error_model='numpy')
def your_function(df1_in,df1_out,df1_vals,df2_in,df2_out,df2_vals):
sum=0.
for i in nb.prange(len(df1_in)):
for j in range(len(df2_in)):
if (df1_in[i] <= df2_out[j] and df1_out[i] >= df2_in[j]):
sum+=df1_vals[i]*df2_vals[j]
return sum
Run Code Online (Sandbox Code Playgroud)
测试
dict1 = {'vals': np.random.randint(1, 100, 1000),
'in': np.random.randint(1, 10, 1000),
'out': np.random.randint(1, 10, 1000)}
df1 = pd.DataFrame(data=dict1)
dict2 = {'vals': np.random.randint(1, 100, 1500),
'in': 5*np.random.random(1500),
'out': 5*np.random.random(1500)}
df2 = pd.DataFrame(data=dict2)
# First call has some compilation overhead
res=your_function(df1['in'].values, df1['out'].values, df1['vals'].values,
df2['in'].values, df2['out'].values, df2['vals'].values)
t1 = time.time()
for i in range(1000):
res = your_function(df1['in'].values, df1['out'].values, df1['vals'].values,
df2['in'].values, df2['out'].values, df2['vals'].values)
print(time.time() - t1)
Run Code Online (Sandbox Code Playgroud)
时间安排
vectorized solution @AGN Gazer: 9.15ms
parallelized Numba Version: 0.7ms
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3561 次 |
| 最近记录: |