仪表板数据展示

人工智能与机器学习

概述

人工智能(AI)和机器学习(ML)是当今科技领域最热门的话题之一。AI是指计算机系统能够执行通常需要人类智能的任务,如视觉识别、语音识别和决策制定。ML是AI的一个子集,专注于开发能够从数据中学习的算法。

关键技术

深度学习

深度学习是ML的一个分支,使用多层神经网络来处理复杂的数据模式。它在图像和语音识别方面取得了显著的成果。

强化学习

强化学习是一种通过试错来学习的ML方法。它通常用于游戏和机器人控制等领域。

应用领域

医疗保健

AI和ML在医疗诊断、药物发现和个性化治疗方面有广泛应用。

金融

在金融领域,AI用于风险管理、欺诈检测和算法交易。

挑战

数据隐私

随着AI和ML的发展,数据隐私成为一个重要问题。如何在不侵犯个人隐私的情况下利用数据是一个挑战。

伦理问题

AI系统的决策过程可能不透明,这引发了关于伦理和责任的讨论。

未来展望

AI和ML的未来充满希望,但也伴随着挑战。随着技术的进步,我们期待看到更多创新的应用和解决方案。

仪表板是用于提供导航和展示数据的组件组合。下面我们将介绍如何使用图表、表格和值框展示数据,以及如何在仪表板中包含叙述性内容。

图表

图表是目前为止仪表板中最常见的展示内容类型。支持交互式基于JavaScript的图表(例如AltairPlotly)以及标准基于光栅的图表(例如Matplotlibggplot2)。

下面我们提供一些特定语言的技巧和技术,用于在仪表板中包含图表。

plotly

Plotly是一个流行的基于JavaScript的Python图表包,非常适合在仪表板布局中使用。Plotly尤其值得注意,因为它包含了许多交互式功能,同时仍然不需要服务器。例如,这个图表支持随着时间变化显示值的动画展示:

```{python}
#| title: GDP和预期寿命
import plotly.express as px
df = px.data.gapminder()
px.scatter(
  df, x="gdpPercap", y="lifeExp", 
  animation_frame="year", animation_group="country",
  size="pop", color="continent", hover_name="country", 
  facet_col="continent", log_x=True, size_max=45, 
  range_x=[100,100000], range_y=[25,90]
)
```

一张标题为GDP和预期寿命的卡片截图。卡片包含一个散点图集合。图表下方有一个包含播放和停止按钮的年份滑块。

altair

Altair是一个基于Vega和Vega-Lite的声明式统计可视化库,适用于Python。Altair图表基于JavaScript,因此它们会自动调整大小以适应仪表板中的容器。

```{python}
#| title: 爱荷华州电力
import altair as alt
from vega_datasets import data
source = data.iowa_electricity()
alt.Chart(source).mark_area(opacity=0.3).encode(
  x="year:T",
  y=alt.Y("net_generation:Q").stack(None),
  color="source:N"
)
```

matplotlib

如果你在使用静态仪表板中的传统绘图库,你需要更加注意确保图表的大小适合它们将被查看的布局。请注意,这对于交互式 Shiny 仪表板中的图表来说不是问题,因为所有图表类型都会由 Shiny 动态调整大小。

如果你使用的是Matplotlib(或基于它的库如Seaborn),那么你可以使用figure.figsize全局选项来设置图表大小(或者在更方便的情况下逐个图表设置):

```{python}
import matplotlib.pyplot as plt
plt.rcParams['figure.figsize'] = (12, 3)
```

在图表布局为更宽的宽高比的情况下,设置此选项在利用可用空间方面可以产生巨大差异。例如,下面堆叠中的顶部图表使用了默认的8 x 5的图表大小,而底部图表则使用了上面指定的12 x 3的宽高比:

两张卡片上下排列的截图。顶部卡片包含一个图表,两侧有大片空白区域。底部卡片包含相同的图表,但重新调整大小以减少空白区域。

需要注意的是,需要显式设置图表大小的情况仅限于传统的绘图库——如果你使用Plotly或其他基于JavaScript的绘图系统,图表会自动调整大小以填充其容器。

htmlwidgets

htmlwidgets框架为JavaScript数据可视化库提供了高级的R绑定。一些流行的htmlwidgets包括PlotlyLeafletdygraphs

你可以像使用普通R图表一样使用htmlwidgets。例如,下面是如何嵌入一个Leaflet地图:

```{r}
library(leaflet)
leaflet() %>%
  addTiles() %>% 
  addMarkers(lng=174.768, lat=-36.852, 
             popup="R的诞生地")
```

CRAN上有数十个提供htmlwidgets的包。你可以在htmlwidgets的展示中找到几个更流行的htmlwidgets的示例用法,并在画廊中浏览所有可用的widget。

R图形

