使用Python Bokeh调色板绘制多条线图

3
我正在尝试绘制下面代码中列表"w"的长度的线图。当我使用bokeh的spectral11时,我只得到了11条线的图表,而列表包含24个参数。是否有其他调色板可以让我绘制列表"w"中的所有线条?
#Import the library
import pandas 
import bokeh
import MySQLdb
from bokeh.plotting import figure, output_file, show
from bokeh.palettes import Spectral11


w=['F1','F2','F3','F4','F5','F6','F7','F8','F9','F10','F11','F12','G1','G2','G3','G4','G5','G6','G7','G8','G9','G10','G11','G12']

p = figure(plot_width=800, plot_height=500, x_axis_type="datetime")
p.title.text = 'Click on legend entries to hide the corresponding lines'
# Open database connection
db = MySQLdb.connect("localhost","user","password","db" )

在下面的for循环中,只有11个数据框被创建,最终绘制这11条线。
for name, color in zip(w, Spectral11):
   stmnt='select date_time,col1,w,test_value from db where w="%s"'%(name)
   df=pandas.read_sql(stmnt,con=db)

p.line(df['date_time'], df['test_value'], line_width=2, color=color, alpha=0.8, legend=name)

p.legend.location = "top_left"
p.legend.click_policy="hide"

output_file("interactive_legend.html", title="interactive_legend.py example")

show(p)

以下是代码生成的结果图:上述代码生成的图像结果

请发布一个 [mcve],如果必要,请使用虚拟数据。如果我们不知道 wellsSpectra11 中有什么(尽管它被命名为“11”并且你有11个情节似乎不是巧合...),我们将无法提供太多帮助。您确定应该得到24个情节吗? - Ajean
我知道使用Spectral11只能绘制11个,想了解其他调色板,以便给我提供超过11个选项。 - Maverick
2个回答

3
问题在于zip会在较短的列表结束时截断。
In [1]: from bokeh.palettes import Spectral11

In [2]: w=['F1','F2','F3','F4','F5','F6','F7','F8','F9','F10','F11','F12','G1','G2','G3','G4','G5','G6','G7','G8'
    ...: ,'G9','G10','G11','G12']

In [3]: for name, color in zip(w, Spectral11):
    ...:     print(name, color)
    ...:
F1 #5e4fa2
F2 #3288bd
F3 #66c2a5
F4 #abdda4
F5 #e6f598
F6 #ffffbf
F7 #fee08b
F8 #fdae61
F9 #f46d43
F10 #d53e4f
F11 #9e0142

选择一个比你的 w 列表更长的调色板可以解决这个问题(正如 @PabloReyes 所提到的)。您还可以使用 itertools.cycle
In [4]: import itertools

In [5]: for name, color in zip(w, itertools.cycle(Spectral11)):
    ...:     print(name, color)
    ...:
F1 #5e4fa2
F2 #3288bd
F3 #66c2a5
F4 #abdda4
F5 #e6f598
F6 #ffffbf
F7 #fee08b
F8 #fdae61
F9 #f46d43
F10 #d53e4f
F11 #9e0142
F12 #5e4fa2
G1 #3288bd
G2 #66c2a5
G3 #abdda4
G4 #e6f598
G5 #ffffbf
G6 #fee08b
G7 #fdae61
G8 #f46d43
G9 #d53e4f
G10 #9e0142
G11 #5e4fa2
G12 #3288bd

您可能还想使用line_dash参数。
In [6]: import bokeh.plotting
   ...: import numpy as np
   ...: import pandas as pd
   ...:
   ...: bokeh.plotting.output_file('cycle_demo.html')
   ...: lines = np.random.random((100, len(w))) + np.arange(24)
   ...: df = pd.DataFrame(lines)
   ...: df.columns = w
   ...:
   ...: line_dash_styles = [[10, 0], [20, 1], [10, 1], [5, 1]]
   ...: p = bokeh.plotting.figure()
   ...: for name, color, line_dash in zip(w, itertools.cycle(Spectral11), itertools.cycle(line_dash_styles)):
   ...:     p.line(np.arange(100), df[name], color=color, legend=name, line_dash=line_dash)
   ...:
   ...: p.legend.location = "top_left"
   ...: bokeh.plotting.show(p)
   ...:

enter image description here


+1. 使用 itertools.cycle 中不同的 line_dash 更容易区分 Spectral11 颜色,而在 inferno(24) 中相邻线条几乎具有相同的颜色。如果可能的话,我会在虚线设计中增加更多的空白间隔。 - Pablo Reyes
@PabloReyes,使用我演示的列表嵌套语法,您可以自定义破折号,甚至在同一行中交替多个线条和破折号定义;使用 [4, 2, 6, 4] 将会绘制一个长度为 4 的实线,长度为 2 的空白,长度为 6 的实线,然后长度为 4 的空白。等我有时间时,我想调整我的演示,使其在经过所有颜色之后仅循环 line_dash(使用嵌套循环很容易,但我想查找如何使用 itertools 实现此操作)。 - Steven C. Howell
还要考虑D3Colorblind调色板,它们适用于分类数据。 - Steven C. Howell

2

有不同类型的调色板,颜色数量也不同。查看:http://docs.bokeh.org/en/latest/docs/reference/palettes.html。您可以选择其中之一。

我推荐使用那些是函数的调色板,您可以从像viridis或inferno这样的大调色板中指定您想要的颜色数量。

from bokeh.palettes import inferno
mypalette = inferno(24)

在Jupyter笔记本中使用随机行进行测试:

import bokeh
import bokeh.plotting
import numpy as np
bokeh.io.output_notebook()

lines = np.random.random((24,100))
p = bokeh.plotting.figure()
mypalette24 = bokeh.palettes.inferno(24)
for i,color in enumerate(mypalette24):
    p.line(np.arange(100),i+lines[i,:],color=color,legend=str(i+1))
p.legend.location = "top_left"
bokeh.io.show(p)

Simple_Example


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接