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

yem*_*emu 9 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)
Run Code Online (Sandbox Code Playgroud)

然后我将临时列表插入到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)
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

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

EdC*_*ica 10

您可以通过以下方法执行此操作,并将pandas方式与您的方式进行比较,并且速度提高了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
Run Code Online (Sandbox Code Playgroud)

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

UPDATE

看到你只是从前一行做一个减法,有内置的方法,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
Run Code Online (Sandbox Code Playgroud)

另一个更新

还有一个用于系列和数据帧划分的内置方法,这现在可以减少更多的时间,并且我实现了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
Run Code Online (Sandbox Code Playgroud)