你可以在仪表板中使用任何由标准R光栅图形(基本图形、网格、等)创建的图表。在使用标准R图形与静态仪表板时,你需要更多地注意图表的大小是否适合它们将被查看的布局。请注意,这对于交互式Shiny仪表板中的图表来说不是问题,因为所有图表类型都会由Shiny动态调整大小。 在静态仪表盘中实现良好尺寸行为的关键是定义knitr的fig-widthfig-height选项,使图形尽可能紧密地适应其布局容器。

以下是一个包含3个来自R基础图形的图表的布局示例:

## 行 {height="65%"}

```{r}
#| fig-width: 10
#| fig-height: 8
plot(cars)
```

## 行 {height="35%"}
        
```{r}
#| fig-width: 5
#| fig-height: 4
plot(pressure)
```
    
```{r}
#| fig-width: 5
#| fig-height: 4
plot(airmiles)
```

我们为每个图形指定了明确的fig-heightfig-width,以使它们的渲染尺寸尽可能紧密地适应其布局容器。请注意,这些尺寸的最佳值通常需要通过实验来确定。

Tip

对于静态仪表板,使用基于JavaScript的图表有其利弊。虽然基于JavaScript的图表在调整大小以填充其容器方面比静态图表做得更好,但它们也会将底层数据直接嵌入到发布的页面中(每个图表对应一个数据集的副本),这可能会导致加载时间变慢。

对于交互式Shiny仪表板,所有图表类型的大小都是动态调整的,因此与静态仪表板不同,调整大小的行为不是问题。

表格

您可以通过以下两种方式之一在仪表盘中包含数据表:

  • 作为简单的表格显示。
  • 作为包含排序和过滤功能的交互式小部件。

下面我们提供一些特定于语言的提示和技术,用于在仪表盘中包含表格。

有许多Python包可用于生成表格输出。我们将在下面介绍两个更流行的库(itables和tabulate)。

itables

Python itables 包支持从Pandas和Polars DataFrame创建交互式数据表,您可以对其进行排序和过滤。

使用itablesshow()方法显示一个交互式表格:

```{python}
from itables import show
show(penguins)
```

显示企鹅数据表格的卡片的截图。表格上方出现一个搜索框。数据框列名以粗体显示在顶部一行,每列都有排序按钮。

选项

请注意,一些itables选项在仪表盘中自动设置,以确保它们在不同大小的卡片中显示良好。默认选项如下:

from itables import options
options.dom = 'fiBrtlp'
options.maxBytes = 1024 * 1024
options.language = dict(info = "显示 _TOTAL_ 条记录")
options.classes = "display nowrap compact"
options.paging = False
options.searching = True
options.ordering = True
options.info = True
options.lengthChange = False
options.autoWidth = False
options.responsive = True
options.keys = True
options.buttons = []

您可以根据需要指定替代选项来覆盖这些默认值。选项可以在调用show()时指定,也可以全局指定,如上所示。以下是一个在show()中指定选项的示例:

show(penguins, searching = False, ordering = False)

您可以在此处找到所有DataTables选项的参考:https://datatables.net/reference/option/。所有基础选项都可用,以及以下扩展的选项(Quarto会自动包含这些扩展):

例如,要在调用show()时启用复制和导出(excel/pdf)按钮:

show(penguins, buttons = ['copy', 'excel', 'pdf'])

或者,要为所有表格启用这些按钮:

from itables import options
options.buttons = ['copy', 'excel', 'pdf']

下采样

当显示表格时,表格数据嵌入在仪表板输出中。为了避免较大的数据集导致仪表板加载过重,itables将仅显示表格的一个子集——适合maxBytes(默认1024kb)的部分。

如果愿意,您可以增加maxBytes的值,甚至禁用该限制(使用maxBytes=0)。例如,要设置200kb的限制:

```{python}
show(penguins, maxBytes = 200 * 1024)
```

tabulate

Python tabulate 包支持从Pandas数据框、NumPy数组和许多其他数据类型创建markdown表格。您可以通过to_markdown()方法从任何Pandas数据框生成markdown表格(确保使用IPython将其包装为Markdown输出):

```{python}
import pandas as pd
from IPython.display import Markdown
penguins = pd.read_csv("penguins.csv")
Markdown(penguins.to_markdown(index=False))
```

请注意,index = False参数抑制了行索引的显示。以下是包含tabulate输出的卡片的截图:

显示企鹅数据表格的卡片的截图。数据框列名以粗体显示在顶部一行。数据行背景在白色和灰色之间交替。

您也可以直接导入tabulate并将对象传递给直接打印:

