Определить относительное положение координат - python - PullRequest
3 голосов
/ 31 января 2020

У меня есть координаты, представляющие точки в различных временных масштабах. Я хочу вычислить среднее значение этих точек по отношению друг к другу.

Чтобы достичь этого, я стремлюсь вычислить расстояние между каждой точкой и остальными точками. Затем я надеюсь усреднить эти точки.

Ниже вычисляется расстояние между каждой парой точек.

import pandas as pd
from scipy.spatial import distance
import itertools

df = pd.DataFrame({   
        'Time' : [1,1,1,2,2,2,3,3,3],             
        'id' : ['A','B','C','A','B','C','A','B','C'],                 
        'X' : [1.0,3.0,2.0,2.0,4.0,3.0,3.0,5.0,4.0],
        'Y' : [1.0,1.0,0.5,2.0,2.0,2.5,3.0,3.0,3.0],
    })

ids = list(df['id'])

# get the points
points = df[["X", "Y"]].values

# calculate distance of each point from every other point.
# row i contains contains distances for point i. 
# distances[i, j] contains distance of point i from point j.
distances = distance.cdist(points, points, "euclidean")
distances = distances.flatten()

# get the start and end points
cartesian = list(itertools.product(ids, ids))

data = dict(
            start_region = [x[0] for x in cartesian],
            end_region = [x[1] for x in cartesian],
            distance = distances
        )

df1 = pd.DataFrame(data)

Все, что мне действительно нужно вывести:

   Time start_point end_point    X    Y
0     1           A         B  2.0  0.0
1     1           A         C  1.0 -0.5
2     1           B         C -1.0 -0.5
3     2           A         B  2.0  0.0
4     2           A         C  1.0  0.5
5     2           B         C -1.0  0.5
6     3           A         B  2.0  0.0
7     3           A         C  1.0  0.0
8     3           B         C -1.0  0.0

enter image description here

Таким образом, среднее положение этих точек по отношению друг к другу будет зелеными координатами.

Но если я усредню набор данных над ним, то отобразится:

enter image description here

Я понимаю, как это происходит. Это не ссылается на другие пункты.

Ответы [ 2 ]

1 голос
/ 05 февраля 2020

Вот мой взгляд на это

import itertools

def relative_dist(gp):
     combs = list(itertools.combinations(gp.index, 2))
     df_gp = pd.concat([gp.loc[tup,:].diff() for tup in combs], keys=combs).dropna()

     return df_gp

df_dist = (df.set_index('id').groupby('Time')[['X','Y']].apply(relative_dist)
             .droplevel('id').rename_axis(['Time','start_point','end_point'])
             .reset_index())

Out[341]:
   Time start_point end_point    X    Y
0     1           A         B  2.0  0.0
1     1           A         C  1.0 -0.5
2     1           B         C -1.0 -0.5
3     2           A         B  2.0  0.0
4     2           A         C  1.0  0.5
5     2           B         C -1.0  0.5
6     3           A         B  2.0  0.0
7     3           A         C  1.0  0.0
8     3           B         C -1.0  0.0

df_avg = df_dist.groupby(['start_point','end_point'], as_index=False)[['X','Y']].mean()

Out[347]:
  start_point end_point    X    Y
0           A         B  2.0  0.0
1           A         C  1.0  0.0
2           B         C -1.0  0.0
0 голосов
/ 04 февраля 2020

Вот предложение о том, как визуализировать относительные положения ваших точек. Я бы хотел, чтобы для каждой временной метки был построен эллипс в позиции (X_, Y_), где:

  • X_ - это среднее значение ваших координат X для этой временной метки.
  • Y_ - это среднее значение ваших координат X для этой отметки времени.
  • ширина эллипса равна дисперсии координат вашей точки X для этой отметки времени.
  • высота эллипса равна дисперсии координат ваших точек Y для этой отметки времени.

Таким образом, одним взглядом и для каждой временной отметки вы можете прочитать статистику очень высокого уровня о вашем распределении координат в этой временной отметке.

Вот некоторый код для генерации такой визуализация:

%matplotlib inline
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.patches import Ellipse

# sample data with 4 timestamps
df = pd.DataFrame({   
        'Time' : [1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4],             
        'id' : ['A','B','C','D','A','B','C','D','A','B','C','D','A','B','C','D'],                 
        'X' : [1,2,1,2,1,2,1,2,4,4,3,4,10,8,5,6],
        'Y' : [1,1,3,3,1,1,2,2,5,5,8,5,6,6,7,6],
       })

# for each timestamp, compute means and variances within all samples for that timestamp
means = df.groupby("Time")[["X", "Y"]].mean()
variances = df.groupby("Time")[["X", "Y"]].var()
df_ = pd.concat([means, variances], axis=1)
df_.columns = ["X_", "Y_", "var_X", "var_Y"]

# plot 
fig, ax = plt.subplots(subplot_kw={'aspect': 'equal'})
for row in df_.itertuples():
    ellipse = Ellipse(xy=(row.X_, row.Y_),  # position of the ellipse is (X,Y)
                width=row.var_X,  # width helps to get a grasp on X variance
                height=row.var_Y,  # height helps to get a grasp on Y variance
                angle=0)
    ax.add_artist(ellipse)
    ellipse.set_clip_box(ax.bbox)
    ellipse.set_alpha(.4)
    plt.text(x=row.X_+0.2, y=row.Y_+0.2, s=f"t={row.Index}")  # just add timestamp legend


ax.set_xlim(0, 10)
ax.set_ylim(0, 10)

plt.show()

Что бы выглядело так:

enter image description here

Что вы думаете? Другая идея может состоять в том, чтобы сделать GIF (в случае, если среднее значение временных меток слишком сильно сталкивается).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...