Python / Pandas是否可以向量化与相对类别中所有其他点的比较?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python / Pandas是否可以向量化与相对类别中所有其他点的比较?相关的知识,希望对你有一定的参考价值。
我有一个x,y点的数据集,它们分别位于两个单独的类别中。我想对10个左右点的许多“框架”进行分组(或分割),而不要遍历。我想将类别A中的每个点与类别B中的所有点进行比较。特别是我想要它们之间的距离。我尚未找到将groupby操作向量化的正确组合。
这里是样本df:
frame_id point_id x y cat
0 1 1 1.769 2.491 A
1 1 2 1.024 0.981 A
2 1 3 4.327 9.81 A
3 1 4 5.407 4.33 A
4 1 5 0.936 0.019 B
5 1 6 5.1 7.639 B
6 1 7 9.139 6.721 B
7 1 8 1.954 5.424 B
8 2 1 5.835 9.702 A
9 2 2 1.784 1.374 A
10 2 3 0.23 1.921 A
11 2 4 9.328 5.836 A
12 2 5 5.516 8.971 B
13 2 6 9.108 8.917 B
14 2 7 4.412 1.033 B
15 2 8 1.33 5.898 B
理想情况下,在此示例中,我将添加四列。每个距离的一列指向另一类别。我想象有某种方法可以执行df.groupby(['frame_id'])或df.groupby(['frame_id','cat'])并以这种方式进行比较,但我还没有弄清楚。
我已经能够通过迭代来完成此任务:
import scipy.spatial
for idx, fid in enumerate(frame_ids):
if idx % 1000 == 0:
print(idx)
# separate categories
cat_a = df.loc[(df.frame_id==fid)&(df.Cat=="A")]
cat_b = df.loc[(df.frame_id==fid)&(df.Cat=="B")]
# get distance to every opposing category point
a_mat = scipy.spatial.distance.cdist(cat_a[['X','Y']], cat_b[['X','Y']], metric='euclidean')
b_mat = scipy.spatial.distance.cdist(cat_b[['X','Y']], cat_a[['X','Y']], metric='euclidean')
a_ids = cat_a[['frame_id','point_id']].values
b_ids = cat_b[['frame_id','point_id']].values
a_dist = np.concatenate((a_ids, a_mat),axis=1)
b_dist = np.concatenate((b_ids, b_mat),axis=1)
### then concat one by one w/ larger dataframe (takes forever) ###
输出(为清楚起见,删除了几列):
frame_id point_id Dist_Opp1 Dist_Opp2 Dist_Opp3 Dist_Opp4
0 1 1 2.60858 6.13168 8.49763 2.93883
1 1 2 0.966017 7.80658 9.93986 4.53929
2 1 3 10.3616 2.30451 5.71815 4.9868
3 1 4 6.21084 3.32321 4.43223 3.62216
4 1 5 2.60858 0.966017 10.3616 6.21084
5 1 6 6.13168 7.80658 2.30451 3.32321
6 1 7 8.49763 9.93986 5.71815 4.43223
7 1 8 2.93883 4.53929 4.9868 3.62216
8 2 1 0.797573 3.36582 8.78502 5.89622
9 2 2 8.46417 10.5137 2.65003 4.54672
10 2 3 8.8116 11.3032 4.27524 4.12632
11 2 4 4.93554 3.08884 6.87284 7.99824
12 2 5 0.797573 8.46417 8.8116 4.93554
13 2 6 3.36582 10.5137 11.3032 3.08884
14 2 7 8.78502 2.65003 4.27524 6.87284
15 2 8 5.89622 4.54672 4.12632 7.99824
没有必要比较同一类别内的点。
答案
最终想通了。它只需要使用numpy矩阵进行创意重塑/重复。
df['loc'] = list(zip(df['x'],df['y']))
groupA = df.loc[df.Cat==1]
groupB = df.loc[df.Cat==0]
groupA = groupA[['frame_id','point_id','loc']]
groupB = groupB[['frame_id','point_id','loc']]
acol = groupA['loc'].values
bcol = groupB['loc'].values
group_size = 4
acol = np.repeat(acol,group_size,axis=0)
bcol = bcol.reshape(-1,group_size)
bcol = np.repeat(bcol,group_size,axis=0)
bcol = bcol.reshape(-1)
# numpy requires replacing tuple with 2d point
acol = np.array([*acol])
bcol = np.array([*bcol])
# distance calc
desired_matrix = np.linalg.norm(acol - bcol, axis=-1)
以上是关于Python / Pandas是否可以向量化与相对类别中所有其他点的比较?的主要内容,如果未能解决你的问题,请参考以下文章