【问题标题】:How to iterate through 'nested' dataframes without 'for' loops in pandas (python)?如何在熊猫(python)中没有“for”循环的情况下遍历“嵌套”数据帧?
【发布时间】:2018-03-24 22:08:39
【问题描述】:

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

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

这是我正在尝试的矢量化格式 - '对于来自 df1 的每一对点 (a,b),如果从 df2 到任何点 (d,e) 的距离为 > 阈值,则将“是”打印到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

【问题讨论】:

  • 这是预期的行为。正如你所说的all but one distances > 1,这是C列中标记为yes的那个。
  • 有 3x3 的距离要检查,所以 9 个中有 8 个是 >1。所有输入行都超过 dist = 1,所以都应该得到 yes。

标签: python-3.x pandas iteration


【解决方案1】:

【讨论】:

  • 谢谢,我去看看。尽管试图最小化额外的包,因为它们在我们的环境中设置并不容易。
【解决方案2】:

这里有一个想法可以帮助您开始...

源 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

具有笛卡尔积的辅助 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

【讨论】:

  • 我已经搞定了,谢谢。也许最好还是分几步完成,而不是像我尝试使用单线一样一次完成。仍然“矢量化”,一旦我在真实数据上尝试它应该会更快。
猜你喜欢
  • 2020-08-09
  • 1970-01-01
  • 1970-01-01
  • 2021-12-22
  • 1970-01-01
  • 1970-01-01
  • 2020-11-20
  • 1970-01-01
相关资源
最近更新 更多