```{python}
from tabulate import tabulate
Markdown(tabulate(penguins, headers='keys', tablefmt='pipe'))
```
| species | island    | bill_length_mm | bill_depth_mm | flipper_length_mm | body_mass_g | sex    |
|---------|-----------|----------------|---------------|-------------------|-------------|--------|
| Adelie  | Torgersen | 39.1           | 18.7          | 181               | 3750        | male   |
| Adelie  | Torgersen | 39.5           | 17.4          | 186               | 3800        | female |
| Adelie  | Torgersen | 40.3           | 18.0          | 195               | 3250        | female |
| Adelie  | Torgersen | NA             | NA            | NA                | NA          | NA     |
| Adelie  | Torgersen | 36.7           | 19.3          | 193               | 3450        | female |

有许多可用于生成表格输出的R包。我们将在下面介绍两种更流行的方法(kable和DT)。

kable

简单的markdown表格非常适合较少的记录数量(即20-250行)。使用knitr::kable()函数输出markdown表格:

```{r}
knitr::kable(mtcars)
```

显示企鹅数据表格的卡片截图。数据框列名在顶部一行以粗体显示。数据行具有交替的白色和灰色背景。

仪表板中的简单markdown表格会自动填充其容器(根据需要水平和垂直滚动)。

DT

DT包(一个DataTables JavaScript库的接口)可以将R矩阵或数据框显示为支持过滤、分页和排序的交互式HTML表格。

要包含一个DataTable,你可以使用DT::datatable函数:

```{r}
library(DT)
datatable(mtcars)
```

显示企鹅数据表格的卡片截图。表格上方有一个搜索框。数据框列名在顶部一行以粗体显示,每列都有排序按钮。

选项

请注意,在仪表板中会自动设置一些DT选项,以确保它们在不同大小的卡片中显示良好。选项的默认值为:

options(DT.options = list(
  bPaginate = FALSE, 
  dom = "ifrt", 
  language = list(info = "Showing _TOTAL_ entries")
))

你可以根据需要指定其他选项来覆盖这些默认值。

数值框

数值框是在仪表板中突出显示简单值的好方法。例如,这里是一个包含三个数值框的仪表板行:

一行三个数值框。第一个有灰色背景,一个大铅笔图标,小文字显示每天的文章,一个大数字45。第二个有灰色背景,一个大评论图标,小文字显示每天的评论,一个大数字126。第三个有黄色背景,一个大垃圾桶图标,小文字显示每天的垃圾邮件,一个大数字50。

以下是你可能用来创建这些数值框的代码。请注意,我们在本例中混合使用了Python和R单元格,以说明每种语言的语法。还要注意,我们假设变量articlescommentsspam在文档中已经计算过。

## 行 

```{python}
#| content: valuebox
#| title: "每天的文章"
#| icon: pencil
#| color: primary
dict(
  value = articles
)
```

```{python}
#| content: valuebox
#| title: "每天的评论"
dict(
  icon = "chat",
  color = "primary",
  value = comments
)
```

```{r}
#| content: valuebox
#| title: "每天的垃圾邮件"
list(
  icon = "trash",
  color = "danger",
  value = spam
)
```

你可以在YAML中或在由单元格打印的dict()list()(分别用于Python和R)中指定数值框选项。当你希望iconcolor根据值动态变化时,后一种语法很方便。

图标和颜色

数值框中使用的icon可以是2,000多个可用的bootstrap图标中的任何一个。

color可以是任何CSS颜色值,但有一些特别为仪表板调整的颜色别名,你可能默认使用:

颜色别名 默认主题颜色
primary 蓝色
secondary 灰色
success 绿色
info 亮蓝色
warning 黄色/橙色
danger 红色
light 浅灰色
dark 黑色

你可以通过在自定义主题中指定数值框Sass变量来覆盖这些默认值。

虽然别名适用于所有主题,但它们对应的颜色会有所不同。

Shiny

在Shiny交互式仪表板中,你可以有根据应用程序状态动态更新的数值框。具体操作方法因语言而异:

在带有@render.ui装饰器的函数中使用ui.value_box()函数。例如:

```{python}
from shiny.express import render, ui
@render.ui
def value():
    return ui.value_box("Value", input.value())
```

使用bslib::value_box()函数,并可选地从bsicons包中绘制一个图标。例如:

```{r}
library(bslib)
library(bsicons)
value_box(
  title = "Value",
  value = textOutput("valuetext"),
  showcase = bs_icon("music-note-beamed")
)
```

Markdown语法

你还可以使用纯markdown创建数值框,在这种情况下,你通常会通过内联表达式包含数值。例如:

## 行

::: {.valuebox icon="pencil" color="blue"}
每天的文章

`{python} articles`
:::

虽然你经常在仪表板卡片中填充图表和表格,但你也可以在仪表板的任何位置包含任意的Markdown内容。

内容卡片

以下是一个仪表板示例,其中一列的最后一个卡片是纯Markdown内容:

