Pandas数据框列异常及Seaborn箱线图仅绘制单列问题排查
问题描述
运行代码时出现两个异常:
- Seaborn绘制的箱线图仅输出2.1列的内容,未展示所有列的箱线图
- 生成的DataFrame对象df、dfs中,2.1列前存在一个异常的单空格命名列,该列就是实际被绘图的列
- 相同代码在其他数据集上可正常运行,常规排查无法定位根因
使用的数据集
1.1;1.2;1.3;2.1;2.2;2.3;2.4;3.1;3.2;3.3;3.4;4.1;4.2;4.3;5.1;5.2 1;1;-;1;1;1;-;1;1;2;-;-;1;-;-;- 6;6;5;6;6;6;6;4;3;2;3;6;0;5;5;2 2;1;1;1;1;2;1;1;1;1;1;1;1;1;1;1 4;1;2;4;1;2;-;2;1;-;1;-;-;1;-;- 1;1;-;1;-;1;-;-;1;-;-;-;-;-;-;- 0;0;0;1;2;0;0;0;0;1;1;0;0;0;0;0 1;1;1;1;0;1;1;1;1;2;1;1;-;-;-;- 0;1;1;1;-;0;-;-;0;-;-;-;-;-;-;- 2;0;-;0;1;-;-;0;1;-;1;-;-;-;-;- -;1;1;1;-;1;-;-;1;-;-;-;-;1;-;- 2;1;1;1;1;1;1;1;1;-;1;1;-;1;-;- 0;2;-;4;1;1;-;1;0;-;0;-;-;0;-;- 0;-;-;1;1;2;1;-;-;-;-;-;-;-;1;- 1;1;2;1;1;1;1;1;1;2;1;1;1;1;1;1 1;1;1;1;1;1;-;1;1;1;1;1;0;1;-;- 2;1;1;1;1;1;-;1;1;-;1;1;-;-;-;- 3;3;1;0;2;1;0;1;1;0;0;1;0;1;1;0 3;4;-;2;1;-;-;1;1;-;1;1;-;-;-;- 4;1;1;1;3;2;3;1;1;2;1;1;2;0;4;4
原始实现代码
import csv import glob import re import pandas as pd import matplotlib.pyplot as plt import seaborn as sns files = glob.glob(f"session*C.csv") # load dataset with pandas df = pd.read_csv(files[0], sep = ';') # replace "-" data with 0 dfs = df.replace(r'^-$', 0, regex=True) print(dfs) # Seaborn boxplot sns.set_style('darkgrid') fig, ax = plt.subplots(figsize=(9, 10)) sns.boxplot(data=dfs, orient="h", ax=ax) plt.show()
问题根因
两个异常的核心诱因是当前CSV文件开头携带了UTF-8 BOM标记(字节顺序标记,对应字符为\ufeff):
- pandas默认以
utf-8编码读取文件时,不会自动过滤开头的BOM标记,会把这个不可见字符拼接到第一列的列名前,导致第一列列名显示为异常的空白/单空格,后续所有列的解析出现错位 - 列错位+
-替换后没有做类型转换,大部分列被识别为object字符串类型,seaborn的boxplot默认只会对数值类型的列绘制箱线,最终仅识别到一列符合要求的数值列,也就是仅输出单列内容的现象。
修复方案
只需要修改两处读取和类型处理的逻辑即可:
- 读取CSV时指定编码为
utf-8-sig,该编码会自动识别并过滤文件开头的BOM标记,不会生成异常空列 - 替换完
-占位符后,将所有列强制转换为数值类型,保证seaborn可以识别全部列的数值进行绘图
注:原始代码中导入的csv、re库未被实际调用,可直接删除减少冗余。
修复后的可运行代码:
import glob import pandas as pd import matplotlib.pyplot as plt import seaborn as sns files = glob.glob("session*C.csv") # 读取时指定编码自动处理BOM头 df = pd.read_csv(files[0], sep=';', encoding='utf-8-sig') # 替换"-"占位符为0 dfs = df.replace(r'^-$', 0, regex=True) # 强制所有列转为数值类型 dfs = dfs.apply(pd.to_numeric) # 验证列名,此时不会存在异常空列 print("列名列表:", dfs.columns.tolist()) print(dfs) # 绘制箱线图 sns.set_style('darkgrid') fig, ax = plt.subplots(figsize=(9, 10)) sns.boxplot(data=dfs, orient="h", ax=ax) plt.tight_layout() plt.show()
运行后即可正常展示所有16列的箱线图,DataFrame中也不会再出现异常的空格命名列。
内容的提问来源于stack exchange,提问作者macxpat
相关产品推荐
相关产品推荐

