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

Python 将函数应用于多列和多行,python,pandas,Python,Pandas,我有一个数据帧,行和列中有连续的像素坐标“xpos”,“ypos”,我想计算连续像素之间每条路径的角度(以度为单位)。目前,我有下面介绍的解决方案,它可以很好地工作,而且我的文件的大小足够快,但是遍历所有行似乎不是这样做的方法。我知道如何将函数应用于不同的列,以及如何将函数应用于不同的列行,但不知道如何将两者结合起来 这是我的密码: fix_df = pd.read_csv('fixations_out.csv') # wyliczanie kąta sakady temp_list=[] f

我有一个数据帧,行和列中有连续的像素坐标“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行),迭代速度比apply慢近9倍,比不使用apply时慢约1500倍:

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

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

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


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

您可以通过以下方法来实现这一点,我将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
此外,如果可能,请避免使用
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

首先,您可以将差异计算为
df['xpos'].shift()-df['xpos']
,而不是按行计算,然后你可以在整列上使用你的函数计算角度。我已经更新了我的答案,我得到的性能不到1ms,这比
abs
要快很多个数量级。abs在第一种情况下应该是
np。abs
?@joris,是的,为了保持一致性,但是1.27ms和1.29ms没有什么区别,不过我会更新答案,谢谢