关于python:提高Pandas合并性能

您所在的位置:网站首页 大学生看的书推荐小说 关于python:提高Pandas合并性能

关于python:提高Pandas合并性能

#关于python:提高Pandas合并性能 | 来源: 网络整理| 查看: 265

正如其他帖子所建议的那样,我特别不喜欢Pands Merge的性能问题,但是我有一个类,其中包含许多方法,这些方法对数据集进行了大量合并。

该班级大约有10个分组依据,大约15个合并。尽管groupby相当快,但在类的总执行时间为1.5秒的情况下,在这15个merge调用中大约为0.7秒。

我想在那些合并调用中提高性能。由于我将进行约4000次迭代,因此在单次迭代中总共节省了0.5秒,这将导致整体性能降低30分钟左右,这非常好。

有什么建议我应该尝试吗?我试过了: 赛顿 Numba和Numba较慢。

谢谢

编辑1: 添加示例代码段: 我的合并语句:

12345678910111213tmpDf = pd.merge(self.data, t1, on='APPT_NBR', how='left') tmp = tmpDf tmpDf = pd.merge(tmp, t2, on='APPT_NBR', how='left') tmp = tmpDf tmpDf = pd.merge(tmp, t3, on='APPT_NBR', how='left') tmp = tmpDf tmpDf = pd.merge(tmp, t4, on='APPT_NBR', how='left') tmp = tmpDf tmpDf = pd.merge(tmp, t5, on='APPT_NBR', how='left')

并且,通过实现Joins,我合并了以下内容:

123456789101112131415dat = self.data.set_index('APPT_NBR') t1.set_index('APPT_NBR', inplace=True) t2.set_index('APPT_NBR', inplace=True) t3.set_index('APPT_NBR', inplace=True) t4.set_index('APPT_NBR', inplace=True) t5.set_index('APPT_NBR', inplace=True) tmpDf = dat.join(t1, how='left') tmpDf = tmpDf.join(t2, how='left') tmpDf = tmpDf.join(t3, how='left') tmpDf = tmpDf.join(t4, how='left') tmpDf = tmpDf.join(t5, how='left') tmpDf.reset_index(inplace=True)

注意,所有这些都是名为def的函数的一部分:def merge_earlier_created_values(self):

而且,当我通过以下方式定时从profilehooks拨打电话时:

12@timedcall(immediate=True) def merge_earlier_created_values(self):

我得到以下结果:

该方法的分析结果为:

12@profile(immediate=True) def merge_earlier_created_values(self):

通过使用Merge进行功能分析如下:

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950*** PROFILER RESULTS *** merge_earlier_created_values (E:\\Projects\\Predictive Inbound Cartoon     Estimation-MLO\\Python\\CodeToSubmit\\helpers\\get_prev_data_by_date.py:122) function called 1 times      71665 function calls (70588 primitive calls) in 0.524 seconds Ordered by: cumulative time, internal time, call count List reduced from 563 to 40 due to restriction ncalls  tottime  percall  cumtime  percall filename:lineno(function)     1    0.012    0.012    0.524    0.524 get_prev_data_by_date.py:122(merge_earlier_created_values)    14    0.000    0.000    0.285    0.020 generic.py:1901(_update_inplace)    14    0.000    0.000    0.285    0.020 generic.py:1402(_maybe_update_cacher)    19    0.000    0.000    0.284    0.015 generic.py:1492(_check_setitem_copy)     7    0.283    0.040    0.283    0.040 {built-in method gc.collect}    15    0.000    0.000    0.181    0.012 generic.py:1842(drop)    10    0.000    0.000    0.153    0.015 merge.py:26(merge)    10    0.000    0.000    0.140    0.014 merge.py:201(get_result)   8/4    0.000    0.000    0.126    0.031 decorators.py:65(wrapper)     4    0.000    0.000    0.126    0.031 frame.py:3028(drop_duplicates)     1    0.000    0.000    0.102    0.102 get_prev_data_by_date.py:264(recreate_previous_cartons)     1    0.000    0.000    0.101    0.101 get_prev_data_by_date.py:231(recreate_previous_appt_scheduled_date)     1    0.000    0.000    0.098    0.098 get_prev_data_by_date.py:360(recreate_previous_freight_type)    10    0.000    0.000    0.092    0.009 internals.py:4455(concatenate_block_managers)    10    0.001    0.000    0.088    0.009 internals.py:4471()   120    0.001    0.000    0.084    0.001 internals.py:4559(concatenate_join_units)   266    0.004    0.000    0.067    0.000 common.py:733(take_nd)   120    0.000    0.000    0.061    0.001 internals.py:4569()   120    0.003    0.000    0.061    0.001 internals.py:4814(get_reindexed_values)     1    0.000    0.000    0.059    0.059 get_prev_data_by_date.py:295(recreate_previous_appt_status)    10    0.000    0.000    0.038    0.004 merge.py:322(_get_join_info)    10    0.001    0.000    0.036    0.004 merge.py:516(_get_join_indexers)    25    0.001    0.000    0.024    0.001 merge.py:687(_factorize_keys)    74    0.023    0.000    0.023    0.000 {pandas.algos.take_2d_axis1_object_object}    50    0.022    0.000    0.022    0.000 {method 'factorize' of 'pandas.hashtable.Int64Factorizer' objects}   120    0.003    0.000    0.022    0.000 internals.py:4479(get_empty_dtype_and_na)    88    0.000    0.000    0.021    0.000 frame.py:1969(__getitem__)     1    0.000    0.000    0.019    0.019 get_prev_data_by_date.py:328(recreate_previous_location_numbers)    39    0.000    0.000    0.018    0.000 internals.py:3495(reindex_indexer)   537    0.017    0.000    0.017    0.000 {built-in method numpy.core.multiarray.empty}    15    0.000    0.000    0.017    0.001 ops.py:725(wrapper)    15    0.000    0.000    0.015    0.001 frame.py:2011(_getitem_array)    24    0.000    0.000    0.014    0.001 internals.py:3625(take)    10    0.000    0.000    0.014    0.001 merge.py:157(__init__)    10    0.000    0.000    0.014    0.001 merge.py:382(_get_merge_keys)    15    0.008    0.001    0.013    0.001 ops.py:662(na_op)   234    0.000    0.000    0.013    0.000 common.py:158(isnull)   234    0.001    0.000    0.013    0.000 common.py:179(_isnull_new)    15    0.000    0.000    0.012    0.001 generic.py:1609(take)    20    0.000    0.000    0.012    0.001 generic.py:2191(reindex)

