Я хотел бы проверить координаты (x, y, z) из dataframe-1 (df1), чтобы увидеть, находится ли местоположение достаточно близко к нерегулярной поверхности, которая имеет свои собственные координаты (x, y, z), хранящиеся в dataframe-2 ( df2 ) .

Я могу пройти через каждую координату в df1, затем просмотреть все координаты в df2 и проверить ее расстояние. Затем повторите для всех координат в df1, но это займет слишком много времени, когда у меня есть более 1 000 000 координат в df1 для проверки.

Я пользуюсь пандами и задаюсь вопросом, можно ли это сделать без зацикливания.

Если координата в df1 близка к df2, я хочу выбрать ее и сохранить в df3.

1
kyzerkenso 16 Апр 2019 в 08:46

2 ответа

Лучший ответ

Сципи может помочь тебе. Посмотрите на следующий гипотетический пример:

import pandas as pd 
from scipy.spatial import cKDTree

dataset1 = pd.DataFrame(pd.np.random.rand(100,3))
dataset2 = pd.DataFrame(pd.np.random.rand(10, 3))

ck = cKDTree(dataset1.values)

ck.query_ball_point(dataset2.values, r=0.1)

массив ([список ([]), список ([]), список ([]), список ([]), список ([28, 83]), список ([79]), список ([]), список ([86]), list ([40]), list ([29, 60, 95])], dtype = object)

1
bubble 16 Апр 2019 в 06:37

Используя Numpy методы:

Если ваши два фрейма данных выглядят так:

df1
    coords
0   (4,3,5)
1   (5,4,3)

df2
    coords
0   (6,7,8)
1   (8,7,6)

Тогда:

import numpy as np
from itertools import product

#convert dataframes into numpy arrays
df1_arr = np.array([np.array(x) for x in df1.coords.values])
df2_arr = np.array([np.array(x) for x in df2.coords.values])

#create array of cartesian product of elements of the two arrays
cart_arr = np.array([x for x in product(df1_arr,df2_arr)])

#compute Euclidian distance (or norm) between pairs of elements in two arrays
#outputs new array with one value per pair of coordinates
norms_arr = np.linalg.norm(np.diff(cart_arr,axis=1)[:,0,:],axis=1)

#create distance threshold for "close enough"
radius = 5.5

#find values in norms array that are less than or equal to distance threshold
good_idxs = np.argwhere(norms_arr <= radius)[:,0]
good_coord_pairs = cart_arr[good_idxs]

#store corresponding pairs of coordinates and distances in new dataframe
final_df = pd.DataFrame({'df1_coords':list(map(tuple,good_coord_pairs[:,0,:])),
   'df2_coords':list(map(tuple(good_coord_pairs[:,1,:])), 'distance':norms_arr[good_idxs],
   index=list(range(len(good_coord_pairs))))

Произведет:

final_df
    df1_coords  df2_coords  distance
0   (4,3,5)     (6,7,8)     5.385165
1   (5,4,3)     (8,7,6)     5.196152
1
AlexK 16 Апр 2019 в 08:31