for循环的嵌套dict向所有嵌套键添加相同的值

2024-09-28 23:19:16 发布

您现在位置:Python中文网/ 问答频道 /正文

我有带多边形的地址数据和形状文件,正在尝试确定每个地址与每个多边形的最近距离(以英里为单位),然后创建一个包含所有信息的嵌套dict,格式如下:

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并检查地址时,它会为每个多边形列出相同的距离。你知道吗

因此,内部dict键“123 Main Street”对于外部dict中的每个多边形键将有5.25英里,而“456 South Street”对于外部dict中的每个多边形键将有6.13英里

我意识到我一定在用for循环设置的方式做一些愚蠢的事情,但我想不出来。我颠倒了for语句的顺序,弄乱了缩进——结果都一样。你知道吗

我想说清楚的是:

  • 拿一个多边形来说
  • 对于地址数据中的每个地址,找到与该多边形的距离,并将地址作为键,距离作为值添加到地址字典中
  • 计算完所有地址后,将整个address dict作为polygon key的值添加到dtc中
  • 转到下一个多边形并继续

你知道我遗漏了什么吗?你知道吗


Tags: in距离foraddressaddresses地址coords多边形
1条回答
网友
1楼 · 发布于 2024-09-28 23:19:16

问题很简单,您总是使用相同的address_dict实例。 你只需要在每个键循环中重新创建它。你知道吗

import pandas as pd
from shapely.geometry import mapping, Polygon, LinearRing, Point
import geopandas as gpd
from math import radians, cos, sin, asin, sqrt

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

sludge_dtc = {k: [] for k in sf_geo.unique_name}

# Here's the key loop that isn't working correctly
for unique_name, i in zip(sf_geo.unique_name, sf_geo.index):

    address_dict = {k: [] for k in addresses_geo.input_string}

    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)

另一个考虑因素:

您正在创建以空列表作为值的空字典,但是在您直接设置值之后(将替换空列表)。如果需要收集值列表,则应将append值添加到现有列表中,例如:

address_dict[address].append(dist)

以及

sludge_dtc[unique_name].append(address_dict)

相关问题 更多 >