python bokeh
Bokeh prides itself on being a library for interactive data visualization.
Bokeh以成为交互式数据可视化的库而自豪。
Unlike popular counterparts in the Python visualization space, like Matplotlib and Seaborn, Bokeh renders its graphics using HTML and JavaScript. This makes it a great candidate for building web-based dashboards and applications. However, it’s an equally powerful tool for exploring and understanding your data or creating beautiful custom charts for a project or report.
与Python可视化领域的流行同行(例如Matplotlib和Seaborn)不同,Bokeh使用HTML和JavaScript渲染其图形。 这使其非常适合构建基于Web的仪表板和应用程序。 但是,它是用于浏览和理解数据或为项目或报告创建漂亮的自定义图表的功能同样强大的工具。
Using a number of examples on a real-world dataset, the goal of this tutorial is to get you up and running with Bokeh.
通过使用真实数据集上的许多示例,本教程的目标是使您开始使用Bokeh。
You’ll learn how to:
您将学习如何:
So let’s jump in.
因此,让我们进入。
Free Bonus: Click here to get access to a chapter from Python Tricks: The Book that shows you Python’s best practices with simple examples you can apply instantly to write more beautiful + Pythonic code.
免费红利: 单击此处可访问Python技巧的一章:该书通过简单的示例向您展示了Python的最佳实践,您可以立即应用这些示例编写更精美的Pythonic代码。
Building a visualization with Bokeh involves the following steps:
使用Bokeh构建可视化过程涉及以下步骤:
Let’s explore each step in more detail.
让我们更详细地探索每个步骤。
Any good data visualization starts with—you guessed it—data. If you need a quick refresher on handling data in Python, definitely check out the growing number of excellent Real Python tutorials on the subject.
任何好的数据可视化都始于(您猜对了)数据。 如果您需要快速处理Python中的数据,请一定要查看有关该主题的越来越多的出色Real Python教程 。
This step commonly involves data handling libraries like Pandas and Numpy and is all about taking the required steps to transform it into a form that is best suited for your intended visualization.
此步骤通常涉及诸如Pandas和Numpy之类的数据处理库,并且全部涉及采取必要步骤将其转换为最适合您的预期可视化的形式。
At this step, you’ll determine how you want to generate and ultimately view your visualization. In this tutorial, you’ll learn about two common options that Bokeh provides: generating a static HTML file and rendering your visualization inline in a Jupyter Notebook.
在这一步,您将确定如何生成并最终查看可视化效果。 在本教程中,您将了解Bokeh提供的两个常用选项:生成静态HTML文件以及在Jupyter Notebook中内嵌呈现可视化效果。
From here, you’ll assemble your figure, preparing the canvas for your visualization. In this step, you can customize everything from the titles to the tick marks. You can also set up a suite of tools that can enable various user interactions with your visualization.
在这里,您将组装图形,为可视化准备画布。 在此步骤中,您可以自定义从标题到刻度线的所有内容。 您还可以设置一套工具,以实现与可视化的各种用户交互。
Next, you’ll use Bokeh’s multitude of renderers to give shape to your data. Here, you have the flexibility to draw your data from scratch using the many available marker and shape options, all of which are easily customizable. This functionality gives you incredible creative freedom in representing your data.
接下来,您将使用Bokeh的大量渲染器来使数据成形。 在这里,您可以使用许多可用的标记和形状选项灵活地从头开始绘制数据,所有这些都可以轻松自定义。 此功能为您提供了令人难以置信的创作自由,可以代表您的数据。
Additionally, Bokeh has some built-in functionality for building things like stacked bar charts and plenty of examples for creating more advanced visualizations like network graphs and maps.
此外,Bokeh具有一些内置功能,可用于构建诸如堆积的条形图之类的东西,以及用于创建更高级的可视化效果(如网络图和地图)的大量示例。
If you need more than one figure to express your data, Bokeh’s got you covered. Not only does Bokeh offer the standard grid-like layout options, but it also allows you to easily organize your visualizations into a tabbed layout in just a few lines of code.
如果您需要一个以上的数字来表达您的数据,那么Bokeh就可以满足您的要求。 Bokeh不仅提供标准的类似于网格的布局选项,而且还使您可以轻松地用几行代码将可视化内容组织到选项卡式布局中。
In addition, your plots can be quickly linked together, so a selection on one will be reflected on any combination of the others.
此外,您的地块可以快速链接在一起,因此一个地块的选择将反映在其他地块的任何组合上。
Finally, it’s time to see what you created.
最后,是时候看看您创建的内容了。
Whether you’re viewing your visualization in a browser or notebook, you’ll be able to explore your visualization, examine your customizations, and play with any interactions that were added.
无论您是在浏览器中还是在笔记本电脑中查看可视化,您都可以浏览可视化,检查自定义设置并进行添加的交互。
If you like what you see, you can save your visualization to an image file. Otherwise, you can revisit the steps above as needed to bring your data vision to reality.
如果您喜欢所看到的内容,则可以将可视化文件保存到图像文件中。 否则,您可以根据需要重新查看上述步骤,以实现数据愿景。
That’s it! Those six steps are the building blocks for a tidy, flexible template that can be used to take your data from the table to the big screen:
而已! 这六个步骤是一个整洁,灵活的模板的构建块,可用于将数据从表移至大屏幕:
"""Bokeh Visualization Template
"""Bokeh Visualization Template
This template is a general outline for turning your data into a
This template is a general outline for turning your data into a
visualization using Bokeh.
visualization using Bokeh.
"""
"""
# Data handling
# Data handling
import import pandas pandas as as pd
pd
import import numpy numpy as as np
np
# Bokeh libraries
# Bokeh libraries
from from bokeh.io bokeh.io import import output_fileoutput_file , , output_notebook
output_notebook
from from bokeh.plotting bokeh.plotting import import figurefigure , , show
show
from from bokeh.models bokeh.models import import ColumnDataSource
ColumnDataSource
from from bokeh.layouts bokeh.layouts import import rowrow , , columncolumn , , gridplot
gridplot
from from bokeh.models.widgets bokeh.models.widgets import import TabsTabs , , Panel
Panel
# Prepare the data
# Prepare the data
# Determine where the visualization will be rendered
# Determine where the visualization will be rendered
output_fileoutput_file (( 'filename.html''filename.html' ) ) # Render to static HTML, or
# Render to static HTML, or
output_notebookoutput_notebook () () # Render inline in a Jupyter Notebook
# Render inline in a Jupyter Notebook
# Set up the figure(s)
# Set up the figure(s)
fig fig = = figurefigure () () # Instantiate a figure() object
# Instantiate a figure() object
# Connect to and draw the data
# Connect to and draw the data
# Organize the layout
# Organize the layout
# Preview and save
# Preview and save
showshow (( figfig ) ) # See what I made, and save if I like it
# See what I made, and save if I like it
Some common code snippets that are found in each step are previewed above, and you’ll see how to fill out the rest as you move through the rest of the tutorial!
上面已预览了每个步骤中发现的一些常见代码段,在本教程的其余部分中,您将看到如何填写其余部分!
There are multiple ways to output your visualization in Bokeh. In this tutorial, you’ll see these two options:
有多种方法可以在Bokeh中输出可视化效果 。 在本教程中,您将看到以下两个选项:
output_file('filename.html')
will write the visualization to a static HTML file.output_notebook()
will render your visualization directly in a Jupyter Notebook.output_file('filename.html')
会将可视化内容写入静态HTML文件。 output_notebook()
将直接在Jupyter Notebook中呈现可视化效果。 It’s important to note that neither function will actually show you the visualization. That doesn’t happen until show()
is called. However, they will ensure that, when show()
is called, the visualization appears where you intend it to.
重要的是要注意,这两个功能实际上都不会为您显示可视化效果。 在调用show()
之前不会发生这种情况。 但是,它们将确保在调用show()
时,可视化内容将显示在您想要的位置。
By calling both output_file()
and output_notebook()
in the same execution, the visualization will be rendered both to a static HTML file and inline in the notebook. However, if for whatever reason you run multiple output_file()
commands in the same execution, only the last one will be used for rendering.
通过在同一执行中同时调用output_file()
和output_notebook()
,可视化文件将呈现为静态HTML文件并在笔记本中内联。 但是,如果出于某种原因在同一执行中运行多个output_file()
命令,则仅使用最后一个命令进行渲染。
This is a great opportunity to give you your first glimpse at a default Bokeh figure()
using output_file()
:
这是一个很好的机会,可以使用output_file()
默认的Bokeh figure()
output_file()
:
As you can see, a new browser window opened with a tab called Empty Bokeh Figure and an empty figure. Not shown is the file generated with the name output_file_test.html in your current working directory.
如您所见,将打开一个新的浏览器窗口,其中包含一个名为Empty Bokeh Figure和一个空图的选项卡。 在当前工作目录中未显示名称为output_file_test.html的文件。
If you were to run the same code snippet with output_notebook()
in place of output_file()
, assuming you have a Jupyter Notebook fired up and ready to go, you will get the following:
如果要使用output_notebook()
代替output_file()
运行相同的代码段,并假设已启动Jupyter Notebook并准备就绪,则将获得以下内容:
# Bokeh Libraries
# Bokeh Libraries
from from bokeh.io bokeh.io import import output_notebook
output_notebook
from from bokeh.plotting bokeh.plotting import import figurefigure , , show
show
# The figure will be right in my Jupyter Notebook
# The figure will be right in my Jupyter Notebook
output_notebookoutput_notebook ()
()
# Set up a generic figure() object
# Set up a generic figure() object
fig fig = = figurefigure ()
()
# See what it looks like
# See what it looks like
showshow (( figfig )
)
As you can see, the result is the same, just rendered in a different location.
如您所见,结果是相同的,只是在不同的位置呈现。
More information about both output_file()
and output_notebook()
can be found in the Bokeh official docs.
可以在Bokeh官方文档中找到有关output_file()
和output_notebook()
更多信息。
Note: Sometimes, when rendering multiple visualizations sequentially, you’ll see that past renders are not being cleared with each execution. If you experience this, import and run the following between executions:
注意:有时,当顺序渲染多个可视化对象时,您会看到每次执行都不会清除过去的渲染。 如果遇到这种情况,请在两次执行之间导入并运行以下命令:
Before moving on, you may have noticed that the default Bokeh figure comes pre-loaded with a toolbar. This is an important sneak preview into the interactive elements of Bokeh that come right out of the box. You’ll find out more about the toolbar and how to configure it in the Adding Interaction section at the end of this tutorial.
在继续之前,您可能已经注意到默认的Bokeh图形已预装了工具栏。 这是开箱即用的Bokeh交互元素的重要预览。 您将在本教程结尾的“ 添加交互”部分中找到有关工具栏以及如何配置它的更多信息。
Now that you know how to create and view a generic Bokeh figure either in a browser or Jupyter Notebook, it’s time to learn more about how to configure the figure()
object.
既然您知道如何在浏览器或Jupyter Notebook中创建和查看通用的Bokeh人物,是时候了解有关如何配置fig figure()
对象的更多信息了。
The figure()
object is not only the foundation of your data visualization but also the object that unlocks all of Bokeh’s available tools for visualizing data. The Bokeh figure is a subclass of the Bokeh Plot object, which provides many of the parameters that make it possible to configure the aesthetic elements of your figure.
figure()
对象不仅是数据可视化的基础,而且是解锁Bokeh可用的用于可视化数据的所有工具的对象。 散景图是“ 散景图”对象的子类,该对象提供许多参数,这些参数使您可以配置图形的美学元素。
To show you just a glimpse into the customization options available, let’s create the ugliest figure ever:
为了让您了解可用的自定义选项,让我们创建有史以来最丑陋的人物:
# Bokeh Libraries
# Bokeh Libraries
from from bokeh.io bokeh.io import import output_notebook
output_notebook
from from bokeh.plotting bokeh.plotting import import figurefigure , , show
show
# The figure will be rendered inline in my Jupyter Notebook
# The figure will be rendered inline in my Jupyter Notebook
output_notebookoutput_notebook ()
()
# Example figure
# Example figure
fig fig = = figurefigure (( background_fill_colorbackground_fill_color == 'gray''gray' ,
,
background_fill_alphabackground_fill_alpha == 0.50.5 ,
,
border_fill_colorborder_fill_color == 'blue''blue' ,
,
border_fill_alphaborder_fill_alpha == 0.250.25 ,
,
plot_heightplot_height == 300300 ,
,
plot_widthplot_width == 500500 ,
,
h_symmetryh_symmetry == TrueTrue ,
,
x_axis_labelx_axis_label == 'X Label''X Label' ,
,
x_axis_typex_axis_type == 'datetime''datetime' ,
,
x_axis_locationx_axis_location == 'above''above' ,
,
x_rangex_range == (( '2018-01-01''2018-01-01' , , '2018-06-30''2018-06-30' ),
),
y_axis_labely_axis_label == 'Y Label''Y Label' ,
,
y_axis_typey_axis_type == 'linear''linear' ,
,
y_axis_locationy_axis_location == 'left''left' ,
,
y_rangey_range == (( 00 , , 100100 ),
),
titletitle == 'Example Figure''Example Figure' ,
,
title_locationtitle_location == 'right''right' ,
,
toolbar_locationtoolbar_location == 'below''below' ,
,
toolstools == 'save''save' )
)
# See what it looks like
# See what it looks like
showshow (( figfig )
)
Once the figure()
object is instantiated, you can still configure it after the fact. Let’s say you want to get rid of the gridlines:
实例化fig figure()
对象后,您仍然可以在配置之后进行配置。 假设您要摆脱网格线:
The gridline properties are accessible via the figure’s grid
attribute. In this case, setting grid_line_color
to None
effectively removes the gridlines altogether. More details about figure attributes can be found below the fold in the Plot class documentation.
可通过图形的grid
属性访问gridline属性。 在这种情况下,将grid_line_color
设置为None
可以完全删除网格线。 有关图形属性的更多详细信息,可以在Plot类文档的首屏下面找到。
Note: If you’re working in a notebook or IDE with auto-complete functionality, this feature can definitely be your friend! With so many customizable elements, it can be very helpful in discovering the available options:
注意:如果您使用的是具有自动完成功能的笔记本电脑或IDE,那么此功能绝对可以成为您的朋友! 有这么多可定制的元素,在发现可用选项时会非常有帮助:
Otherwise, doing a quick web search, with the keyword bokeh and what you are trying to do, will generally point you in the right direction.
否则,使用关键字bokeh和您要尝试的操作进行快速的网络搜索通常会为您指明正确的方向。
There is tons more I could touch on here, but don’t feel like you’re missing out. I’ll make sure to introduce different figure tweaks as the tutorial progresses. Here are some other helpful links on the topic:
在这里,我还有很多其他可以触及的地方,但不要觉得您错过了。 随着教程的进行,我将确保引入不同的图形调整。 这是有关此主题的其他一些有用的链接:
figure()
object, from which figures inherit a lot of their attributes.figure()
object.figure()
对象的超类, figure()
从中继承许多属性。 figure()
对象的参数的更多详细信息的好地方。 Here are a few specific customization options worth checking out:
以下是一些值得一试的自定义选项:
Sometimes, it isn’t clear how your figure needs to be customized until it actually has some data visualized in it, so next you’ll learn how to make that happen.
有时,在实际显示一些数据之前,还不清楚如何对您的图形进行自定义,因此接下来您将学习如何实现这一目标。
An empty figure isn’t all that exciting, so let’s look at glyphs: the building blocks of Bokeh visualizations. A glyph is a vectorized graphical shape or marker that is used to represent your data, like a circle or square. More examples can be found in the Bokeh gallery. After you create your figure, you are given access to a bevy of configurable glyph methods.
一个空虚的图形并不是那么令人兴奋,所以让我们看一下字形:Bokeh可视化的基础。 字形是矢量化的图形形状或标记,用于表示您的数据,例如圆形或正方形。 可以在Bokeh画廊中找到更多示例。 创建图形之后,您就可以访问一系列可配置的字形方法 。
Let’s start with a very basic example, drawing some points on an x-y coordinate grid:
让我们从一个非常基本的示例开始,在xy坐标网格上绘制一些点:
# Bokeh Libraries
# Bokeh Libraries
from from bokeh.io bokeh.io import import output_file
output_file
from from bokeh.plotting bokeh.plotting import import figurefigure , , show
show
# My x-y coordinate data
# My x-y coordinate data
x x = = [[ 11 , , 22 , , 11 ]
]
y y = = [[ 11 , , 11 , , 22 ]
]
# Output the visualization directly in the notebook
# Output the visualization directly in the notebook
output_fileoutput_file (( 'first_glyphs.html''first_glyphs.html' , , titletitle == 'First Glyphs''First Glyphs' )
)
# Create a figure with no toolbar and axis ranges of [0,3]
# Create a figure with no toolbar and axis ranges of [0,3]
fig fig = = figurefigure (( titletitle == 'My Coordinates''My Coordinates' ,
,
plot_heightplot_height == 300300 , , plot_widthplot_width == 300300 ,
,
x_rangex_range == (( 00 , , 33 ), ), y_rangey_range == (( 00 , , 33 ),
),
toolbar_locationtoolbar_location == NoneNone )
)
# Draw the coordinates as circles
# Draw the coordinates as circles
figfig .. circlecircle (( xx == xx , , yy == yy ,
,
colorcolor == 'green''green' , , sizesize == 1010 , , alphaalpha == 0.50.5 )
)
# Show plot
# Show plot
showshow (( figfig )
)
Once your figure is instantiated, you can see how it can be used to draw the x-y coordinate data using customized circle
glyphs.
实例化图形后,您将看到如何使用它使用定制的circle
字形来绘制xy坐标数据。
Here are a few categories of glyphs:
以下是字形的一些类别:
Marker includes shapes like circles, diamonds, squares, and triangles and is effective for creating visualizations like scatter and bubble charts.
Line covers things like single, step, and multi-line shapes that can be used to build line charts.
Bar/Rectangle shapes can be used to create traditional or stacked bar (hbar
) and column (vbar
) charts as well as waterfall or gantt charts.
标记包括圆形,菱形,正方形和三角形等形状,对于创建散点图和气泡图等可视化效果非常有效。
折线涵盖可以用于构建折线图的单线,阶梯和多线形状。
条形/矩形形状可用于创建传统的或堆叠的条形图( hbar
)和柱形图( vbar
)以及瀑布图或甘特图。
Information about the glyphs above, as well as others, can be found in Bokeh’s Reference Guide.
有关上述字形以及其他字形的信息,可以在Bokeh的参考指南中找到 。
These glyphs can be combined as needed to fit your visualization needs. Let’s say I want to create a visualization that shows how many words I wrote per day to make this tutorial, with an overlaid trend line of the cumulative word count:
这些字形可以根据需要进行组合,以满足您的可视化需求。 假设我想创建一个可视化效果,以显示我每天编写多少个单词来制作本教程,并使用累积单词数的叠加趋势线进行显示:
To combine the columns and lines on the figure, they are simply created using the same figure()
object.
要组合图形上的列和线,只需使用相同的figure()
对象即可创建它们。
Additionally, you can see above how seamlessly a legend can be created by setting the legend
property for each glyph. The legend was then moved to the upper left corner of the plot by assigning 'top_left'
to fig.legend.location
.
此外,您可以在上方看到通过设置每个字形的legend
属性如何无缝创建legend
。 然后通过为fig.legend.location
分配'top_left'
,将'top_left'
移至图的fig.legend.location
。
You can check out much more info about styling legends. Teaser: they will show up again later in the tutorial when we start digging into interactive elements of the visualization.
您可以查看有关样式图例的更多信息 。 预告片:当我们开始深入研究可视化的交互元素时,它们将在本教程的稍后部分再次显示。
Anytime you are exploring a new visualization library, it’s a good idea to start with some data in a domain you are familiar with. The beauty of Bokeh is that nearly any idea you have should be possible. It’s just a matter of how you want to leverage the available tools to do so.
每当您探索新的可视化库时,最好从熟悉的域中的一些数据开始。 散景的魅力在于,您几乎可以拥有任何想法。 只是您要如何利用可用工具来这样做。
The remaining examples will use publicly available data from Kaggle, which has information about the National Basketball Association’s (NBA) 2017-18 season, specifically:
其余示例将使用Kaggle的公开数据,该数据包含有关美国国家篮球协会(NBA)2017-18赛季的信息 ,尤其是:
This data has nothing to do with what I do for work, but I love basketball and enjoy thinking about ways to visualize the ever-growing amount of data associated with it.
这些数据与我的工作无关,但我喜欢篮球,喜欢思考如何可视化与之相关的不断增长的数据量。
If you don’t have data to play with from school or work, think about something you’re interested in and try to find some data related to that. It will go a long way in making both the learning and the creative process faster and more enjoyable!
如果您没有从学校或工作中获得的数据,请考虑您感兴趣的事情,并尝试查找与此相关的数据。 这将使学习和创作过程更快,更有趣,这将大有帮助!
To follow along with the examples in the tutorial, you can download the datasets from the links above and read them into a Pandas DataFrame
using the following commands:
要遵循本教程中的示例,您可以从上面的链接下载数据集,并使用以下命令将其读取到Pandas DataFrame
:
import import pandas pandas as as pd
pd
# Read the csv files
# Read the csv files
player_stats player_stats = = pdpd .. read_csvread_csv (( '2017-18_playerBoxScore.csv''2017-18_playerBoxScore.csv' , , parse_datesparse_dates == [[ 'gmDate''gmDate' ])
])
team_stats team_stats = = pdpd .. read_csvread_csv (( '2017-18_teamBoxScore.csv''2017-18_teamBoxScore.csv' , , parse_datesparse_dates == [[ 'gmDate''gmDate' ])
])
standings standings = = pdpd .. read_csvread_csv (( '2017-18_standings.csv''2017-18_standings.csv' , , parse_datesparse_dates == [[ 'stDate''stDate' ])
])
This code snippet reads the data from the three CSV files and automatically interprets the date columns as datetime
objects.
此代码段从三个CSV文件中读取数据,并将日期列自动解释为datetime
对象 。
It’s now time to get your hands on some real data.
现在是时候掌握一些真实数据了。
ColumnDataSource
对象 (Using the ColumnDataSource
Object)The examples above used Python lists and Numpy arrays to represent the data, and Bokeh is well equipped to handle these datatypes. However, when it comes to data in Python, you are most likely going to come across Python dictionaries and Pandas DataFrames, especially if you’re reading in data from a file or external data source.
上面的示例使用Python列表和Numpy数组表示数据,并且Bokeh具备处理这些数据类型的能力。 但是,当涉及到Python中的数据时,您很可能会遇到Python字典和Pandas DataFrames ,尤其是当您从文件或外部数据源中读取数据时。
Bokeh is well equipped to work with these more complex data structures and even has built-in functionality to handle them, namely the ColumnDataSource
.
Bokeh能够很好地处理这些更复杂的数据结构,甚至具有处理它们的内置功能,即ColumnDataSource
。
You may be asking yourself, “Why use a ColumnDataSource
when Bokeh can interface with other data types directly?”
您可能会问自己:“当Bokeh可直接与其他数据类型接口时,为什么要使用ColumnDataSource
?”
For one, whether you reference a list, array, dictionary, or DataFrame directly, Bokeh is going to turn it into a ColumnDataSource
behind the scenes anyway. More importantly, the ColumnDataSource
makes it much easier to implement Bokeh’s interactive affordances.
首先,无论您直接引用列表,数组,字典还是DataFrame,Bokeh都会将其变成幕后的ColumnDataSource
。 更重要的是, ColumnDataSource
使实现Bokeh的交互式功能更加容易。
The ColumnDataSource
is foundational in passing the data to the glyphs you are using to visualize. Its primary functionality is to map names to the columns of your data. This makes it easier for you to reference elements of your data when building your visualization. It also makes it easier for Bokeh to do the same when building your visualization.
ColumnDataSource
是将数据传递到用于可视化的字形的基础。 它的主要功能是将名称映射到数据的列。 这使您在建立可视化文件时更容易引用数据元素。 这也使Bokeh在构建可视化文件时更容易执行相同的操作。
The ColumnDataSource
can interpret three types of data objects:
ColumnDataSource
可以解释三种类型的数据对象:
Python dict
: The keys are names associated with the respective value sequences (lists, arrays, and so forth).
Pandas DataFrame
: The columns of the DataFrame
become the reference names for the ColumnDataSource
.
Pandas groupby
: The columns of the ColumnDataSource
reference the columns as seen by calling groupby.describe()
.
Python dict
:键是与各个值序列(列表,数组等)关联的名称。
熊猫DataFrame
:对的列DataFrame
成为参考名称ColumnDataSource
。
Pandas groupby
: ColumnDataSource
的列引用通过调用groupby.describe()
看到的列。
Let’s start by visualizing the race for first place in the NBA’s Western Conference in 2017-18 between the defending champion Golden State Warriors and the challenger Houston Rockets. The daily win-loss records of these two teams is stored in a DataFrame named west_top_2
:
首先让我们想象一下卫冕冠军金州勇士队和挑战者休斯顿火箭队之间在2017-18赛季NBA西部决赛中的第一场比赛。 这两个团队的每日输赢记录存储在一个名为west_top_2
:
>>> west_top_2 = ( standings [( standings [ 'teamAbbr' ] == 'HOU' ) | ( standings [ 'teamAbbr' ] == 'GS' )]
... . loc [:, [ 'stDate' , 'teamAbbr' , 'gameWon' ]]
... . sort_values ([ 'teamAbbr' , 'stDate' ]))
>>> west_top_2 . head ()
stDate teamAbbr gameWon
9 2017-10-17 GS 0
39 2017-10-18 GS 0
69 2017-10-19 GS 0
99 2017-10-20 GS 1
129 2017-10-21 GS 1
From here, you can load this DataFrame
into two ColumnDataSource
objects and visualize the race:
从这里,您可以将此DataFrame
加载到两个ColumnDataSource
对象中,并可视化种族:
Notice how the respective ColumnDataSource
objects are referenced when creating the two lines. You simply pass the original column names as input parameters and specify which ColumnDataSource
to use via the source
property.
请注意,创建这两行时,如何分别引用ColumnDataSource
对象。 您只需将原始列名作为输入参数传递,然后通过source
属性指定要使用的ColumnDataSource
。
The visualization shows the tight race throughout the season, with the Warriors building a pretty big cushion around the middle of the season. However, a bit of a late-season slide allowed the Rockets to catch up and ultimately surpass the defending champs to finish the season as the Western Conference number-one seed.
可视化显示了整个赛季的紧张比赛,勇士在整个赛季中期建立了相当大的缓冲。 然而,季后赛的一些下滑让火箭得以追赶,并最终超越了卫冕冠军,成为了西部联盟的头号种子。
Note: In Bokeh, you can specify colors either by name, hex value, or RGB color code.
注意:在散景中,您可以按名称,十六进制值或RGB颜色代码指定颜色。
For the visualization above, a color is being specified for the respective lines representing the two teams. Instead of using CSS color names like 'red'
for the Rockets and 'blue'
for the Warriors, you might have wanted to add a nice visual touch by using the official team colors in the form of hex color codes. Alternatively, you could have used tuples representing RGB color codes: (206, 17, 65)
for the Rockets, (0, 107, 182)
for the Warriors.
对于上面的可视化,正在为代表两个团队的相应行指定颜色。 与其使用CSS颜色名称(例如,火箭使用'red'
和勇士使用'blue'
,您可能不希望通过使用十六进制颜色代码形式的官方团队颜色来添加良好的视觉效果。 表示RGB颜色代码或者,可以在已使用的元组: (206, 17, 65)
为火箭, (0, 107, 182)
为勇士。
Bokeh provides a helpful list of CSS color names categorized by their general hue. Also, htmlcolorcodes.com is a great site for finding CSS, hex, and RGB color codes.
散景提供了有用CSS颜色名称列表,并按其一般色调进行了分类 。 另外, htmlcolorcodes.com是查找CSS,十六进制和RGB颜色代码的好网站。
ColumnDataSource
objects can do more than just serve as an easy way to reference DataFrame
columns. The ColumnDataSource
object has three built-in filters that can be used to create views on your data using a CDSView
object:
ColumnDataSource
对象不仅可以作为引用DataFrame
列的简便方法,还可以做更多的事情。 ColumnDataSource
对象具有三个内置过滤器,可用于使用CDSView
对象在数据上创建视图:
GroupFilter
selects rows from a ColumnDataSource
based on a categorical reference valueIndexFilter
filters the ColumnDataSource
via a list of integer indicesBooleanFilter
allows you to use a list of boolean
values, with True
rows being selectedGroupFilter
根据分类参考值从ColumnDataSource
选择行 IndexFilter
通过整数索引列表过滤ColumnDataSource
BooleanFilter
允许您使用boolean
值列表,并选择True
行 In the previous example, two ColumnDataSource
objects were created, one each from a subset of the west_top_2
DataFrame. The next example will recreate the same output from one ColumnDataSource
based on all of west_top_2
using a GroupFilter
that creates a view on the data:
在前面的示例中,创建了两个ColumnDataSource
对象,每个对象来自west_top_2
DataFrame的子集。 下一个示例将使用GroupFilter
来创建基于数据的视图,基于所有west_top_2
从一个ColumnDataSource
重新创建相同的输出:
# Bokeh libraries
# Bokeh libraries
from from bokeh.plotting bokeh.plotting import import figurefigure , , show
show
from from bokeh.io bokeh.io import import output_file
output_file
from from bokeh.models bokeh.models import import ColumnDataSourceColumnDataSource , , CDSViewCDSView , , GroupFilter
GroupFilter
# Output to file
# Output to file
output_fileoutput_file (( 'west-top-2-standings-race.html''west-top-2-standings-race.html' ,
,
titletitle == 'Western Conference Top 2 Teams Wins Race''Western Conference Top 2 Teams Wins Race' )
)
# Create a ColumnDataSource
# Create a ColumnDataSource
west_cds west_cds = = ColumnDataSourceColumnDataSource (( west_top_2west_top_2 )
)
# Create views for each team
# Create views for each team
rockets_view rockets_view = = CDSViewCDSView (( sourcesource == west_cdswest_cds ,
,
filtersfilters == [[ GroupFilterGroupFilter (( column_namecolumn_name == 'teamAbbr''teamAbbr' , , groupgroup == 'HOU''HOU' )])
)])
warriors_view warriors_view = = CDSViewCDSView (( sourcesource == west_cdswest_cds ,
,
filtersfilters == [[ GroupFilterGroupFilter (( column_namecolumn_name == 'teamAbbr''teamAbbr' , , groupgroup == 'GS''GS' )])
)])
# Create and configure the figure
# Create and configure the figure
west_fig west_fig = = figurefigure (( x_axis_typex_axis_type == 'datetime''datetime' ,
,
plot_heightplot_height == 300300 , , plot_widthplot_width == 600600 ,
,
titletitle == 'Western Conference Top 2 Teams Wins Race, 2017-18''Western Conference Top 2 Teams Wins Race, 2017-18' ,
,
x_axis_labelx_axis_label == 'Date''Date' , , y_axis_labely_axis_label == 'Wins''Wins' ,
,
toolbar_locationtoolbar_location == NoneNone )
)
# Render the race as step lines
# Render the race as step lines
west_figwest_fig .. stepstep (( 'stDate''stDate' , , 'gameWon''gameWon' ,
,
sourcesource == west_cdswest_cds , , viewview == rockets_viewrockets_view ,
,
colorcolor == '#CE1141''#CE1141' , , legendlegend == 'Rockets''Rockets' )
)
west_figwest_fig .. stepstep (( 'stDate''stDate' , , 'gameWon''gameWon' ,
,
sourcesource == west_cdswest_cds , , viewview == warriors_viewwarriors_view ,
,
colorcolor == '#006BB6''#006BB6' , , legendlegend == 'Warriors''Warriors' )
)
# Move the legend to the upper left corner
# Move the legend to the upper left corner
west_figwest_fig .. legendlegend .. location location = = 'top_left'
'top_left'
# Show the plot
# Show the plot
showshow (( west_figwest_fig )
)
Notice how the GroupFilter
is passed to CDSView
in a list. This allows you to combine multiple filters together to isolate the data you need from the ColumnDataSource
as needed.
注意如何将GroupFilter
传递到列表中的CDSView
。 这使您可以将多个过滤器组合在一起,以根据需要将所需的数据与ColumnDataSource
隔离开。
For information about integrating data sources, check out the Bokeh user guide’s post on the ColumnDataSource
and other source objects available.
有关集成数据源的信息,请查阅ColumnDataSource
和其他可用源对象上的Bokeh用户指南。
The Western Conference ended up being an exciting race, but say you want to see if the Eastern Conference was just as tight. Not only that, but you’d like to view them in a single visualization. This is a perfect segue to the next topic: layouts.
西部会议最终是一场激动人心的比赛,但您要说一下东部会议是否同样紧张。 不仅如此,您还想在一个可视化视图中查看它们。 这是下一个主题的完美选择:布局。
The Eastern Conference standings came down to two rivals in the Atlantic Division: the Boston Celtics and the Toronto Raptors. Before replicating the steps used to create west_top_2
, let’s try to put the ColumnDataSource
to the test one more time using what you learned above.
东部联盟的排名下降到了大西洋赛区的两个对手:波士顿凯尔特人队和多伦多猛龙队。 在复制用于创建west_top_2
的步骤之前,让我们尝试使用上面学到的方法west_top_2
ColumnDataSource
进行测试。
In this example, you’ll see how to feed an entire DataFrame into a ColumnDataSource
and create views to isolate the relevant data:
在此示例中,您将看到如何将整个DataFrame馈入ColumnDataSource
并创建视图以隔离相关数据:
The ColumnDataSource
was able to isolate the relevant data within a 5,040-by-39 DataFrame
without breaking a sweat, saving a few lines of Pandas code in the process.
ColumnDataSource
能够在5,040×39的DataFrame
隔离相关数据,而不会费力,在此过程中节省了几行Pandas代码。
Looking at the visualization, you can see that the Eastern Conference race was no slouch. After the Celtics roared out of the gate, the Raptors clawed all the way back to overtake their division rival and finish the regular season with five more wins.
通过可视化,您可以看到东部会议竞赛没有懈怠。 凯尔特人大吼一声后,猛龙队一路追回,超越了自己的分区对手,并在常规赛中再赢了五场胜利。
With our two visualizations ready, it’s time to put them together.
准备好我们的两个可视化之后,是时候将它们放在一起了。
Similar to the functionality of Matplotlib’s subplot
, Bokeh offers the column
, row
, and gridplot
functions in its bokeh.layouts
module. These functions can more generally be classified as layouts.
与Matplotlib subplot
的功能相似,Bokeh在其bokeh.layouts
模块中提供了column
, row
和gridplot
功能。 这些功能通常可以归类为布局 。
The usage is very straightforward. If you want to put two visualizations in a vertical configuration, you can do so with the following:
用法非常简单。 如果要垂直放置两个可视化文件,可以使用以下方法:
# Bokeh library
# Bokeh library
from from bokeh.plotting bokeh.plotting import import figurefigure , , show
show
from from bokeh.io bokeh.io import import output_file
output_file
from from bokeh.layouts bokeh.layouts import import column
column
# Output to file
# Output to file
output_fileoutput_file (( 'east-west-top-2-standings-race.html''east-west-top-2-standings-race.html' ,
,
titletitle == 'Conference Top 2 Teams Wins Race''Conference Top 2 Teams Wins Race' )
)
# Plot the two visualizations in a vertical configuration
# Plot the two visualizations in a vertical configuration
showshow (( columncolumn (( west_figwest_fig , , east_figeast_fig ))
))
I’ll save you the two lines of code, but rest assured that swapping column
for row
in the snippet above will similarly configure the two plots in a horizontal configuration.
我将为您节省两行代码,但是请放心,上面代码段中的column
换row
类似地将两个图配置为水平配置。
Note: If you’re trying out the code snippets as you go through the tutorial, I want to take a quick detour to address an error you may see accessing west_fig
and east_fig
in the following examples. In doing so, you may receive an error like this:
注意:如果您在遍历本教程时正在尝试代码段,那么我想快速绕过一个错误,以解决在以下示例中访问west_fig
和east_fig
的错误。 这样做时,您可能会收到如下错误:
This is one of many errors that are part of Bokeh’s validation module, where w-1004
in particular is warning about the re-use of west_fig
and east_fig
in a new layout.
这是Bokeh 验证模块中的许多错误之一,其中w-1004
特别警告有关在新布局中重新使用west_fig
和east_fig
警告。
To avoid this error as you test the examples, preface the code snippet illustrating each layout with the following:
为了避免在测试示例时出现此错误,请在代码段前添加说明每个布局的代码:
# Bokeh libraries
# Bokeh libraries
from from bokeh.plotting bokeh.plotting import import figurefigure , , show
show
from from bokeh.models bokeh.models import import ColumnDataSourceColumnDataSource , , CDSViewCDSView , , GroupFilter
GroupFilter
# Create a ColumnDataSource
# Create a ColumnDataSource
standings_cds standings_cds = = ColumnDataSourceColumnDataSource (( standingsstandings )
)
# Create the views for each team
# Create the views for each team
celtics_view celtics_view = = CDSViewCDSView (( sourcesource == standings_cdsstandings_cds ,
,
filtersfilters == [[ GroupFilterGroupFilter (( column_namecolumn_name == 'teamAbbr''teamAbbr' ,
,
groupgroup == 'BOS''BOS' )])
)])
raptors_view raptors_view = = CDSViewCDSView (( sourcesource == standings_cdsstandings_cds ,
,
filtersfilters == [[ GroupFilterGroupFilter (( column_namecolumn_name == 'teamAbbr''teamAbbr' ,
,
groupgroup == 'TOR''TOR' )])
)])
rockets_view rockets_view = = CDSViewCDSView (( sourcesource == standings_cdsstandings_cds ,
,
filtersfilters == [[ GroupFilterGroupFilter (( column_namecolumn_name == 'teamAbbr''teamAbbr' ,
,
groupgroup == 'HOU''HOU' )])
)])
warriors_view warriors_view = = CDSViewCDSView (( sourcesource == standings_cdsstandings_cds ,
,
filtersfilters == [[ GroupFilterGroupFilter (( column_namecolumn_name == 'teamAbbr''teamAbbr' ,
,
groupgroup == 'GS''GS' )])
)])
# Create and configure the figure
# Create and configure the figure
east_fig east_fig = = figurefigure (( x_axis_typex_axis_type == 'datetime''datetime' ,
,
plot_heightplot_height == 300300 ,
,
x_axis_labelx_axis_label == 'Date''Date' ,
,
y_axis_labely_axis_label == 'Wins''Wins' ,
,
toolbar_locationtoolbar_location == NoneNone )
)
west_fig west_fig = = figurefigure (( x_axis_typex_axis_type == 'datetime''datetime' ,
,
plot_heightplot_height == 300300 ,
,
x_axis_labelx_axis_label == 'Date''Date' ,
,
y_axis_labely_axis_label == 'Wins''Wins' ,
,
toolbar_locationtoolbar_location == NoneNone )
)
# Configure the figures for each conference
# Configure the figures for each conference
east_figeast_fig .. stepstep (( 'stDate''stDate' , , 'gameWon''gameWon' ,
,
colorcolor == '#007A33''#007A33' , , legendlegend == 'Celtics''Celtics' ,
,
sourcesource == standings_cdsstandings_cds , , viewview == celtics_viewceltics_view )
)
east_figeast_fig .. stepstep (( 'stDate''stDate' , , 'gameWon''gameWon' ,
,
colorcolor == '#CE1141''#CE1141' , , legendlegend == 'Raptors''Raptors' ,
,
sourcesource == standings_cdsstandings_cds , , viewview == raptors_viewraptors_view )
)
west_figwest_fig .. stepstep (( 'stDate''stDate' , , 'gameWon''gameWon' , , colorcolor == '#CE1141''#CE1141' , , legendlegend == 'Rockets''Rockets' ,
,
sourcesource == standings_cdsstandings_cds , , viewview == rockets_viewrockets_view )
)
west_figwest_fig .. stepstep (( 'stDate''stDate' , , 'gameWon''gameWon' , , colorcolor == '#006BB6''#006BB6' , , legendlegend == 'Warriors''Warriors' ,
,
sourcesource == standings_cdsstandings_cds , , viewview == warriors_viewwarriors_view )
)
# Move the legend to the upper left corner
# Move the legend to the upper left corner
east_figeast_fig .. legendlegend .. location location = = 'top_left'
'top_left'
west_figwest_fig .. legendlegend .. location location = = 'top_left'
'top_left'
# Layout code snippet goes here!
# Layout code snippet goes here!
Doing so will renew the relevant components to render the visualization, ensuring that no warning is needed.
这样做将更新相关组件以呈现可视化效果,从而确保不需要警告。
Instead of using column
or row
, you may want to use a gridplot
instead.
除了使用column
或row
,您可能还想使用gridplot
。
One key difference of gridplot
is that it will automatically consolidate the toolbar across all of its children figures. The two visualizations above do not have a toolbar, but if they did, then each figure would have its own when using column
or row
. With that, it also has its own toolbar_location
property, seen below set to 'right'
.
gridplot
一个主要区别是它将自动合并其所有子图中的工具栏。 上面的两个可视化没有工具栏,但是如果有的话,那么当使用column
或row
时,每个图形都将具有自己的图形。 这样,它还具有自己的工具toolbar_location
属性,下面将其设置为'right'
。
Syntactically, you’ll also notice below that gridplot
differs in that, instead of being passed a tuple as input, it requires a list of lists, where each sub-list represents a row in the grid:
语法上,您还会在下面注意到gridplot
不同之处在于,它不需要传递元组作为输入,而是需要一个列表列表,其中每个子列表代表网格中的一行:
Lastly, gridplot
allows the passing of None
values, which are interpreted as blank subplots. Therefore, if you wanted to leave a placeholder for two additional plots, then you could do something like this:
最后, gridplot
允许传递None
值,这些值被解释为空白子图。 因此,如果您想为两个额外的图块保留一个占位符,则可以执行以下操作:
# Bokeh libraries
# Bokeh libraries
from from bokeh.io bokeh.io import import output_file
output_file
from from bokeh.layouts bokeh.layouts import import gridplot
gridplot
# Output to file
# Output to file
output_fileoutput_file (( 'east-west-top-2-gridplot.html''east-west-top-2-gridplot.html' ,
,
titletitle == 'Conference Top 2 Teams Wins Race''Conference Top 2 Teams Wins Race' )
)
# Reduce the width of both figures
# Reduce the width of both figures
east_figeast_fig .. plot_width plot_width = = west_figwest_fig .. plot_width plot_width = = 300
300
# Edit the titles
# Edit the titles
east_figeast_fig .. titletitle .. text text = = 'Eastern Conference'
'Eastern Conference'
west_figwest_fig .. titletitle .. text text = = 'Western Conference'
'Western Conference'
# Plot the two visualizations with placeholders
# Plot the two visualizations with placeholders
east_west_gridplot east_west_gridplot = = gridplotgridplot ([[([[ west_figwest_fig , , NoneNone ], ], [[ NoneNone , , east_figeast_fig ]],
]],
toolbar_locationtoolbar_location == 'right''right' )
)
# Plot the two visualizations in a horizontal configuration
# Plot the two visualizations in a horizontal configuration
showshow (( east_west_gridploteast_west_gridplot )
)
If you’d rather toggle between both visualizations at their full size without having to squash them down to fit next to or on top of each other, a good option is a tabbed layout.
如果您希望在两个可视化文件之间进行全尺寸切换,而不必将它们压缩到彼此相邻或重叠的位置,则选项卡式布局是一个不错的选择。
A tabbed layout consists of two Bokeh widget functions: Tab()
and Panel()
from the bokeh.models.widgets
sub-module. Like using gridplot()
, making a tabbed layout is pretty straightforward:
一个选项卡式布局包含两个Bokeh小部件功能: bokeh.models.widgets
子模块中的Tab()
和Panel()
。 就像使用gridplot()
,制作选项卡式布局非常简单:
The first step is to create a Panel()
for each tab. That may sound a little confusing, but think of the Tabs()
function as the mechanism that organizes the individual tabs created with Panel()
.
第一步是为每个选项卡创建一个Panel()
。 这听起来可能有些混乱,但是可以将Tabs()
函数视为一种组织由Panel()
创建的单个选项卡的机制。
Each Panel()
takes as input a child, which can either be a single figure()
or a layout. (Remember that a layout is a general name for a column
, row
, or gridplot
.) Once your panels are assembled, they can be passed as input to Tabs()
in a list.
每个Panel()
将一个孩子作为输入,该孩子可以是一个figure()
或一个布局。 (请记住,布局是column
, row
或gridplot
的通用名称。)组装面板后,可以将其作为输入传递到列表中的Tabs()
。
Now that you understand how to access, draw, and organize your data, it’s time to move on to the real magic of Bokeh: interaction! As always, check out Bokeh’s User Guide for more information on layouts.
现在您已经了解了如何访问,绘制和组织数据,现在该继续学习Bokeh的真正魔力:交互! 与往常一样,请查阅《 Bokeh用户指南》以获取有关布局的更多信息。
The feature that sets Bokeh apart is its ability to easily implement interactivity in your visualization. Bokeh even goes as far as describing itself as an interactive visualization library:
使Bokeh与众不同的功能是可以轻松实现可视化交互性的功能。 Bokeh甚至将自己描述为一个交互式可视化库 :
Bokeh is an interactive visualization library that targets modern web browsers for presentation. (Source)
Bokeh是一个交互式可视化库,面向现代Web浏览器进行演示。 ( 来源 )
In this section, we’ll touch on five ways that you can add interactivity:
在本节中,我们将介绍添加交互性的五种方法:
Implementing these interactive elements open up possibilities for exploring your data that static visualizations just can’t do by themselves.
实施这些交互式元素将为探索数据提供了可能性,而静态可视化本身是无法做到的。
As you saw all the way back in Generating Your First Figure, the default Bokeh figure()
comes with a toolbar right out of the box. The default toolbar comes with the following tools (from left to right):
正如您在“ 生成第一个图形”中所看到的一样,默认的Bokeh figure()
带有一个现成的工具栏。 默认工具栏带有以下工具(从左到右):
The toolbar can be removed by passing toolbar_location=None
when instantiating a figure()
object, or relocated by passing any of 'above'
, 'below'
, 'left'
, or 'right'
.
可以在实例化figure()
对象时通过传递toolbar_location=None
来删除工具栏,或者通过传递'above'
, 'below'
, 'left'
或'right'
任何一个来重新定位工具栏。
Additionally, the toolbar can be configured to include any combination of tools you desire. Bokeh offers 18 specific tools across five categories:
此外,工具栏可以配置为包括所需工具的任何组合。 散景提供五个类别的18种特定工具:
box_select
, box_zoom
, lasso_select
, pan
, xpan
, ypan
, resize_select
poly_select
, tap
wheel_zoom
, xwheel_zoom
, ywheel_zoom
undo
, redo
, reset
, save
crosshair
, hover
box_select
, box_zoom
, lasso_select
, pan
, xpan
, ypan
, resize_select
poly_select
, tap
wheel_zoom
: wheel_zoom
, xwheel_zoom
, ywheel_zoom
undo
, redo
, reset
, save
crosshair
, hover
To geek out on tools , make sure to visit Specifying Tools. Otherwise, they’ll be illustrated in covering the various interactions covered herein.
要了解各种工具,请确保访问“ 指定工具” 。 否则,将在涵盖本文涵盖的各种交互中进行说明。
Implementing selection behavior is as easy as adding a few specific keywords when declaring your glyphs.
声明字形时,实现选择行为就像添加几个特定的关键字一样容易。
The next example will create a scatter plot that relates a player’s total number of three-point shot attempts to the percentage made (for players with at least 100 three-point shot attempts).
下一个示例将创建一个散点图,该散点图将玩家的三分球尝试总数与所做出的百分比相关联(对于至少进行100次三分球尝试的玩家)。
The data can be aggregated from the player_stats
DataFrame:
数据可以从player_stats
DataFrame中汇总:
# Find players who took at least 1 three-point shot during the season
# Find players who took at least 1 three-point shot during the season
three_takers three_takers = = player_statsplayer_stats [[ player_statsplayer_stats [[ 'play3PA''play3PA' ] ] > > 00 ]
]
# Clean up the player names, placing them in a single column
# Clean up the player names, placing them in a single column
three_takersthree_takers [[ 'name''name' ] ] = = [[ ff '' {p["playFNm"]}{p["playFNm"]} {p["playLNm"]}{p["playLNm"]} '
'
for for __ , , p p in in three_takersthree_takers .. iterrowsiterrows ()]
()]
# Aggregate the total three-point attempts and makes for each player
# Aggregate the total three-point attempts and makes for each player
three_takers three_takers = = (( three_takersthree_takers .. groupbygroupby (( 'name''name' )
)
.. sumsum ()
()
.. locloc [:,[[:,[ 'play3PA''play3PA' , , 'play3PM''play3PM' ]]
]]
.. sort_valuessort_values (( 'play3PA''play3PA' , , ascendingascending == FalseFalse ))
))
# Filter out anyone who didn't take at least 100 three-point shots
# Filter out anyone who didn't take at least 100 three-point shots
three_takers three_takers = = three_takersthree_takers [[ three_takersthree_takers [[ 'play3PA''play3PA' ] ] >= >= 100100 ]] .. reset_indexreset_index ()
()
# Add a column with a calculated three-point percentage (made/attempted)
# Add a column with a calculated three-point percentage (made/attempted)
three_takersthree_takers [[ 'pct3PM''pct3PM' ] ] = = three_takersthree_takers [[ 'play3PM''play3PM' ] ] / / three_takersthree_takers [[ 'play3PA''play3PA' ]
]
Here’s a sample of the resulting DataFrame
:
这是生成的DataFrame
的示例:
>>> three_takers . sample ( 5 )
name play3PA play3PM pct3PM
229 Corey Brewer 110 31 0.281818
78 Marc Gasol 320 109 0.340625
126 Raymond Felton 230 81 0.352174
127 Kristaps Porziņģis 229 90 0.393013
66 Josh Richardson 336 127 0.377976
Let’s say you want to select a groups of players in the distribution, and in doing so mute the color of the glyphs representing the non-selected players:
假设您要选择分布中的一组玩家,并以此静音代表未选中玩家的字形的颜色:
First, specify the selection tools you want to make available. In the example above, 'box_select'
, 'lasso_select'
, 'poly_select'
, and 'tap'
(plus a reset button) were specified in a list called select_tools
. When the figure is instantiated, the toolbar is positioned 'below'
the plot, and the list is passed to tools
to make the tools selected above available.
首先,指定要使用的选择工具。 在上面的示例中,在名为select_tools
的列表中指定了'box_select'
, 'lasso_select'
, 'poly_select'
和'tap'
(加上复位按钮)。 实例化图形后,工具栏将位于图形的'below'
,并且列表将传递给tools
以使上面选择的工具可用。
Each player is initially represented by a royal blue square glyph, but the following configurations are set for when a player or group of players is selected:
每个玩家最初都由宝蓝色方块字形表示,但是在选择一个或多个玩家组时会设置以下配置:
deepskyblue
lightgray
color with 0.3
opacity deepskyblue
0.3
不透明0.3
的lightgray
灰色 That’s it! With just a few quick additions, the visualization now looks like this:
而已! 只需快速添加几下,可视化现在看起来像这样:
For even more information about what you can do upon selection, check out Selected and Unselected Glyphs.
有关选择时可以执行的操作的更多信息,请查看选定和未选定字形 。
So the ability to select specific player data points that seem of interest in my scatter plot is implemented, but what if you want to quickly see what individual players a glyph represents? One option is to use Bokeh’s HoverTool()
to show a tooltip when the cursor crosses paths with a glyph. All you need to do is append the following to the code snippet above:
因此,实现了选择散点图中似乎感兴趣的特定玩家数据点的功能,但是如果您想快速查看一个字形代表的是哪个玩家,该怎么办? 一种选择是使用Bokeh的HoverTool()
在光标带有字形的路径上显示工具提示。 您需要做的就是将以下内容添加到上面的代码片段中:
# Bokeh Library
# Bokeh Library
from from bokeh.models bokeh.models import import HoverTool
HoverTool
# Format the tooltip
# Format the tooltip
tooltips tooltips = = [
[
(( 'Player''Player' ,, '@name''@name' ),
),
(( 'Three-Pointers Made''Three-Pointers Made' , , '@play3PM''@play3PM' ),
),
(( 'Three-Pointers Attempted''Three-Pointers Attempted' , , '@play3PA''@play3PA' ),
),
(( 'Three-Point Percentage''Three-Point Percentage' ,, '@pct3PM{00.0%}''@pct3PM{00.0%}' ),
),
]
]
# Add the HoverTool to the figure
# Add the HoverTool to the figure
figfig .. add_toolsadd_tools (( HoverToolHoverTool (( tooltipstooltips == tooltipstooltips ))
))
# Visualize
# Visualize
showshow (( figfig )
)
The HoverTool()
is slightly different than the selection tools you saw above in that it has properties, specifically tooltips
.
HoverTool()
与上面的选择工具略有不同,因为它具有属性,特别是tooltips
。
First, you can configure a formatted tooltip by creating a list of tuples containing a description and reference to the ColumnDataSource
. This list was passed as input to the HoverTool()
and then simply added to the figure using add_tools()
. Here’s what happened:
首先,您可以通过创建包含描述和对ColumnDataSource
引用的元组列表来配置格式化的工具提示。 该列表作为输入传递到HoverTool()
,然后使用add_tools()
简单地添加到图中。 这是发生了什么:
Notice the addition of the Hover button to the toolbar, which can be toggled on and off.
请注意,在工具栏上添加了“悬停”按钮,可以将其打开和关闭。
If you want to even further emphasize the players on hover, Bokeh makes that possible with hover inspections. Here is a slightly modified version of the code snippet that added the tooltip:
如果您想在悬停上进一步强调玩家,Bokeh可以通过悬停检查来实现这一点。 这是添加了工具提示的代码片段的稍作修改的版本:
This is done by creating a completely new glyph, in this case circles instead of squares, and assigning it to hover_glyph
. Note that the initial opacity is set to zero so that it is invisible until the cursor is touching it. The properties that appear upon hover are captured by setting hover_alpha
to 0.5
along with the hover_fill_color
.
这是通过创建一个全新的字形(在这种情况下为圆形而不是正方形)并将其分配给hover_glyph
来hover_glyph
。 请注意,初始不透明度设置为零,以便直到光标触摸它时才可见。 出现在悬停的属性由设置捕获hover_alpha
到0.5
与沿hover_fill_color
。
Now you will see a small black circle appear over the original square when hovering over the various markers:
现在,将鼠标悬停在各种标记上时,您会看到一个小的黑色圆圈出现在原始正方形上:
To further explore the capabilities of the HoverTool()
, see the HoverTool and Hover Inspections guides.
要进一步探索HoverTool()
,请参阅HoverTool和Hover检查指南。
Linking is the process of syncing elements of different visualizations within a layout. For instance, maybe you want to link the axes of multiple plots to ensure that if you zoom in on one it is reflected on another. Let’s see how it is done.
链接是同步布局中不同可视化元素的过程。 例如,也许您想链接多个图的轴,以确保如果放大一个图,它会反映在另一个图上。 让我们看看它是如何完成的。
For this example, the visualization will be able to pan to different segments of a team’s schedule and examine various game stats. Each stat will be represented by its own plot in a two-by-two gridplot()
.
对于此示例,可视化将能够平移团队进度表的不同部分并检查各种游戏统计信息。 每个stat将由其自己的图以2 x 2 gridplot()
。
The data can be collected from the team_stats
DataFrame, selecting the Philadelphia 76ers as the team of interest:
可以从team_stats
DataFrame收集数据,选择费城76人队作为关注的球队:
# Isolate relevant data
# Isolate relevant data
phi_gm_stats phi_gm_stats = = (( team_statsteam_stats [([( team_statsteam_stats [[ 'teamAbbr''teamAbbr' ] ] == == 'PHI''PHI' ) ) &
&
(( team_statsteam_stats [[ 'seasTyp''seasTyp' ] ] == == 'Regular''Regular' )]
)]
.. locloc [:, [:, [[ 'gmDate''gmDate' ,
,
'teamPTS''teamPTS' ,
,
'teamTRB''teamTRB' ,
,
'teamAST''teamAST' ,
,
'teamTO''teamTO' ,
,
'opptPTS''opptPTS' ,]]
,]]
.. sort_valuessort_values (( 'gmDate''gmDate' ))
))
# Add game number
# Add game number
phi_gm_statsphi_gm_stats [[ 'game_num''game_num' ] ] = = rangerange (( 11 , , lenlen (( phi_gm_statsphi_gm_stats )) ++ 11 )
)
# Derive a win_loss column
# Derive a win_loss column
win_loss win_loss = = []
[]
for for __ , , row row in in phi_gm_statsphi_gm_stats .. iterrowsiterrows ():
():
# If the 76ers score more points, it's a win
# If the 76ers score more points, it's a win
if if rowrow [[ 'teamPTS''teamPTS' ] ] > > rowrow [[ 'opptPTS''opptPTS' ]:
]:
win_losswin_loss .. appendappend (( 'W''W' )
)
elseelse :
:
win_losswin_loss .. appendappend (( 'L''L' )
)
# Add the win_loss data to the DataFrame
# Add the win_loss data to the DataFrame
phi_gm_statsphi_gm_stats [[ 'winLoss''winLoss' ] ] = = win_loss
win_loss
Here are the results of the 76ers’ first 5 games:
以下是76人队前5场比赛的结果:
>>> phi_gm_stats . head ()
gmDate teamPTS teamTRB teamAST teamTO opptPTS game_num winLoss
10 2017-10-18 115 48 25 17 120 1 L
39 2017-10-20 92 47 20 17 102 2 L
52 2017-10-21 94 41 18 20 128 3 L
80 2017-10-23 97 49 25 21 86 4 W
113 2017-10-25 104 43 29 16 105 5 L
Start by importing the necessary Bokeh libraries, specifying the output parameters, and reading the data into a ColumnDataSource
:
首先导入必要的Bokeh库,指定输出参数,然后将数据读取到ColumnDataSource
:
Each game is represented by a column, and will be colored green if the result was a win and red for a loss. To accomplish this, Bokeh’s CategoricalColorMapper
can be used to map the data values to specified colors:
每个游戏都由一列表示,如果结果是获胜,则将颜色涂成绿色,而将失败的颜色涂成红色。 为此,可以使用Bokeh的CategoricalColorMapper
将数据值映射到指定的颜色:
# Create a CategoricalColorMapper that assigns a color to wins and losses
# Create a CategoricalColorMapper that assigns a color to wins and losses
win_loss_mapper win_loss_mapper = = CategoricalColorMapperCategoricalColorMapper (( factors factors = = [[ 'W''W' , , 'L''L' ],
],
palettepalette == [[ 'green''green' , , 'red''red' ])
])
For this use case, a list specifying the categorical data values to be mapped is passed to factors
and a list with the intended colors to palette
. For more on the CategoricalColorMapper
, see the Colors section of Handling Categorical Data on Bokeh’s User Guide.
对于此用例,将指定要映射的分类数据值的列表传递给factors
,将具有预期颜色的列表传递给palette
。 有关CategoricalColorMapper
更多信息,请参阅《 Bokeh用户指南》中的“ 处理分类数据”的“ 颜色”部分。
There are four stats to visualize in the two-by-two gridplot
: points, assists, rebounds, and turnovers. In creating the four figures and configuring their respective charts, there is a lot of redundancy in the properties. So to streamline the code a for
loop can be used:
在2 x 2的gridplot
可以看到四个统计数据:得分,助攻,篮板和失误。 在创建四个图形并配置它们各自的图表时,属性中存在很多冗余。 因此,为了简化代码for
可以使用for
循环:
As you can see, the only parameters that needed to be adjusted were the y-axis-label
of the figure and the data that will dictate top
in the vbar
. These values were easily stored in a dict
that was iterated through to create the figures for each stat.
如您所见,唯一需要调整的参数是图形的y-axis-label
和指示vbar
top
的vbar
。 这些值可以轻松地存储在dict
,并对其进行迭代以创建每个统计数据。
You can also see the implementation of the CategoricalColorMapper
in the configuration of the vbar
glyph. The color
property is passed a dict
with the field in the ColumnDataSource
to be mapped and the name of the CategoricalColorMapper
created above.
您还可以在vbar
字形的配置中看到CategoricalColorMapper
的实现。 的color
属性被传递一个dict
与在该领域ColumnDataSource
映射和名称CategoricalColorMapper
上面创建。
The initial view will only show the first 10 games of the 76ers’ season, so there needs to be a way to pan horizontally to navigate through the rest of the games in the season. Thus configuring the toolbar to have an xpan
tool allows panning throughout the plot without having to worry about accidentally skewing the view along the vertical axis.
初始视图仅显示76ers赛季的前10场比赛,因此需要有一种水平移动以浏览本赛季其余比赛的方法。 因此,将工具栏配置为具有xpan
工具可以平移整个图,而不必担心会意外地沿垂直轴倾斜视图。
Now that the figures are created, gridplot
can be setup by referencing the figures from the dict
created above:
现在已经创建了图,可以通过参考上面创建的dict
的图来设置gridplot
:
# Create layout
# Create layout
grid grid = = gridplotgridplot ([[([[ stat_figsstat_figs [[ 'Points''Points' ], ], stat_figsstat_figs [[ 'Assists''Assists' ]],
]],
[[ stat_figsstat_figs [[ 'Rebounds''Rebounds' ], ], stat_figsstat_figs [[ 'Turnovers''Turnovers' ]]])
]]])
Linking the axes of the four plots is as simple as setting the x_range
of each figure equal to one another:
链接四个图的轴非常简单, x_range
将每个图形的x_range
设置为彼此相等即可:
To add a title bar to the visualization, you could have tried to do this on the points figure, but it would have been limited to the space of that figure. Therefore, a nice trick is to use Bokeh’s ability to interpret HTML to insert a Div
element that contains the title information. Once that is created, simply combine that with the gridplot()
in a column
layout:
要将标题栏添加到可视化中,您可以尝试在点图上执行此操作,但仅限于该图的空间。 因此,一个不错的技巧是使用Bokeh的解释HTML的功能来插入包含标题信息的Div
元素。 创建后,只需将其与gridplot()
成column
布局即可:
# Add a title for the entire visualization using Div
# Add a title for the entire visualization using Div
html html = = """Philadelphia 76ers Game Log
"""Philadelphia 76ers Game Log
2017-18 Regular Season
2017-18 Regular Season
Wins in green, losses in red
Wins in green, losses in red
"""
"""
sup_title sup_title = = DivDiv (( texttext == htmlhtml )
)
# Visualize
# Visualize
showshow (( columncolumn (( sup_titlesup_title , , gridgrid ))
))
Putting all the pieces together results in the following:
将所有部分放在一起将得到以下结果:
Similarly you can easily implement linked selections, where a selection on one plot will be reflected on others.
同样,您可以轻松实现链接的选择,其中一个图上的选择将反映在其他图上。
To see how this works, the next visualization will contain two scatter plots: one that shows the 76ers’ two-point versus three-point field goal percentage and the other showing the 76ers’ team points versus opponent points on a game-by-game basis.
若要查看其工作原理,下一个可视化将包含两个散点图:一个显示76ers的两分球命中率与三分球的投篮命中率百分比,另一个显示每个游戏中76ers的队得分与对手分的比率基础。
The goal is to be able to select data points on the left-side scatter plot and quickly be able to recognize if the corresponding datapoint on the right scatter plot is a win or loss.
目的是能够在左侧散点图上选择数据点,并能够快速识别右侧散点图上的相应数据点是赢还是输。
The DataFrame for this visualization is very similar to that from the first example:
此可视化的DataFrame与第一个示例非常相似:
Here’s what the data looks like:
数据如下所示:
>>> phi_gm_stats_2.head()
gmDate team2P% team3P% teamPTS opptPTS game_num winLoss
10 2017-10-18 0.4746 0.4286 115 120 1 L
39 2017-10-20 0.4167 0.3125 92 102 2 L
52 2017-10-21 0.4138 0.3333 94 128 3 L
80 2017-10-23 0.5098 0.3750 97 86 4 W
113 2017-10-25 0.5082 0.3333 104 105 5 L
The code to create the visualization is as follows:
创建可视化的代码如下:
# Bokeh Libraries
# Bokeh Libraries
from from bokeh.plotting bokeh.plotting import import figurefigure , , show
show
from from bokeh.io bokeh.io import import output_file
output_file
from from bokeh.models bokeh.models import import ColumnDataSourceColumnDataSource , , CategoricalColorMapperCategoricalColorMapper , , NumeralTickFormatter
NumeralTickFormatter
from from bokeh.layouts bokeh.layouts import import gridplot
gridplot
# Output inline in the notebook
# Output inline in the notebook
output_fileoutput_file (( 'phi-gm-linked-selections.html''phi-gm-linked-selections.html' ,
,
titletitle == '76ers Percentages vs. Win-Loss''76ers Percentages vs. Win-Loss' )
)
# Store the data in a ColumnDataSource
# Store the data in a ColumnDataSource
gm_stats_cds gm_stats_cds = = ColumnDataSourceColumnDataSource (( phi_gm_stats_2phi_gm_stats_2 )
)
# Create a CategoricalColorMapper that assigns specific colors to wins and losses
# Create a CategoricalColorMapper that assigns specific colors to wins and losses
win_loss_mapper win_loss_mapper = = CategoricalColorMapperCategoricalColorMapper (( factors factors = = [[ 'W''W' , , 'L''L' ], ], palettepalette == [[ 'Green''Green' , , 'Red''Red' ])
])
# Specify the tools
# Specify the tools
toolList toolList = = [[ 'lasso_select''lasso_select' , , 'tap''tap' , , 'reset''reset' , , 'save''save' ]
]
# Create a figure relating the percentages
# Create a figure relating the percentages
pctFig pctFig = = figurefigure (( titletitle == '2PT FG % vs 3PT FG %, 2017-18 Regular Season''2PT FG % vs 3PT FG %, 2017-18 Regular Season' ,
,
plot_heightplot_height == 400400 , , plot_widthplot_width == 400400 , , toolstools == toolListtoolList ,
,
x_axis_labelx_axis_label == '2PT FG%''2PT FG%' , , y_axis_labely_axis_label == '3PT FG%''3PT FG%' )
)
# Draw with circle markers
# Draw with circle markers
pctFigpctFig .. circlecircle (( xx == 'team2P%''team2P%' , , yy == 'team3P%''team3P%' , , sourcesource == gm_stats_cdsgm_stats_cds ,
,
sizesize == 1212 , , colorcolor == 'black''black' )
)
# Format the y-axis tick labels as percenages
# Format the y-axis tick labels as percenages
pctFigpctFig .. xaxisxaxis [[ 00 ]] .. formatter formatter = = NumeralTickFormatterNumeralTickFormatter (( formatformat == '00.0%''00.0%' )
)
pctFigpctFig .. yaxisyaxis [[ 00 ]] .. formatter formatter = = NumeralTickFormatterNumeralTickFormatter (( formatformat == '00.0%''00.0%' )
)
# Create a figure relating the totals
# Create a figure relating the totals
totFig totFig = = figurefigure (( titletitle == 'Team Points vs Opponent Points, 2017-18 Regular Season''Team Points vs Opponent Points, 2017-18 Regular Season' ,
,
plot_heightplot_height == 400400 , , plot_widthplot_width == 400400 , , toolstools == toolListtoolList ,
,
x_axis_labelx_axis_label == 'Team Points''Team Points' , , y_axis_labely_axis_label == 'Opponent Points''Opponent Points' )
)
# Draw with square markers
# Draw with square markers
totFigtotFig .. squaresquare (( xx == 'teamPTS''teamPTS' , , yy == 'opptPTS''opptPTS' , , sourcesource == gm_stats_cdsgm_stats_cds , , sizesize == 1010 ,
,
colorcolor == dictdict (( fieldfield == 'winLoss''winLoss' , , transformtransform == win_loss_mapperwin_loss_mapper ))
))
# Create layout
# Create layout
grid grid = = gridplotgridplot ([[([[ pctFigpctFig , , totFigtotFig ]])
]])
# Visualize
# Visualize
showshow (( gridgrid )
)
This is a great illustration of the power in using a ColumnDataSource
. As long as the glyph renderers (in this case, the circle
glyphs for the percentages, and square
glyphs for the wins and losses) share the same ColumnDataSource
, then the selections will be linked by default.
这很好地说明了使用ColumnDataSource
的强大功能。 只要字形渲染器(在这种情况下,百分比的circle
字形和获胜和损失的square
字形)共享相同的ColumnDataSource
,则默认情况下将链接选择。
Here’s how it looks in action, where you can see selections made on either figure will be reflected on the other:
这是实际的外观,您可以看到在任一图上所做的选择都会反映在另一图上:
By selecting a random sample of data points in the upper right quadrant of the left scatter plot, those corresponding to both high two-point and three-point field goal percentage, the data points on the right scatter plot are highlighted.
通过在左散点图的右上象限中选择数据点的随机样本(对应于较高的两点和三点射门得分百分比),将突出显示右散点图上的数据点。
Similarly, selecting data points on the right scatter plot that correspond to losses tend to be further to the lower left, lower shooting percentages, on the left scatter plot.
同样,在右侧散点图上选择与损失相对应的数据点往往会更靠近左侧散点图上的左下,较低的射击百分比。
All the details on linking plots can be found at Linking Plots in the Bokeh User Guide.
有关链接图的所有详细信息,请参见《 Bokeh用户指南》中的“ 链接图 ”。
That brings us to the final interactivity example in this tutorial: interactive legends.
这使我们进入了本教程中的最终交互性示例:交互式图例。
In the Drawing Data With Glyphs section, you saw how easy it is to implement a legend when creating your plot. With the legend in place, adding interactivity is merely a matter of assigning a click_policy
. Using a single line of code, you can quickly add the ability to either hide
or mute
data using the legend.
在使用字形绘制数据部分中,您看到了在创建图形时实现图例很容易。 有了图例,添加交互性仅是分配click_policy
。 使用单行代码,您可以快速添加使用图例hide
或mute
数据的功能。
In this example, you’ll see two identical scatter plots comparing the game-by-game points and rebounds of LeBron James and Kevin Durant. The only difference will be that one will use a hide
as its click_policy
, while the other uses mute
.
在此示例中,您将看到两个相同的散点图,用于比较勒布朗·詹姆斯和凯文·杜randint的逐场得分和篮板。 唯一的区别将是一个会用一个hide
其click_policy
,而其他用途mute
。
The first step is to configure the output and set up the data, creating a view for each player from the player_stats
DataFrame:
第一步是配置输出并设置数据,从player_stats
DataFrame为每个玩家创建一个视图:
Before creating the figures, the common parameters across the figure, markers, and data can be consolidated into dictionaries and reused. Not only does this save redundancy in the next step, but it provides an easy way to tweak these parameters later if need be:
在创建图形之前,可以将图形,标记和数据上的通用参数合并为字典并重新使用。 这不仅可以节省下一步的冗余,而且还提供了一种简便的方法,可以在以后需要时调整这些参数:
# Consolidate the common keyword arguments in dicts
# Consolidate the common keyword arguments in dicts
common_figure_kwargs common_figure_kwargs = = {
{
'plot_width''plot_width' : : 400400 ,
,
'x_axis_label''x_axis_label' : : 'Points''Points' ,
,
'toolbar_location''toolbar_location' : : NoneNone ,
,
}
}
common_circle_kwargs common_circle_kwargs = = {
{
'x''x' : : 'playPTS''playPTS' ,
,
'y''y' : : 'playTRB''playTRB' ,
,
'source''source' : : player_gm_statsplayer_gm_stats ,
,
'size''size' : : 1212 ,
,
'alpha''alpha' : : 0.70.7 ,
,
}
}
common_lebron_kwargs common_lebron_kwargs = = {
{
'view''view' : : lebron_viewlebron_view ,
,
'color''color' : : '#002859''#002859' ,
,
'legend''legend' : : 'LeBron James'
'LeBron James'
}
}
common_durant_kwargs common_durant_kwargs = = {
{
'view''view' : : durant_viewdurant_view ,
,
'color''color' : : '#FFC324''#FFC324' ,
,
'legend''legend' : : 'Kevin Durant'
'Kevin Durant'
}
}
Now that the various properties are set, the two scatter plots can be built in a much more concise fashion:
现在已经设置了各种属性,可以以更加简洁的方式构建两个散点图:
Note that mute_fig
has an extra parameter called muted_alpha
. This parameter controls the opacity of the markers when mute
is used as the click_policy
.
请注意, mute_fig
还有一个额外的参数,称为muted_alpha
。 该参数控制标记的不透明度时mute
用作click_policy
。
Finally, the click_policy
for each figure is set, and they are shown in a horizontal configuration:
最后,为每个图形设置click_policy
,它们以水平配置显示:
# Add interactivity to the legend
# Add interactivity to the legend
hide_fighide_fig .. legendlegend .. click_policy click_policy = = 'hide'
'hide'
mute_figmute_fig .. legendlegend .. click_policy click_policy = = 'mute'
'mute'
# Visualize
# Visualize
showshow (( rowrow (( hide_fighide_fig , , mute_figmute_fig ))
))
Once the legend is in place, all you have to do is assign either hide
or mute
to the figure’s click_policy
property. This will automatically turn your basic legend into an interactive legend.
图例到位后,您所要做的就是为图形的click_policy
属性分配hide
或mute
。 这将自动将您的基本图例变成交互式图例。
Also note that, specifically for mute
, the additional property of muted_alpha
was set in the respective circle
glyphs for LeBron James and Kevin Durant. This dictates the visual effect driven by the legend interaction.
还要注意的是,专为mute
,附加属性muted_alpha
在各自的设置circle
字形的勒布朗-詹姆斯和凯文-杜randint。 这决定了图例交互驱动的视觉效果。
For more on all things interaction in Bokeh, Adding Interactions in the Bokeh User Guide is a great place to start.
有关Bokeh中所有交互的更多信息,《 Bokeh用户指南》中的“ 添加交互 ”是一个不错的起点。
Congratulations! You’ve made it to the end of this tutorial.
恭喜你! 您已经完成了本教程的结尾。
You should now have a great set of tools to start turning your data into beautiful interactive visualizations using Bokeh.
现在,您应该拥有大量的工具,可以开始使用Bokeh将数据转换为漂亮的交互式可视化图像。
You learned how to:
您学习了如何:
figure()
objectColumnDataSource
figure()
对象 ColumnDataSource
访问和过滤数据 To explore even more of what Bokeh is capable of, the official Bokeh User Guide is an excellent place to dig into some more advanced topics. I’d also recommend checking out Bokeh’s Gallery for tons of examples and inspiration.
要进一步探究Bokeh的功能,官方的《 Bokeh用户指南》是探讨一些更高级主题的好地方。 我还建议您查看Bokeh的Gallery,以获取大量示例和灵感。
翻译自: https://www.pybloggers.com/2018/11/interactive-data-visualization-in-python-with-bokeh/
python bokeh