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

Pandas执行unstack操作去除NaN值合并为单行的方法

问题描述

给定如下测试数据:

import pandas as pd
import io 

data = pd.read_csv(
    io.StringIO(
        ",x,t,t_cls,level\n0,70.0,4.472156319636573,med,level_0\n1,30.0,6.4012513032334235,med,level_1\n"
    )
).drop("Unnamed: 0", axis=1)

执行如下unstack操作:

data.set_index("level", append=True).unstack(level=1)

返回结果中分布大量NaN值,数据分散在两行:

('x', 'level_0')('x', 'level_1')('t', 'level_0')('t', 'level_1')('t_cls', 'level_0')('t_cls', 'level_1')
070NaN4.47216NaNmedNaN
1NaN30NaN6.40125NaNmed

需求是将unstack后的结果合并为无NaN值的单行,保留多级列名结构以便后续自行扁平化,目标效果参考:
unstack后无NaN单行效果参考

现有待优化实现

目前可实现需求的写法如下,但逻辑冗余、性能较差,不够优雅:

import numpy as np
(
    data.set_index("level", append=True)
    .unstack(level=1)
    .apply(lambda x: sorted(x.astype(str)), axis=0)
    .replace({"nan": np.nan})
    .dropna(how="all")
)

该代码运行后可得到符合预期的结果:

('x', 'level_0')('x', 'level_1')('t', 'level_0')('t', 'level_1')('t_cls', 'level_0')('t_cls', 'level_1')
070304.472166.40125medmed
最优实现方案

该场景下unstack输出的每一列仅存在1个有效值,其余位置全为NaN,不需要做字符串转换、排序这类多余操作,直接向下填充后取首行即可,代码简洁且运行效率更高:

(
    data.set_index("level", append=True)
    .unstack(level=1)
    .bfill()  # 用下方行的非空值填充当前行的NaN
    .iloc[[0]] # 取填充完成的第一行,即为所有有效值组成的单行结果
)

如果不需要保留原默认整数行索引,也可以直接用pivot配合列级非空筛选实现:

data.pivot(columns="level", values=["x", "t", "t_cls"]).apply(pd.Series.dropna)

两种写法输出的多级列名结构和预期完全一致,没有多余NaN值,可直接进行后续列名扁平化处理。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 04:45:39