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

将groupby操作生成的Series赋值给DataFrame列时出现NaN的问题求助

解决groupby.apply返回列表赋值DataFrame列全为NaN的问题

问题场景

数据定义:

import pandas as pd

df_SOT = pd.DataFrame({
    'Lane': {26055: 'L2', 26056: 'L2', 26057: 'L2', 26058: 'L2', 26059: 'L2', 
             25972: 'L1', 25973: 'L1', 25974: 'L1', 25975: 'L1', 25976: 'L1'},
    'Carrier SCAC': {26055: 'JNJR', 26056: 'WOSQ', 26057: 'BGME', 26058: 'ITSB', 26059: 'UCSB',
                    25972: 'BGME', 25973: 'SCNN', 25974: 'XPOL', 25975: 'SJRG', 25976: 'MTRK'},
    'Annual Volume': {26055: 5604.0, 26056: 5604.0, 26057: 5604.0, 26058: 5604.0, 26059: 5604.0,
                     25972: 4917.0, 25973: 4917.0, 25974: 4917.0, 25975: 4917.0, 25976: 4917.0},
    'Annual Capacity': {26055: 260.0, 26056: 1300.0, 26057: 2704.0, 26058: 2080.0, 26059: 4368.0,
                       25972: 5408.0, 25973: 3380.0, 25974: 4940.0, 25975: 156.0, 25976: 4940.0}
})

定义分配函数:

def allocation(df_alloc):
    Annual_Volume = df_alloc['Annual Volume']
    Annual_Capacity = df_alloc['Annual Capacity']
    Allocation = []
    Cum_Capacity = 0
    for idx in df_alloc.index:
        Allocate = min(0.5*Annual_Volume[idx], Annual_Capacity[idx], Annual_Volume[idx]-Cum_Capacity)
        Cum_Capacity += Allocate
        Allocation.append(Allocate)
    return Allocation

执行groupby操作后得到结果:

df_SOT.groupby('Lane').apply(allocation)

输出:

Lane
L1         [2458.5, 2458.5, 0.0, 0.0, 0.0]
L2    [260.0, 1300.0, 2704.0, 1340.0, 0.0]
dtype: object

尝试赋值到原DataFrame时出现问题:

df_SOT['Allocation'] = df_SOT.groupby('Lane').apply(allocation)

此时Allocation列全为NaN。

问题原因

groupby('Lane').apply(allocation)返回的Series索引是分组键['L1','L2'],但原DataFrame的索引是26055、26056等行号,两者索引无法对齐,导致赋值时所有位置都匹配不到对应值,最终填充为NaN。

解决方案

方案1:修改函数返回带原组索引的Series

调整allocation函数,让它返回带有原分组行索引的Series,这样apply后会自动对齐原DataFrame的索引:

def allocation(df_alloc):
    Annual_Volume = df_alloc['Annual Volume']
    Annual_Capacity = df_alloc['Annual Capacity']
    Allocation = []
    Cum_Capacity = 0
    for idx in df_alloc.index:
        Allocate = min(0.5*Annual_Volume[idx], Annual_Capacity[idx], Annual_Volume[idx]-Cum_Capacity)
        Cum_Capacity += Allocate
        Allocation.append(Allocate)
    # 返回带原分组行索引的Series
    return pd.Series(Allocation, index=df_alloc.index)

重新执行赋值:

df_SOT['Allocation'] = df_SOT.groupby('Lane').apply(allocation)

此时Allocation列会正确填充对应数值。

方案2:向量化实现(更优)

避免循环,用Pandas的向量化操作提升效率,尤其适合大数据量场景:

def allocation_vectorized(df_alloc):
    half_volume = 0.5 * df_alloc['Annual Volume'].iloc[0]
    # 计算每个位置的剩余可分配量:总半量 - 前面的累积分配
    cum_capacity = df_alloc['Annual Capacity'].cumsum().shift(1, fill_value=0)
    remaining = half_volume - cum_capacity
    # 取三个值的最小值:年度容量、剩余可分配量、半量
    allocation = pd.DataFrame({
        'capacity': df_alloc['Annual Capacity'],
        'remaining': remaining
    }).min(axis=1)
    # 确保累积分配不超过总半量
    cum_allocation = allocation.cumsum()
    excess = cum_allocation - half_volume
    allocation = allocation.where(excess <= 0, allocation - excess)
    return allocation

df_SOT['Allocation'] = df_SOT.groupby('Lane').apply(allocation_vectorized)

这个实现逻辑和原函数一致,但去掉了循环,利用Pandas的内置方法提升计算效率。

内容的提问来源于stack exchange,提问作者Rajib Lochan Sarkar

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 04:35:49