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

如何用Pandas将观测数不足阈值的相邻地理区域合并聚合?

问题描述

需要按编号标识的小型地理区域分组统计观测数据,相邻区域编号相近(如0001与0002、0003相邻)。对于观测数极少的区域,要和相邻区域合并,直到合并后的区域观测数达到指定阈值(如5)。同时需要对数据框中其他列(如收入中位数)进行聚合处理。

示例数据

import pandas as pd

d = {'region': ['0001', '0001','0002','0002','0002','0002','0003','0003','0003','0003','0003','0003','0003','0003'], 
     'observation': ['A1', 'B45', 'B83578','L87846','I4536','J8659','H8756','G0853','P89058','A98','B89056980','U9690','Q9875','N896']}
df = pd.DataFrame(data=d)

# 现有分组统计代码
df_grouped = df.groupby('region')['observation'].count()
print(df_grouped)

现有输出

region
0001    2
0002    4
0003    8
Name: observation, dtype: int64

期望输出

region
[0001,0002]    6
0003           8
Name: observation, dtype: int64

解决方案

以下是实现需求的代码,包含区域合并逻辑和多列聚合处理:

import pandas as pd

# 1. 准备包含额外列的示例数据
d = {
    'region': ['0001', '0001','0002','0002','0002','0002','0003','0003','0003','0003','0003','0003','0003','0003'], 
    'observation': ['A1', 'B45', 'B83578','L87846','I4536','J8659','H8756','G0853','P89058','A98','B89056980','U9690','Q9875','N896'],
    'income': [3000, 3500, 4000, 4200, 3800, 4500, 5000, 5200, 4800, 5500, 4900, 5300, 5100, 4700]
}
df = pd.DataFrame(data=d)

# 2. 计算各区域初始统计量,并按区域编号排序(确保相邻区域顺序正确)
region_stats = df.groupby('region').agg(
    obs_count=('observation', 'count')
).reset_index()
# 将区域编号转为整数,避免字符串排序的异常(比如'0010'和'002'的排序问题)
region_stats['region_num'] = region_stats['region'].astype(int)
region_stats = region_stats.sort_values('region_num').reset_index(drop=True)

# 3. 合并相邻区域直到满足阈值
threshold = 5
merged_groups = []
current_group = {'regions': [], 'total_obs': 0}

for idx, row in region_stats.iterrows():
    current_group['regions'].append(row['region'])
    current_group['total_obs'] += row['obs_count']
    
    # 当当前组观测数达标,或是最后一个区域时,完成该组合并
    if current_group['total_obs'] >= threshold or idx == len(region_stats) - 1:
        # 生成组名:单个区域直接用编号,多个区域用列表格式
        group_name = current_group['regions'][0] if len(current_group['regions']) == 1 else str(current_group['regions'])
        # 提取当前组的所有原始数据,计算多列聚合值(这里以观测数、收入中位数为例)
        group_data = df[df['region'].isin(current_group['regions'])]
        merged_groups.append({
            'region': group_name,
            'obs_count': group_data['observation'].count(),
            'median_income': group_data['income'].median()
        })
        # 重置当前组,准备下一轮合并
        current_group = {'regions': [], 'total_obs': 0}

# 4. 转换为DataFrame并输出
result = pd.DataFrame(merged_groups).set_index('region')
print(result)

代码说明

  • 排序处理:将区域编号转为整数排序,避免字符串排序导致的相邻区域顺序错误(比如'0010'会排在'002'前面的问题)。
  • 合并逻辑:从第一个区域开始逐步合并相邻区域,直到观测数达到阈值,确保只合并相邻区域。
  • 多列聚合:合并后通过提取原始数据重新计算聚合值(如中位数),比直接加权更准确,因为中位数这类统计量不能通过简单加权得到正确结果。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 06:05:30