如何将Pandas DataFrame格式化为指定二维表格并按错误数排序列
问题:Pandas DataFrame 二维格式化与列排序需求
原始数据
+----+------+-----------+---------+ | | Jobs | Measure | Value | |----+------+-----------+---------| | 0 | Job1 | Temp | 43 | | 1 | Job1 | Humidity | 65 | | 2 | Job2 | Temp | 48 | | 3 | Job2 | TempS | 97.4 | | 4 | Job2 | Humidity | nan | | 5 | Job3 | Humidity | 55 | | 6 | Job1 | Temp | 41 | | 7 | Job1 | Duration | 23 | | 8 | Job3 | Temp | 39 | | 9 | Job1 | Temp | nan | | 10 | Job1 | Humidity | 55 | | 11 | Job2 | Temp | 48 | | 12 | Job2 | TempS | 97.4 | | 13 | Job2 | Humidity | nan | | 14 | Job3 | Humidity | 55 | | 15 | Job1 | Temp | nan | | 16 | Job1 | Duration | 25 | | 17 | Job3 | Temp | nan | | 18 | Job2 | Humidity | 61 | +----+------+-----------+---------+
当前代码
from tabulate import tabulate import pandas as pd df = pd.read_csv('logs.csv') print(tabulate(df, headers='keys', tablefmt='psql')) grouped = df.groupby(['Jobs','Measure'], dropna=True) average_temp = grouped.mean() errors = df.groupby(['Jobs','Measure']).agg(lambda x: x.isna().sum()) frames = [average_temp, errors] df_merged = pd.concat(frames, axis=1).set_axis(['Avg', 'Error'], axis='columns') print(df_merged)
当前输出
Table-1 Avg Error Jobs Measure Job1 Duration 24.0 0 Humidity 60.0 0 Temp 42.0 2 Job3 Humidity 55.0 0 Temp 39.0 1 Job2 Humidity 61.0 2 TempS 97.4 0 Temp 48.0 0
初始格式化需求
需要将上述表格转换为二维宽表格式,每个Measure对应的Avg和Error作为独立列,示例如下:
Table-2 Jobs Avg.Temp Err.Temp Avg.Humidity Err.Humidity Avg.Duration ... Job1 42.0 2 60.0 0 24.0 Job2 48.0 0 61.0 0 - Job3 39.0 1 55.0 1 -
注:不同Jobs可能包含不同的Measure字段(如Job2包含TempS),缺失值保留为空或nan。
更新后的状态
参考方案后已生成宽表,但需要按总错误数降序排列列:总错误数最高的Measure对应的Avg和Error列优先展示,其余按总错误数依次排列。示例如下:
+--------------+------------+--------------+----------------+------------------+... | Jobs | Avg.Temp | Error.Temp | Avg.Humidity | Error.Humidity | |--------------+------------+--------------|----------------+------------------+... | Job1 | 42 | 2 | 60 | 0 | | Job3 | 39 | 1 | 55 | 0 | | Job2 | 48 | 0 | 61 | 2 | +--------------+------------+--------------+----------------+------------------+...
(示例中Temp总错误数为3,排在首位;Humidity总错误数次之,依次类推)
解决方案
1. 生成规范的宽表
替换原有合并逻辑,直接通过groupby.agg生成包含Avg和Error的聚合表,再转为宽表:
from tabulate import tabulate import pandas as pd df = pd.read_csv('logs.csv') # 一步完成聚合:计算每个Jobs-Measure组合的平均值和错误数 agg_df = df.groupby(['Jobs', 'Measure']).agg( Avg=('Value', 'mean'), Error=('Value', lambda x: x.isna().sum()) ) # 将Measure从行索引转为列,生成宽表 wide_df = agg_df.unstack() # 合并多层列名为单层(如"Avg.Temp"、"Error.Temp") wide_df.columns = [f"{col[0]}.{col[1]}" for col in wide_df.columns] # 将Jobs从索引转为普通列 wide_df = wide_df.reset_index()
2. 计算Measure的总错误数并排序
统计每个Measure的全局总错误数,按降序排序得到优先级:
# 计算每个Measure的总错误数 total_error_by_measure = df.groupby('Measure')['Value'].apply(lambda x: x.isna().sum()) # 按总错误数降序排序,得到Measure的优先级列表 sorted_measures = total_error_by_measure.sort_values(ascending=False).index.tolist()
3. 按优先级重新排列列
根据排序后的Measure列表,重新组织列顺序,确保每个Measure的Avg和Error列相邻:
# 构建新的列顺序:先保留Jobs列,再依次添加每个Measure的Avg和Error列 new_column_order = ['Jobs'] for measure in sorted_measures: new_column_order.append(f"Avg.{measure}") new_column_order.append(f"Error.{measure}") # 重新排列宽表的列 final_df = wide_df[new_column_order]
4. 输出结果
用tabulate格式化输出最终表格:
print(tabulate(final_df, headers='keys', tablefmt='psql', floatfmt=".1f"))
最终输出将符合要求:列按Measure总错误数降序排列,每个Measure的平均值和错误数列相邻展示。
内容的提问来源于stack exchange,提问作者FotisK
相关产品推荐
相关产品推荐

