我希望有效地使用 pandas
(或 numpy
)而不是带有 if
的嵌套 for
循环解决特定问题的语句。这是一个玩具版本:
假设我有以下两个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)
现在我希望遍历每个数据帧的每一行,并在满足特定条件时乘以 vals。此代码适用于我想要的
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)
但是,显然这非常效率低下,实际上我的 DataFrame 可能有数百万个条目,因此无法使用。我也没有让我们使用 pandas
或 numpy
高效的向量实现。有没有人知道如何有效地矢量化这个嵌套循环?
我觉得这段代码类似于矩阵乘法,所以可以利用 outer
取得进展吗?这是我发现很难插入的 if
条件,因为 if
逻辑需要将 df1
中的每个条目与 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
测试
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)
时间
vectorized solution @AGN Gazer: 9.15ms
parallelized Numba Version: 0.7ms
关于python - 如何矢量化(利用 pandas/numpy)而不是使用嵌套的 for 循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50950953/