使用zip和df.apply()迭代Pandas数据帧

时间:2018-01-15 11:09:31

标签: python pandas dataframe iteration

我试图迭代一个df来计算新列的值,但它花了太长时间。这是代码(为简洁起见,它已被简化):

def calculate(row):
    values = []
    weights = []
    continued = False

    df_a = df[((df.winner_id == row['winner_id']) | (df.loser_id == row['winner_id']))].loc[row['index'] + 1:]
    if len(df_a) < 30:
        df.drop(row['index'], inplace = True)    
        continued = True
    ##if we dropped the row, we don't want to calculate it's value
    if continued == False:
        for match in zip(df_a['winner_id'],df_a['tourney_date'],df_a['winner_rank'],df_a['loser_rank'],
                         df_a['winner_serve_pts_pct']):
                weight = time_discount(yrs_between(match[1],row['tourney_date']))
                ##calculate individual values and weights
                values.append(match[4] * weight * opp_weight(match[3]))
                weights.append(weight)
    ##return calculated value
    return sum(values)/sum(weights)


df['new'] = df.apply(calculate, axis = 1)

我的数据帧不是太大(60,000乘35),但我的代码运行大约需要40分钟。我最初使用iterrows(),但人们建议我使用zip()并申请 - 但它仍然需要很长时间。任何帮助将不胜感激。谢谢

1 个答案:

答案 0 :(得分:0)

对于大型阵列上的浮点运算的性能,实际计算是非常罕见的。限制因素是高速缓存大小和从浮点寄存器和算术单元获取数字是很常见的。

如果您可以接受降低的精度,那么转到32位浮点数而不是默认的64位可能会带来一些好处。这将使数组的大小减半。见Correct way to emulate single precision floating point in python?

它仍将为您提供9,600,000字节的数据结构,大于您需要适合您的活动数据的关键低级缓存。

更好的方法可能是查看组织操作的顺序以有效使用缓存。例如,可以通过将矩阵乘法视为较小子矩阵的一系列乘法的总和来优化矩阵乘法,每个子矩阵适合于高速缓存。无论是沿着行还是列进行迭代都与数组存储在内存中的方式相匹配都会产生很大的不同。

一般而言,请将注意力集中在最小化数据移动上。