Получение ближайших наблюдений с использованием евклидова расстояния

#python #pandas #dataframe

Вопрос:

У меня есть фрейм данных, который выглядит следующим образом

 ID PC1 PC2 12 0.355 0.362 24 0.577 0.425 15 0.257 0.486 06 0.585 0.254 34 0.367 0.533  

Я хочу использовать евклидово расстояние на PC1 и PC2, чтобы получить ближайшие точки данных.

Поэтому я хочу, чтобы, когда я ввожу ID = 15 python, я хотел, чтобы он дал мне список из 3 точек данных, которые находятся ближе всего. Желаемый результат будет выглядеть следующим образом.

 ID PC1 PC2 Distance 34 0.367 0.533 ### 06 0.585 0.254 ### 12 0.355 0.462 ###  

Приведенные выше цифры составлены, но я хочу, чтобы мои выходные данные выглядели именно так. ‘Расстояние » — это расстояние от входной точки данных (ID=15) до каждой соответствующей точки данных на выходе.

Я знаю, что это довольно просто, но я начинающий изучающий python. Я немного не уверен, как подойти к этому, так может ли кто-нибудь мне помочь? Спасибо.

Комментарии:

1. Вы уверены в своих результатах? Я нашел (34, 12, 24).

Ответ №1:

Если вам нужно запросить много точек, вы можете сначала построить KDTree . Вот пример использования scipy :

 from scipy import spatial  # WARNING: This assumes that all points in the DataFrame are distinct.  # construct a KDTree given a set of points tree = spatial.cKDTree(df[["PC1", "PC2"]]) # get four = three   one points closest to a given point (index 15 in this case) # the query point itself will be part of the output distances, indices = tree.query(df.loc[15].values, k=3 1) # get the df of near points df_near = df.iloc[indices[1:]].assign(Distance=distances[1:])  print(df_near) # PC1 PC2 Distance # ID  # 34 0.367 0.533 0.119620 # 12 0.355 0.362 0.158051 # 24 0.577 0.425 0.325762  

Комментарии:

1. Отлично, у нас одинаковый результат 🙂

2. Вы предполагаете, что столбец «ИДЕНТИФИКАТОР» является индексом фрейма данных ( df.loc[15] ). Я так не думаю, может быть, тебе и придется set_index . Затем проверьте 4-й идентификатор -gt; ’06’, а не 6, поэтому тип dtype идентификатора столбца, вероятно, gt; str и нет int .

3. И последний пункт (у меня была та же проблема…). Добавьте строку в начале вашего фрейма данных, например 03 0.257 0.486 . Вы отфильтруете «03» и сохраните «15».

4. Я ценю, как это исправляет данный конкретный пример; однако этот подход потребует знания индекса запроса перед построением KDTree, что в некотором роде противоречит цели. Если требуется запросить только одну точку, нет необходимости создавать дерево KDTree.

5. Вы совершенно правы. Я согласен с этим.

Ответ №2:

Попробуй:

 ID = '15'  # Extract PC1, PC2 from current point (ID='15') point = df.loc[df['ID'] == ID, ['PC1', 'PC2']].squeeze()  # Keep all other points others = df.loc[df['ID'] != ID, ['PC1', 'PC2']]  # Compute the distance between the point and the other points # and keep the 3 points with the smallest distance dist = (others - point).pow(2).sum(1).pow(0.5).nsmallest(3) out = df.loc[dist.index].assign(Distance=dist)  

Выход:

 gt;gt;gt; out  ID PC1 PC2 Distance 4 34 0.367 0.533 0.119620 0 12 0.355 0.362 0.158051 1 24 0.577 0.425 0.325762