Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/325.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 在pandas中更快地替代Series.add功能_Python_Pandas - Fatal编程技术网

Python 在pandas中更快地替代Series.add功能

Python 在pandas中更快地替代Series.add功能,python,pandas,Python,Pandas,我想把两只熊猫系列加在一起。第一个系列非常大,有一个多索引。第二个系列的索引是第一个系列索引的一个小子集 df1 = pd.DataFrame(np.ones((1000,5000)),dtype=int).stack() df1 = pd.DataFrame(df1, columns = ['total']) df2 = pd.concat([df1.iloc[50:55],df1.iloc[2000:2005]]) # df2 is tiny subset of d

我想把两只熊猫系列加在一起。第一个系列非常大,有一个多索引。第二个系列的索引是第一个系列索引的一个小子集

    df1 = pd.DataFrame(np.ones((1000,5000)),dtype=int).stack()
    df1 = pd.DataFrame(df1, columns = ['total'])
    df2 = pd.concat([df1.iloc[50:55],df1.iloc[2000:2005]])  # df2 is tiny subset of df1
第一次使用常规Series.add函数大约需要9秒,后续尝试需要2秒(可能是因为pandas优化了df在内存中的存储方式?)

第一次手动迭代行的长度约为Series.add的2/3,后续尝试时的长度约为Series.add的1/100

    starttime = time.time()
    result = df1.total.copy()
    for row_index, row in df2.iterrows():
        result[row_index] += row
    print "Method 2 took %f seconds" % (time.time() - starttime)
当(此处)索引为多索引时,速度差异尤其明显

为什么Series.add在这里不起作用?有没有加快这一进程的建议?除了迭代序列中的每个元素,还有更有效的替代方法吗


另外,如何对数据帧进行排序或构造,以提高这两种方法的性能?第二次运行这两种方法中的任何一种都要快得多。我怎样才能在第一次演出时获得这样的表演?使用sort_索引进行排序的帮助不大

我认为在这种特定情况下,您的第二个可能会更快,因为您正在迭代较小的数据集(工作量较小),然后只访问较大数据集的少数组件(多亏了pandas开发人员,这是一个高效的操作)

然而,使用
.add
方法,pandas必须查看这两个索引的整体


如果
df1
df2
长度相同,则第一种方法需要54毫秒,但第二种方法需要>2分钟(在我的机器上,显然是YMMV)。

您不需要循环:

df1.total[df2.index] += df2.total
In [11]: %%timeit
result = df1.total.copy()
for row_index, row in df2.iterrows():
    result[row_index] += row
100 loops, best of 3: 17.9 ms per loop

In [12]: %timeit df1.total[df2.index] = (df1.total[df2.index]).add(df2.total, fill_value=0)
1000 loops, best of 3: 325 µs per loop

In [13]: %timeit df1.total[df2.index] += df2.total
1000 loops, best of 3: 283 µs per loop

HYRY回答说,在这种情况下,更有效的方法是只查看df2索引的一小部分。您可以使用稍微更健壮的函数(可以填充NAN)来实现这一点:

虽然这里的语法不是很枯燥

通过比较一些timeit信息,我们可以看到add并没有显著降低速度,两者都是对您的naive for循环的巨大改进:

df1.total[df2.index] += df2.total
In [11]: %%timeit
result = df1.total.copy()
for row_index, row in df2.iterrows():
    result[row_index] += row
100 loops, best of 3: 17.9 ms per loop

In [12]: %timeit df1.total[df2.index] = (df1.total[df2.index]).add(df2.total, fill_value=0)
1000 loops, best of 3: 325 µs per loop

In [13]: %timeit df1.total[df2.index] += df2.total
1000 loops, best of 3: 283 µs per loop
这是一个有趣的问题(我可能会在后面补充)什么样的相对尺寸会更快,但在这种极端情况下肯定会有一个巨大的胜利

要从中吸取的东西是:
如果您正在编写一个for循环(用python)来加快速度,那么您就错了!:)

第二次更快的原因是在需要时计算索引哈希表,然后缓存(这就是快速查找元素的原因)。您在这里所做的是将一个小得多的系列重新索引为一个大的系列,这就是为什么它需要时间,但不是必需的@下面的HYRY解决方案就是解决方法。明白了!谢谢HYRY和Andy的详细解释。谢谢!循环仍然胜过天真的np.add,但仅仅添加一个片段就可以轻而易举地击败这两个角色。