带可变子分段的嵌套饼图:零填充Jagged Array颜色排序问题
动态生成嵌套饼图的主/子段匹配色调(自动适配Jagged Array输入)
直接上可复用的解决方案,解决你之前硬编码颜色的问题,完全适配任意输入的Jagged Array(经过pad_sequences处理后的矩阵):
核心逻辑
给每个主饼段分配一个基础色调,然后为该主段下的所有子饼段生成同色调、不同明度的颜色——既保证主副段颜色关联,又能通过亮度区分子项,而且全程自动根据输入结构生成,不用手动写颜色列表。
完整实现代码
import numpy as np import matplotlib.pyplot as plt from matplotlib.colors import to_rgb, to_hex from tensorflow.keras.utils import pad_sequences as ps # 工具函数:调整颜色明度,保持色调不变 def adjust_color_lightness(color, lightness_factor): rgb = np.array(to_rgb(color)) max_rgb, min_rgb = rgb.max(), rgb.min() delta = max_rgb - min_rgb # 计算HSL参数 if delta == 0: h = 0 elif max_rgb == rgb[0]: h = ((rgb[1] - rgb[2]) / delta) % 6 elif max_rgb == rgb[1]: h = (rgb[2] - rgb[0]) / delta + 2 else: h = (rgb[0] - rgb[1]) / delta + 4 h *= 60 l = (max_rgb + min_rgb) / 2 s = delta / (1 - abs(2 * l - 1)) if delta != 0 else 0 # 调整明度(限制在0-1之间,避免过暗/过亮) new_l = np.clip(l * lightness_factor, 0, 1) # HSL转回RGB def hsl_to_rgb(h, s, l): c = (1 - abs(2 * l - 1)) * s x = c * (1 - abs((h / 60) % 2 - 1)) m = l - c / 2 if 0 <= h < 60: r, g, b = c, x, 0 elif 60 <= h < 120: r, g, b = x, c, 0 elif 120 <= h < 180: r, g, b = 0, c, x elif 180 <= h < 240: r, g, b = 0, x, c elif 240 <= h < 300: r, g, b = x, 0, c else: r, g, b = c, 0, x return (r + m, g + m, b + m) return to_hex(hsl_to_rgb(h, s, new_l)) # 处理你的输入数据 jagged_data = [[9.0, 8.0, 8.0], [2.0, 7.0, 8.0, 8.0], [6.0, 6.0, 8.0, 5.0], [2.0, 4.0, 10.0, 4.0, 5.0]] vals = ps(jagged_data) # 生成外层饼图颜色(选tab20c间隔色调,保证区分度) tab20c = plt.color_sequences["tab20c"] outer_colors = [tab20c[i] for i in [0, 4, 8, 12]] # 动态生成内层饼图颜色 inner_colors = [] # 明度从0.7到1.3渐变,子项越多,渐变越细腻 lightness_steps = np.linspace(0.7, 1.3, vals.shape[1]) for base_color in outer_colors: # 给当前主段的每个子项生成对应明度的颜色 for step in lightness_steps: inner_colors.append(adjust_color_lightness(base_color, step)) # 绘制嵌套饼图(和官方示例逻辑一致) outer_sizes = [len(row) for row in jagged_data] inner_sizes = vals.flatten().tolist() fig, ax = plt.subplots() ax.pie(outer_sizes, radius=1, colors=outer_colors, wedgeprops=dict(width=0.3, edgecolor='white')) ax.pie(inner_sizes, radius=0.7, colors=inner_colors, wedgeprops=dict(width=0.3, edgecolor='white')) ax.set(aspect="equal") plt.show()
为什么这方案能解决你的问题?
- 完全动态适配:不管你的Jagged Array有多少组、每组有多少元素,只要经过pad_sequences处理,代码会自动对应生成颜色列表,不用硬编码
- 颜色关联清晰:每个主段的子项都用主段色调的明度变体,一眼就能看出子项属于哪个主分类
- 可自定义调整:如果觉得明度范围不合适,直接改
lightness_steps的数值就行(比如改成np.linspace(0.6, 1.4, ...)),或者调整外层颜色的选取逻辑
内容的提问来源于stack exchange,提问作者Signor Pizza
相关产品推荐
相关产品推荐

