在这个例子中避免使用iterrows的好方法是什么?

时间:2014-07-21 21:26:59

标签: python pandas

我讨论了iterrows previously的性能问题,并得到了很好的一般回应。这个问题是一个特殊情况,我希望你能帮助你更好地应用更好的东西,因为它的速度很慢。

我相信这个问题对任何新的python / pandas程序员来说都很有用,他们会因为行迭代心态而陷入困境。

我见过的使用' map'或者'申请'通常显示一个看起来足够直观的数据表。但是,我正在处理两个表并且它们很大(T1是250万行,T2是96000行)。

这是一个简单的例子(它适用于我的会话):

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]

print table3

输出结果为:

  letter number2
0      a     0.5
1      b     0.1

[2 rows x 2 columns]

总体思路:

  1. 制作表3是目标 - 它与表1具有相同的尺寸
  2. 使用'最佳'填充表格3。表2中的行,给出表1中的相应输入。
  3. 表2中使用的数据是基于'字母的子集。来自表1
  4. (显然这种情况并不慢,因为它很小,但是当处理数百万行时,请注意,在实际示例中,我在两个表中都有更多列。)

2 个答案:

答案 0 :(得分:3)

对我而言,最简单的事情就是在lettergroupby上合并。

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)

table3 = table1.merge(table2,on='letter')

grouped = table3.groupby('letter')

def get_optimization(df):
    product_column = df.number1 * df.number2
    idx_of_prod_col_max = product_columns.idxmax()
    return_val = df.ix[idx_of_prod_col_max]['number2']
    return return_val

table3 = grouped.apply(get_optimization)

答案 1 :(得分:0)

正如我在the other answer中发布的那样,有时问题不在于循环,而是在DataFrame或Series中不必要地装入数据。

def iterthrough():
    ret = []
    grouped = table2.groupby('letter', sort=False)
    t2info = table2.to_records()
    for index, letter, n1 in table1.to_records():
        t2 = t2info[grouped.groups[letter].values]
        maxrow = np.multiply(t2.number2, n1).argmax()
        # `[1:]` removes the index column
        ret.append(t2[maxrow].tolist()[1:])
    return pd.DataFrame(ret, columns=('letter', 'number2'))

改善方法包括:

  1. 使用groupbygroups索引来避免重复的布尔计算。
  2. 使用to_records来避免将记录转换为Series
  3. 在编译完所有数据之前,不要创建DataFrame。