使用Joins进行的分析如下:

1234567891011121314151617181920212223242526272829303132333435363738394041424344454665079 function calls (63990 primitive calls) in 0.550 seconds Ordered by: cumulative time, internal time, call count List reduced from 592 to 40 due to restriction ncalls  tottime  percall  cumtime  percall filename:lineno(function)     1    0.016    0.016    0.550    0.550 get_prev_data_by_date.py:122(merge_earlier_created_values)    14    0.000    0.000    0.295    0.021 generic.py:1901(_update_inplace)    14    0.000    0.000    0.295    0.021 generic.py:1402(_maybe_update_cacher)    19    0.000    0.000    0.294    0.015 generic.py:1492(_check_setitem_copy)     7    0.293    0.042    0.293    0.042 {built-in method gc.collect}    10    0.000    0.000    0.173    0.017 generic.py:1842(drop)    10    0.000    0.000    0.139    0.014 merge.py:26(merge)   8/4    0.000    0.000    0.138    0.034 decorators.py:65(wrapper)     4    0.000    0.000    0.138    0.034 frame.py:3028(drop_duplicates)    10    0.000    0.000    0.132    0.013 merge.py:201(get_result)     5    0.000    0.000    0.122    0.024 frame.py:4324(join)     5    0.000    0.000    0.122    0.024 frame.py:4371(_join_compat)     1    0.000    0.000    0.111    0.111 get_prev_data_by_date.py:264(recreate_previous_cartons)     1    0.000    0.000    0.103    0.103 get_prev_data_by_date.py:231(recreate_previous_appt_scheduled_date)     1    0.000    0.000    0.099    0.099 get_prev_data_by_date.py:360(recreate_previous_freight_type)    10    0.000    0.000    0.093    0.009 internals.py:4455(concatenate_block_managers)    10    0.001    0.000    0.089    0.009 internals.py:4471()   100    0.001    0.000    0.085    0.001 internals.py:4559(concatenate_join_units)   205    0.003    0.000    0.068    0.000 common.py:733(take_nd)   100    0.000    0.000    0.060    0.001 internals.py:4569()   100    0.001    0.000    0.060    0.001 internals.py:4814(get_reindexed_values)     1    0.000    0.000    0.056    0.056 get_prev_data_by_date.py:295(recreate_previous_appt_status)    10    0.000    0.000    0.033    0.003 merge.py:322(_get_join_info)    52    0.031    0.001    0.031    0.001 {pandas.algos.take_2d_axis1_object_object}     5    0.000    0.000    0.030    0.006 base.py:2329(join)    37    0.001    0.000    0.027    0.001 internals.py:2754(apply)     6    0.000    0.000    0.024    0.004 frame.py:2763(set_index)     7    0.000    0.000    0.023    0.003 merge.py:516(_get_join_indexers)     2    0.000    0.000    0.022    0.011 base.py:2483(_join_non_unique)     7    0.000    0.000    0.021    0.003 generic.py:2950(copy)     7    0.000    0.000    0.021    0.003 internals.py:3046(copy)    84    0.000    0.000    0.020    0.000 frame.py:1969(__getitem__)    19    0.001    0.000    0.019    0.001 merge.py:687(_factorize_keys)   100    0.002    0.000    0.019    0.000 internals.py:4479(get_empty_dtype_and_na)     1    0.000    0.000    0.018    0.018 get_prev_data_by_date.py:328(recreate_previous_location_numbers)    15    0.000    0.000    0.017    0.001 ops.py:725(wrapper)    34    0.001    0.000    0.017    0.000 internals.py:3495(reindex_indexer)    83    0.004    0.000    0.016    0.000 internals.py:3211(_consolidate_inplace)    68    0.015    0.000    0.015    0.000 {method 'copy' of 'numpy.ndarray' objects}    15    0.000    0.000    0.015    0.001 frame.py:2011(_getitem_array)

