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

如何在Pandas中对groupby对象的多列应用函数生成新列?

问题描述

现有如下结构的DataFrame:

block  lat  lon
0      0  112   50
1      0  112   50
2      0  112   50
3      1  105   20
4      1  105   20
5      2  130   30

需要按block列分组后,对每组的lat和lon调用get_location_id(lat, lon)函数(该函数接收经纬度参数,返回单个字符串ID),生成location_id列,要求同一分组的所有行对应相同ID,最终结果如下:

block  lat  lon location_id
0      0  112   50  1
1      0  112   50  1
2      0  112   50  1
3      1  105   20  23
4      1  105   20  23
5      2  130   30  15

尝试了以下代码但无法运行,且lambda函数无法使用axis=1参数:

df['location_id'] = df.groupby('block').apply(lambda x: get_location_id(x['lat'], x['lon']))

由于数据集较大,希望避免直接对未分组的DataFrame调用该函数,以提升效率。

解决方案

方法1:聚合生成映射表后合并(大数据集首选)

因为同一block内的lat和lon完全一致,我们可以先为每个block生成对应的location_id,得到映射关系后再合并回原DataFrame。这种方式仅需对每个分组调用一次函数,计算效率最高:

# 生成block到location_id的映射
id_mapping = df.groupby('block').apply(
    lambda group: get_location_id(group['lat'].iloc[0], group['lon'].iloc[0])
).reset_index(name='location_id')

# 合并映射表到原DataFrame
df = df.merge(id_mapping, on='block', how='left')

方法2:使用transform直接生成列

如果希望直接在原DataFrame上添加列,可使用transform方法,它会将分组计算的结果自动广播到该分组的所有行,保持索引对齐:

df['location_id'] = df.groupby('block').transform(
    lambda group: get_location_id(group['lat'].iloc[0], group['lon'].iloc[0])
)

原代码问题说明

原代码中groupby.apply()返回的是一个以block为索引的Series(每个block对应一个ID),直接赋值给df['location_id']会因为索引不匹配导致报错。而上述两种方法都能确保结果与原DataFrame的行一一对应,同时避免重复计算。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 21:35:35