【发布时间】: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 等功能原语应用您的自定义函数。优化循环和索引没有意义,您应该完全重新考虑您的方法。
-
添加了输入和预期输出示例
-
这应该是一个简单的矢量化问题(这将大大提高性能),但是您应该发布一组最小且可重现的示例数据框,以便那些试图回答的人可以复制您的案例。只需包含一小部分数据,以展示您要实现的功能。
标签: python pandas for-loop dataframe optimization