熊猫迭代有性能问题吗?

熊猫迭代有性能问题吗?

我注意到在使用熊猫的迭代时表现很差。

这是别人经历过的吗?它是否特定于迭代,对于一定大小的数据(我正在处理的是2300万行),是否应该避免这个函数?

这次讨论在GitHub上,我相信这是在将dtype混合到dataframe中时引起的,但是下面的简单示例显示,即使使用一个dtype(Float 64),它也存在。这在我的机器上需要36秒:

import pandas as pdimport numpy as npimport time

s1 = np.random.randn(2000000)s2 = np.random.randn(2000000)dfa = pd.DataFrame({'s1': s1, 's2': s2})start = time.time()i=0for rowindex,
 row in dfa.iterrows():
    i+=1end = time.time()print end - start

为什么像应用这样的向量化操作要快得多?我想一定有一些逐行迭代在那里进行。

在我的情况下,我不知道如何不使用迭代(这将为将来的问题保留下来)。因此,如果您一直能够避免此迭代,我将非常感谢您的收听。我是根据不同数据中的数据进行计算。谢谢!

-编辑:我想运行的代码的简化版本添加在下面-

import pandas as pdimport numpy as np#%% Create the original tablest1 = {'letter':['a','b'],
      'number1':[50,-10]}t2 = {'letter':['a','a','b','b'],
      'number2':[0.2,0.5,0.1,0.4]}table1 = pd.DataFrame(t1)table2 = pd.DataFrame(t2)
      #%% Create the body of the new tabletable3 = pd.DataFrame(np.nan, columns=['letter','number2'], index=[0])
      #%% Iterate through filtering relevant data, optimizing, returning infofor row_index, row in table1.iterrows():   
    t2info = table2[table2.letter == row['letter']].reset_index()
    table3.ix[row_index,] = optimize(t2info,row['number1'])#%% Define optimizationdef optimize(t2info, t1info):
    calculation = []
    for index, r in t2info.iterrows():
        calculation.append(r['number2']*t1info)
    maxrow = calculation.index(max(calculation))
    return t2info.ix[maxrow]


守候你守候我
浏览 448回答 3
3回答

ITMISS

一般来说,iterrows应该只在非常具体的情况下使用。这是执行各种操作的一般优先顺序:1) vectorization2) using a custom cython routine3) apply     a) reductions that can be performed in cython     b) iteration in python space4) itertuples5) iterrows6) updating an empty frame (e.g. using loc one-row-at-a-time)使用自定义cython例程通常太复杂了,所以现在我们跳过它。1)矢量化永远是第一选择,也是最好的选择。然而,有一小部分病例无法以明显的方式向量化(大多涉及复发)。此外,在一个较小的框架内,做其他方法可能会更快。3)申请涉及能,会,可以通常由Cython空间中的迭代器完成(这是在熊猫内部完成的)(这是一个例子)。这取决于应用表达式中发生的事情。G.df.apply(lambda x: np.sum(x))很快就会被执行(当然df.sum(1)甚至更好)。然而,类似于:df.apply(lambda x: x['b'] + 1)将在python空间中执行,因此速度更慢。4) itertuples不将数据装箱到Series中,只需将其作为元组返回即可5) iterrows将数据放入“系列”中。除非您真的需要这样做,否则请使用另一种方法。(6)在时间上更新空帧a-单行。我见过这种方法使用得太多了。这是迄今为止最慢的。它可能是常见的地方(对于某些python结构来说也是相当快的),但是DataFrame对索引做了相当多的检查,所以每次更新一行总是非常慢的。更好的方法是创建新的结构concat.

繁花不似锦

Numpy和大熊猫的病媒操作是快得多比vanillaPython中的标量操作有以下几个原因:摊销式查找:Python是一种动态类型化语言,因此数组中的每个元素都有运行时开销。然而,Numpy(因此也是熊猫)用C进行计算(通常是通过Cython)。数组的类型只有在迭代开始时才能确定;仅这一节省就是最大的胜利之一。更好的缓存在C数组上迭代是对缓存友好的,因此非常快。熊猫DataFrame是一个“面向列的表”,这意味着每个列实际上只是一个数组。因此,您可以在DataFrame上执行的本机操作(比如对列中的所有元素进行求和)将很少有缓存丢失。更多并行的机会一个简单的C数组可以通过SIMD指令操作。Numpy的某些部分支持SIMD,这取决于您的CPU和安装过程。并行化的好处不会像静态类型和更好的缓存那样引人注目,但它们仍然是一个坚实的胜利。故事的寓意:在Numpy和熊猫中使用向量运算。它们比Python中的标量操作更快,原因很简单,因为这些操作正是C程序员手工编写的操作。(只不过数组概念比嵌入SIMD指令的显式循环更容易读取。)

Cats萌萌

这是解决你问题的方法。这都是矢量化的。In [58]: df = table1.merge(table2,on='letter')In [59]: df['calc'] = df['number1']*df['number2']In [60]: dfOut[60]:   letter  number1  number2  calc0      a       50      0.2    101      a       50      0.5    252      b      -10      0.1    -13      b      -10      0.4    -4In [61]: df.groupby('letter')['calc'].max()Out[61]: lettera         25b         -1Name: calc, dtype: float64In [62]: df.groupby('letter')['calc'].idxmax()Out[62]: lettera         1b         2Name: calc, dtype: int64In [63]: df.loc[df.groupby('letter')['calc'].idxmax()]Out[63]:   letter  number1  number2  calc1      a       50      0.5    252      b      -10      0.1    -1
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Python