一尘不染

Python- pandas的行程是否有性能问题?

python

我注意到使用pandas的迭代器时性能非常差。

这是别人所经历的吗?它特定于迭代吗?对于一定大小的数据(我正在处理2-3百万行),应该避免使用此功能吗?

在GitHub上进行的讨论使我相信,这是在数据帧中混合dtypes时引起的,但是下面的简单示例显示,即使使用一个dtype(float64)也存在该问题。这在我的机器上需要36秒:

import pandas as pd
import numpy as np
import time

s1 = np.random.randn(2000000)
s2 = np.random.randn(2000000)
dfa = pd.DataFrame({'s1': s1, 's2': s2})

start = time.time()
i=0
for rowindex, row in dfa.iterrows():
    i+=1
end = time.time()
print end - start

为什么矢量化运算之类的应用这么快?我想象那里也必须进行逐行迭代。

我无法弄清楚在我的情况下如何不使用迭代(这将在以后的问题中予以保留)。因此,如果你一直能够避免这种迭代,不胜感激。我正在基于单独数据框中的数据进行计算。谢谢!

—编辑:下面添加了我要运行的简化版本—

import pandas as pd
import numpy as np

#%% Create the original tables
t1 = {'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 table
table3 = pd.DataFrame(np.nan, columns=['letter','number2'], index=[0])

#%% Iterate through filtering relevant data, optimizing, returning info
for row_index, row in table1.iterrows():   
    t2info = table2[table2.letter == row['letter']].reset_index()
    table3.ix[row_index,] = optimize(t2info,row['number1'])

#%% Define optimization
def optimize(t2info, t1info):
    calculation = []
    for index, r in t2info.iterrows():
        calculation.append(r['number2']*t1info)
    maxrow = calculation.index(max(calculation))
    return t2info.ix[maxrow]

阅读 505

收藏
2020-02-09

共1个答案

一尘不染

通常,iterrows仅应在非常特殊的情况下使用。这是执行各种操作的一般优先顺序:

1) vectorization
2) using a custom cython routine
3) apply
    a) reductions that can be performed in cython
    b) iteration in python space
4) itertuples
5) iterrows
6) updating an empty frame (e.g. using loc one-row-at-a-time)

使用自定义的cython例程通常太复杂了,所以现在就跳过它。

1)矢量化始终是首选。但是,有一小部分案例无法以明显的方式进行向量化(主要涉及复发)。此外,在较小的框架上,执行其他方法可能会更快。

3)应用包括可通常是通过在用Cython空间迭代器(这在pandas内部完成的)来进行(这是一个)的情况下。

这取决于apply表达式内部发生的情况。例如,df.apply(lambda x: np.sum(x))将很快执行(当然df.sum(1)更好)。但是,类似:的操作df.apply(lambda x: x['b'] + 1)将在python空间中执行,因此速度较慢。

4)itertuples不会将数据装箱成一个系列,而只是将其作为元组返回

5)是否iterrows将数据包装到系列中。除非你真的需要此方法,否则请使用其他方法。

6)一次更新一个空行。我已经看到这种方法使用了太多的方法。这是迄今为止最慢的。它可能很常见(对于某些python结构来说相当快),但是DataFrame对索引进行了大量检查,因此每次更新一行总是很慢。创建新的结构和方法更好concat

2020-02-09