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

如何在循环绘制饼图时为相同类别指定固定颜色?

问题描述

需要针对不同条件(按qseqid分组)下的同一类别绘制饼图,要求同一类别在所有饼图中颜色保持一致(例如rhinovirus在所有饼图中颜色相同)。现有Python代码如下,如何实现该需求?

#!/usr/bin/env python3

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

df = pd.read_csv('blast_results', sep='\t', names=['qseqid','sseqid','staxid','salltitles','length','pident','qstart','qend','sstart','send','qcovhsp','evalue','bitscore','qseq','sseq'])

#divide column
df[['sseqid', 'organism']] = df['sseqid'].str.split('|', 1, expand=True)
df['organism'] = df['organism'].str.split(':').str.get(1).astype(str).str.lower()

#add to salltitles the organism where not present
df['salltitles'] = np.where(df['organism']!='human', df['organism'] + ' ' +  df['salltitles'], df['salltitles'])

# divide column
df[['salltitles', 'strain','segment','host']] = df['salltitles'].str.split('|', 3, expand=True)

# remove unused column
df.drop(['organism','segment', 'staxid'], inplace=True, axis=1)


primers = df['qseqid'].unique()

for i in primers:
    print(i)
    subset = df[df['qseqid'] == i]
    subset[['salltitles', 'subtype']] = subset['salltitles'].str.split(' ', 1, expand=True)
    results = pd.DataFrame(subset.groupby('salltitles')['qseqid'].count())
    results.reset_index(inplace=True)
    results.sort_values('salltitles', inplace=True)
    x = [0.05 for i in range(0, results.shape[0])]
    explode = tuple(x)
    plt.figure()
    plt.pie(results['qseqid'], labels=results['salltitles'], autopct='%.1f%%', colors = ['#98F5FF', 'coral','#A2CD5A','#FF1493','#FF6EB4'], explode=explode)
    plt.title(i)
解决方案

核心是创建固定的类别-颜色映射字典,让每个类别对应唯一颜色,绘制饼图时根据当前子集的类别从字典中提取对应颜色,步骤如下:

1. 提前生成全局类别-颜色映射

先处理所有数据,得到所有可能的salltitles类别,给每个分配固定颜色。可以用自定义颜色列表,也可以用matplotlib内置颜色循环:

# 先处理全量数据,提取所有唯一类别
df_full = df.copy()
df_full[['salltitles', 'subtype']] = df_full['salltitles'].str.split(' ', 1, expand=True)
all_categories = df_full['salltitles'].unique()

# 自定义颜色列表(可根据实际类别数量补充)
color_list = ['#98F5FF', 'coral','#A2CD5A','#FF1493','#FF6EB4', '#FFD700', '#8B4513', '#4169E1']
# 创建类别-颜色映射字典,类别数量超出自定义颜色时循环复用
category_color_map = {cat: color_list[i % len(color_list)] for i, cat in enumerate(all_categories)}

2. 修改循环内的饼图颜色调用

在循环绘制饼图时,根据当前results中的salltitles从映射字典中获取对应颜色,替换原代码中固定的colors参数:

plt.pie(results['qseqid'], 
        labels=results['salltitles'], 
        autopct='%.1f%%', 
        colors=[category_color_map[cat] for cat in results['salltitles']], 
        explode=explode)

完整修改后的代码

#!/usr/bin/env python3

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

df = pd.read_csv('blast_results', sep='\t', names=['qseqid','sseqid','staxid','salltitles','length','pident','qstart','qend','sstart','send','qcovhsp','evalue','bitscore','qseq','sseq'])

# 分割列
df[['sseqid', 'organism']] = df['sseqid'].str.split('|', 1, expand=True)
df['organism'] = df['organism'].str.split(':').str.get(1).astype(str).str.lower()

# 给非人类的salltitles添加organism前缀
df['salltitles'] = np.where(df['organism']!='human', df['organism'] + ' ' +  df['salltitles'], df['salltitles'])

# 分割列
df[['salltitles', 'strain','segment','host']] = df['salltitles'].str.split('|', 3, expand=True)

# 删除无用列
df.drop(['organism','segment', 'staxid'], inplace=True, axis=1)

# 提前生成全局类别-颜色映射
df_full = df.copy()
df_full[['salltitles', 'subtype']] = df_full['salltitles'].str.split(' ', 1, expand=True)
all_categories = df_full['salltitles'].unique()

# 自定义颜色列表(可根据实际类别数量补充)
color_list = ['#98F5FF', 'coral','#A2CD5A','#FF1493','#FF6EB4', '#FFD700', '#8B4513', '#4169E1']
category_color_map = {cat: color_list[i % len(color_list)] for i, cat in enumerate(all_categories)}

primers = df['qseqid'].unique()

for i in primers:
    print(i)
    subset = df[df['qseqid'] == i]
    subset[['salltitles', 'subtype']] = subset['salltitles'].str.split(' ', 1, expand=True)
    results = pd.DataFrame(subset.groupby('salltitles')['qseqid'].count())
    results.reset_index(inplace=True)
    results.sort_values('salltitles', inplace=True)
    x = [0.05 for i in range(0, results.shape[0])]
    explode = tuple(x)
    plt.figure()
    plt.pie(results['qseqid'], 
            labels=results['salltitles'], 
            autopct='%.1f%%', 
            colors=[category_color_map[cat] for cat in results['salltitles']], 
            explode=explode)
    plt.title(i)

plt.show()

说明

  • 无论哪个qseqid对应的饼图,同一个salltitles类别都会使用映射字典里的固定颜色
  • 如果类别数量超过自定义颜色列表长度,会通过i % len(color_list)循环复用颜色,也可以直接扩展color_list添加更多颜色

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 22:36:34