一个包含三个卡片的仪表板截图,这些卡片垂直排列在一列中。前两个卡片包含图表,最后一个卡片包含以'Gapminder结合了来自多个来源的数据...'开头的文本。

要实现这一点,只需在其他单元格旁边包含一个.card div:

## 列

```{python}
#| title: 人口
px.area(df, x="year", y="pop", color="continent", 
        line_group="country")
```

```{python}
#| title: 预期寿命
px.line(df, x="year", y="lifeExp", color="continent", 
        line_group="country")
```

::: {.card}
Gapminder将来自多个来源的数据结合成独特的连贯时间序列,这些时间序列在其他地方无法找到。在<https://www.gapminder.org/data/>了解更多关于Gampminder数据集的信息。
:::

请注意,如果你使用Jupyter Notebook进行创作,那么Markdown单元格会自动成为.card div(即它们不需要显式的::: div包围)。

单元格内的内容

要在单元格输出旁边包含内容,只需将单元格和内容都包含在一个.card div中。例如:

::: {.card title="预期寿命"}

```{python}
px.line(df, x="year", y="lifeExp", color="continent", 
        line_group="country")
```

Gapminder将来自多个来源的数据结合成独特的连贯时间序列,这些时间序列在其他地方无法找到。在<https://www.gapminder.org/data/>了解更多关于Gampminder数据集的信息。
:::

一个包含图表的单个卡片的截图,图表下方是'Gapminder结合了来自多个来源的数据...'开头的文本。

引导内容

包含在仪表板顶部的内容(并且没有明确包含在.content div中)被视为引导内容,并且将按原样包含,没有卡片样式(例如,没有边框)。例如:

---
title: "我的仪表板"
format: dashboard
---

此内容将出现在所有其他行/列的上方,没有边框。

## 行

```{python}
```

动态内容

你可以使用内联表达式使文本内容动态化。例如,这里我们有一行使用Python表达式的文本内容:

::: {.card}
样本大小为`{python} sample`。报告的平均评分是`{python} rating`。
:::

单元格输出

笔记本或源文档中每个计算单元格的输出将包含在卡片内。下面我们描述一些创建卡片时的特殊规则。

动态标题

你可以通过将title=表达式打印为单元格的第一个输出来创建动态title(与将title作为YAML单元格选项包含相反)。例如:

```{python}
from ipyleaflet import Map, basemaps, basemap_to_tiles

lat = 48
long = 350

print("title=", f"World Map at {lat}, {long}")

Map(basemap=basemap_to_tiles(basemaps.OpenStreetMap.Mapnik),
    center=(lat, long), zoom=2)
```
```{r}
library(leaflet)

lat <- 48
long <- 350

cat("title=", "World Map at", lat, long)

leaflet() |> addTiles() |> 
  setView(long, lat, zoom = 2)
```

排除的单元格

不产生输出的单元格不会变成卡片(例如,用于导入包、加载和过滤数据的单元格等)。如果一个单元格产生了你不希望的输出,请向单元格添加output: false选项:

```{python}
#| output: false
# (产生意外输出的代码)
```

表达式打印

默认情况下,来自顶级表达式的所有输出都会显示在仪表板中。这意味着可以从一个单元格轻松生成多个图表。例如:

```{python}
#| title: "小费行为"
px.box(df, x="sex", y="total_bill", color="smoker")
px.violin(df, x="sex", y="total_bill", color="smoker")
```

此行为对应于Jupyter shell交互性"all"设置。你可以在Quarto中使用ipynb-shell-interactivity选项自定义此行为。

卡片布局

如果一个单元格产生多个输出,你可以使用单元格布局选项来组织它们的显示。例如,这里我们修改示例以使用layout-ncol选项并排显示图表:

```{python}
#| title: "小费行为"
#| layout-ncol: 2
px.box(df, x="sex", y="total_bill", color="smoker")
px.violin(df, x="sex", y="total_bill", color="smoker")
```

一个标题为'小费行为'的仪表板卡片的截图,显示两个并排的图表。

有关自定义布局的更多文档,请参见图表文章。

了解更多

布局展示了如何控制导航栏,以及如何在页面、行、列、标签集和卡片中安排你的内容。 输入 展示了多种布局交互式仪表盘输入的方式(侧边栏、工具栏、直接将输入附加到卡片等)。

示例 提供了一个示例仪表盘画廊,您可以将其作为自己设计的灵感。

主题 描述了自定义仪表盘外观的多种方法,包括字体、颜色、布局等方面。

参数 解释了如何通过定义参数并在命令行中提供不同的值来创建仪表盘变体。

部署 涵盖了如何部署静态仪表盘(只需网页主机,无需服务器)和Shiny仪表盘(需要Shiny服务器)。

交互性 探讨了创建交互式仪表盘的各种方法,使数据探索更加灵活。