使用 R 的数据可视化手册:初学者教程
动手教程
以更互动的方式创建我们的数据可视化
目录(仅适用于 web)
1 [What’s leaflet?](/data-visualization-with-leaflet-using-r-eea044c0c328#f65e)
2 [Interaction Features](#b0ea)
3 [Prerequisites](#69bd)
4 [Let’s Create the Data Viz](#7752)
5 [Recap](#7432)
6 [Conclusion](#5cd8)
7 [References](#150f)
传单是什么?
he leaflet 是一个开源库,可以轻松地实现空间数据可视化。因为它是一个开源库,并集成到任何平台和编程语言中,所以它目前成为世界上最流行的地图库。从历史上看,这份传单是由 Vladimir Agafonkin 于 2011 年首次开发的。
先决条件
在我们开始构建可视化之前,确保我们满足以下要求。
让我们创建数据,即
用 R 构建一个脚本来创建传单地图非常简单。但是,如果我们想建立一个交互式的美丽的地图,当然,一些脚本必须添加。下面的脚本将创建我们的简单地图(实际上这很酷)。为什么?因为我们已经给我们的标记添加了一些信息,如地点的名称、地址、经度、纬度、主管、和学生的姓名,而不是只有标记。单击标记后,该信息将通过弹出窗口显示。
leaflet(data.location) %>%
addProviderTiles(providers$OpenStreetMap) %>%
addMarkers(lng = ~long,
lat = ~lat,
popup = paste(paste('<b>Office:</b>',
data.location$place),
paste('<b>Address:</b>',
data.location$address),
paste('<b>Lat:</b>',
data.location$lat),
paste('<b>Long:</b>',
data.location$long),
paste('<b>Supervisor:</b>',
data.location$supervisor),
data.location$student1,
data.location$student2,
data.location$student3,
sep = '<br/>'),
label = ~place,
group = 'data.location')
好的,让我们在地图上添加一些特征。在放大和缩小每个位置后,最好将我们的视图重置为默认值。所以,我们可以添加一个重置地图按钮。此外,我们有一个搜索功能来简化我们的搜索,只需输入我们的位置名称,算法就会根据我们的关键字显示相关的结果。所以,只需在前一个脚本的底部添加以下脚本即可。
addResetMapButton() %>%
addSearchFeatures(
targetGroups = 'data.location',
options = searchFeaturesOptions(zoom = 15,
openPopup = TRUE,
firstTipSubmit = TRUE,
autoCollapse = TRUE,
hideMarkerOnCollapse = TRUE))
好,然后,我们添加测量按钮,并突出显示它的一般信息或标题。对于 measure 按钮,正如它的名字一样,它将向我们显示两点或更多点之间的距离。我们可以利用这个特性来估计两个城市之间的距离。如果遇到之字形路线,可以逐点画一条直线。测量单位必须根据我们的需要来设置,例如以米为单位。最后,为了显示我们的一般信息,最好添加一个信息框。
addMeasure(
position = 'bottomleft',
primaryLengthUnit = 'meters',
primaryAreaUnit = 'sqmeters',
activeColor = '#3D535D',
completedColor = '#7D4479') %>%
addControl("<P><b>Masterpiece Statistics 53</b>
<br/>Search for offices/ industries<br/>in Java by name.</P>",
position = 'topright')
概述
概括一下我们的脚本,我们可以正确地运行下面的脚本,瞧,我们的地图已经准备好解释并开始生产了。
完整版本的数据脚本,即使用传单
我们可以看看我们的地图,如下图所示。
使用传单的数据可视化(图片由作者提供)
我们可以试试搜索的功能。例如,根据我们以前的代码,它将从数据中读取任何输入。
从传单中搜索的特征(图片由作者提供)
结论
因此,我们可以很容易地使用传单作为我们的工具来可视化的空间数据。它提供了许多功能,如搜索功能、缩放等。传单也很容易部署到 HTML 中。
参考
[1]伍德拉夫,穆林斯,琼斯 宣传单:制作网络地图!(2014)。
[2]诉阿加丰金。 宣传单:一个面向移动友好的交互式地图的开源 JavaScript 库(2019)https://leafletjs.com/index.html。
Python 中 Matplotlib 的数据可视化
破解数据科学就业市场的最佳实践
在分析数据之前,首先要做的事情之一就是数据可视化。在 Python 中,有许多高质量的可视化库。最流行的通用可视化库是 Matplotlib,它主要致力于生成静态出版物质量的 2D 和 3D 图形。我们可以将它用于许多不同的图,如直方图、条形图、热图、线图、散点图等。
Matplotlib 基础
在 Matplotlib 中,您将会遇到和使用一些重要的概念,以及它们的含义或作用。
Matplotlib 中的绘图元素
- 轴—这代表一条数字线,用于确定图形界限。
- 轴——这些代表我们所理解的情节。一个图形可以包含尽可能多的轴。
- 艺术家——指的是你能在你的图形上看到的一切,例如
collection
对象、Line2D
对象和Text
对象。请记住,大多数艺术家都在轴上。 - 图形—指您正在处理的整个图形。
一个图形可以包含多个轴实例,例如,在一个图形中显示多个面板,或者在另一个轴实例中显示插图。
基本 Matplotlib 函数
Matplotlib
库一开始看起来可能相当复杂,但是有了基本的编码知识,对你来说应该会更容易。以下是您将在 Matplotlib 中使用的绘图列表。
- 箭筒-用于创建 2D 箭场
- 步长(step )-用于创建步长图
- Stem-用于构建 stem 图
- 散点图(scatter )-创建 x 相对于 y 的散点图
- 堆叠图-用于为堆叠区域创建图
- 绘图(plot )-为轴创建标记或绘图线
- 极坐标(polar )-创建极坐标图
- 饼图—创建饼图
- 条形图-创建水平条形图
- 条形图-创建条形图
- 箱形图-创建须状和箱形图
- 直方图—用于创建直方图
- Hist2d 用于在 2d 创建直方图
此外,如果您经常使用图像,您应该使用以下图像功能。
- Imshow —用于显示坐标轴上的图像
- Imsave —用于以图像文件的形式保存数组
- Imread —用于将文件从图像读入数组
做中学
这本书里的所有脚本都是通过 Jupyter 笔记本执行的。因此,您应该安装 Jupyter 笔记本或在 Saturn Cloud 上创建一个帐户。
完整的源代码
导入 Matplotlib
让我们看看如何使用它。我们必须首先从我们的Matplotlib
包中导入pyplot
模块,然后才能创建一个图。
设置样式
我们将使用plt.style
指令为我们的人物选择合适的美学风格。这里我们将设置默认样式,这确保我们创建的绘图使用默认的 Matplotlib 样式。
图片由 Matplotlib 提供
简化,执行以下命令。
你也可以使用不同的风格。点击此处进一步阅读。请注意,从 Matplotlib 版本 1.5 开始支持这里使用的样式表,因此如果您使用的是 Matplotlib 的早期版本,则只有默认样式可用。
绘制函数
我们将学习如何用 Python w/ Matplotlib 绘制正弦波。我们将绘制sin(x)
及其在区间0
和2π
之间的倍数和次倍数角度。
NumPy
库有sin()
函数,它接受一组值并为它们提供正弦值。
使用以下命令,将您的绘图的静态图像嵌入笔记本中。
math
库将帮助定义pi
来生成 x 轴的随机值。
计算每个样本在处的正弦波值,然后指定 x 轴和 y 轴标签以及图标题,如图所示。
线条图
我们要绘制的第二个图是线形图。线形图是所有 Matplotlib 图中最简单的一种。线形图主要用于绘制两组数值之间的关系。
现在,我们创建两个不同风格的独特系列。使用linspace ()
功能确定 x 坐标。x
坐标从0
开始,到20
结束,因此您应该有以下函数。
按以下顺序在你的坐标轴上画线。
在上面的例子中,作为默认线条的第一条是实线,而第二条是虚线。
调整线条的颜色和样式
要调整颜色,可以使用 color 关键字,该关键字接受一个字符串参数,表示几乎任何可以想象的颜色。颜色可以通过多种方式指定。
如果没有指定颜色,Matplotlib 将自动循环显示多行的一组默认颜色。
同样,我们可以使用linestyle
关键字调整线条样式,如下所示。
调整绘图的轴限制
调整轴极限的最基本方法是使用plt.xlim()
和plt.ylim()
方法。
如果您想让任一轴反向显示,只需执行此命令。
此外,我们还可以通过传递一个指定[x-min, x-max, y-min, y-max]
的列表来设置 x 和 y 限制。
标记图
我们可以创建图的标签,如标题、轴标签和简单的图例。
标题和轴标签是最简单的标签,如下所示。
可以通过plt.legend()
方法创建图例。
对数图
对数图本质上是一个基本图,但它是在对数标度上设置的。这与普通线性标度的区别在于,间隔是按照大小顺序设置的。我们有两种不同类型的对数图。
- 双对数图。
- 半对数图。
例如,执行下面的代码片段来显示对数图。
散点图
散点图用于以散点的形式绘制两个数字列之间的关系。通常,对于 x 轴上的每个值,如果 y 轴上有多个值,则使用散点图。
使用plt.scatter()
功能创建散点图,如下所示。例如,我们使用来自sklearn
库的虹膜数据,其中每个样本都是三种类型的花中的一种,其花瓣和萼片的大小已经过仔细测量。
我们可以同时探索数据的四个不同维度:每个点的(x, y)
位置对应于萼片长度和宽度,该点的size
与花瓣宽度相关,而color
与特定种类的花相关。
如何绘制带误差线的条形图?
误差线对问题解决者很有用,因为误差线显示了一组测量值或计算值的置信度或精度。可以用plt.errorbar()
方法创建一个基本的误差栏。
我们使误差线比点本身更亮,如下所示。
使用具有双界面的多个轴和图形
为了创建多个支线剧情,我们也可以使用subplot()
函数在主图中创建多个绘图区域。
此外,我们可以使用下面的代码从上面的图中创建垂直分割。
如何创建条形图?
条形图用于显示与分类数据相关的值。然而,plt.bar()
函数接受一个位置和值的列表,x 的标签由plt.xticks()
提供。
例如,我们显示了越南电信公司 2019 年的服务收入如下。
我们也可以在同一个图表中包含多个 X 值。Viettel 是 2019 年越南最大的纳税人,具体如下。
对于堆叠条形图,我们需要提供参数bottom
,这通知 matplotlib 条形图应该从哪里开始,因此我们将添加下面的值。
绘制直方图
直方图是概率分布的图形表示。事实上,直方图只是一种特定的条形图。
以下脚本从正态分布中提取 1000 个值,然后生成 20 个柱的直方图。
绘制箱线图
通过方便地显示一组值的中值、四分位数、最大值和最小值,箱线图允许您比较值的分布。以下脚本显示了从正态分布中抽取的 100 个随机值的箱线图。
饼图
要比较数量的相对重要性,没有什么比饼图更好的了。
将数字保存到文件中
要将图形保存到文件中,我们可以使用savefig
方法。这个方法接受一个字符串,输出文件名作为第一个参数,还有几个可选的关键字参数。例如,要将前面的图形保存为 PNG 文件,您可以运行以下命令。
使用savefig
的transparent=True
参数也可以使图形画布透明。
输出。
my_figure.png 文件
都是关于用 Python 中的 Matplotlib 进行数据可视化。
参考
[1]https://matplotlib.org
[2]https://www.saturncloud.io/s/
[3]https://matplotlib . org/3 . 2 . 1/gallery/style _ sheets/style _ sheets _ reference . html
用 Python 实现数据可视化
(图片由作者提供)
终极指南
掌握 python 的数据可视化库(matplotlib,seaborn,pandas,和 plotly。)
《一图胜千言》
——弗雷德·r·巴纳德
数据可视化是数据的视觉(或图形)表示,以便在数据中找到有用的见解(即趋势和模式),并使数据分析过程变得更加容易和简单。
数据可视化的目的是在第一眼就能快速清晰地理解数据,并使其在视觉上可以呈现以理解信息。
在 Python 中,有几个全面的库可用于创建高质量、有吸引力、交互式和信息丰富的统计图形(2D 和 3D)。
Python 中一些流行的数据可视化库
- Matplotlib 就是这样一个流行的可视化库,它允许我们创建高质量的图形,包括散点图、折线图、条形图、直方图和饼图。
- Seaborn 是 Python 的另一个数据可视化库**,它构建在 Matplotlib、**之上,拥有一个具有吸引力设计的高级接口。此外,它减少了产生与 Matplotlib 相同结果所需的代码行数。
- Pandas 是 Python 中另一个很棒的数据分析库(数据操作、时序分析、集成数据索引等)。). Pandas Visualization (构建于 Matplotlib 之上)是 Pandas library 的一个工具,它允许我们更快更容易地创建数据帧(以列和行的表格形式排列的数据)和系列(能够保存任何类型数据的一维标签数组)的可视化表示。
- Plotly 库用于创建交互式和多维绘图,通过提供更好的数据可视化,使数据分析过程更容易。
通过这篇文章,我们将能够通过学习如何在不同的 Python 库中绘制数据来可视化不同形式的数据,并理解在哪里适当地使用哪一个。
注意:我们可以使用Google co laboratory来避免安装库的过程。只需将所有库导入笔记本即可使用。
了解 Maplotlib 的基础知识
(图片由作者 ) 图中的元素
- **图:**一切都被绘制的整个区域。它可以包含多个带轴的图、图例、轴范围、网格、图标题等。
- **轴:**图形下方正在构建图形的区域(或图形出现的区域)被称为轴。一个图形中可以有多个轴。
- **轴:**这是图表中的数字线,代表绘图的数值范围(上图中提到的 X 轴和 Y 轴)。在多维图形的情况下,图形中可以有两个以上的轴。
- **图标题:**标题位于轴上方的中央,给出了图的概况。
导入数据集
在本文中,我们将在不同的地方使用 虹膜数据集 ( 作为一个例子),它是免费的,并且是常用的(因为它是模式识别文献中最著名的数据库之一)。
我们可以通过两种方式导入该数据集:
1.使用 Scikit-learn 库:
使用 Scikt-learn 库导入虹膜数据集
无需下载.csv
文件,我们可以使用 python 中的 sci-kit 学习库直接导入工作空间中的数据集。
(图片由作者 ) 数据集中的前五个头
2.使用熊猫图书馆:
使用 Pandas 库导入数据集
使用上面的(通过导入 Pandas 库)代码,并下载数据集的.csv
格式,我们可以在我们的工作空间中导入数据。这些是iris
数据集中的前五个元素:
(图片由作者 ) 数据集中的前五个头
上述两种方法都可以用于导入数据集和创建图表,但我们将使用后者,因为数据的可读性更好(正如您可以看到的两种方法的输出结果的差异)。
Matplotlib 入门
我们首先使用以下代码在笔记本中导入库:
导入 matplotlib
该库中有多种样式可用于绘制地块。
线条图
折线图或折线图表示一个系列(连续)中的数据,沿数字线显示数据的频率。它可以用来比较数值组。这是我们可以用 python 制作的最简单的图表之一。
基本线图的代码
这里,使用numpy
linspace()
函数,我们将生成数据点并将其存储在变量x
中,计算x
值的平方并将其存储在另一个变量y
中。
我们将使用plt.plot()
功能绘制图形,使用plt.show()
显示图形。
(图片由作者)y = x 的折线图
我们可以给我们的图添加更多的函数,使它更容易解释。
- 添加标签:
x-axis label
和y-axis label
我们将分别使用plt.xlabel()
和plt.ylabel()
函数。 - 我们也可以使用
plt.title()
函数给我们的图一个标题。 - 图中的网格可通过调用
plt.grid(True)
函数简单应用(使数据更容易解释)。
随着这些功能的增加,图表变得更加易读和易于分析。
(图片由作者)y = x 的折线图
我们可以在绘图中添加多条线,并通过使用不同的颜色和一些其他功能来区分它们:
在上面的代码中,我们添加了另一个变量z=x**3
(z=x)并更改了线条的样式和颜色。
要改变线图中线条的颜色,我们必须在plt.plot()
函数中添加color=''
参数。
要改变线图中线条的样式,我们必须在plt.plot()
函数中添加linestyle=’’
参数(或者我们可以简单地添加’ * ‘或’-',等等)。
(图片由作者)y = x 和 z=x 的折线图
这使得信息的提取和数据变量的比较更加容易。
同样,我们也可以为数学函数创建图:
在这里,我们为sin(x)
和cos(x)
创建了一个情节。
我们可以通过使用 x 轴的功能plt.xlim(lower_limit,upper_limit)
和 y 轴的功能plt.lim(lower_limit,upper_limit)
来调整轴的限制。
为了进一步标记该图,我们可以添加具有plt.legend()
功能的legend
,这将有助于识别哪条线代表哪种功能。
(图片由作者)sin(x)和 cos(x)的折线图
支线剧情
为了在同一个图形中创建单独的(多个)图,我们可以使用plt.subplots(num_rows,num_cols)
功能。这里每个支线剧情的细节可以不同。
创建支线剧情
plt.sublots()
函数创建子情节的图形和网格,其中我们可以通过传递一个int
值作为参数来定义列和行的数量。此外,我们还可以通过使用gridspec_kw={'hspace': , 'wspace': }
参数来改变子选项之间的间距。之后,通过简单地使用子情节的索引号,我们可以很容易地绘制图形。
(图片由作者 ) 一张图中的四个支线剧情
散点图
这种图使用“点”来表示不同变量的数字数据。
散点图可用于分析一个变量如何影响其他变量。(我们可以使用任何数量的变量来绘制图表。)
我们将使用dataset_name.plot()
函数来创建图形,在参数中,我们将应用带有标签x-axis
和y-axis
的kind = 'scatter’
。看看下面提到的例子(虹膜数据集)。
这里,我们比较了数据集中不同种类的花的petal length
和petal width
。
(图片由作者 ) 虹膜数据集散点图
但是,在这里,我们很难从这个图中分析和提取信息,因为我们无法区分存在的类别。
所以现在,我们将尝试另一种方法来解决我们的问题。在此方法中,我们将使用plt.scatter()
创建一个散点图。
为了根据花卉的种类改变点 的颜色,我们可以创建一个字典,存储与种类名称相对应的颜色。通过使用for
循环,我们创建了三种不同物种的单个散点图(每种用不同的颜色表示)。
这个情节比上一个好得多。物种的数据变得更容易区分,并为更容易的信息分析提供了总体清晰性。
(图片由作者 ) 虹膜数据集彩色散点图
条形图
条形图可用于比较分类数据。我们必须提供频率和类别,我们希望在图上表现出来。
使用 matplotlib 绘制条形图
这里我们使用 iris 数据集来比较不同种类的花的数量(然而,它们等于 50)。为了找到数据集中每个唯一类别的计数,我们使用了value_counts()
函数。下面代码中的变量species
和count
存储每个唯一类别的名称(.index
函数)和每个类别的频率(.values
函数)
(图片由作者 ) 虹膜数据集中不同种类花朵的数量
这是最基本的条形图,您可以尝试该图的一些变化,如同一图中的多个条形图,改变条形的宽度(使用width=
参数)或创建堆积条形图(使用bottom
参数)。
箱线图
箱线图通过绘制基于样本最小值、下四分位数、中值、上四分位数和样本最大值的数据分布来帮助绘制和比较值(称为五位数汇总)。这可以帮助我们分析数据,找出数据中的异常值和变化。
箱形图
我们在这里排除了物种列,因为我们只比较 iris 数据集中所有花的petal length, petal width, sepal length, sepal width
。我们使用.boxplot()
功能创建盒状图。
(图片由作者 ) 方框图
直方图
直方图用于表示数据的频率分布(或者我们可以说是概率分布)。我们必须使用plt.hist()
函数来创建直方图,我们还可以为该图定义bins
(即,将整个数值范围分解为一系列区间,并计算落入每个区间的数值计数)。
直方图是一种特殊的条形图。
使用 matplotlib 创建直方图的代码
(图片由作者 ) 直方图
误差线
误差线是一个很好的工具,通过直观地显示数据的变化来找出一组数据之间的统计差异。它有助于指出数据分析过程中的误差和精度(并决定模型的质量)。
用于创建误差线 matplotlib 的代码
为了绘制误差线,我们必须使用errorbar()
函数,其中x
和y
是数据点位置,yerr
和xerr
定义误差线的大小(在这段代码中,我们只使用了yerr
)。
我们还可以通过使用fmt
参数来改变误差线的样式和颜色(就像在这个特定的例子中我们将样式设置为点’o’
),使用ecolor
来改变点的颜色,使用color
参数来改变垂直线的颜色。
通过在plt.legend()
函数中添加loc = ''
参数,我们可以确定图例在图中的位置。
(图片由作者 ) cos(x)误差棒图
热图
热图用于以**‘颜色编码图像图’**(数据中的值以颜色表示)的形式表示分类数据,以找到数据中特征的相关性(聚类分析)。在热图的帮助下,我们可以直观地对数据进行快速而深入的分析。
使用 matplotlib 创建热图
在本例中,我们使用 iris 数据集来创建热图。.corr()
是熊猫的数据框函数,用来寻找数据集中的相关性。热图是通过使用.imshow()
函数创建的,其中我们将数据集的correlation
、cmap
(用于设置绘图的样式和颜色)作为参数传递。为了添加工具栏,我们使用了.figure.colorbar()
函数。最后,为了添加注释(你可以在色块上看到提到的值),我们使用了两个 for 循环。
(图片由作者 ) 虹膜数据集热图
饼图
饼图用于查找数据类别组成之间的相关性(可以是数据的百分比或比例),其中每个切片代表一个不同的类别,提供整个数据的摘要。
饼图 matplotlib
为了绘制饼图,我们必须使用plt.pie()
函数。为了给绘图带来 3D 效果,我们使用了shadow = True
参数、explode
参数来显示与绘图其余部分分开的类别,为了显示每个类别的百分比,我们必须使用autopct
参数。为了使圆成比例,我们可以使用plt.axis('equal')
功能。
(图片由作者 ) 饼状图 matplotlib
海生的
凭借 seaborn 的高级界面和吸引人的设计,我们可以用更好的可视化效果创造出惊人的情节。此外,所需的代码行数在很大程度上减少了(与 matplotlib 相比)。
在工作区中导入库的代码:
导入 seaborn 库
线形图
我们可以通过使用sns.lineplot()
函数在 seaborn 库中简单地创建线图。
在这里,我们可以使用库中可用的.set_style()
功能改变网格/背景的颜色。并且使用sns.lineplot()
功能我们可以绘制折线图。
(图片由作者 ) 折线图使用 seaborn 库
散点图
有了 seaborn 库,我们只用一行代码就可以创建散点图!
使用 seaborn 库的散点图
这里,我们使用了**FacetGrid()**
函数(通过它我们可以快速浏览我们的数据集)来创建绘图,我们可以在其中定义hue
(即散点的颜色)和.map
函数来定义图形类型。(创建散点图的另一种方法是使用sns.scatterplot()
(图片由作者 ) 散点图使用 seaborn 库
条形图
我们可以使用sns.barplot()
函数在 seaborn 库中创建一个柱状图。
(图片由作者 ) 棒图使用 seaborn 库
直方图
我们可以使用sns.distplot()
函数在 seaborn 库中创建一个直方图。我们还可以使用这个库进行数据分析,计算概率分布频率(PDF)、累积分布频率(CDF)、核密度估计 (KDE) 。
Seaborn 提供了比 matplotlib 更多的数据可视化特性。
(图片由作者 ) 直方图使用 seaborn 库
热图
Seaborn 在创建热图方面非常高效,它显著减少了创建图表的代码行。
matplotlib 中的多行代码减少到只有两行!
(图片由作者 ) 使用 seaborn 库的热图
配对图
这是 seaborn 图书馆提供的一种独特的情节。这绘制了数据集中的成对关系(在单个图中)。对于数据分析来说,这是一个非常棒的工具。
通过使用sns.pairplot()
功能,我们可以创建配对图(height
用于调整图的高度)。
(图片由作者 ) Pairplot 使用 seaborn 库
熊猫可视化
这个库提供了一种使用 pandas 数据框和数据结构绘制图表的简单方法。这个库也是建立在 matplotlib 之上的,因此需要更少的代码行。
直方图
用这个库创建直方图非常简单,我们只需使用.plot.hist()
函数。我们也可以通过使用subplots=True
参数在同一个图中创建支线剧情。
(图片由作者 ) 直方图使用熊猫库
线形图
通过使用.plot.line()
函数,我们可以使用该库创建线图。图例也会自动添加到该库中。
(图片由作者 ) 线条图使用熊猫库
Plotly
有了这个库,我们就可以创建多维互动剧情了!这是一个易于使用的高级接口库。我们可以使用下面的代码导入这个库:
4D 图(虹膜数据集)
您可以试着自己运行这段代码来检查和处理这个图。
(图片由作者 ) 互动多维剧情
结论
我希望通过这篇文章,您能够使用 python 中的不同库来可视化数据,并开始分析它。
为了更好地理解这些概念,我建议您尝试编写这些代码。继续探索,我相信你会发现新的特性。我在文档末尾分享了我的笔记本储存库,供您参考。
如果你有任何问题或意见,请发表在评论区。
permalink dissolve GitHub 是超过 5000 万开发人员的家园,他们一起工作来托管和审查代码,管理…
github.com](https://github.com/kk189/Hello/blob/master/data_visualization.ipynb)
如果您想改进编写代码的方式,请查看我们的另一篇文章:
如何编写高效、更快的代码来提高程序的性能?
medium.com](https://medium.com/swlh/how-to-write-efficient-and-faster-code-67567e74ef87)
最初发表于:www.patataeater.blogspot.com
Resources:
[https://plotly.com/](https://plotly.com/)
[https://matplotlib.org/](https://matplotlib.org/)
[https://pandas.pydata.org/](https://pandas.pydata.org/)
[https://seaborn.pydata.org/](https://seaborn.pydata.org/#)
使用 seaborn 库实现数据可视化
7 个 seaborn 图表,用于快速有效的数据分析
图片由 Pixabay 的 Mudassar Iqbal 提供
简介
如果您还没有使用 Seaborn 进行数据探索,这是学习一些基本情节的绝佳时机。在本文中,我们将介绍几种可以在 Seaborn 中使用的不同类型的图表:
计数图
条形图
柱状图
接合图
配对图
箱线图
小提琴剧情
我们将在著名的 Iris 数据集上演示如何使用它们。
为什么要用 seaborn?
从库站点中摘录的这句话很好地描述了使用 Seaborn 的原因:
“Seaborn 是一个基于 matplotlib 的 Python 数据可视化库。它提供了一个高级界面,用于绘制有吸引力且信息丰富的统计图形。”
我想强调一下*【高层接口】和一个形容词【吸引人】*。这两者的结合使得 Seaborn 对我们这些用户来说非常有吸引力。它基本上允许你用最少的努力创建漂亮的图形。
安装 seaborn
安装 Seaborn 非常简单。只要从命令行运行这个命令,您就应该准备好了。
pip install seaborn
加载数据集
由于我们将展示如何使用真实数据集的图表,我们应该首先加载它。下面的代码使用 seaborn load_dataset 函数将著名的 Iris 数据集加载到数据框中。
import seaborn as sns;
df = sns.load_dataset("iris")
df.head()
让我们调用 info()函数来获取一些附加信息。
df.info()
该数据有 5 列 150 个条目。每个条目是一朵花,前四列是描述花的尺寸的浮点数,最后一列是表示花的分类的字符串。我们应该有三个不同的鸢尾种类。
计数图
我们可以使用 countplot 来可视化这个数据集上的物种分布。
计数图是可视化分类变量数值计数的理想选择。
sns.countplot(x ='species', data=df);
正如我们提到的有三类:刚毛,云芝,,和海滨锦鸡儿。我们还可以看到,这是一个平衡的数据集,每个花卉类别有 50 个例子。
柱状图
柱状图是一种广泛用于比较连续变量平均值的图表。让我们看看如何将它应用于虹膜数据集。
import matplotlib.pyplot as plt
sns.barplot(data=df)
plt.xticks(rotation=45)
请注意,该图自动排除了分类变量。对于数字列,现在很容易读取每个测量的平均值。此外,每个测量都有黑色的误差线(黑线在上面)。可以通过更改 x、y 和色调参数来操纵这种类型的图形。所以玩吧!
我还必须在代码末尾添加一个 matplotlib 函数,否则 x 轴上的标签会重叠。
直方图
如果您想在 Seaborn 中绘制直方图,我只想指出,它不像您在本文中遇到的以前的图表那样需要数据框。相反,您只需要向它传递一个数据序列,例如数据帧中的一列。
让我们在萼片长度栏上试试。
sns.distplot(df['sepal_length'])
如你所见,结果是一个直方图。伴随它的蓝线是核密度估计(kde ),它比直方图本身提供了更多的分布信息。
但是我如何绘制整个数据帧的直方图呢?我需要一个 for 循环吗?您可以使用 for 循环来实现这一点,或者更好地使用 pairplot。
配对图
Pairplot 将为所有连续变量创建直方图,并可视化所有对之间的相关性。让我们来看看如何使用它。
sns.pairplot(data=df.drop(columns='species'), kind='reg');
那看起来非常有用。请注意,配对图将数据框作为其输入。
我还添加了种类参数,并将其设置为*‘reg’(*kind =‘reg’)。这是为了得到适合相关图的线性回归,因为我认为它有助于可视化。
Pairplot 还有一个色调参数,对于数据探索非常有用。色调应该是一个分类变量,允许你将一个数据集划分成更小的组。在我们的例子中,我们只有一个分类变量,即*‘物种’*。让我们看看如何在 pairplot 中使用它。
sns.pairplot(df, hue='species');
太好了!现在你可以看到变量之间的相关性与它的物种划分。
接头图
如果您处理包含大量变量的数据集,或者只想更深入地研究一对变量,您可以使用 jointplot。让我们看看萼片长度和萼片宽度的相关性。
sns.jointplot(data=df, x='sepal_length', y='sepal_width', kind='reg')
如你所见,这又是一个非常有用的信息。对于每个变量,我们在图的两侧有直方图和核密度估计,主要部分显示为带有线性回归线的单个点。
箱线图
允许我们检查连续变量分布的另一个有用的可视化是箱线图。它为我们提供了四分位范围信息,并允许我们看到异常值。
让我们看看如何使用来可视化我们的连续变量。
sns.boxplot(data=df)
如你所见,我们可以看到连续变量分布的快速概览。只有萼片宽度有异常值,它们在须的两侧(上下)。
您可以使用 x、y 和色调参数来进一步自定义箱线图。例如,你可以通过在前面的代码中添加 x 和 y 参数来查看不同花卉种类的萼片长度的分布。
sns.boxplot(data=df, x='species', y='sepal_length')
小提琴剧情
Violin 图类似于箱线图,它们允许我们通过显示核密度估计来查看分布。
让我们看看数据集的小提琴图。
sns.violinplot(data=df)
我们可以看到花瓣宽度的 kde 有两个峰值。我的猜测是,每一种花都可能导致不同的穗状花序。你可以进一步定制小提琴的情节来展示这一点。
sns.violinplot(data=df, x='petal_width', y='species')
看起来我的停职是正确的。每个花种都有不同的分布花瓣宽度变量。
总结
正如你所看到的,使用 Seaborn 制作有效且漂亮的可视化效果非常简单。我们在这里使用的大部分代码不超过一行!这个库非常直观和用户友好,即使对于还没有完全掌握 python 的人来说也是如此。
我建议你现在选择一个数据集,自己尝试一些情节!
最初发布于 aboutdatablog.com: 用 seaborn 库进行数据可视化,2020 年 7 月 23 日。
PS:我正在 Medium 和上撰写深入浅出地解释基本数据科学概念的文章。你可以订阅我的 邮件列表 每次我写新文章都会收到通知。如果你还不是中等会员,你可以在这里加入。**
下面还有一些你可能喜欢的帖子:
学习如何使用折线图、散点图、直方图、箱线图和其他一些可视化技术
towardsdatascience.com](/9-pandas-visualizations-techniques-for-effective-data-analysis-fc17feb651db) [## 熊猫概况和探索性数据分析的第一行代码!
了解如何为自动 EDA 安装和使用 pandas profiling
towardsdatascience.com](/pandas-profiling-and-exploratory-data-analysis-with-line-one-of-code-423111991e58) [## Jupyter 笔记本自动完成
数据科学家的最佳生产力工具,如果您还没有使用它,您应该使用它…
towardsdatascience.com](/jupyter-notebook-autocompletion-f291008c66c) [## 9 大 Jupyter 笔记本扩展
改进笔记本电脑功能,提高您的工作效率
towardsdatascience.com](/top-9-jupyter-notebook-extensions-7a5d30269bc8)**
数据即诊所:改进排名图
无论是公司排名还是日常商品价格排名,媒体都有很多排名图表。一些渠道做到了这一点,而其他渠道往往会失败。
约书亚·戈尔德在 Unsplash 上拍摄的照片
人类是视觉动物。我们喜欢观察自然、动物和我们周围的一切生物。新闻帖子中的图片也是如此。我们喜欢让我们更接近故事的视觉层,而不仅仅是阅读纯文本。因此,我们的眼睛很可能会停留在文章中的一两张图片上。这就引出了今天的话题,排行榜。媒体喜欢排名,可以是根据年收入或员工数量对财富 500 强公司进行排名。
爱沙尼亚初创企业景观
我们爱沙尼亚人引以为豪的一件事就是我们的初创企业。对于爱沙尼亚以外的人来说,这里有一些你可能听说过的名字:
- 网络电话
- 转移方式
- 管道驱动
- 博尔特(原名 Taxify)
- Veriff
- 莫内塞
- 星际飞船技术公司
所有这些初创企业都来自波罗的海小国——爱沙尼亚,该死的,我们为他们感到骄傲。所以自然地,我们的媒体喜欢比较他们和他们的统计数据。今天的例子(再一次)来自 Delfi,并根据员工数量对这些初创企业进行排名。
资料来源:Delfi arileht。数据来源:初创爱沙尼亚
该图有 3 个不同的系列:
- 2018 年员工数量
- 2019 年的员工数量
- 员工增加/减少(Kasv)
对于 10 家公司来说,这使得 30 个不同的数据点被绘制在一个图表上,并且这些系列的配色方案非常相似。此外,由于它非常简洁,几乎没有任何空间来添加额外的上下文数字。这使得人们很难了解整个故事。因此,我们如何改善这一点,以更好地向公众说明?
你的使命,你是否应该选择接受它
我们今天的挑战是让这张图表更简单,同时显示额外的信息。这对于那些进一步研究图表和分析数据的人来说至关重要,但与此同时,这也将迎合对高水平数字感兴趣的更广泛的受众。我根据相同的数据创建了两个不同的选项,但是使用了两个不同的图表。
方案一:更进一步
有一种方法可以快速提升原有观想,而不需要做太多改变。我们可以将它保留为柱形图,但我们可以将它堆叠起来,而不是将 3 个不同的系列一个接一个地显示出来。这将把 3 个系列减少为 1 个,仅显示雇员,堆叠区域将显示逐年增加/减少。结果如下:
这样做的结果是一个更清晰的图表,您可以很容易地看到同比增长是正还是负,并显示所有 3 个高水平的数字:
- 2018 年员工数量
- 2019 年员工增减数
- 2019 年底员工总数
这是唯一的选择吗?不,肯定不是,但这是我们可以利用的。如果我们考虑排名(例如体育),他们倾向于从上到下,而不是从左到右,反之亦然。这也是我们的眼睛喜欢解释这些结果的方式。所以——回到制图板。
方案二:我们来排列一下
我准备用一个普通的条形图,而不是堆积柱形图。这一次我不想使用堆叠版本,因为我想使用额外的空间来引入更多的数字细节。
在选项 1 中,我使用了 3 种颜色来代表 2018 年和 2019 年期间员工的增加/减少。方案 2 使用 2 种颜色,一种代表 2018 年(灰色),一种代表 2019 年(蓝色)。我选择显示 2019 年底的员工人数,因为这是我们追求的关键数字。额外的数字细节已添加到条形内,并反映了 2019 年的增加/减少以及同比百分比变化。不同于关注总人数,年度同比数据清楚地表明,增长最高的是 Veriff,他从 65 名员工增加到 305 名员工,增加了 240 ,反映出 369% 的同比变化。
结论
生成不同的图形很容易,但让它们变得容易理解却是另一回事。我在本文中提出的两个选项以更有意义的方式引出了故事,而不是本文中提出的原始图表。
再一次,让我们不要考虑我们使用的图表和图形的视觉方面,而是更多地考虑如何让看到这些视觉化的人们容易地使用它们。
来源:
*** 数据&图形 ***—Delfi arileht—https://arileht . Delfi . ee/news/uudised/eesti-idufirmad-kasva sid-mullu-taas-Lendu-tousis-uus-staar?id=88948031
数据即使用 Python 和 Tableau:从 API 调用到托管仪表板
互动图表是视觉叙事的关键。
Tableau 仪表板,我们将在本文中创建。
构建信息图通常在您第一次浏览数据时就开始了。 Matplotlib、Seaborn 和 ggplot2 是经典的编程图表,而 Plotly 也大受欢迎。但对我来说,没有什么比得上画面的干净专业美感。在本文中,我们将抛开内联 Jupyter 笔记本图表,学习如何使用 Tableau Public 创建托管的交互式图表。
本文由三部分组成:
- 研究 — **你的主题是什么,你将如何提取数据?在本文中,我们将了解BLS 劳工统计局的 API。**我们能够使用带有参数的 HTTP POST 请求来检索数据,这些参数包括每个 BLS 查询的查询 id。我们需要的数据是各州的失业数据。
- 数据清理 —使用 python,我们将调用 BLS API,并使用 Pandas 将数据清理成整齐的垂直格式。这可以用 Jupyter 笔记本或 Python 脚本来完成。数据将保存到 CSV 文件和 SQLite 数据库中。
- Tableau —创建一个 choropleth(地理)地图和一个树形地图,并将图表发布给 Tableau Public。我们将能够共享带有嵌入链接的图表。
您可以遵循我的 GitHub repo 中的查询和清理数据部分!这是一篇来自新冠肺炎疫情的失业分析的姊妹篇。
这个笔记本描述了几个查询美国劳工统计局 API 的例子,并把数据整理成一个…
github.com](https://github.com/rchardptrsn/COVID-Employment-Analysis)
第 1 部分:研究和查询数据
Bureau of Labor Statistics API 是一个 REST API ,它基于惟一的查询 id 提供数据。BLS 查询 id 基于许多因素,如州和行业。要找到查询 ID,您需要浏览到 BLS 数据库、表格&计算器并找到与您的数据相关的类别。各州的失业情况可以在“本地失业统计——一屏搜索”中找到。您会注意到每个查询都有一个惟一的 ID。如果您可以确定模式,您可以通过编程方式生成这些 id,而不是复制和粘贴。
第 2 部分:查询 API 和清理数据
在 GitHub repo 中,有一个名为 blspandas.py 的模块,它具有包装器函数,用于清理和执行检索数据的 HTTP POST 请求(Credit:BD Economics)。下面的脚本调用这些函数来创建一个查询 id 列表,执行 HTTP 请求,并将结果保存为 pandas 数据帧。
blspandas.py 模块的一个关键部分是clean_bls_data(combined_queries)
函数。在我们运行df = blspandas.clean_bls_data(combined_queries)
之前,我们的数据是这样的:
我们需要像《T2》一样的整齐垂直格式的数据。熊猫融化对于这种转变来说再合适不过了。
运行df = blspandas.clean_bls_data(combined_queries)
后,数据如下所示:
清理数据的目标
为此,让我们思考一下我们最终需要什么。我们的目标是创建一个 choropleth 图和一个树形图,显示从 2020 年 1 月到 2020 年 6 月的失业率变化。这将描述新冠肺炎疫情对劳动力市场的影响,并显示哪些州没有反弹。
我们需要做的是找出每个州两个日期之间的失业率差异。我们将通过定位包含这两个日期的所有日期行,并从六月份的失业人数中减去一月份的失业人数。
产生的chg_emp
数据帧如下所示:
这就是我们创造画面视觉效果所需要的一切!只需通过运行以下命令将chg_emp
数据帧写入 CSV 文件:
chg_emp.to_csv('Change in unemployment by state.csv', index=False)
第三部分:画面
此时,要么注册 Tableau Public,要么购买该软件。作为一名学生,我可以免费注册并获得完整的桌面版本。
Choropleth 图
通过将 CSV 文件导入工作簿来加载数据。单击新工作表,并按如下方式进行配置:
你会注意到在“标记”下面还有其他选项来显示每个州的名称和失业情况。
树形地图
对于树形图,我们将显示相同的数据,但是以一种允许更多细节的方式,包括州名和失业率的变化。在标记下,您需要:
- 状态标签
- 失业百分比的颜色
- 失业百分比标签
创建仪表板
您可以通过单击“仪表板 1”并拖动两个工作表来创建仪表板。在这里,我将 Choropleth 排列在树状图的顶部。
推送到 Tableau Public
最后,我们将把 Tableau 工作簿推送到 Tableau Public。
为此,我们需要提取我们的 CSV 数据源。这将允许工作簿作为单个捆绑文件上传到 Tableau Public。
一旦摘录完成,我们可以将我们的工作簿发布到 Tableau Public。
上传到 Tableau 后,它将在您的浏览器窗口中打开。此时,您只需点击右下角的“共享”按钮,将链接发送给您的朋友,即可共享您的仪表盘!点击这里查看我的托管仪表板版本!
嵌入式仪表盘
您有几个选择:
- 嵌入脚本—这可以嵌入到 html 中,以提供 Tableau Public 的实时仪表板版本。这篇文章演示了如何将动态仪表盘嵌入到 WordPress 博客文章中。
- 不幸的是,您不能在中型文章中嵌入 live dashboard。
- 另一个不错的选择是在一个简单的 python web 服务器上嵌入仪表板。
感谢您的阅读,我希望您和我一样发现 python+Tableau 堆栈很有吸引力!
数据即 Python:应用和仪表板
Markus Spiske 摄于 Pexels
探索 Python 中最流行的开源数据可视化工具
作为一名顾问数据科学家,我非常清楚将我的工作总结到仪表板和应用程序中的重要性。
这让我能够推广我的算法和工作,并将它们放入直觉图形中,以便更好、更快地理解。在本文中,我们将介绍设计dashboards
和applications
时使用的最著名的工具和python
库。
目录
摘要如下:
- 阴谋地破折号
- 流线
- 散景
- 基巴纳
- Heroku 部署
神秘地闪过
Dash 是 Plotly 开发的开源工具。它允许插入多种类型的小部件,可以选择布局和样式,因为 dash 的布局是基于 HTML 的,并允许 CSS 样式。
通过运行以下命令行完成设置:
pip install dash
pip install dash_core_components
pip install dash_html_components
dash 应用程序的布局是组件的层次树,是 HTML 元素和图形的混合,使用:
- dash_html_components 库提供了所有 html 标签的类,关键字参数描述了 HTML 属性,如样式、类名和 id。使用这个库,我们可以添加 HTML 元素,比如
Div, H1, P,... etc
。更多细节,我建议你查看它的文档。 - dash_core_components 库生成更高级别的组件,如控件和图形,并使用 Plotly 的语法。例如,我们可以插入一个
Button, Dropdown, Slider,DatePickerRange, ... etc.
。更多详情请访问官方网站。
可以使用以下 python 代码开发一个简单的 Dash 应用程序:
import dash
import dash_core_components as dcc
import dash_html_components as html
app = dash.Dash(__name__)
app.title='Hello World'
app.layout = html.Div(children=[
html.H1(children='Hello Dash!', style={'textAlign':
'center', 'color': '#7FDBFF'}),
html.Div(children='''
Dash: A web application framework for Python.
'''),
dcc.Graph(
id='example-graph',
figure={
'data': [
{'x': [1, 2, 3], 'y': [4, 1, 2], 'type': 'bar',
'name': 'SF'},
{'x': [1, 2, 3], 'y': [2, 4, 5], 'type': 'bar',
'name': u'Montréal'},
],
'layout': {
'title': 'Dash Data Visualization'
}
}
),
])if __name__ == '__main__':
app.run_server(debug=True)
选项debug=True
允许考虑最近的修改,而无需重新运行应用程序。
要运行应用程序,我们使用以下命令行:
python app_file.py
你可以在 http://127.0.0.1:8050/ 上运行以下应用程序:
作者图片
式样
可以添加一个覆盖应用程序基本样式的 CSS 文件,允许您自定义图形和 HTML 元素。为此,文件夹的结构应该如下所示:
app.py
assets/
|-- style.css
|-- custom-script.js
|-- img.png
|-- background.jpg
|-- favicon.ico
必须将 CSS 文件和所有其他插入的图像放在一个名为assets
的文件夹中,以便 Dash 读取。一旦完成,我们所要做的就是使用以下 python 行指定样式表:
external_stylesheets=["assets/style.css"]
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
引导程序
当构建 dash-app 时,我个人更喜欢使用 Bootstrap。这是一个用于 Plotly Dash 的 python 库,包含样式化和高级元素。
使用以下命令行完成设置:
pip install dash-bootstrap-components
将 bootstrap 主题作为样式表之一包括进来是很重要的:
external_stylesheets=["assets/style.css", dbc.themes.BOOTSTRAP]
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
Boostrap 包含了DropDownMenu, Navbar, Progress, Button, ... etc
等很多元素。最有用的元素之一是Layout
,它允许使用行和列来构建仪表板,这对应用程序的结构非常有用。
欲了解更多详情,请随时访问官方文档。
复试
像任何其他应用程序一样,支持图形之间的交互性是很重要的,这可以通过回调函数来实现。
每个插入元素都有两个重要特征
- id :元素的唯一称谓
- 属性:元素与元素不同
链接应用程序中的两个元素的方式如下:
作者图片
在这种特殊情况下,第一个元素影响第二个元素:通过其 id_1 选择的第一个元素的 property_1 影响通过其 id_2 访问的第二个元素的 property_2 。
from dash.dependencies import Input, Output
@app.callback(
Output(component_id='id_2', component_property='property_2'),
[Input(component_id='id_1', component_property='property_1')]
)
def callback_function(input_value):
"""
What to do
"""
NB :在回调函数中可以接受多个输入。
隐藏物
当开发一个应用程序时,在缓存中保存元素是非常重要的,这样可以减轻加载的负担,提高交互性,缓存允许这样做。
Dash 不支持特定的缓存特性,但是克服这个问题的一个方法是在 python 中使用global variables
。
制表符
Dash 中的选项卡可以使用dcc.Tab
组件插入,其中其子项是组成选项卡的元素。
import dash
import dash_html_components as html
import dash_core_components as dcc
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
app.layout = html.Div([
dcc.Tabs([
dcc.Tab(label='1st Tab', children=[
dcc.Graph(),
###
]),
dcc.Tab(label='2nd Tab', children=[
dcc.Graph(),
###
]),
dcc.Tab(label='3rd Tab', children=[
dcc.Graph(),
###
]),
])
])
走廊
Dash 有一个图库,你可以在那里浏览和发现其他仪表盘,这是一个很好的基线和灵感来源。
细流
Streamlit 是一个开源应用程序框架,主要用于使用 python 以快速高效的方式创建 ML 仪表盘。设置非常简单,可以使用以下命令行来执行:
pip install streamlit
与 Dash 相比,Streamlit 具有更好的缓存处理能力,这将在接下来的章节中进行介绍,因此可以使用以下流程实现更快的开发迭代:
streamlit.io
一旦创建了您的文件,您可以键入这个命令行,它将在 http://localhost:8501 上运行您的应用程序
streamlit run file.py
和 Dash 一样,可以选择模式Always re-run
来实时修改。
Streamlit 的 widgets gallery 包含多个条目,它们都可以使用一行代码插入:Markdown
、SelectBox
、Slider
、Plot
等…注意,小部件可以插入到one-page area
或sidebar
中,插入是在vertical stacking
之后完成的:
import streamlit as st
import matplotlib.image as mpimg
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from sklearn import datasets
from sklearn.decomposition import PCA
import pandas as pd
img=mpimg.imread('imgs/streamlite_funct.png')
iris = datasets.load_iris()
feature_names=['sepal length (cm)',
'sepal width (cm)',
'petal length (cm)',
'petal width (cm)']
database=pd.DataFrame(iris.data, columns=feature_names)
database["class"]=iris.target
# plot the first three PCA dimensions
fig = plt.figure(1, figsize=(8, 6))
ax = Axes3D(fig, elev=-150, azim=110)
X_reduced = PCA(n_components=3).fit_transform(iris.data)
ax.scatter(X_reduced[:, 0], X_reduced[:, 1], X_reduced[:, 2], c=iris.target,
cmap=plt.cm.Set1, edgecolor='k', s=40)
ax.set_title("First three PCA directions")
ax.set_xlabel("1st eigenvector")
ax.w_xaxis.set_ticklabels([])
ax.set_ylabel("2nd eigenvector")
ax.w_yaxis.set_ticklabels([])
ax.set_zlabel("3rd eigenvector")
ax.w_zaxis.set_ticklabels([])
def main():
########### Sidebar ##############################
st.sidebar.markdown("# Hello World")
st.sidebar.selectbox('Select a tool', ["Dash", "Kibana", "Streamlit", "Bokeh"])
st.markdown("## Multiselection")
st.multiselect('Select a tool', ["Dash", "Kibana", "Streamlit", "Bokeh"])
st.markdown("## Radio buttons")
st.radio('Select a tool', ["Dash", "Kibana", "Streamlit", "Bokeh"])
st.markdown("## Slider")
st.slider('Select a Number', min_value=1, max_value=4, value=1)
st.markdown("## Image")
st.image(img, width=500)
st.markdown("## DataBase")
st.dataframe(database)
st.markdown("## Plot")
st.write(fig)
if __name__ == "__main__":
main()
我们得到以下应用程序:
作者图片
函数st.write
非常重要,可以用来插入很多 python 元素。要了解更多细节,我建议您阅读 streamlit 的文档。
交互性:每个元素都可以被赋予一个代表其当前值的变量,接下来,它可以被用来更新另一个元素,从而更新交互性。
隐藏物
缓存通常用于存储恒定的数据,无论在应用程序上做出何种选择,这些数据都不会改变。我们可能经常在应用程序中定义函数,但每次刷新应用程序时都不需要重新运行这些函数,我们可以使用以下 python 代码缓存这些函数:
@st.cache
def function_1():
####
制表符
在许多应用程序中,选项卡可能非常重要:在 Streamlit 中实现这一点的一种方法是在侧边栏中添加一个selectbox
,它的选择将影响仪表板的结构,并在框的值上使用 if 语句。
st.sidebar.markdown("Tabs")
tab=st.sidebar.selectbox('Select a Tab', ["Home", "Documentation", "Partners", "Contact"])
if tab=="Home":
#Develop the one_pager
##
elif tab=="Documentation":
###
elif tab=="Partners":
###
elif tab=="Contact":
###
健康应用——Streamlit
当我开始发现 Streamlit 时,我决定通过开发一个简单的健康应用程序来投入使用。
作者图片
您可以使用这个 url 访问应用程序,脚本托管在这个 git 存储库中。更多 app 可以访问官方图库。
散景
Bokeh 是一个 python 库,允许创建一个交互式仪表板。可以使用以下命令行安装它:
pip install bokeh
例如,可以使用以下 python 脚本创建以下应用程序:
作者图片
from bokeh.io import show, curdoc
from bokeh.plotting import figure, ColumnDataSource
from bokeh.layouts import row, column
from bokeh.models.widgets import Tabs, Panel
from bokeh.models import Slider, CheckboxGroup, RadioGroup, Button, CustomJS
#data source
x = [x*0.005 for x in range(0, 200)]
y = x
source = ColumnDataSource(data=dict(x=x, y=y))
#Plots
plot_1 = figure(plot_width=400, plot_height=400)
plot_1.line('x', 'y', source=source, line_width=3, line_alpha=0.6)
plot_2=figure(tools='box_zoom, lasso_select')
plot_2.circle(x=[1,2,3,4,5], y=[2,3,1,1,2])
plot_2.background_fill_color = 'black'
plot_3=figure(tools='box_zoom, lasso_select')
plot_3.circle(x=[1,2,3,4,5], y=[2,3,1,1,2])
#widgets
slider = Slider(start=0.1, end=4, value=1, step=.1, title="power")
button = Button(label='Click')
checkbox = CheckboxGroup(labels=['Kibana', 'Bokeh', 'Streamlit', 'Dash'])
radio = RadioGroup(labels=['Kibana', 'Bokeh', 'Streamlit', 'Dash'])
#Interactivity
callback = CustomJS(args=dict(source=source), code="""
var data = source.data;
var f = cb_obj.value
var x = data['x']
var y = data['y']
for (var i = 0; i < x.length; i++) {
y[i] = Math.pow(x[i], f)
}
source.change.emit();
""")
slider.js_on_change('value', callback)
#Plots zoom-linking
plot_2.x_range=plot_3.x_range
plot_2.y_range=plot_3.y_range
#Tabs
first=Panel(child=row(column(slider, button, checkbox, radio), plot_1), title='first')
second=Panel(child=row(plot_2,plot_3), title='second')
tabs=Tabs(tabs=[first, second])
#App
curdoc().add_root(tabs)
show(tabs)
注意,一旦我们定义了图形plot
,我们就使用语法plot.graph
来为它分配想要的图形。使用ColumnDataSource
处理数据,使用row, column
布局。我们定制添加的小部件Slider, CheckboxGroup, RadioGroup, Button
,并使用 JS 回调CustomJS
将它们链接到图形。要在http://localhost:5006/myapp上运行您的应用程序,您可以使用以下命令行:
bokeh serve --show myapp.py
走廊
和所有其他工具一样,散景一开始就有非常丰富的图库。
弹性堆叠
弹性搜索
Elasticsearch 是一种特殊类型的表格索引,它提供了一个更快的搜索引擎。我们可以将 pandas 数据库转换成一个Elasticbase
,然后使用 Kibana 可视化它,Kibana 是 stack Elastic 的可视化工具。首先,你需要根据你的操作系统下载Kibana&elastic search。安装后,我们将使用 elasticsearch 正确地索引我们的熊猫数据框架。为此,我们首先需要使用命令行启动服务 elasticsearch 和 kibana:
./elasticsearch-7.6.1/bin/elasticsearch
./kibana-7.6.1/bin/kibana
一旦 Kibana 启动,我们就可以使用这个 python 脚本向 Elasticsearch 服务发送数据
import pandas as pd
from elasticsearch import Elasticsearch
# Database loading and service openning
database=pd.read_excel("data/test_db.xlsx")
es_client = Elasticsearch(http_compress=True)
#Elasticsearch does not accept NAN values
print(database.isna().sum().sum())
df=database.copy()
INDEX="laposte" #Its name in Elasticsearch (laposte for example)
TYPE= "record"
def rec_to_actions(df):
import json
for record in df.to_dict(orient="records"):
yield ('{ "index" : { "_index" : "%s", "_type" : "%s" }}'% (INDEX, TYPE))
yield (json.dumps(record, default=int))
e = Elasticsearch()
r = e.bulk(rec_to_actions(df))
#Verify if everything went fine
print(not r["errors"])
基巴纳
servie kibana 在本地主机的端口5601
上启动,我们可以使用地址localhost:5601
在浏览器中访问它。一旦进入主页面,我们可以点击Dashboard
和Create dashboard
,如下所示:
作者图片
我们现在可以通过以下步骤添加小部件:
作者图片
可以使用光标定位插入的图形,这使得布局易于定制。请注意搜索栏的存在,其中的数据是使用 Elasticsearch 索引的,这使得查询耗时更少,并增加了仪表板的交互性,尤其是在处理大型数据库时。交互在 kibana 中自动处理。
作者图片
制表符
Kibana 中的选项卡可以使用 markdowns 小部件中的嵌入式链接来创建。您首先在不同的仪表板中创建所有选项卡,然后在每个选项卡中添加到其他选项卡的嵌入链接。
走廊
不要犹豫去参观基巴纳的官方画廊。
Heroku 部署
应用程序开发完成后,您可以在线托管它,这样任何人都可以使用 Url 访问它。一种方法是使用 Heroku,它提供这种有一些限制的免费服务。你首先需要注册,然后在线创建一个 heroku 应用程序,它将链接到你的 git 库。回购应具有以下结构:
.
├── app.py
├── requirements.txt
├── setup.sh
└── Procfile
您可以查看我的 git 存储库了解更多信息。在本地 git 文件夹上运行以下命令行:
heroku create
git push heroku master
heroku ps:scale web=1
heroku open
你的应用程序会一直等待你在 git 中的每一次推送,以便考虑最新的变化。
结论
应用程序和仪表板是每个项目非常重要和决定性的阶段,它们允许总结我们的工作,并通过一个本能的界面让用户更容易访问。每种技术的使用主要取决于您的交付和截止日期:一些工具允许更大的灵活性,另一些工具开发起来更快:
作者图片
在我个人看来,如果所有条件都满足,Dash
可以是最佳的搭配选项。
原载于 2020 年 5 月 20 日 https://www.ismailmebsout.com。
数据仓库综合指南
在数据清理过程完成之前,数据科学无法启动。了解数据仓库作为可用于分析的数据集的存储库的角色。
在企业环境中寻找干净的数据。陈虎在 Unsplash 上拍照。
作为一名数据科学家,了解一些基本的数据仓库概念是很有价值的。我们所做的大部分工作都涉及到在需要清晰易懂的数据集上增加企业价值。对于达到其生命周期的那个阶段的数据集,它已经通过了数据架构的许多组件,并且希望通过许多数据质量过滤器。这就是我们如何避免数据科学家最终将 80%的时间花在数据争论上的不幸情况。
让我们花点时间通过了解与建立数据仓库相关的各种考虑来加深对数据架构过程的理解。
数据仓库是一个特定的基础设施元素,它为包括数据分析师和数据科学家在内的线下用户提供对数据的访问,这些数据已经过整形以符合业务规则并以易于查询的格式存储。
数据仓库通常连接来自多个“真实来源”事务数据库的信息,这些数据库可能存在于单个业务单元中。与存储在事务数据库中的信息不同,数据仓库的内容被重新格式化,以提高查询速度和方便性。
数据必须符合验证质量的特定业务规则。然后,它被存储在一个非规范化的结构中——这意味着将可能被一起查询的信息存储在一起。这有助于通过降低从仓库中获取数据所需的查询的复杂性(即,通过减少数据连接的数量)来提高性能。
在本指南中:
构建数据仓库
在为数据仓库开发 维度模型 的过程中,设计通常会经过三个阶段:(1)业务模型,它根据业务需求概括数据,(2)逻辑模型,它设置列类型,(3)物理模型,它代表关系数据仓库的实际设计蓝图。
因为数据仓库将包含来自业务各个方面的信息,利益相关者必须事先同意将要存储的数据的(即粒度级别)。
一个假设的 safari tours 业务的示例星形模式。
数据仓库中的底层结构通常被称为 星型模式 —它将信息分类为维度或事实(即度量)。 事实表 存储观察或事件(即销售、订单、库存余额等。)维度表包含关于这些事实的描述性信息(即日期、位置等。)
有三种不同类型的事实表:(1)标准化粒度的事务记录,(2)给定时间范围内的定期记录,(3)给定业务流程内的累积记录。
除了星型模式,还有将数据排列到雪花模式的选项。这里的区别是每个维度都是归一化的。
规范化是一种数据库设计技术,用于创建包含原子级信息的记录。
然而,雪花模式给维度模型增加了不必要的复杂性,通常星型模式就足够了。
增强性能并根据大小进行调整
除了了解如何构建数据之外,设计数据仓库的人还应该熟悉如何提高性能。
一种增强性能的技术是按照通常的查询顺序对数据创建一个聚集索引。例如,我们可以选择按旅游日期降序来组织事实表,这样接下来的旅游将首先显示在表中。建立聚集索引会对记录的物理存储方式进行重新排序,从而提高检索速度。除了可选的单个聚集索引之外,一个表还可以有多个非聚集索引,这些索引不会影响表的物理存储方式,而是会在内存中创建额外的副本。**
另一个性能增强包括将非常大的表分成多个较小的部分。这叫做分区。通过将一个大表分割成更小的单个表,只需要访问一小部分数据的查询可以运行得更快。分区可以是垂直的(拆分列)或水平的(拆分行)。这里有一个链接,你可以在这里下载。rtf 文件包含用于 SQL 的分区脚本以及其他数据库架构资源,如项目启动和管理清单。
是的,我会偷你的免费资源和有用的工具。由Slawek在 Unsplash 上拍照
考虑总数据库大小是调优性能的另一个关键因素。根据服务级别协议(SLA) ,在设计数据仓库时估计结果数据库的大小将有助于使性能与应用程序需求保持一致。此外,它将提供对物理磁盘空间的预算需求或云存储成本的洞察。
要进行这种计算,只需合计每个表的大小,这很大程度上取决于索引。如果数据库的大小明显大于预期,您可能需要规范化数据库的某些方面。相反,如果您的数据库变小了,您可以进行更多的非规范化,这将提高查询性能。
相关数据存储选项
数据仓库中的数据可以重新组织成较小的数据库,以满足组织的需要。例如,一个业务部门可能会创建一个数据集市,提供特定于他们部门的信息。这个只读信息源为那些可能不太了解数据架构技术细节的业务用户提供了清晰度和可访问性。这里有一个创建数据集市时要部署的规划策略。
类似地,可以为操作报告建立一个操作数据存储(ODS) 。 主数据管理(MDM)系统 存储有关独特业务资产的信息(即客户、供应商、员工、产品等。)
使用大数据
为了处理大数据,数据架构师可能会选择实施一种工具,如 Apache Hadoop 。Hadoop 基于谷歌开发的用于索引万维网的 MapReduce 技术,并于 2006 年向公众发布。在高度结构化的数据仓库环境中,信息已经过上游验证以符合业务规则,与此相反,Hadoop 是一个软件库,它接受各种数据类型,并允许跨计算机集群进行分布式处理。Hadoop 通常用于处理流数据。
Hadoop 加快了多台计算机集群的数据处理速度。通过 GIPHY 。
虽然 Hadoop 能够快速处理流数据,但它在查询速度、查询复杂性、安全性和编排方面存在问题。近年来,随着基于云的解决方案(例如 Amazon Kinesis )的崛起,Hadoop 已经不再受欢迎——在处理非结构化数据的速度方面提供了相同的收益,同时与云生态系统中解决这些潜在弱点的其他工具相集成。
提取、转换、加载(ETL)
提取 、 转换 、 加载 定义将数据移出其原始位置(E),进行某种形式的转换(T),然后将其加载(L)到数据仓库中的过程。数据库架构师应该着眼于实现一种系统化的方法,考虑到围绕设计考虑、操作问题、故障点和恢复方法的最佳实践,而不是以一种特别的、零碎的方式来处理 ETL 管道。另请参见这个关于设置 ETL 管道的有用资源。
*ETL 的文档包括创建*源到目标的映射:关于如何将源系统中的数据结构和内容转换为目标系统的结构和内容的一组转换指令。这里有一个用于此步骤的样本模板。
您的组织也可以考虑 ELT——加载没有任何转换的数据,然后使用目标系统的能力(通常是基于云的工具)来执行转换步骤。
从仓库中获取数据
一旦建立了数据仓库,用户应该能够方便地从系统中查询数据。优化查询可能需要一些培训,重点是:
数据存档
最后说一下优化你组织的 数据归档 策略。存档的数据对组织来说仍然很重要,对于希望使用历史趋势进行回归的数据科学家来说尤其重要。
数据架构师应该针对这一需求进行规划,将不再频繁使用的历史数据重新定位到一个具有更高延迟和强大搜索功能的独立存储系统中。将数据移动到成本较低的存储层是这一过程的一个明显优势。组织还可以从取消对归档数据的写访问中获益,保护数据不被修改。
摘要
本文涵盖了建立数据仓库的可靠实践。通过发表评论,让我知道你是如何在工作中使用这些信息的。
遵循这些步骤,你将成为数据丛林之王。由 Pixabay 在像素上拍摄的照片。
****如果你觉得这篇文章对有帮助,请关注我的 Medium 、 LinkedIn 和 Twitter ,了解更多提升你的数据科学技能的想法。
如何提高数据仓库的数据质量
Google 的 BigQuery 的演练示例
照片由安德里亚斯·古尔霍恩在 Unsplash 拍摄
您可以在数据仓库流程中构建一些简单的数据质量检查,以检测由于 ETL/ELT 管道中的错误或连接失败而导致的数据不一致。衡量数据质量和快速检测错误总是一个好主意,否则会导致消费者缺乏信任。下面的文章将向您展示一些易于在源系统和目标系统之间进行数据一致性检查的方法——例如数据仓库或数据湖。
数据质量测量流程—作者提供的图片
通过计数行检查表格
检测源系统和目标系统之间偏差的一个非常简单的检查是计算两个系统中表的行数。当然,这种检查只有在源系统和目标系统中有相同的表结构时才有意义,这是通过 ELT 过程实现的。
大查询中的行数示例:
SELECT count(1) FROM `double-silo-282323.Test_Data.table_1` ;
SELECT count(1) FROM `double-silo-282323.Test_Data.table_2`
您可以在两个系统中手动完成这项工作,但是自动方法会更好——例如,通过 ETL 工具将计数结果从源系统带到您的数据仓库/Lake,并创建如下图所示的报告:
示例报告—按作者分类的图像
您还可以通过触发警报(例如使用云功能)并通过电子邮件发送给数据工程师来改善这种情况。
通过业务关键数字检查表格内容
要检查表的内容是否相同,除了计算行数之外,还需要其他技术。一个例子是关键数字的使用。您可以对某些行(如价格或金额)求和,并检查源系统表和目标系统表的总和是否相同。这里的挑战是找到好的关键人物。建议与业务部门合作。然而,您不需要太多的计算能力就可以实现这种检查,只需要 SQL 中一个简单的SUM()
函数。
单一数据记录检查
要检查每一列和每一个值,可以使用下面的语句— UNION ALL
of two EXCEPT DISTINCT
:
(
SELECT * FROM `double-silo-282323.Test_Data.table_1`
EXCEPT DISTINCT
SELECT * from `double-silo-282323.Test_Data.table_2`
)UNION ALL(
SELECT * FROM `double-silo-282323.Test_Data.table_2`
EXCEPT DISTINCT
SELECT * from `double-silo-282323.Test_Data.table_1`
)
结果将是,所有在源或目标系统中不同或不存在的行都被显示出来。
查询结果示例-按作者排序的图像
这是上述方法中最有效的检测数据问题的方法,但也会耗费大量的计算能力和金钱。这是因为像 Big Query 这样的数据仓库技术会对每次查询和查询的数据量进行收费。这里的解决方案可以是每月从源系统的一个完整的表中获取数据,将其写入目标系统,并与数据仓库中的表进行比较。它将向您提供数据是否一致以及 ETL/ELT 过程是否 100%事务安全的信息。
确保数据一致性的其他可能性
您可以实现的其他可能性有:
- 监控您的 ETL/ELT 作业—例如,如果由于连接错误导致数据未能传输,您会收到警报。
- 构建如上所示的报告,并添加信息,如上次刷新数据时的信息。
- 如果您的数据复制过程失败,则实施归档/恢复系统。
- 使用 ELT 而不是 ETL——在紧急情况下或当您必须重新加载大量数据时(ELT 通常比 ETL 过程快得多)。
- 拥有一个处理用户数据质量投诉的流程或票证系统。
- 监控源系统,以便您知道何时出现技术困难。
- 构建您的 ETL/ELT 作业,以便它们能够处理停机时间并重试。
结论
为了快速检测错误和故障,持续监控数据质量和数据传输非常重要。本文中提到了一些方法,但是由于技术设置和成本的原因,您必须找到适合您的过程的方法。但是请记住,数据质量是一个非常重要的话题。否则,您可能会缺乏用户和业务部门的信任。
进一步阅读
[## 标准 SQL | BigQuery | Google Cloud 中的 Abfragesyntax
建议使用一种或多种药片或药片,并在技术上加以改进。在…
cloud.google.com](https://cloud.google.com/bigquery/docs/reference/standard-sql/query-syntax?hl=de) [## 基于 MaxCompute 的数据仓库数据质量管理
作者:海清
alibaba-cloud.medium.com](https://alibaba-cloud.medium.com/data-quality-management-of-data-warehouses-based-on-maxcompute-2ca15c698bee)
面向娱乐和非营利组织的数据堆栈—第一部分
为您的副业项目选择数据仓库
萨拉·库菲在 Unsplash 上拍摄的照片
驱动几乎所有数据科学团队的引擎是某种形式的数据仓库,它充当组织中各种不同数据源的中央收集点和存储库。这些来源可能包括组织的主要事务性数据库、日志、电子邮件、SaaS API、CRM、ERP 以及各种形式的随机平面文件。数据仓库的目的是将所有这些数据收集到一个真实的数据源中,并通过一个访问点方便用户访问。此工作流中的终端可能是手动 SQL 查询、某个 BI 平台或数据科学家的自动化模型培训工作流。
图片来自 dbt,这是一个令人惊叹的开源数据仓库管理框架。
当数据仓库得到组织的财政支持时,它们是一种有用的资源,但是个人数据从业者如何为了个人项目的目的或作为培训资源来模仿这种经验呢?一个人如何用个人预算创建自己的个人数据仓库?这是一个我长期以来一直在寻找满意解决方案的问题,因此这是我将探索现代分析平台产品生态系统中一些可用选项的系列博客帖子中的第一篇。这第一部分将主要集中在想象标准和一些可能的解决方案堆栈可能看起来像什么,然后稍后我将调查和评估不同的选项。
显而易见的初步答案是建立一个本地 PostgreSQL 数据库,并编写一些 Python/R/SQL 代码等。,但这并不完全模拟我们所追求的确切体验。它对学习一些 SQL 和手工 ETL 工作流的痛苦很有用,但它缺乏远程数据存储、灵活的可伸缩性、配置 CI/CD 工作流以及利用互联网可访问的数据存储作为各种 BI 解决方案的中心的能力。在我教的数据科学课程中,学生们经常表示有兴趣将访问大规模数据仓库平台作为课程的一部分,这显然是非常昂贵的,但我可以理解学生们为什么觉得创建玩具 SQLite 数据库并不能满足他们的需求。
理想的个人数据仓库应该是什么样的?嗯,理想情况下,它应该是便宜的,因为我们大多数人可能都希望避免支付与常见的 SaaS 平台相关的高额月费。在可能的情况下,无服务器将比连续服务器更受欢迎。大多数情况下,我们希望数据处于静态(产生最小的费用),只有在加载和转换操作需要时才会产生计算费用。我们可能还希望尽可能地减少配置和管理负担,因为我们不太可能从系统管理员那里获得支持。任何开源组件可能也是可取的。
因此,在我们探索哪些选项符合这些标准之前,让我们首先简要回顾一下我们寻求利用(廉价)或替换的平台的当前生态系统。为了存储我们的数据,我们有几个仓库平台可供选择,包括亚马逊红移,谷歌大查询,以及雪花。
ETL (Extract/Transform/Load)传统上是开发和维护数据仓库中最费力的工作之一,通常涉及 SQL、Python 等重要的软件工程。今天,我们有许多可用的商业平台,它们抽象出了 ETL 系统中固有的大量重复逻辑。其中包括五针、针和针。
在数据可视化方面,我们有 BI 平台,包括 Tableau、Looker、PowerBI 等等。其中一些有免费/公共版本,但是我们也有足够的能力通过 Shiny、Jupyter 和更多我不想列举的技术来制作我们自己的仪表板。出于本系列的目的,我们将主要关注栈的数据存储和 ETL 部分。
我确信我想要包括的一个组件是令人惊奇的开源的 dbt。
dbt 是一个开发环境,它使用任何地方的数据分析师的首选语言— SQL。借助 dbt,分析师可以掌控整个分析工程工作流程,从编写数据转换代码到部署和文档。
使用 dbt,您可以按照最古老的软件工程最佳实践之一来编写数据转换代码:模块化。编写模块化 SQL 意味着您的查询更容易更新和故障排除,并且执行速度会大大加快。
简而言之,dbt 是一个强大而方便的框架,用于组织仓库中的所有转换和数据模型。像 Fivetran 和 Stitch 这样的 ETL 平台非常适合将数据加载到您的仓库中,但是生成的数据可能不会按照您希望的方式进行组织,并且您可能还希望集成其中的一些数据源。这就是 dbt 的用武之地。该工具本身是免费的,他们的云部署平台也有一个适合个人项目的免费层,还有一个活跃在 Slack 和 Discourse 上的优秀用户社区。
**(左)**图片由雪花 | **(中)**图片由谷歌— BigQuery | **(右)**图片由亚马逊网络服务—雅典娜
数据存储呢?根据我们的搜索标准,基于传统服务器的平台(如 Redshift)不在选择之列。虽然我很喜欢雪花,但它没有任何适合我们需求的(永久)免费层。这是一个现收现付的平台,所以有可能将成本降到最低,但我不太确定成本会维持在多低的水平。事实上,似乎有一个 25 美元的每月最低限额是不可行的,但我不一定完全排除雪花。
AWS Athena 是一个有趣的选择。它是 Presto 的无服务器部署,位于您自己的 S3 对象之上。您只需为运行查询和低得可以忽略不计的 S3 存储成本付费。Athena 有 event dbt 支持,但目前还处于早期开发阶段。雅典娜看起来肯定是个不错的选择。
另一个我之前没有考虑过的选项是 Google 的 BigQuery。我总是把 BigQuery 归为 GCP 的红移或雪花,但事实证明,谷歌实际上提供了一个完整的免费 BigQuery 层,只要你在一定的限制内操作。只要您保持 10GB 的加载存储和 1TB 的查询处理,您就可以完全免费使用 BigQuery!
ETL 平台呢?像 Fivetran 和 Stitch 这样的服务对个人来说可能太贵了。Fivetran 最近确实切换到了基于消耗的定价系统,因此它的利用率可能会被限制在一个低廉的水平。然而,这些付费平台的大部分价值与忠实地将复杂的内部数据库镜像到仓库的挑战更直接相关,而不是摄取格式或多或少相同的平面文件。因此,我认为我们可以将从 API、电子邮件和类似来源提取的数据抽象到其他未来项目中。这些未来提取服务的基本端点是将平面文件存放到对象存储中(S3 或其他)。
有了基于 Athena 的仓库,人们只需开发工作流,将数据提取到 S3 进行暂存。AWS 还提供 Glue 和其他一些编排服务,这些服务可能会保持在成本之下。BigQuery 有类似的兄弟服务,包括数据流和数据存储,以及直接从 Google Storage 和 Google Drive 加载数据的能力。还可以选择从 S3 将数据加载到 BigQuery 中。我说过 BI 选择超出了这个搜索的范围,但是同样值得一提的是 BigQuery 直接集成到了 DataStudio 中。
至此,我认为我们已经有了三个合理的候选筹码:
- BigQuery 数据仓库,使用来自 Google Drive 和 S3 数据传输的数据,用于数据建模的 dbt,以及一些带有 DataStudio 的仪表板。
- Athena 数据仓库,使用 S3 分阶段数据,dbt + dbt-athena 插件进行数据建模。
- 雪花数据仓库,使用外部存储集成和 SnowPipe 进行接收,使用 dbt 进行数据建模,使用 Snowsight 进行仪表板。
我将通过在每个平台上配置帐户并使用 dbt 建立一些简单的数据模型,开始尝试这些选项。在第二部分中,我将分享我对最终架构的想法,该架构似乎最适合低成本的个人项目,并开始深入研究特定于所选平台的仓库设计和工作流编排。
你怎么想呢?你最喜欢的云仓库栈会是什么样子?欢迎在评论中留下你的想法!
数据仓库转换代码有味道
留意 SQL 转换中的这些问题迹象
当涉及到转换代码时,在数据工程中有一个奇怪的范例。虽然我们越来越多地将提取和加载(“EL”)编程作为生产软件标准,但是转换代码仍然被视为二等公民。具有讽刺意味的是,转换代码通常包含复杂的业务逻辑,这可以从像对待软件一样对待软件中获益匪浅。
代码气味是一种表面迹象,通常对应于系统中更深层次的问题。“更简单地说,代码气味是软件中的模式,它要求我们更仔细地观察。您应用程序中的代码气味与冰箱中的实际气味没有什么不同:刺鼻的气味可能表明有令人讨厌的东西存在(就像那盒放了十年的木须肉),或者它可能像林堡干酪一样无害。代码味道并不保证问题存在,通常情况下,最佳重构类似于不同的味道。其价值在于,每一次出现都会提示您,哪种解决方案提供了最易读、最易维护的转换代码。
下面是一组特定于多维数据仓库转换的代码味道。遇到它们会让你停下来,给你机会离开代码库,比你发现它的时候更好。
多列联合语句
COALESCE(reciept_price,
COALESCE(label_price,
COALESCE(catalog_price),0))) AS item_price
翻译成英文:“如果没有收据价格,试试标签价格,如果没有标签价格,试试目录价格,如果其他都不行,把价格算成 0。”
**为什么会有味道:**在少数几列中摸索以获取第一个可用值表明数据没有被很好地理解。要么代码不知道为什么一个列值值得优先选择,要么结果列是几个应该独立的状态的混搭。
**可能的重构:**上面的嵌套联合很可能表示多个独立的状态被强制为假条件。考虑用显式决策树(通常是一个CASE
语句)替换,或者将每个状态分解成不同的事实。
作为标识符的保留字
SELECT user_sp_role AS "ROLE"
翻译成英文:“命名 user_sp_role 列ROLE
,大家就知道是什么意思了。”
数据仓库设计的一个核心原则是界面应该简单。使用保留字(甚至是你的特定方言允许的保留字)会带来复杂性和混淆的机会。
**可能的重构:**坚持使用易于使用的详细标识符,不需要引号,并且将保持所有 SQL 能力的用户都可以访问数据仓库。ROLE
可以更直观地命名为web_application_role
,避免无谓的混淆。
维度中的基本空值
SELECT
customer_name
,customer_address_id # null means we have no address on file
,customer_phone
FROM
customer
翻译成英文:“如果您想要所有没有注册电话号码的客户,只需选择电话号码为NULL
的位置。”
为什么有味道: NULL
在数据仓库世界里是一个非常重要的值。如果一个 join 出错,将会有NULL
值。如果一个group by
失败或者一个窗口函数没有像我们预期的那样滑动,那么就有NULL
值。当NULL
作为合法数据值执行双重任务时,调试变得几乎不可能。除此之外,BI 工具在呈现NULL
值时通常表现不一致,这为 bug 提供了一个完美的藏身之处。
**可能的重构:**不要在维度中使用NULL
值;明确陈述每个可能的条件(即在CASE
语句中使用ELSE
),这样任何NULL
值都会立即引起审查。这不仅会强化您的转换代码,而且有助于最终产品数据的直观性。NULL
可以表示很多东西,但是'No Phone Number Available'
是非常清楚的。
这种味道只适用于维度属性。NULL
数值不仅是正确的,而且是附加事实的重要数据点(如total_sale_value
)。
神奇的数字
SELECT
customer_name
,customer_address
,customer_phone
...
WHERE
customer_unit_id IN (1,3,19)
AND
customer_value_type = "a"
翻译成英文:“我们不再使用客户单元 8 或 13,所以我们忽略它们(ted 说 1、3 和 19 才是最重要的)。我们也只关心主要的网站客户价值类型(Bob 说这些是用‘a’表示的)。
**为什么有味道:**好的代码是自文档化的。这通常意味着你可以在没有解码环的情况下阅读代码并理解它的作用。上面的例子并不是因为复杂的业务逻辑或技术复杂性而具有挑战性,而是因为它充满了部落知识。
**可能的重构:**cte 是很好的数据映射工具:
WITH
value_types AS (
"a" AS primary_website_customer
...
)
...
AND
customer_value_type = value_types.primary_website_customer
当更大的重构不可行时,注释总比没有好。寻找可以更形象地命名的变量和常量,作为一种大大改进代码库的廉价方法。
数据消除
WITH all_visits AS (
SELECT
*
FROM
website_visits
),
SELECT
*
FROM
website_visits
WHERE
visit_id IS NOT NULL
翻译成英语:“网站访问应该总是有一个visit_id
,所以如果他们没有,记录就是坏的,我们应该把它扔出去。”
**为什么有味道:**任何数据仓库的基础都是真理。不仅仅是一些,而是全部的真相,这是破坏性的转换所不能提供的。缺少记录(甚至是“坏”记录)的数据仓库没有可信度,您会很快发现消费者要求访问原始源。
**可能的重构:**转换逻辑应该是附加的,为最终用户提供更大的价值。在上面的例子中,一个新的列valid_record
将过滤到 BI 层中的同一个数据集,同时为消费者提供访问“所有数据”的信心。
假设的商业逻辑
CASE
WHEN user_time_zone IS NULL THEN (last_login time at time zone 'pst')
ELSE (last_login_time at time zone user_time_zone)
END AS last_login_time
翻译成英语:“我们的大部分网络流量来自旧金山湾区,所以如果一个网络访问丢失了时间戳,我们就把它更新到太平洋标准时间。”
**为什么有味道:**数据仓库的工作是为用户提供做出明智决策的能力,而不是为他们做决策。每次转换逻辑为数据选择路径时,它都不可避免地在这个过程中删除消费者的选项。
**可能的重构:**在上面的例子中,最初的last_login_time
将理想地呈现last_login_time_without_timezone
和last_login_time_with_timezone
;最终用户可以自行决定对缺失的时区做出假设。
运行时间作为输入
SELECT
*
FROM
all_records
WHERE
created_at::DATE >= DATEADD('days',-1, CURRENT_DATE())
翻译成英文:“创建日期大于昨天的记录是新记录。”
**为什么有异味:**任何时候,相同的代码可以针对相同的数据运行两次,并返回不同的结果,请考虑这是一个问题。好的转换逻辑既是幂等的又是确定性的。当前日期或时间等不稳定元素会使代码变得脆弱,如果转换作业失败或运行两次,很容易使系统处于不可纠正的状态。
**可能的重构:**以自我修复的方式设计转换。使用相同的示例:
- 如果记录保证增加(没有迟到的记录),只需要稍微修改。
SELECT
*
FROM
all_records
WHERE
created_at > (SELECT MAX(created_at) FROM target_table)
- 源数据的更大波动性要求更大的转换复杂性(和更大的计算成本)。根据记录到达的时间有多晚,可以使用谓词语句将代码限制在一个窗口中。
SELECT
all_records.*
FROM
all_records
WHERE
MD5(all_records.*::TEXT) NOT IN (SELECT MD5(target_table.*::TEXT) FROM target_table)
/*
if records are always < 30 days late, you could restrict the lookup ie (SELECT MD5(target_table.*::TEXT) FROM target_table WHERE target_table.created_at::DATE >= DATEADD('days',-30, CURRENT_DATE()))
*/
不一致的时态、前缀和后缀
SELECT
user_id
,id
,identifier
FROM
users
JOIN
site
...
JOIN
dim_visits
**翻译成英语:**围绕标识符的非结构化语法,列名的不规则前缀,以及缺乏词汇系统。
在数据仓库中,模式就是产品接口。不可预测的词汇会给用户带来不必要的摩擦。桌子是order
还是orders
?栏目是sale_price
还是order_sale_price
?没有模式,这些都是数据仓库可用性的开销。
**可能的重构:**选择约定。记录下来。更新转换代码以反映它们。使用同类语言的相同查询可能如下所示:
SELECT
user_id
,site_id
,visit_id
FROM
user
JOIN
site
...
JOIN
visit
标识符中的技术参考
CREATE OR REPLACE TABLE POSTGRES_USERS AS ...
**翻译成英文:**任何名称反映源系统(即postgres_user
)、提取-加载介质(即DATA_WAREHOUSE.STITCH.USERS
)或 ELT 过程的任何其他机械组件(即cron_daily.users
)的表、视图、模式、数据库或列。
为什么会有气味:工程师很难走出我们自己的生活空间。这种味道通常是由于设计一个“源代码向下”而不是“最终用户向上”的模式而产生的。数据仓库必须以反映业务领域对象的方式表示信息;举个例子,某医院并没有把自己的消费者想成“账单用户”和“图表系统用户”和“处方用户”,他们都是简单的“患者”。
这是一种特别难察觉的味道,因为业务领域经常与技术领域非常接近,用户可能已经训练自己不正确地将一个与另一个对齐。如果零售商有不同的电子商务和物理销售点系统,很容易认为电子商务系统代表web_users
而 POS 系统代表in_store_users
。但事实并非如此;这家企业只有CUSTOMERS
可能会在商店、网上或两者兼而有之。
可能的重构:把你的数据产品想象成 UX 设计师设计意图驱动的应用程序界面的方式。如果您登录您的 Medium 帐户,系统会要求您输入您的用户名和密码,而不是您的“dynamo _ db”用户名和密码。按照同样的逻辑,你的数据仓库用户群感兴趣的是页面访问量,而不是谷歌分析页面访问量或 Adobe 分析页面访问量。
代码库外部的过程/函数
SELECT
super_amazing_stored_proc(122, 'another_magic_value') AS RPI_VALUE
**翻译成英语:**不是目标数据仓库的本地 SQL 方言的一部分,也不是作为代码库的一部分创建的函数。
**为什么会有味道:**如果我们将转换代码库视为构建数据仓库的蓝图,那么存储过程(不是作为代码库的一部分创建的)就是“帐外工作”。代码库不再拥有机器的所有元素,不能有效地复制仓库。这种危险而脆弱的状态使得仓库在实例崩溃时面临灾难性的失败。
**可能的重构:如果你正在使用像 DBT 这样的 SQL 框架(或者任何真正的 SQL 预编译),完全避免存储过程和函数。对于那些存储过程或函数是唯一可行的解决方案的罕见情况(或者如果您使用存储过程作为您的转换层),在您的代码库中包含具有DROP.. CREATE
或CREATE OR REPLACE
模式的过程的定义,以确保每次运行都从您的代码中重新创建。这将最小化代码状态和产品状态之间的差距。
引用标识符
SELECT 1776 AS "FOUNDING_YEAR" FROM countries."America"."Important Dates"
**翻译成英文:**区分大小写或包含特殊字符或保留字的标识符。
为什么这么说: SQL 是第四代语言,像大小写折叠(将标识符视为不区分大小写的值)这样的约定的目的是为了更好地模拟人与人之间的交流。引用的标识符通常与这种意图背道而驰,迫使用户考虑大写,并可能导致混淆"Leads_Prod"
与"leads_prod"
的情况(这是两个不同的表!).
**可能的重构:**永远不要引用标识符。通过对数据库、表/视图和列使用详细的描述性名称来避免混淆和开销。额外的好处是,这样你的代码将是可移植的(case folding 在不同的平台上是不一致的,所以任何引用的标识符都是立即不可移植的)。
在数据仓库的早期,有一种勇敢的努力来引用所有的东西,使得标识符尽可能的漂亮,并且可以用像 T2 这样的列名来准备报告。在当时,这很有意义,因为大部分消费是直接从数据仓库表到报告和电子表格摘录。今天,我认为 BI 工具是这种“表示抛光”的最佳场所,并且数据仓库通过保持标识符的干净和冗长而受益更多。
没有时区的时间戳/时区不在 UTC 中
SELECT
TIMESTAMP '2020-01-01 13:10:02' AS questionable_tstamp
,TIMESTAMP WITH TIME ZONE '2020-01-01 01:11:21+04' AS another_confusing_tstamp
**翻译成英文:**任何未显式转换为 UTC 值的时间戳,尤其是使用“本地时间”作为标准。
**为什么有味道:**时间戳是最混乱的数据类型。时间戳的实现和处理因平台、语言和工具的不同而有很大的差异。
**可能的重构:**显式地将所有时间戳转换为 UTC 进行存储。请注意,这与转换然后剥离时区不同(这是一种奇怪但痛苦的常见做法,可能源于一种信念,即没有时区的时间戳“更容易”)。
统一使用 UTC 将简化新数据集的入职流程,消除夏令时混乱,以及超越单一时区的面向未来的组织知识。让 BI 工具去担心时间戳表示(大多数工具都会这样做,那些“有用的”上游转换可能弊大于利)。
正常化
SELECT
u.user_name
,u.user_area_code
,si.site_name
FROM
users u
INNER JOIN
sites s
ON
u.site_id = s.id
INNER JOIN
site_identifiers si
ON
s.id = si.site_id
**翻译成英语:**反映传统的 BCNF 的模式,你会期望在事务数据库设计中找到这些模式。在这个例子中,site_identifiers
已经从site
中规范化出来,以保护引用完整性。
**闻起来的原因:**数据仓库是 OLAP 结构,它满足了与事务数据库完全不同的需求。规范化和引用约束是 OLTP 系统如何工作的重要部分——但是这些工具不利于知识库的目标。数据仓库并不代表期望的状态(即所有的page_views
都有一个存在于traffic_sources
表中的source_id
,它们代表的是现实(即一个 bug 将一百万个page_views
关联到一个不存在的源)。从更高的角度来看,大量规范化的存在可能是一个强有力的指标,表明在整个代码库中已经遵循了其他 OLTP 约定。
**可能的重构:**维度模型设计超出了本文的范围(为了更好地理解维度模型与事务模型的区别,我强烈推荐 Ralph Kimball 的数据仓库工具包)。一般来说,这些标准化值应该“退化”成宽而平的维度表,如下所示:
SELECT
name
,area_code
,site_name
FROM
users
隐藏的“模糊”逻辑
-- DDL for DATA_WAREHOUSE.SESSIONS
WITH
ordered_sessions AS (
SELECT
*
FROM
sessions
ORDER BY insert_id
)
,session_merger AS (
SELECT
CASE
WHEN TIMESTAMP_DIFF(a.session_end,b.session_start) < 60
AND
ABS(a.thumbprint_hash_points - b.thumbprint_hash_points) < 5
AND
EARTH_DISTNACE(a.location,b.location) < 0.5
THEN LEAST(a.session_id,b.session_id)
ELSE NULL
END AS merged_session_id
FROM
ordered_sessions a
INNER JOIN
ordered_sessions b
ON
a.insert_id +1 = b.insert_id
)
,refined_sessions AS (
SELECT
o.*
FROM
ordered_sessions o
WHERE
o.session_id IN (SELECT merged_session_id FROM session_merger)
)
CREATE TABLE sessions AS
SELECT * FROM refined_sessions
**翻译成英文:**被看似稳定的标识符掩盖的复杂变换。
为什么有味道:“粘糊糊的”逻辑是任意合理的业务逻辑:在上面的例子中,代码判定“两个间隔不到一分钟、指纹非常接近、来自(几乎)相同位置的会话很可能是同一个用户会话。”这里的味道不是逻辑——这是否是合并浏览器会话的准确方式取决于企业;气味代表“可能与绝对值相同的用户会话”session
。
**可能的重构:**数据仓库转换代码表示已知为真的东西。在这个例子中,我们知道每个会话都存在,而我们假设某些会话实际上是同一个会话。如果假设得到业务的支持,它可以很容易地以likely_parent_session
列的形式表示为附加信息。这个假设之上的聚合可以存在于另外的物化中,即dim_collapsed_session
和fact_collapsed_conversion
等。通常需要不止一个假设来支持业务用例的范围。在这种情况下,每个假设要么可以在特定领域的市场中进一步具体化,要么被“标记”并用于丰富数据仓库中的dim_session
。
/* downstream mart */
SELECT
amalgamated_session_id
,duration
...
FROM marketing.amalgamated_sessions
/* "branded" in dim_session */
SELECT
session_id
,aggressive_merge_session_id
,conservative_merge_session_id
,halifax_merge_session_id
...
FROM
dim_session
没有消费者文件
/* what do these mean?!? */
SELECT
halifax_merge_session_id
,aggressive_merge_session_id
FROM
dim_session
**翻译成英语:**对于使用数据仓库的消费者来说,他们需要来自转换作者的输入。
**为什么有味道:**数据仓库既是商业工具,也是消费品。像任何商业用途的复杂工具一样,它必须附带全面的文档。想象一下,学习使用 Excel 中的VLOOKUP
函数的唯一方法是打电话给微软工程师!没有面向消费者的文档,产品将无法使用。
可能的重构:文档可以存在于很多地方。几乎所有的数据仓库平台都支持 SQL comment
meta for objects。如果你使用像 DBT 这样的转换框架,那么面向消费者的文档就和 T6 结合在一起了。文档也可以用类似于 Sphinx 、Read Docs的工具来管理,甚至是简单的 markdown 文件。文档解决方案至少必须:*易于消费者访问。*作为数据产品的一部分进行维护。*支持有效的搜索和导航。*尽可能完整,“内部”参考
查询式标识符命名
SELECT
s.order_id
,w.order_id
...
FROM
confirmed_ecom_system_orders s
JOIN
client_side_web_orders w
**翻译成英文:**使用速记模式的别名,往往一两个字母长。
**为什么有味道:**缩写的速记对于编写快速的即席查询非常有用。但是像所有好的软件一样,转换代码应该是自文档化的,并使用有含义的对象名。
**可能的重构:**命名标识符是软件开发中的两大难题之一。使用在转换中具有描述性和唯一性的别名,并传达所表示的表/CTE/数据集的内容:
SELECT
ecom_orders.order_id
,web_orders.order_id
...
FROM
confirmed_ecom_system_orders ecom_orders
JOIN
client_side_web_orders web_orders
KPI 中的迎合逻辑
SELECT
is_conversion_marketing
,is_conversion_business_development
,is_conversion_finance
FROM
web_orders
翻译成英语:“垂直行业拒绝就围绕 KPI 的业务逻辑达成一致,因此我们支持真相的多个版本。”
为什么这么臭: 组织成熟度是任何成功的数据计划的关键要素。如果企业不愿意(或不能)做出有时很困难的决策,并使用统一的事实来源向前推进,这种犹豫不决将反映在数据仓库代码库中。
**可能的重构:**对这种气味的重构在技术上很简单,但实际上很难。业务必须发展,并宣布一个所有垂直行业都将采用的单一定义。在 SQL 中,这很简单:
SELECT
is_conversion
FROM
web_orders
在现实世界中,这可能是一个政治雷区。
最初发表于https://yoyodynedata.com。
数据仓库:理论
构建数据仓库
由 Unsplash 上的 chuttersnap 拍摄
在数据领域,我们已经到了这样一个地步:跟上不同的技术以及使用和处理数据的不同步骤,就像是一项工作本身;将它们应用到实践中更是如此。有数据的收集,存储,清理,分析,数据的使用:这些步骤中的每一步都有人们可以使用的多种工具和编程语言,这些步骤中的每一步都有许多不同的方法来处理你的数据,在云或公司服务器上,旨在实现相同的目标。最近,我有机会接触数据仓库。
假人介绍
数据仓库(DWH)的一个简单定义是专用于数据分析和报告、维护数据历史的数据库。DWH 应用程序通常被称为 OLAP(在线分析处理),但是它们并没有针对事务处理进行优化,事务处理是 OLTP 系统的领域。数据通常通过不同来源(如 OLTP 应用程序、外部数据提供者或大型机应用程序)的 ETL(提取转换加载)过程加载。用户可以读取数据,但不能写入;他们经常执行与时间相关的数据分析。
数据仓库通常被描述为不同数据源的集合,经过转换以便于查询和维护,适应业务需求以进行分析;商业智能环境的基础。
建设 DWH 的优势有很多,但其中一些最重要的优势是:
- 不同数据源的整合
- 轻松查询/访问数据
- 阶段步骤的历史记录
- 分析不同业务单位的数据
通用模式
与任何其他过程一样,有源头也有目的地。在数据仓库的情况下,数据源可以是任何东西,其思想是我们的目标是将许多不同的源放在一起,如平面 excel 文件或操作系统,将它们提供给仓库,从而准备好供最终用户分析。然而,在建立仓库的整个过程中有一些中间步骤。
作者图片
在数据源和仓库之间有一个中转区。临时区域的目的是作为数据源之间的桥梁,收集来自不同数据源的数据,复制它们并将其与一些系统数据一起存储。它们通常每天加载,但可以更频繁地加载。暂存数据也带来了一些好处:
- 数据历史:数据按时间存储,记录它们的历史
- 隔离:数据仓库与数据源分离
紧接着就是真正的仓库。仓库由一个维度模型组成。DWH 视野开阔,因为它拥有公司内所有不同单位的数据,因此是结构化数据的中心点。因此,在到达最终用户之前,还存在另一个可能的步骤:数据集市。
数据集市是 DWH 的一个子集,具有预处理的数据,面向业务部门进行分析。
数据集市的用途是分离不同单元的数据,减少需要考虑的数据量,使访问数据更容易,并将它们与其余单元隔离开来。然而,数据集市的存在是可选的。
无论有没有数据集市,经过处理和组织良好的数据都将用于其最初的目的:分析数据,试图找到有用的事实和见解,在这些数据的基础上构建报告,使提取的信息可视化,或者做更复杂的事情,如数据挖掘。
维度模型
数据仓库的数据模型称为维度模型。命名的原因来自于模型由维度和事实组成。
事实表是那些衡量业务绩效以及它如何随时间变化的表。
这些表包含两种类型的列:事实和维度表的外键/代理键。它可以包含添加剂、半添加剂和非添加剂计量类型,通常占 DWH 的 90%。它们可以有三种不同的类型:事务性、周期性快照和累积快照。事实表的例子是所有那些跟踪公司内定期(每日、每月、每季度等)活动的表,如员工的日常活动、销售、签票等。
维度表是为事实表提供基础的表,具有用于筛选记录、分组记录和标记报告的描述性属性。
相反,维度表为事实表提供了结构良好的信息,这也意味着它们的主要目的是提供数据的过滤、分组和标记。维度的例子有人员、人员的层次结构、产品、地点等。
设计维度模型的第一步是识别两种类型的表、它们的粒度以及它们之间存在的关系。建议这两个表都有代理键,并保持清晰的命名约定。设计这些表格时要考虑的一个重要方面是渐变维度(SCD)。这种表是那些记录随时间变化的属性的表。例如,在保存雇员职位的表格中,重要的是跟踪职位随时间的变化,以便知道每个职位的开始和结束日期。这些表有 6 种不同的类型,选择哪一种适合您的模型取决于稍后将对这些数据进行分析的业务需求。
虚拟星形模式示例—图片由作者提供
星型模式是数据模型中最基本和最有效的模式,其中事实表位于连接到维度的中心。
该模型还有另一个模式,称为雪花模式。
虚拟雪花示例—作者图片
雪花模式与星型模式非常相似,不同之处在于维度之间也是相互连接的。
星型模式是雪花型模式的一个特例。雪花模式只影响维度,事实表相对于星型模式不会改变:维度以规范化的形式保存,以减少冗余,这使它们易于维护并减少存储空间,但这也导致查询数据时所需的连接数量增加。
虚拟总线矩阵示例—图片由作者提供
当该说的都说了,该做的都做了,按照 Kimball 的建议以及几乎任何类型的文档都需要的,可以生成一个总线矩阵,在这里我们再次显示表之间的关系,在这种情况下,强调事实和维度之间的区别。
谨记在心
与数据世界中的任何其他事物一样,不存在适用于所有情况的金科玉律,因此无法给出非常具体的指导原则,它既取决于手头的数据,也取决于业务需求。因此,在考虑构建数据仓库时,需要考虑的是,在构建模型之前,大部分时间都花在了了解可用数据以及您/业务部门希望从这些数据中获得什么。通过这样做,你就能够想到一个模型,以及如何构建每个单独的表,以及如何将它们连接起来。然而,有两个重要方面需要记住:
- 适应变化 :在构建 DWH 时,可能会有来自业务方面的特定需求,但作为一名数据工程师,您必须考虑可能的发展和不同的未来场景,这将对编写模型时做出的决策产生影响。
- 取决于业务审批:DWH 或数据集市的最终用户也是提供需求的人。只有当模型满足其中涉及的业务单元的需求时,才认为模型是有效的。
来源 :
- 罗斯·金博尔:《数据仓库工具包》
- O’Riley 学习:敏捷数据仓库设计
程式化的事实
📈Python for finance 系列
统计预测未来需要什么?
警告 : 这里没有神奇的公式或圣杯,尽管一个新的世界可能会为你打开大门。
📈Python For Finance 系列
我们总说“让数据自己说话”。但是数据要么大声呼喊,要么低声耳语。一些数据属性很容易发现,而另一些则不那么明显,被淹没在噪声中。就像耳边的低语,你必须努力去理解他们在说什么。一旦你从数据中揭示了隐藏的信息,在某些情况下,你可能有机会通过在当前可用的数据中寻找你认为将持续到未来的统计模式来预测未来。换句话说,找出一种方法,让未来看起来更像现在,只是时间更长。本文的目的是向您展示如何从通常不被注意但很有用的数据中获取这些属性。
在我们开始之前,让我们花一分钟思考一个简单的问题:我们可以从一组随机生成的数据中获取多少信息。大多数人可能会给出一个很长的列表,比如最大值、最小值、平均值、众数、中位数、方差、标准差、范围、等等。。人脑能进行抽象思维,其他动物做不到。这些就是统计有用的原因,因为它可以将数据转换成对人们有意义的信息。更重要的是,推断出的信息可以用来推断一些经验发现,即金融中所谓的程式化的经验事实。
本文末尾引用的程式化事实的定义是:
“资产价格看似随机的变化确实有一些非常重要的统计特性。这种在各种工具、市场和时间段中普遍存在的特性被称为程式化的经验事实
用简单的语言来说,就是说如果你想用过去的数据来预测未来,未来的数据必须和过去的数据有共同点。否则,一切都没有意义。所以,这些数据中过去和未来的常见模式被称为程式化事实。金融资产中有一系列广泛的程式化事实,在参考资料中也有解释。
随着程式化事实的出现,另一个概念出现了,静止。对于时间序列数据,平稳时间序列的统计特性如均值、方差、自相关等。都是不变的。大多数统计预测方法都是基于这样的假设,即通过使用数学变换可以使时间序列近似平稳。然后,通过反转先前使用的任何数学变换,可以“不变换”平稳化序列的预测,以获得原始序列的预测。
好了,关于“程式化的事实”和“固定的”已经说得够多了,让我们做一些编码来说明这两个概念。
1.数据准备
为了保持一致,在所有的📈Python for finance 系列,我会尽量重用相同的数据。关于数据准备的更多细节可以在这里,在这里,在这里找到。
*#import all the libraries*
import pandas as pd
import numpy as np
import seaborn as sns
import scipy.stats as scsimport yfinance as yf *#the stock data from Yahoo Finance*import matplotlib.pyplot as plt #set the parameters for plotting
plt.style.use('seaborn')
plt.rcParams['figure.dpi'] = 300df = yf.download('AAPL',
start = '2000-01-01',
end= '2010-12-31') #download Apple stock priced1 = pd.DataFrame(df['Adj Close'])#create a df with only stock price
d1.rename(columns={'Adj Close':'adj_close'}, inplace=True)
d1['simple_rtn']=d1.adj_close.pct_change()#percentage return
d1['log_rtn'] = np.log(d1.adj_close/d1.adj_close.shift(1))
#log return with 1 day lagd1.head()
我想争论的另一件事是去除异常值,我使用简单的平均值和 2 倍的标准差来设定边界。
*#get mean and std*
mu = d1.describe().loc['mean', 'log_rtn']
sigma = d1.describe().loc['std', 'log_rtn']condition = (d1['log_rtn'] > mu + sigma * 2) | (d1['log_rtn'] < mu - sigma * 2) #set the condition to be 2 times of std around mean
d1['outliers'] = np.where(condition, 1, 0)#like an if, else
d1.head()
然后,我去除所有的异常值。
*#using pd's bool selection to remove outliers*
d1_removed_outliers = d1.loc[d1['outliers'] == 0].iloc[:, :-1]
d1_removed_outliers.head()
d1_removed_outliers.info()
如你所见,2765 个数据点中还剩 2667 个数据点。为了方便起见,让我们再次使用 d1 作为数据帧名称。
d1 = d1_removed_outliers
同样,如何去除异常值的所有细节都可以在这里、这里和这里找到。
对数回报和简单百分比回报之间的差异可以在这里找到。简而言之,变量自然对数的微小变化可以直接解释为百分比变化。换句话说,只要变化足够小(在+/- 5%的范围内),百分比变化和自然对数变化几乎完全相同。事实上,如上表所示,simple_rtn
和log_rtn
中的数字非常接近。
我们可以检查 simple_rtn 和 log_rtn 的相关性,
#calculate the pearson correlation
d1[['simple_rtn', 'log_rtn']].corr()
这两种回报高度相关。从热图中甚至可以清楚地看出:
#draw heatmap with seaborne
cmap = sns.diverging_palette(220, 20, as_cmap=True)
ax = sns.heatmap(corr, annot=True, cmap=cmap,
square=True, linewidths=3,
linecolor='w')
ax.set_title('Autocorrelation Plots', fontsize=26)
sns.set(font_scale=2);
关于熊猫的一个好处是,很容易直接得到那些描述性的统计数据。
d1.describe().round(4)
2.收益的正态(高斯)分布
讨论最多的程式化事实之一是收益的正态(高斯)分布。大量重要的金融模型都是建立在股票收益是正态分布的假设上,而你在本文结尾会看到,可能并不是这样。因此,正态分布可以被认为是金融中最重要的分布之一,也是许多金融理论的主要统计构件之一。
我们来看看调整后价格、百分比回报、自然对数回报的正态性。首先,我们定义一个函数来从d1.describe()
中提取描述性统计数据
*#extract all the stats from describe() function*
def extract_data_stats(col):
d_stat = col.describe()
mu = d_stat['mean']
sigma = d_stat['std']
rtn_range = np.linspace(d_stat['min'], d_stat['max'], num=1000)
norm_pdf = scs.norm.pdf(rtn_range, loc=mu, scale=sigma)
return mu, sigma, rtn_range, norm_pdf
准备好平均值、标准差和正态概率密度函数(PDF)后,我们可以绘制直方图和 PDF。
#*draw the histogram with Probability Density Function*
def draw_hist(col, xlim=(-0.2, 0.2)):
mu, sigma, rtn_range, norm_pdf = extract_data_stats(col) sns.distplot(col, kde=True, norm_hist=True, label='Hist')
plt.plot(rtn_range, norm_pdf, 'r', lw=3,
label=f'N({mu:.3f}, {sigma**2:.4f})')
plt.axvline(x=0, c='c',linestyle='--', lw=3)
plt.title(f'Distribution of {col.name}', fontsize=24)
plt.xlim(xlim)
plt.legend(loc='upper right', fontsize=20,
frameon=True,fancybox=True,
framealpha=1, shadow=True, borderpad=1);
百分比回报的直方图和 PDF。
draw_hist(d1.simple_rtn)
自然对数收益率的直方图和 PDF。
draw_hist(d1.log_rtn)
调整后价格的直方图和 PDF。
draw_hist(d1.adj_close,xlim=(-10,50))
显然,股票价格有趋势或周期,这使其远离正态分布。然而,对数回报率和百分比回报率非常相似,接近正常水平。但是常态能被检验吗?
✍Tip!
以防你的图看起来不一样,这里是我使用的 *matplotlib*
参数:
plt.rcParams['figure.figsize'] = [16, 9]
plt.rcParams['figure.dpi'] = 300
plt.rcParams['font.size'] = 20
plt.rcParams['axes.labelsize'] = 20
plt.rcParams['axes.titlesize'] = 24
plt.rcParams['xtick.labelsize'] = 16
plt.rcParams['ytick.labelsize'] = 16
plt.rcParams['font.family'] = 'serif'
关于matplotlib
的更多信息,请访问👉Python 中关于绘图的一切。
3.综合高斯性
有一个程式化的事实来自与常态相关的文章末尾的引用,它说:
"4.随着计算收益的时间尺度的增加,它们的分布看起来越来越像正态分布。特别是,在不同的时间尺度上,分布的形状并不相同。”
让我们看看这是否站得住脚。我们创建了一个新的数据框架来保存所有滞后的股票价格回报。
#*get 5 days lagged return by a for loop*
df_simple_rtn = pd.DataFrame(d1['adj_close'])
lags = 5for lag in range(1, lags+1):
col = f'lag_{lag}_simple_rtn'
df_simple_rtn[col] = df_simple_rtn['adj_close']. \
pct_change(periods=lag)
df_simple_rtn.dropna(inplace=True)
df_simple_rtn.head()
#*get 5 days lagged return by a for loop*
df_log_rtn = pd.DataFrame(d1['adj_close'])
lags = 5for lag in range(1, lags+1):
col = f'lag_{lag}_log_rtn'
df_log_rtn[col] = np.log(df_log_rtn['adj_close']/\
df_log_rtn['adj_close'].shift(lag))
df_log_rtn.dropna(inplace=True)
df_log_rtn.head()
我们可以通过修改前面的函数draw_hist()
来绘制直方图和 PDF,赋予它一次绘制多个图的额外能力。
#using ax to draw multi-grahps
def draw_hist_multi(col, xlim=(-0.2, 0.2), ax=None):
mu, sigma, rtn_range, norm_pdf = extract_data_stats(col) sns.distplot(col, kde=True, norm_hist=True, \
label='Hist', ax=ax)
ax.plot(rtn_range, norm_pdf, 'r', lw=3, \
label=f'N({mu:.3f}, {sigma**2:.4f})')
ax.axvline(x=0, c='c',linestyle='--', lw=3)
#*adj_close x axis range is wider*
if ( col.name == 'adj_close'):
ax.set_xlim(-10,50)
else:
ax.set_xlim(xlim)
ax.legend(loc='upper right', fontsize=8,
frameon=True,fancybox=True);
你可能注意到了,我用ax
而不是plt
来画这些图,原因在中有很好的解释👉 用 Python 谋划一切。
现在我们可以把所有的情节放在一个有 2×3 个支线情节的单一图形中。
#*create subplots figure with each plot drawed by draw_hist_multi()*
def draw_hist_subplots(df):
fig, axs = plt.subplots(nrows=2, ncols=3, figsize=(16,9))
fig.subplots_adjust(hspace = .5) #wspace=.001
fig.suptitle('Distribution of returns with increased \
time scale', fontsize=24)
axs = axs.ravel()
for i, col in enumerate(df.columns):
draw_hist_multi(df[col], ax=axs[i])
在一个循环中绘制多个支线剧情的关键是使用axs = axs.ravel()
,通过展平支线剧情矩阵,我们可以逐个遍历所有支线剧情。
draw_hist_subplots(df_simple_rtn)
在自然对数回报方面,和预期的一样,没有明显的区别。
draw_hist_subplots(df_log_rtn)
从滞后对数和百分比回报来看,的确,随着计算回报的时间尺度的增加,它们的分布看起来越来越像正态分布。特别是,在不同的时间尺度上,分布的形状并不相同。
4.正规性检验
从上面的图表来看,尽管趋势很明显,但实际上很难判断常态。通过利用scipy.stats
包,我们可以用描述性统计进行更严格的正态性检验。
在我们开始做正态性检验之前,我们需要知道两个概念。在统计学中,偏斜度是概率分布中对称钟形曲线的扭曲程度。而峰度是测量分布的峰值和平坦度。回报分布的高峰值和偏斜度意味着投资者将偶尔经历极端回报(正或负)。
正负峰度
正负偏斜度
对于正态分布的数据,偏斜度应该大约为零。
大于零的偏度值意味着分布的右尾有更多的权重,反之亦然。
#*using DataFrame to contain all the stats*
def build_stats(df):
stats = pd.DataFrame({'skew':scs.skew(df),
'skew_test':scs.skewtest(df)[1],
'kurtosis': scs.kurtosis(df),
'kurtosis_test' : scs.kurtosistest(df)[1],
'normal_test' : scs.normaltest(df)[1]},
index = df.columns)
return stats
对于百分比回报
build_stats(df_simple_rtn)
对于日志返回
build_stats(df_log_rtn)
所有的p-值都远低于 0.05,接近于零。具有统计显著性的测试结果(p-值≤ 0.05)意味着测试假设是错误的或者应该被拒绝。一个p-值大于 0.05 意味着没有观察到影响。当p-值为零时,我们必须拒绝零假设,即样本数据的返回具有与高斯分布相匹配的偏斜度和峰度。
我注意到的一件事是,对数收益的偏斜度和峰度的绝对值实际上比百分比收益的要大。剔除异常值后,均值变大,标准差变小,偏度和峰度没有变化。
5.互相关和自相关
在这篇文章结束之前,我想快速浏览一下滞后回报的相关性,如下面的参考文献中所述。
"1.缺乏自相关性:(线性)资产回报的自相关性通常是不明显的,除了非常小的日内时间范围(20 分钟)之外,微观结构效应在这种时间范围内发挥作用。”
就相关性而言,有 3 种不同的类型,互相关、自相关和循环相关。
百分比回报的交叉相关性为
corr_s = df_simple_rtn.corr()
corr_s
和日志返回的相关性
corr_l = df_log_rtn.corr()
corr_l
百分比回报和对数回报的互相关性都随时间而下降。如热图所示。
#*using seaborne to draw heatmap*
sns.set(style="white")
cmap = sns.diverging_palette(220, 20, as_cmap=True)
ax = sns.heatmap(corr_s, annot=True, cmap=cmap,
square=True, linewidths=3,
linecolor='w')
ax.set_title('Correlation Plots', fontsize=32)
ax.set_xticklabels(
ax.get_xticklabels(),
rotation=45,
horizontalalignment='right');
#*using seaborne to draw heatmap*
sns.set(style="white")
cmap = sns.diverging_palette(220, 20, as_cmap=True)
ax = sns.heatmap(corr_l, annot=True, cmap=cmap,
square=True, linewidths=3,
linecolor='w')
ax.set_title('Correlation Plots', fontsize=32)
ax.set_xticklabels(
ax.get_xticklabels(),
rotation=45,
horizontalalignment='right');
一天滞后(之前或之后)的回报的大多数相关性是相关的,因为它们的系数超过 0.8。但是这种相关性很快就消失了。
我仍然很难完全理解自相关性,尽管绘制自相关性很容易。
#*draw autocorrelation for log return with 50 days time lag*
from statsmodels.graphics.tsaplots import plot_acf
fig, ax = plt.subplots()
acf = plot_acf(d1.log_rtn, lags=50, ax=ax)
ax.set_xlabel('lags')
ax.set_ylabel('auto-correlation');
如果你能解释一下自相关、互相关和部分自相关,并在下面留下你的评论,我将不胜感激,谢谢。
现在有一个很大的问题,如何把你的回报转移到一个正态分布?敬请关注更多,即将推出!
参考
- 资产回报的经验属性:程式化的事实和统计问题。量化金融 2001,1 (2),223–236。