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

如何按条件展开DataFrame并添加指定值的Val与Category列?

问题:DataFrame按指定列非零值展开并赋值

原始数据

import pandas as pd
import numpy as np

df = pd.DataFrame({
    'Name': ['x', 'y', 'z'],
    'A': [1.1, 0, 0.5],
    'B': [0, 0.1, 0.1],
    'C': [0.2, 0, 0.3],
    'Val': [np.nan, np.nan, np.nan],
    'Category': [np.nan, np.nan, np.nan]
})

期望结果

# 输出格式:
#   Name    A    B    C  Val Category
# 0    x  1.1  0.0  0.2  1.1    first
# 1    x  1.1  0.0  0.2  0.2    third
# 2    y  0.0  0.1  0.0  0.1   second
# 3    z  0.5  0.1  0.3  0.5    first
# 4    z  0.5  0.1  0.3  0.1   second
# 5    z  0.5  0.1  0.3  0.3    third

错误尝试分析

你的代码存在以下问题:

  • 循环索引逻辑错误:range(1, len(df_repeat)-3,3)起始值为1,会跳过第一组重复行,终止条件也不合理,导致大量行未被处理
  • 链式索引赋值无效:df_repeat.iloc[i][['Target','Category']]属于链式索引,pandas无法确保修改会作用到原DataFrame,大概率出现修改无效的情况
  • 函数返回值与赋值逻辑不匹配:targeta返回整行数据和分类值,但你试图将其赋值给不存在的Target列(应该是Val列),逻辑完全错误
  • 未过滤0值:代码没有处理0值的情况,会生成不必要的行

可行解决方案

方法1:使用melt+过滤+合并(推荐,高效简洁)

利用pandas的melt函数将A/B/C列转成键值对,过滤0值后与原表合并:

# 定义列名与Category的映射关系
col_cat_map = {'A': 'first', 'B': 'second', 'C': 'third'}

# 将A/B/C列转成键值对格式
melted_df = df.melt(
    id_vars=['Name'],
    value_vars=['A', 'B', 'C'],
    var_name='SourceCol',
    value_name='Val'
)

# 过滤0值并添加Category列
filtered_df = melted_df[melted_df['Val'] != 0].assign(
    Category=melted_df['SourceCol'].map(col_cat_map)
)

# 合并原表的A/B/C列,调整最终列顺序
result = pd.merge(filtered_df, df[['Name', 'A', 'B', 'C']], on='Name')
result = result[['Name', 'A', 'B', 'C', 'Val', 'Category']].reset_index(drop=True)

print(result)

方法2:使用apply生成多行(逻辑直观)

对每一行生成符合条件的多行数据,再拼接结果:

def expand_single_row(row):
    output_rows = []
    # 遍历目标列和对应的分类
    for col, category in zip(['A', 'B', 'C'], ['first', 'second', 'third']):
        val = row[col]
        if val != 0:
            new_row = row.copy()
            new_row['Val'] = val
            new_row['Category'] = category
            output_rows.append(new_row)
    return pd.DataFrame(output_rows)

# 对每行应用函数并拼接结果
result = pd.concat(
    [expand_single_row(row) for _, row in df.iterrows()],
    ignore_index=True
)

print(result)

两种方法均可得到预期结果,方法1更适合大数据量场景,执行效率更高;方法2逻辑清晰,易于理解和调试。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 12:07:26