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

如何格式化含大量NaN值的DataFrame,合并非NaN起始行与其余行

合并DataFrame分组中的非NaN行

问题背景

给定如下DataFrame:

import pandas as pd
import numpy as np

df = pd.DataFrame({
    'col1': [1, np.nan, np.nan, np.nan, 5, np.nan, np.nan, np.nan],
    'col2': [np.nan, 2, np.nan, np.nan, np.nan, 6, np.nan, np.nan],
    'col3': [np.nan, np.nan, 3, np.nan, np.nan, np.nan, 7, np.nan],
    'col4': [np.nan, np.nan, np.nan, 4, np.nan, np.nan, np.nan, 8]
})

原始数据展示:

col1  col2  col3  col4
0   1.0   NaN   NaN   NaN
1   NaN   2.0   NaN   NaN
2   NaN   NaN   3.0   NaN
3   NaN   NaN   NaN   4.0
4   5.0   NaN   NaN   NaN
5   NaN   6.0   NaN   NaN
6   NaN   NaN   7.0   NaN
7   NaN   NaN   NaN   8.0

需求:保留所有col1为非NaN的起始行,并将后续对应行的非NaN值合并到这些起始行中,最终得到如下结果:

col1  col2  col3  col4
0     1     2     3     4
4     5     6     7     8

解决方案

方法1:简洁的填充筛选法

利用bfill()向下填充NaN值,再筛选出col1非NaN的行:

# 向下填充NaN,让起始行获取后续行的对应列值
filled_df = df.bfill()
# 筛选出col1非NaN的起始行
new_df = filled_df.loc[df['col1'].notna()]

print(new_df)

解释:

  • bfill()会沿着每一列,用下方最近的非NaN值填充当前行的NaN,这样行0会被行1、2、3的col2、col3、col4值填满,行4会被行5、6、7的对应值填满。
  • 最后通过df['col1'].notna()筛选出原始的起始行,即可得到目标结果。

方法2:分组聚合法

通过生成分组键,将每组行聚合为一行:

# 生成分组键:col1非NaN的位置累加,形成分组标识
groups = df['col1'].notna().cumsum()
# 按分组聚合,取每个列的第一个非NaN值(每组内仅一个有效值)
new_df = df.groupby(groups).first()
# 将索引替换为原DataFrame中的起始行索引
new_df.index = df[df['col1'].notna()].index

print(new_df)

解释:

  • df['col1'].notna().cumsum()会为每一组起始行+后续行生成相同的分组ID(比如行0-3为1,行4-7为2)。
  • groupby(groups).first()会提取每组内每个列的第一个非NaN值(也就是对应列的唯一有效值)。
  • 最后替换索引为原起始行的索引,匹配目标结果的格式。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 22:05:27