У меня есть адресные данные и шейп-файлы с полигонами, и я пытаюсь определить ближайшее расстояние (в милях) каждого адреса от каждого полигона, а затем создать вложенный диктат, содержащий всю информацию, в следующем формате:
nested_dict = {poly_1: {address1: distance, address2 : distance},
poly2: {address1: distance, address2: distance}, etc}
Полный применимый код, который я использую:
import pandas as pd
from shapely.geometry import mapping, Polygon, LinearRing, Point
import geopandas as gpd
from math import radians, cos, sin, asin, sqrt
address_dict = {k: [] for k in addresses_geo.input_string}
sludge_dtc = {k: [] for k in sf_geo.unique_name}
def haversine(lon1, lat1, lon2, lat2):
"""
Calculate the great circle distance between two points
on the earth (specified in decimal degrees)
"""
# convert decimal degrees to radians
lon1, lat1, lon2, lat2 = map(radians, [lon1, lat1, lon2, lat2])
# haversine formula
dlon = lon2 - lon1
dlat = lat2 - lat1
a = sin(dlat/2)**2 + cos(lat1) * cos(lat2) * sin(dlon/2)**2
c = 2 * asin(sqrt(a))
r = 3956 # Radius of earth in miles. Use 6371 for kilometers
return c * r
# Here's the key loop that isn't working correctly
for unique_name, i in zip(sf_geo.unique_name, sf_geo.index):
for address, pt in zip(addresses_geo.input_string, addresses_geo.index):
pol_ext = LinearRing(sf_geo.iloc[i].geometry.exterior.coords)
d = pol_ext.project(addresses_geo.iloc[pt].geometry)
p = pol_ext.interpolate(d)
closest_point_coords = list(p.coords)[0]
# print(closest_point_coords)
dist = haversine(addresses_geo.iloc[pt].geometry.x,
addresses_geo.iloc[pt].geometry.y,
closest_point_coords[0], closest_point_coords[1])
address_dict[address] = dist
sludge_dtc[unique_name] = address_dict
# Test results on a single address
addresses_with_sludge_distance = pd.DataFrame(sludge_dtc)
print(addresses_with_sludge_distance.iloc[[1]].T)
Если я нарушу этот код и попытаюсь вычислить расстояния для одного многоугольника, кажется, он работает нормально. Однако, когда я создаю DataFrame и проверяю адрес, он перечисляет одинаковое расстояние для каждого полигона.
Таким образом, внутренний ключ-диктат '123 Main Street' будет иметь 5,25 миль за каждый из ключей многоугольника во внешнем диктанте, а '456 South Street' будет иметь 6,13 миль за каждый из ключей многоугольника ввнешний диктат. (Придуманные примеры.)
Я понимаю, что должен делать что-то глупое, как у меня настроены циклы for, но я не могу понять это. Я изменил порядок операторов for, перепутанных с отступами - все тот же результат.
Чтобы было ясно, что я хочу, это:
- Взятьодин полигон, затем
- Для каждого адреса в адресных данных найдите расстояние от этого полигона и добавьте его в словарь address_dict с адресом в качестве ключа и расстоянием в качестве значения
- Когда всеадреса были вычислены, добавьте полный адрес dict в качестве значения для ключа многоугольника в sludge_dtc
- Перейдите к следующему многоугольнику и продолжите
Есть идеи, что мне не хватает?