You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

双循环遍历DataFrame时索引j未更新问题及坐标合并需求求助

合并近似坐标地点并统计数量的问题排查

我有一个包含未知地点经纬度的DataFrame,其中存在大量坐标近似的地点。希望生成一个“过滤后未知地点”的DataFrame,将近似坐标的地点合并为一个,并统计每个合并后地点包含的原地点数量。

尝试用两层for循环解决,代码如下:

accuracy = 0.2 #km
df_unknown_places_filtered = pd.DataFrame(columns = ['GpsLatitude', 'GpsLongitude', 'Count'])
        
for i, row in df_unknown_places.iterrows():
    min_dist = 999999
    closest = 0
    for j, row2 in df_unknown_places_filtered.iterrows():
        dist = self.distance(row['GpsLatitude'], row['GpsLongitude'], row2['GpsLatitude'], row2['GpsLongitude'])
        if dist < min_dist:
            min_dist = dist
            closest = j
    if min_dist < accuracy:
        current_count = df_unknown_places_filtered.at[closest, 'Count'] 
        df_unknown_places_filtered.at[closest,'Count'] = current_count + 1
    else:
        row_to_insert = {'GpsLatitude':row['GpsLatitude'],
                        'GpsLongitude':row['GpsLongitude'],
                        'Count': 1                                                            
                                            }
        df_unknown_places_filtered = pd.concat([df_unknown_places_filtered, pd.DataFrame.from_records([row_to_insert])], axis = 0)

但内层iterrows()的j值并未正确更新,导致逻辑出错,问题出在这几个地方:

  • 索引混乱:每次用pd.concat新增行时,新生成的单行DataFrame默认索引是0,导致过滤表的索引重复,iterrows()返回的j会重复出现,你误以为是j没更新,实际是索引重复导致定位错误。
  • 初始值不合理:closest初始化为0,当过滤表为空时内层循环不执行,这时候虽不会触发更新逻辑,但当过滤表有重复索引时,at[closest, 'Count']会修改错误的行。
  • 效率极低:两层循环+频繁concat拼接DataFrame,不仅速度慢,还容易引发索引问题。

修复方案

方案1:修复原有逻辑,改用列表维护中间数据

用列表代替DataFrame存储过滤后的结果,避免索引混乱,同时提升效率:

accuracy = 0.2  # km
filtered_data = []  # 用列表存储中间结果,避免索引问题

for _, row in df_unknown_places.iterrows():
    min_dist = 999999
    closest_idx = -1  # 初始化为-1,表示未找到匹配项
    # 遍历列表,用enumerate拿到正确的索引
    for idx, item in enumerate(filtered_data):
        dist = self.distance(row['GpsLatitude'], row['GpsLongitude'], 
                             item['GpsLatitude'], item['GpsLongitude'])
        if dist < min_dist:
            min_dist = dist
            closest_idx = idx
    # 找到近似地点则计数+1
    if min_dist < accuracy and closest_idx != -1:
        filtered_data[closest_idx]['Count'] += 1
    # 否则新增地点
    else:
        filtered_data.append({
            'GpsLatitude': row['GpsLatitude'],
            'GpsLongitude': row['GpsLongitude'],
            'Count': 1
        })

# 最后将列表转为DataFrame
df_unknown_places_filtered = pd.DataFrame(filtered_data)

方案2:用DBSCAN空间聚类(大数据量首选)

如果数据量较大,两层循环的O(n²)效率极低,推荐用专门的空间聚类算法DBSCAN,结果更准确且效率更高:

from sklearn.cluster import DBSCAN
import numpy as np

# 将经纬度转为弧度(haversine度量要求输入弧度)
coords = np.radians(df_unknown_places[['GpsLatitude', 'GpsLongitude']].values)
# eps=0.2/6371:将0.2公里转为弧度(6371是地球平均半径,单位公里)
# min_samples=1:允许单个点作为一个聚类
db = DBSCAN(eps=0.2/6371, min_samples=1, metric='haversine').fit(coords)

# 给原数据添加聚类标签
df_unknown_places['cluster'] = db.labels_

# 按聚类标签分组,统计数量并取每组平均坐标(也可以取第一个点的坐标)
df_unknown_places_filtered = df_unknown_places.groupby('cluster').agg(
    GpsLatitude=('GpsLatitude', 'mean'),
    GpsLongitude=('GpsLongitude', 'mean'),
    Count=('cluster', 'count')
).reset_index(drop=True)

内容的提问来源于stack exchange,提问作者Sjig

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 08:20:36