如何在Plotly中使用自定义温度关联的RGB调色板?
解决Plotly自定义温度调色板应用错误的方案
错误原因
你遇到的Invalid value of type 'builtins.dict' received for the 'colorscale' property错误,是因为Plotly的color_continuous_scale参数不接受字典格式。它仅支持以下输入类型:
- Plotly内置调色板名称字符串(如
'Viridis'); - 颜色值组成的列表(每个元素为RGB/HEX字符串或归一化RGB数组);
- 刻度-颜色对的列表(格式示例:
[[0, 'rgb(0,0,0)'], [0.5, 'rgb(128,128,128)'], [1, 'rgb(255,255,255)']])。
你之前将RGB通道拆分为字典的操作不符合参数要求,因此触发报错。
解决方案
根据你需要将B-V色指数映射到开尔文温度调色板的需求,提供两种可行方案:
方案1:直接传入颜色序列(快速匹配趋势)
将生成的colorList转换为Plotly可识别的格式,直接作为color_continuous_scale的值传入,Plotly会自动将B-V的数值范围映射到你的调色板序列:
import matplotlib.pyplot as plt import plotly.express as px import pandas as pd # 假设convert_K_to_RGB已定义,返回0-1之间的归一化RGB值 step_size = 10 colorList = [] # 生成0-15000K对应的RGB颜色(转成Plotly兼容的rgb字符串) for temp in range(0, 15000, step_size): rgb_norm = convert_K_to_RGB(temp) # 转成0-255的RGB字符串 rgb_str = f"rgb({int(rgb_norm[0]*255)}, {int(rgb_norm[1]*255)}, {int(rgb_norm[2]*255)})" colorList.append(rgb_str) # 保留原matplotlib调色板预览代码 plt.plot((temp, temp), (0, 1), linewidth=step_size/2.0, linestyle="-", color=rgb_norm) # 绘制3D散点图,直接传入颜色列表 fig = px.scatter_3d(datap, x=x, y=y, z=z, color=datap['B-V'], color_continuous_scale=colorList, color_continuous_midpoint=(datap['B-V'].max() + datap['B-V'].min())/2) fig.show()
方案2:严格匹配温度-颜色对应关系(精准映射)
如果需要让每个恒星的颜色严格对应其B-V指数转换后的温度,需先建立B-V到开尔文温度的映射,再匹配调色板中的对应颜色:
import matplotlib.pyplot as plt import plotly.graph_objects as go import pandas as pd # 1. 定义B-V转开尔文温度的经验公式(根据恒星物理关系调整) def bv_to_temperature(bv): return 4600 * (1/(0.92*bv + 1.7) + 1/(0.92*bv + 0.62)) # 2. 生成温度-颜色映射表 step_size = 10 color_map = {} colorList = [] for temp in range(0, 15000, step_size): rgb_norm = convert_K_to_RGB(temp) rgb_str = f"rgb({int(rgb_norm[0]*255)}, {int(rgb_norm[1]*255)}, {int(rgb_norm[2]*255)})" color_map[temp] = rgb_str colorList.append(rgb_str) # 预览调色板 plt.plot((temp, temp), (0, 1), linewidth=step_size/2.0, linestyle="-", color=rgb_norm) # 3. 为数据添加温度和对应颜色列 datap['temperature'] = datap['B-V'].apply(bv_to_temperature) # 确保温度在0-15000范围内,并匹配对应颜色 datap['star_color'] = datap['temperature'].apply( lambda t: color_map[max(0, min(14999, int(t)//step_size * step_size))] ) # 4. 绘制3D散点图,直接指定每个点的颜色 fig = go.Figure(data=[go.Scatter3d( x=datap[x], y=datap[y], z=datap[z], mode='markers', marker=dict( color=datap['star_color'], size=5 ) )]) fig.update_layout(title='恒星位置与温度颜色映射') fig.show()
关键说明
- 方案1适合快速实现颜色趋势匹配,无需额外的B-V温度转换;
- 方案2适合需要精准温度-颜色对应场景,需确保B-V转温度的公式符合你的数据需求;
- 如果
convert_K_to_RGB返回的是0-255的整数,无需乘以255,直接拼接字符串即可。
内容的提问来源于stack exchange,提问作者Adrian
相关产品推荐
相关产品推荐

