如何在pandas(python)中没有'for'循环的情况下迭代'嵌套'数据帧?

时间:2017-10-12 20:46:14

标签: python-3.x pandas iteration

我正在尝试检查一个数据框中每组点与另一个数据帧中的散点集之间的笛卡尔距离,以查看输入是否超出了检查点的阈值“距离”。

我使用嵌套for循环,但速度很慢(40k输入行约7分钟,每行检查约180行,+一些开销操作)。

如果从df2到ANY点(d,e)的距离是>,那么我正在尝试矢量化格式 - 对于来自df1的每对点(a,b)。阈值,在输入点旁边的df1.c中打印“是”。

..但是我从这里得到了意想不到的行为。对于给定的数据,除了一个距离之外的所有距离都> 1,但只有df1.1c得到'是'。

感谢任何想法 - 问题可能在'df1.loc ...'行:

import numpy as np
from pandas import DataFrame

inp1 = [{'a':1, 'b':2, 'c':0}, {'a':1,'b':3,'c':0}, {'a':0,'b':3,'c':0}]
df1 = DataFrame(inp1)

inp2 = [{'d':2, 'e':0}, {'d':0,'e':3}, {'d':0,'e':4}]
df2 = DataFrame(inp2)

threshold = 1

df1.loc[np.sqrt((df1.a - df2.d) ** 2 + (df1.b - df2.e) ** 2) >   threshold, 'c'] = "yes"

print(df1)
print(df2)

   a  b    c
0  1  2  yes
1  1  3    0
2  0  3    0

   d  e
0  2  0
1  0  3
2  0  4

2 个答案:

答案 0 :(得分:1)

答案 1 :(得分:1)

这是一个帮助你开始......

的想法

来源DF:

In [170]: df1
Out[170]:
   c  x  y
0  0  1  2
1  0  1  3
2  0  0  3

In [171]: df2
Out[171]:
   x  y
0  2  0
1  0  3
2  0  4

Helper DF与笛卡儿产品:

In [172]: x = df1[['x','y']] \
                 .reset_index() \
                 .assign(k=0).merge(df2.assign(k=0).reset_index(), 
                                    on='k', suffixes=['1','2']) \
                 .drop('k',1)


In [173]: x
Out[173]:
   index1  x1  y1  index2  x2  y2
0       0   1   2       0   2   0
1       0   1   2       1   0   3
2       0   1   2       2   0   4
3       1   1   3       0   2   0
4       1   1   3       1   0   3
5       1   1   3       2   0   4
6       2   0   3       0   2   0
7       2   0   3       1   0   3
8       2   0   3       2   0   4

现在我们可以计算距离:

In [169]: x.eval("D=sqrt((x1 - x2)**2 + (y1 - y2)**2)", inplace=False)
Out[169]:
   index1  x1  y1  index2  x2  y2         D
0       0   1   2       0   2   0  2.236068
1       0   1   2       1   0   3  1.414214
2       0   1   2       2   0   4  2.236068
3       1   1   3       0   2   0  3.162278
4       1   1   3       1   0   3  1.000000
5       1   1   3       2   0   4  1.414214
6       2   0   3       0   2   0  3.605551
7       2   0   3       1   0   3  0.000000
8       2   0   3       2   0   4  1.000000

或过滤:

In [175]: x.query("sqrt((x1 - x2)**2 + (y1 - y2)**2) > @threshold")
Out[175]:
   index1  x1  y1  index2  x2  y2
0       0   1   2       0   2   0
1       0   1   2       1   0   3
2       0   1   2       2   0   4
3       1   1   3       0   2   0
5       1   1   3       2   0   4
6       2   0   3       0   2   0