pandas将函数应用于多列和多行

时间:2014-06-13 09:32:09

标签: python pandas

我有一个数据帧,在行和列'xpos','ypos'中有连续的像素坐标,我想计算连续像素之间每条路径的角度。目前我有下面提供的解决方案,它工作正常,我的文件的大小足够快,但迭代所有行似乎不是熊猫的方式来做到这一点。我知道如何将函数应用于不同的列,以及如何将函数应用于不同的列行,但无法弄清楚如何将两者结合起来。

这是我的代码:

fix_df = pd.read_csv('fixations_out.csv')

# wyliczanie kąta sakady
temp_list=[]
for count, row in df.iterrows():
    x1 = row['xpos']
    y1 = row['ypos']
    try:
        x2 = df['xpos'].ix[count-1]
        y2 = df['ypos'].ix[count-1]
        a = abs(180/math.pi * math.atan((y2-y1)/(x2-x1)))
        temp_list.append(a)
    except KeyError:
        temp_list.append(np.nan)

然后我将临时列表插入到df

编辑: 在实施我的评论提示之后:

df['diff_x'] = df['xpos'].shift() - df['xpos']
df['diff_y'] = df['ypos'].shift() - df['ypos']

def calc_angle(x):
    try:
        a = abs(180/math.pi * math.atan((x.diff_y)/(x.diff_x)))
        return a
    except ZeroDivisionError:
        return 0

df['angle_degrees'] = df.apply(calc_angle, axis=1)

我比较了我的df的三个解决方案的时间(df的大小约为6k行),迭代几乎比应用慢9倍,比没有应用时慢了大约1500倍:

迭代解决方案的执行时间,包括将新列插入df: 1,51s

没有迭代的解决方案的执行时间,应用: 0.17s

EdChum使用diff()接受答案的执行时间,没有迭代且没有申请: 0.001s

建议:不要使用迭代或应用,并始终尝试使用矢量化计算;)它不仅更快,而且更具可读性。

1 个答案:

答案 0 :(得分:9)

你可以通过以下方法做到这一点,我将熊猫的方式与你的方式进行了比较,它的速度提高了1000多倍,而且没有将列表作为新列添加回来!这是在10000行数据框上完成的

In [108]:

%%timeit
import numpy as np
df['angle'] = np.abs(180/math.pi * np.arctan(df['xpos'].shift() - df['xpos']/df['ypos'].shift() - df['ypos']))

1000 loops, best of 3: 1.27 ms per loop

In [100]:

%%timeit
temp_list=[]
for count, row in df.iterrows():
    x1 = row['xpos']
    y1 = row['ypos']
    try:
        x2 = df['xpos'].ix[count-1]
        y2 = df['ypos'].ix[count-1]
        a = abs(180/math.pi * math.atan((y2-y1)/(x2-x1)))
        temp_list.append(a)
    except KeyError:
        temp_list.append(np.nan)
1 loops, best of 3: 1.29 s per loop

另外,如果可能的话,请避免使用apply,因为这会逐行操作,如果你能找到一个可以在整个系列或数据帧上工作的矢量化方法,那么总是喜欢这个。

<强>更新

看到你正在从前一行进行减法,这个diff的内置方法会导致更快的代码:

In [117]:

%%timeit
import numpy as np
df['angle'] = np.abs(180/math.pi * np.arctan(df['xpos'].diff(1)/df['ypos'].diff(1)))

1000 loops, best of 3: 1.01 ms per loop

另一次更新

还有一个用于系列和数据帧划分的构建方法,这现在可以减少更多的时间,并且我实现了1ms的时间:

In [9]:

%%timeit
import numpy as np
df['angle'] = np.abs(180/math.pi * np.arctan(df['xpos'].diff(1).div(df['ypos'].diff(1))))

1000 loops, best of 3: 951 µs per loop