Я хочу взять ввод миллионов длинных точек широты (с числовым атрибутом) и затем найти все геопространственные кластеры с фиксированным радиусом, где сумма атрибута в круге выше определенного порога.
Я начал с использования sklearn BallTree для суммирования атрибута в любом определенном круге, чтобы затем расширить его, чтобы пробегать сетку или решетку окружностей.Время пробега для одного круга составляет около 0,01 с, так что это хорошо для небольших решеток, но не масштабируется, если я хочу пробежать круги радиусом 200 м по всей территории Великобритании.
#example data (use 2m rows from postcode centroid file)
df = pandas.read_csv('National_Statistics_Postcode_Lookup_Latest_Centroids.csv', usecols=[0,1], nrows=2000000)
#this will be our grid of points (or lattice) use points from same file for example
df2 = pandas.read_csv('National_Statistics_Postcode_Lookup_Latest_Centroids.csv', usecols=[0,1], nrows=2000)
#reorder lat long columns for balltree input
columnTitles=["Y","X"]
df = df.reindex(columns=columnTitles)
df2 = df2.reindex(columns=columnTitles)
# assign new columns to existing dataframe. attribute will hold the data we want to sum over (set to 1 for now)
df['attribute'] = 1
df2['aggregation'] = 0
RADIANT_TO_KM_CONSTANT = 6367
class BallTreeIndex:
def __init__(self, lat_longs):
self.lat_longs = np.radians(lat_longs)
self.ball_tree_index =BallTree(self.lat_longs, metric='haversine')
def query_radius(self,query,radius):
radius_km = radius/1000
radius_radiant = radius_km / RADIANT_TO_KM_CONSTANT
query = np.radians(np.array([query]))
indices = self.ball_tree_index.query_radius(query,r=radius_radiant)
return indices[0]
#index the base data
a=BallTreeIndex(df.iloc[:,0:2])
#begin to loop over the lattice to test performance
for i in range(0,100):
b = df2.iloc[i,0:2]
output = a.query_radius(b, 200)
accumulation = sum(df.iloc[output, 2])
df2.iloc[i,2] = accumulation
По ощущениямкак будто приведенный выше код действительно неэффективен, так как мне не нужно выполнять вычисления на всех кругах в моей решетке (так как большинство будет намного ниже моего порога - или вообще не будет иметь точек данных).
Вместо этого для цикла, есть ли лучший способ масштабирования этого алгоритма, чтобы дать мне наиболее плотные круги?
Я новичок в Python, поэтому любая помощь будет высоко ценится !!