У меня есть набор данных x, y точек, которые находятся в двух отдельных категориях. Есть много «кадров» из десяти или около того точек, которые я хочу сгруппировать (или разделить на части) вместо того, чтобы перебирать. Я хочу сравнить каждую точку в категории A со всеми точками в категории B. В частности, я хочу расстояние между ними. Я не нашел правильной комбинации групповых операций для ее векторизации.
Вот пример 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
Нет необходимости сравнивать точки в пределахтой же категории.