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

如何为Pandas DataFrame计算行占比并生成降序带列名描述列

问题描述

原始DataFrame代码如下:

import pandas as pd

data1 = [['A', 10, 30, 15, 45], 
        ['B', 22, 35, 25, 18], 
        ['C', 40, 27, 28, 5]]
       
df1 = pd.DataFrame(data1, columns= ['Units', 'Normal', 'Bad', 'Good', 'Neutral'])

需求:
为df1新增一列Proportion by largest to smallest,实现以下效果:

  • 计算每行中Normal、Bad、Good、Neutral列的数值占该行总和的比例
  • 将这些比例按从高到低排序
  • 保留对应列名,格式为列名 = 比例值%,多个结果用逗号分隔

目标效果示例:

data2 = [['A', 10, 30, 15, 45, 'Neutral = 0.45%, Bad = 0.3%, Good = 0.15%, Normal = 0.10%'], 
            ['B', 22, 35, 25, 18, 'Bad = 0.35%, Good = 0.25%, Normal = 0.22%, Neutral = 0.18%'], 
            ['C', 40, 27, 28, 5, 'Normal = 0.4%, Good = 0.28%, Bad = 0.27%, Neutral = 0.05%']]
           
df2 = pd.DataFrame(data2, columns= ['Units', 'Normal', 'Bad', 'Good', 'Neutral', 'Proportion by largest to smallest'])
解决方案

通过自定义函数结合apply方法实现自动化处理,适配大规模数据集:

import pandas as pd

# 定义单行处理函数
def format_proportions(row):
    # 提取数值列,排除非数值的Units列
    numeric_vals = row.drop('Units')
    # 计算该行数值总和
    total = numeric_vals.sum()
    # 计算每个数值占总和的比例
    proportions = numeric_vals / total
    # 按比例降序排序
    sorted_props = proportions.sort_values(ascending=False)
    # 格式化每个条目,自动去除小数末尾多余的0
    formatted_items = []
    for col, val in sorted_props.items():
        formatted_val = "{:.2f}".format(val).rstrip('0').rstrip('.')
        formatted_items.append(f"{col} = {formatted_val}%")
    # 拼接成最终字符串
    return ', '.join(formatted_items)

# 应用函数到每行,生成目标列
df1['Proportion by largest to smallest'] = df1.apply(format_proportions, axis=1)

# 查看结果
print(df1)

代码说明

  • format_proportions函数负责单行数据处理:
    1. 筛选出该行的数值列,排除Units列
    2. 计算该行所有数值的总和
    3. 计算每个数值占总和的比例
    4. 按比例从高到低排序
    5. 将列名与对应比例格式化为指定字符串,最后拼接成完整文本
  • apply(axis=1)将函数批量应用到每一行,自动生成目标列,无需手动处理每行数据

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 13:41:13