【问题标题】:Pandas For Loop OptimizationPandas 循环优化
【发布时间】:2019-01-01 07:10:07
【问题描述】:

我是 python 新手,虽然我可以毫无问题地编写 for 循环,但我发现它们非常慢。这是我的代码:

perc_match 是一个在两个向量之间运行计算的函数,在本例中是数据帧的行。

def perc_match(customer_id,bait_name):
    score = int(df_master.loc[customer_id,:].dot(df_pim.loc[bait_name,:].values))
    perfect = int(df_master.loc[customer_id,:].dot(df_perf.iloc[0,:].values))
    if perfect == 0:
        return 0
    elif (score / perfect)*100 < 0:
        return 0
    else:
        percent = round((score / perfect)*100,3)
        percent = float(percent)
    return percent

match_maker 为两个数据帧中的每一行调用perc_match,并将输出放在df_match 中的相应单元格中。

def match_maker(df_match):
    for i in df_match.index:
        for j in df_match.columns:
             df_match.loc[i,j] = perc_match(i,j)

供参考:

df_master.shape = (122905, 33) df_pim.shape = (36, 33) df_perf.shape = (1, 33) df_match.shape = (122905, 36)

这一切都很好 - 除了我测试需要多长时间......

5.49 s ± 72 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

当我在 100,000 行上运行它时效果不佳。我知道有一些方法可以优化代码,但我很难理解它。精简此代码的最佳方法是什么?

编辑:

输入看起来像这样:

df_master:

 Customer ID       Email       Technique 1       ...        Technique 33
 12345             i@me.com    1                 ...        0
 ...

df_pim:

 Product ID        Technique 1        ...        Technique 33
 Product 1         1                             0
 ...

df_perc(所有值为1):

 index             Technique 1        ...        Technique 33
                   1                             1

df_match:

 Customer ID       Email       Product 1         ...        Product N
 12345             i@me.com    0                 ...        0
 ...

我希望编辑df_match 的函数看起来像这样:

df_match(根据技术值之间的比较给出百分比匹配):

 Customer ID       Email       Product 1         ...        Product N
 12345             i@me.com    12.842            ...        44.312
 ...

【问题讨论】:

  • 这似乎很容易矢量化。你能发布一个输入和预期输出的小例子吗? [参考:minimal reproducible example)
  • 目前您将 DataFrame 视为具有随机访问的多维数组。这不是通常使用 pandas 和其他数据科学包的方式。正如您所发现的,它非常慢。相反,人们通常将他们的问题形式化并尝试将他们的解决方案表达为一系列预定义的数组操作。为此,您应该知道存在哪些操作(请参阅 pandas 文档)。至少您应该通过 map、reduce 等功能原语应用您的自定义函数。优化循环和索引没有意义,您应该完全重新考虑您的方法。
  • 添加了输入和预期输出示例
  • 这应该是一个简单的矢量化问题(这将大大提高性能),但是您应该发布一组最小且可重现的示例数据框,以便那些试图回答的人可以复制您的案例。只需包含一小部分数据,以展示您要实现的功能。
  • 从数据示例来看,如果我理解正确的话,看起来你有一个类似数据库的问题。如果您熟悉关系数据库和 SQL,则可以尝试使用自定义函子根据联接和聚合来制定解决方案。 Pandas 有相关功能:12。与您的初始循环相比,它应该非常短且速度极快。

标签: python pandas for-loop dataframe optimization


【解决方案1】:

假设: 我假设 perc_match() 第 3 行中的 df_perf 是一个错字,而您的意思是 df_perc。

您希望将事物视为要计算的单个值。您使用的 .dot 运算符可以处理二维和单个维度。

在你的 perc_match() 你有:

score = int(df_master.loc[customer_id,:].dot(df_pim.loc[bait_name,:].values))

这一次在一行上运行,然后在另一行上运行。如何制作一个分数数据框:

columns = ["Technique "+str(a) for a in range(1,34)]
score_df = df_master[columns].dot(df_pim)

如果您将它们乘以一个数据框,那么完美的线条几乎是不必要的。那么这样的事情怎么样:

perfect = int(df_master.sum(axis=0))

这会让你思考一段时间。我稍后会完成这个答案,或者我不在时有人可以接听。

【讨论】:

    猜你喜欢
    • 2021-06-22
    • 2020-03-18
    • 2021-11-27
    • 1970-01-01
    • 2017-07-20
    相关资源
    最近更新 更多