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

如何基于列标题扩展Pandas DataFrame的行数?

需求说明

给定如下分组汇总后的DataFrame:

name  0  1  2
0    A  4  2  1
1    B  2  3  4
2    C  1  3  2

需要将每行数据扩展:除name列外,每行元素根据列标题对应的数值确定保留该列值的行数,超出部分填充NaN,最终得到如下格式的结果:

name 0    1    2
------------------
A    0    1    2
A    0    1    nan
A    0    nan  nan
A    0    nan  nan
B    0    1    2
B    0    1    2
B    nan  1    2
B    nan  nan  2
C    0    1    2
C    nan  1    2
C    nan  1    nan

可复现代码:

import pandas as pd
df = pd.DataFrame({'name': ['A','B','C'], 0:[4,2,1], 1:[2,3,3], 2:[1,4,2]})

之前尝试用df.iterrows()向空DataFrame添加数据,但代码混乱且存在bug,需要更高效简洁的Pandas解决方案。


解决方案

可以通过构造行掩码矩阵结合repeat和条件赋值实现,避免低效的逐行循环操作:

步骤1:分离列并确定扩展行数

先拆分name列与数值列,每行的扩展行数由该行数值的最大值决定:

name_col = df['name']
num_cols = df.drop('name', axis=1)
# 每行需要扩展的行数
row_expand_counts = num_cols.max(axis=1)

步骤2:生成每行的保留掩码

对每行数值列,生成对应扩展行数的布尔矩阵:第k行扩展后的记录中,若当前行索引小于该列的数值,则保留列值,否则标记为False:

mask_list = []
for idx, row in num_cols.iterrows():
    expand_count = row_expand_counts[idx]
    # 生成expand_count行的掩码
    row_mask = pd.DataFrame([
        [expand_idx < val for expand_idx, val in enumerate(row)]
        for _ in range(expand_count)
    ])
    mask_list.append(row_mask)

# 合并所有行的掩码并重置索引
full_mask = pd.concat(mask_list, ignore_index=True)

步骤3:扩展name列并填充结果

将name列按扩展行数重复,再通过掩码筛选填充数值列(保留位置填列名,否则填pd.NA):

# 扩展name列
expanded_names = name_col.repeat(row_expand_counts).reset_index(drop=True)

# 构造结果DataFrame
result = pd.DataFrame({
    col: full_mask[col].apply(lambda x: col if x else pd.NA)
    for col in num_cols.columns
})
# 插入name列到首位
result.insert(0, 'name', expanded_names)

完整可运行代码

import pandas as pd

# 初始化原始数据
df = pd.DataFrame({'name': ['A','B','C'], 0:[4,2,1], 1:[2,3,3], 2:[1,4,2]})

# 分离列与确定扩展行数
name_col = df['name']
num_cols = df.drop('name', axis=1)
row_expand_counts = num_cols.max(axis=1)

# 生成掩码矩阵
mask_list = []
for idx, row in num_cols.iterrows():
    expand_count = row_expand_counts[idx]
    row_mask = pd.DataFrame([
        [expand_idx < val for expand_idx, val in enumerate(row)]
        for _ in range(expand_count)
    ])
    mask_list.append(row_mask)
full_mask = pd.concat(mask_list, ignore_index=True)

# 构造最终结果
expanded_names = name_col.repeat(row_expand_counts).reset_index(drop=True)
result = pd.DataFrame({
    col: full_mask[col].apply(lambda x: col if x else pd.NA)
    for col in num_cols.columns
})
result.insert(0, 'name', expanded_names)

print(result)

运行输出

name     0     1     2
0     A     0     1     2
1     A     0     1  <NA>
2     A     0  <NA>  <NA>
3     A     0  <NA>  <NA>
4     B     0     1     2
5     B     0     1     2
6     B  <NA>     1     2
7     B  <NA>  <NA>     2
8     C     0     1     2
9     C  <NA>     1     2
10    C  <NA>     1  <NA>

(注:Pandas中pd.NA与nan功能等价,显示差异不影响使用)


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 11:57:42