您可以看到,合并的速度比联接要快,尽管它的值很小,但是经过4000次迭代,这个小的值在几分钟内变成了一个巨大的数字。

谢谢

相关讨论 将您的合并列设置为索引,并使用df1.join(df2)代替。

合并列上的

set_index确实可以加快速度。下面是julien-marrec的Answers的一个更现实的版本。

123456789101112131415161718192021222324import pandas as pd import numpy as np myids=np.random.choice(np.arange(10000000), size=1000000, replace=False) df1 = pd.DataFrame(myids, columns=['A']) df1['B'] = np.random.randint(0,1000,(1000000)) df2 = pd.DataFrame(np.random.permutation(myids), columns=['A2']) df2['B2'] = np.random.randint(0,1000,(1000000)) %%timeit     x = df1.merge(df2, how='left', left_on='A', right_on='A2')   #1 loop, best of 3: 664 ms per loop %%timeit       x = df1.set_index('A').join(df2.set_index('A2'), how='left') #1 loop, best of 3: 354 ms per loop %%time     df1.set_index('A', inplace=True)     df2.set_index('A2', inplace=True) #Wall time: 16 ms %%timeit     x = df1.join(df2, how='left')   #10 loops, best of 3: 80.4 ms per loop

当两个表中要连接的列的整数顺序不同时,您仍然可以期望将速度提高8倍。

相关讨论 简短的解释说明为什么通过索引而不是通过"普通"列进行合并更快:索引具有哈希表。意味着您可以在摊销的O(1)中查找它们。对于普通列,在最坏的情况下需要O(n),这意味着将两个dfs与len n合并会在最坏的情况下花费O(n ^ 2)。 在我的情况下,DataFrame.merge()明显更快(x5)。我正在从3m行数据框(如左)和900行数据框(如右)进行左联接。我的索引是字符串,这几乎是我能看到的唯一解释 请注意:速度的提高将取决于您的索引是否唯一。如果索引不是唯一的,则合并索引上的两个数据帧可能甚至需要更长的时间。 还是可以用于multindex? x = df1.set_index(['A','B'])。join(df2.set_index((['A','B']),how ='left')吗?

我建议您将合并列设置为索引,并使用df1.join(df2)代替merge,这要快得多。

下面是一些包含概要分析的示例:

1234567In [1]: import pandas as pd import numpy as np df1 = pd.DataFrame(np.arange(1000000), columns=['A']) df1['B'] = np.random.randint(0,1000,(1000000)) df2 = pd.DataFrame(np.arange(1000000), columns=['A2']) df2['B2'] = np.random.randint(0,1000,(1000000))

这是A和A2的常规左合并:

1234In [2]: %%timeit         x = df1.merge(df2, how='left', left_on='A', right_on='A2') 1 loop, best of 3: 441 ms per loop

使用连接:

1234In [3]: %%timeit         x = df1.set_index('A').join(df2.set_index('A2'), how='left') 1 loop, best of 3: 184 ms per loop

现在很明显,如果您可以在循环之前设置索引,则时间方面的收益将更大:

1234567# Do this before looping In [4]: %%time df1.set_index('A', inplace=True) df2.set_index('A2', inplace=True) CPU times: user 9.78 ms, sys: 9.31 ms, total: 19.1 ms Wall time: 16.8 ms

然后在循环中,您会得到比这种情况快30倍的结果:

123In [5]: %%timeit         x = df1.join(df2, how='left') 100 loops, best of 3: 14.3 ms per loop 相关讨论 这是左合并/联接。合并中的参数如何为" left",将与join一起使用? 不知何故,我的数据集性能没有太大改善。如果将所有合并转换为联接,则时间会增加约0.1-0.3秒。我将一些合并转换为联接,可以将时间减少约0.2秒。有什么我想念的吗?还是我需要产生类似代码的任何东西? 如果您要在问题中加入mcve,这将有助于测试您的特定应用程序。这也是为什么这个问题被标记为"偏离主题"的部分原因 请查看更新的问题,并希望此问题引起关注。如果是的话,如果您可以删除主题外的标记,那也很好,因为进行大量合并的人们可能会发现此标记很有用,因为没有太多与此问题类似的帖子。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3