我有一个数据帧,在行和列'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
建议:不要使用迭代或应用,并始终尝试使用矢量化计算;)它不仅更快,而且更具可读性。
答案 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