Как проверить, что точка находится внутри заданного радиуса? - PullRequest
0 голосов
/ 15 октября 2018

У меня есть следующий код, выполнение которого занимает очень много времени.Панды DataFrames df и df_plants очень малы (менее 1 МБ).Интересно, есть ли способ оптимизировать этот код:

import pandas as pd
import geopy.distance
import re

def is_inside_radius(latitude, longitude, df_plants, radius):
    if (latitude != None and longitude != None):
        lat = float(re.sub("[a-zA-Z]", "", str(latitude)))
        lon = float(re.sub("[a-zA-Z]", "", str(longitude)))
        for index, row in df_plants.iterrows():
            coords_1 = (lat, lon)
            coords_2 = (row["latitude"], row["longitude"])
            dist = geopy.distance.distance(coords_1, coords_2).km
            if dist <= radius:
                return 1
    return 0

df["inside"] = df.apply(lambda row: is_inside_radius(row["latitude"],row["longitude"],df_plants,10), axis=1)

Я использую регулярное выражение для обработки широты и долготы в df, потому что значения содержат некоторые ошибки (символы), которые следует удалить.

Функция is_inside_radius проверяет, находятся ли row[latitude] и row[longitude] в радиусе 10 км от любой из точек в df_plants.

Ответы [ 2 ]

0 голосов
/ 15 октября 2018

Можете ли вы попробовать это?

import pandas as pd
from geopy import distance
import re

def is_inside_radius(latitude, longitude, df_plants, radius):
  if (latitude != None and longitude != None):
    lat = float(re.sub("[a-zA-Z]", "", str(latitude)))
    lon = float(re.sub("[a-zA-Z]", "", str(longitude)))
    coords_1 = (lat, lon)

    for row in df_plants.itertuples():
      coords_2 = (row["latitude"], row["longitude"])
      if distance.distance(coords_1, coords_2).km <= radius:
        return 1
  return 0

df["inside"] = df.map(
                    lambda row: is_inside_radius(
                      row["latitude"],
                      row["longitude"],
                      df_plants,
                      10),
                    axis=1)
0 голосов
/ 15 октября 2018

Я уже сталкивался с такой проблемой раньше и вижу одну простую оптимизацию: постарайтесь избежать вычисления с плавающей запятой настолько, насколько это возможно, что вы можете сделать следующим образом:
Представьте себе:
У вас есть круг, определяемый Mx и My (координаты центра) и R (радиус).
У вас есть точка, определяемая координатами X и Y.

Если ваша точка (X, Y) даже не находится в пределахквадрат, определенный (Mx, My) и размером 2 * R, тогда он также не будет находиться внутри круга, определенного (Mx, My) и радиусом R.
В псевдокоде:

function is_inside(X,Y,Mx,My,R):
  if (abs(Mx-X) >= R) OR (abs(My-Y) >= R)
  then return false
  else:
    // and only here you perform the floating point calculation
...