昨天我们讲到了处理小部件事件和控制部件的输出,今天我们讲剩下的部分。
传送门:用交互组件(ipywidgets)“盘活”Jupyter Notebook(上)
4、链接小部件输出
继续前面的例子,假设我们也希望按目的过滤。
如果我们继续添加另一个下拉列表,我们将很快意识到数据帧只响应最近更改的下拉列表中的过滤器。我们需要做的是将两者联系在一起,这样它就可以在两个价值观(即年和目标)上发挥作用。
让我们看看它应该如何工作:
首先,我们需要两个下拉列表的公共输出:
output = widgets.Output()
以下是两个下拉列表:
dropdown_year = widgets.Dropdown(options = unique_sorted_values_plus_ALL(df_london.year))dropdown_purpose = widgets.Dropdown(options = unique_sorted_values_plus_ALL(df_london.purpose))
然后我们创建一个新的函数common_filtering,它将由两个事件处理程序调用。此函数将在数据框上应用一个过滤器,用于年份和目的:
我们正在清除输出,然后检查是否所有的值,在这种情况下,我们考虑删除相应的过滤器。当两个过滤器都存在时,在else语句中,我们在两个过滤器中应用&操作。最后,我们捕获输出:
def common_filtering(year, purpose):
output.clear_output()
if (year == ALL) & (purpose == ALL):
common_filter = df_london
elif (year == ALL):
common_filter = df_london[df_london.purpose == purpose]
elif (purpose == ALL):
common_filter = df_london[df_london.year == year]
else:
common_filter = df_london[(df_london.year == year) &
(df_london.purpose == purpose)]
with output:
display(common_filter)
我们将事件处理程序修改为调用common_filtering函数并传递更改。新值以及其他下拉框的当前值:
def dropdown_year_eventhandler(change):
common_filtering(change.new, dropdown_purpose.value)def dropdown_purpose_eventhandler(change):
common_filtering(dropdown_year.value, change.new)
我们将处理程序绑定到下拉列表,就这样!
dropdown_year.observe(
dropdown_year_eventhandler, names='value')dropdown_purpose.observe(
dropdown_purpose_eventhandler, names='value')
代码片段:
[caption id="attachment_40122" align="aligncenter" width="920"]
基于两个值筛选数据帧[/caption]
下面是演示:
[caption id="attachment_40123" align="aligncenter" width="1018"]
演示:基于两个值筛选数据帧[/caption]
5、创建仪表盘
到目前为止,我们已经通过过滤和显示伦敦数据集的数据为仪表盘奠定了基础。我们将根据用户选择的值对数值着色。
一个有用的数字小部件是boundedfloatText;我们将给它一个最小值、最大值和初始值,以及增量步骤。
bounded_num = widgets.BoundedFloatText(
min=0, max=100000, value=5, step=1)
为了给数据帧单元上色,我们将定义此功能:
def colour_ge_value(value, comparison):
if value >= comparison:
return 'color: red'
else:
return 'color: black'
现在,我们将把常用的_过滤功能修改为:
def common_filtering(year, purpose, num):
- 通过调用三个数值列的colour_ge_value函数来应用样式:
with output:
display(common_filter
.style.applymap(
lambda x: colour_ge_value(x, num),
subset=['visits','spend', 'nights']))
需要调整现有的事件处理程序以传递绑定的_num.value:
def dropdown_year_eventhandler(change):
common_filtering(change.new, dropdown_purpose.value,
bounded_num.value)def dropdown_purpose_eventhandler(change):
common_filtering(dropdown_year.value, change.new,
bounded_num.value)
最后,我们将插入新小部件的事件处理程序:
def bounded_num_eventhandler(change):
common_filtering(dropdown_year.value, dropdown_purpose.value,
change.new)bounded_num.observe(bounded_num_eventhandler, names='value')
代码片段:
[caption id="attachment_40124" align="aligncenter" width="920"]
颜色数据框值[/caption]
下面是演示:
[caption id="attachment_40125" align="aligncenter" width="1026"]
演示:颜色数据框值[/caption]
绘图
接下来,我们将添加一个新的图表来绘制访问次数的基本单变量密度(kde→内核密度估计)。我们将使用Seaborn,所以让我们导入库:
import seaborn as sns
import matplotlib.pyplot as plt
继续前面的用例,我们将捕获一个新的输出变量中的绘图:
plot_output = widgets.Output()
现在,我们将修改公共过滤函数以绘制新图表:
plot_output.clear_output()
- 然后我们通过传递访问次数来调用seaborn的kdeplot方法:
with plot_output:
sns.kdeplot(common_filter['visits'], shade=True)
plt.show()
最后,我们唯一需要做的就是在一个新的单元格中显示输出:
display(output)
display(plot_output)
代码片段:
[caption id="attachment_40126" align="aligncenter" width="920"]
控制图[/caption]
下面是演示:
[caption id="attachment_40127" align="aligncenter" width="920"]
演示:控制图[/caption]
6、仪表盘布局
到目前为止,我们的用户界面是功能性的,但是占用了大量的空间。
我们将首先水平排列输入小部件。HBox将从左到右依次添加小部件:
input_widgets = widgets.HBox(
[dropdown_year, dropdown_purpose, bounded_num])display(input_widgets)
[caption id="attachment_40128" align="aligncenter" width="920"]
HBox[/caption]
def colour_ge_value(value, comparison):
if value >= comparison:
return 'color: red'
else:
return 'color: black'
接下来,我们将为输出创建一个容器。Tab非常适合这个功能。第一个选项卡将承载数据帧,第二个选项卡承载图形。
tab = widgets.Tab([output, plot_output])
tab.set_title(0, 'Dataset Exploration')
tab.set_title(1, 'KDE Plot')display(tab)
[caption id="attachment_40129" align="aligncenter" width="920"]
Tab[/caption]
最后,我们将使用VBox将输入小部件和选项卡堆叠在一起。
dashboard = widgets.VBox([input_widgets, tab])display(dashboard)
[caption id="attachment_40130" align="aligncenter" width="920"]
VBox[/caption]
感觉有点“卡住”,所以作为最后一步,我们将通过增加一些空间来优化仪表盘。我们将定义一个布局,在项目之间提供50px的空白。
item_layout = widgets.Layout(margin='0 0 50px 0')
我们将为每个项目调用此布局:
input_widgets = widgets.HBox(
[dropdown_year, dropdown_purpose, bounded_num],
layout=item_layout)tab = widgets.Tab([output, plot_output],
layout=item_layout)
我们完成了仪表盘:
最终演示:
PS:出于演示目的,在一些演示中,我使用了数据集的一个子集,即:df_london=df_london.sample(250)。
如果你想更深入的学习…
你也可以使用一些第三方小工具,其中最流行的是:
- 二维图表:BQplot
- 三维可视化:pythreejs和ipyvolume
- 映射:ipyleaflet和gmap。
回顾
我们看到了相当广泛的小部件在运行,但我们仍然只触及了皮毛-我们可以使用ipywidgets构建非常复杂和广泛的gui。我希望你们都同意他们应该在任何数据科学家的工具箱中占有一席之地,因为他们可以提高我们的生产力,并在数据探索过程中增加很多价值。
感谢你的阅读!