pandas按Glycopeptide和group分组绘制箱线图报错解决
错误原因
pandas.DataFrame.boxplot的column参数要求传入用于统计分布的数值列名,你传入的是字符串类型的分类列Glycopeptide。箱线图计算分位数的过程需要执行数值除法运算,对字符串类型数据做该操作就会触发你看到的true_divide类型错误。- 绘图参数映射逻辑完全颠倒:你的需求是X轴按糖肽类型分组、箱体颜色按分组区分,但你把分类列传给了数值列参数
column,把颜色分组维度传给了分面参数by,完全不符合参数设计逻辑。 melt操作没有明确指定要转换的数值列范围,容易混入无关列引发类型异常。
正确实现方案
直接用以下代码即可实现需求,优先用seaborn绘制,自定义分组颜色更简便:
import pandas as pd import seaborn as sns import matplotlib.pyplot as plt # 此处替换为你自己的DataFrame读取/构造逻辑 df = pd.DataFrame({'ProteinName': {622: '>sp|O75882|ATRN_HUMAN Attractin OS=Homo sapiens OX=9606 GN=ATRN PE=1 SV=2', 1146: '>sp|O75882|ATRN_HUMAN Attractin OS=Homo sapiens OX=9606 GN=ATRN PE=1 SV=2', 1232: '>sp|O75882|ATRN_HUMAN Attractin OS=Homo sapiens OX=9606 GN=ATRN PE=1 SV=2', 1270: '>sp|O75882|ATRN_HUMAN Attractin OS=Homo sapiens OX=9606 GN=ATRN PE=1 SV=2'}, 'Position': {622: 731.0, 1146: 731.0, 1232: 731.0, 1270: 731.0}, 'Glycopeptide': {622: 'R.NSEGQISIFR.Y.HexNAc(4)Hex(5)NeuAc(1)', 1146: 'R.NSEGQISIFR.Y.HexNAc(4)Hex(5)Fuc(1)NeuAc(1)', 1232: 'R.NSEGQISIFR.Y.HexNAc(4)Hex(5)NeuAc(1)', 1270: 'R.NSEGQISIFR.Y.HexNAc(4)Hex(5)Fuc(1)NeuAc(2)'}, 'icPercentageGly_PCU-C1': {622: 0.0, 1146: 0.0, 1232: 0.0, 1270: 0.0}, 'icPercentageGly_PCU-C2': {622: 32.93651891157215, 1146: 0.0, 1232: 0.0, 1270: 0.0}, 'icPercentageGly_PCU-C3': {622: 0.0, 1146: 0.0, 1232: 0.0, 1270: 0.0}, 'icPercentageGly_PCU-C4': {622: 34.30630765208948, 1146: 0.0, 1232: 0.0, 1270: 0.0}, 'icPercentageGly_PCU-C5': {622: 96.26885645836441, 1146: 0.0, 1232: 0.0, 1270: 0.0}, 'group': {622: 'CONTROL', 1146: 'TREATMENT', 1232: 'TREATMENT', 1270: 'TREATMENT'}, 'icPercentageGly_PCU-T1': {622: 0.0, 1146: 50.31435590892384, 1232: 0.0, 1270: 0.0}, 'icPercentageGly_PCU-T2': {622: 0.0, 1146: 0.0, 1232: 56.079171598895186, 1270: 43.920828401104814}, 'icPercentageGly_PCU-T3': {622: 0.0, 1146: 31.116328385337777, 1232: 68.88367161466222, 1270: 0.0}, 'icPercentageGly_PCU-T4': {622: 0.0, 1146: 20.64630643302238, 1232: 35.10173373882788, 1270: 27.416074077070935}, 'icPercentageGly_PCU-T5': {622: 0.0, 1146: 24.95894470029631, 1232: 44.43968440969619, 1270: 30.601370890007495}}) # 筛选所有以icPercentage开头的数值列 ic_cols = [col for col in df.columns if col.startswith('icPercentage')] # 重塑为长格式,明确指定保留的分类列和转换的数值列 plotdf = pd.melt( df, id_vars=['Glycopeptide', 'group'], value_vars=ic_cols, value_name='gly_percentage' ) # 强制转换数值列类型,彻底避免类型错误 plotdf['gly_percentage'] = plotdf['gly_percentage'].astype(float) # 绘制箱线图 plt.figure(figsize=(11, 6)) sns.boxplot( data=plotdf, x='Glycopeptide', y='gly_percentage', hue='group', # 按group列区分箱体颜色 palette={'CONTROL':'#2c7fb8', 'TREATMENT':'#d95f02'} # 可自行修改配色 ) # 旋转X轴标签避免重叠 plt.xticks(rotation=30, ha='right') plt.ylabel('Glycosylation Percentage (%)') plt.xlabel('Glycopeptide Type') plt.tight_layout() plt.show()
代码说明
- 先通过列名前缀精准筛选需要的数值列,避免无关列参与数据重塑
- melt时明确指定维度列和值列,从根源避免列类型混淆
- 强制将数值列转为float类型,彻底杜绝类型运算错误
- 绘图维度完全匹配需求:X轴对应唯一糖肽值、Y轴为所有样本的糖基化百分比、箱体颜色按对照组/处理组区分,自动生成对应图例
注:从你提供的样本数据来看,对照组的非0值全部集中在第一种糖肽,其余三种糖肽的对照组数值均为0,绘制出的箱线图会如实体现这个分布特征。
内容的提问来源于stack exchange,提问作者Lucas Lazari
相关产品推荐
相关产品推荐

