为了账号安全,请及时绑定邮箱和手机立即绑定

熊猫迭代有性能问题吗?

熊猫迭代有性能问题吗?

守候你守候我 2019-06-09 15:22:50
熊猫迭代有性能问题吗?我注意到在使用熊猫的迭代时表现很差。这是别人经历过的吗?它是否特定于迭代,对于一定大小的数据(我正在处理的是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]
查看完整描述

3 回答

?
ITMISS

TA贡献1871条经验 获得超8个赞

一般来说,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.


查看完整回答
反对 回复 2019-06-09
?
繁花不似锦

TA贡献1851条经验 获得超4个赞

Numpy和大熊猫的病媒操作是快得多比vanillaPython中的标量操作有以下几个原因:

  • 摊销式查找:Python是一种动态类型化语言,因此数组中的每个元素都有运行时开销。然而,Numpy(因此也是熊猫)用C进行计算(通常是通过Cython)。数组的类型只有在迭代开始时才能确定;仅这一节省就是最大的胜利之一。

  • 更好的缓存在C数组上迭代是对缓存友好的,因此非常快。熊猫DataFrame是一个“面向列的表”,这意味着每个列实际上只是一个数组。因此,您可以在DataFrame上执行的本机操作(比如对列中的所有元素进行求和)将很少有缓存丢失。

  • 更多并行的机会一个简单的C数组可以通过SIMD指令操作。Numpy的某些部分支持SIMD,这取决于您的CPU和安装过程。并行化的好处不会像静态类型和更好的缓存那样引人注目,但它们仍然是一个坚实的胜利。

故事的寓意:在Numpy和熊猫中使用向量运算。它们比Python中的标量操作更快,原因很简单,因为这些操作正是C程序员手工编写的操作。(只不过数组概念比嵌入SIMD指令的显式循环更容易读取。)


查看完整回答
反对 回复 2019-06-09
?
Cats萌萌

TA贡献1805条经验 获得超9个赞

这是解决你问题的方法。这都是矢量化的。


In [58]: df = table1.merge(table2,on='letter')


In [59]: df['calc'] = df['number1']*df['number2']


In [60]: df

Out[60]: 

  letter  number1  number2  calc

0      a       50      0.2    10

1      a       50      0.5    25

2      b      -10      0.1    -1

3      b      -10      0.4    -4


In [61]: df.groupby('letter')['calc'].max()

Out[61]: 

letter

a         25

b         -1

Name: calc, dtype: float64


In [62]: df.groupby('letter')['calc'].idxmax()

Out[62]: 

letter

a         1

b         2

Name: calc, dtype: int64


In [63]: df.loc[df.groupby('letter')['calc'].idxmax()]

Out[63]: 

  letter  number1  number2  calc

1      a       50      0.5    25

2      b      -10      0.1    -1


查看完整回答
反对 回复 2019-06-09
  • 3 回答
  • 0 关注
  • 447 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信