python - 如何矢量化(利用 pandas/numpy)而不是使用嵌套的 for 循环

标签 python pandas numpy vectorization

我希望有效地使用 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 可能有数百万个条目,因此无法使用。我也没有让我们使用 pandasnumpy 高效的向量实现。有没有人知道如何有效地矢量化这个嵌套循环?

我觉得这段代码类似于矩阵乘法,所以可以利用 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/

相关文章:

python - 迭代构建 Pandas DataFrame 的最佳方式

python - 根据包含 Pandas 中列表对象的列,按一列排序并计算数据框另一列的值

python - 高效,快速的numpy直方图

python - POST 响应长度非零,但读取为空

python - ValueError : You are trying to merge on datetime64[ns] and object columns. 如果你想继续你应该使用 pd.concat

python - 如何在python脚本中发送post请求正文

python - 找到等于的运行平均值

python - 使用 Windows 10 使用 django-extensions 生成 PNG 格式的模型图(不使用 Conda 或 Anaconda)

python - 如何迭代 pandas 列中的列表以查找匹配项?

python - 在 NumPy 中将行向量转换为列向量