数据可视化黑客马拉松风格
我努力将数据从电子表格中解放出来
每个人——公司、政府、个人——都有数据,但很少有人知道如何有效地使用它。数据可以告诉我们如何做出更好的决策,但这些知识往往隐藏在数字中。一个问题是大多数数据看起来像这样:
虽然这里的信息,全球二氧化碳排放量,是“开放数据”,任何人都可以公开下载,但它也可以被锁在电子表格中,这对任何人都有好处。数据科学的核心是将这些毫无意义的数字转化为有用的知识。揭示数字内部洞察力的最有效方式之一是通过数据可视化。
Data from a spreadsheet turned into knowledge
对于在凯斯西储大学举办的黑客马拉松 HackCWRU 2018 ,我想探索公开的二氧化碳数据,并让普通观众可以访问。对于那些没有经验的人来说,一个黑客马拉松是一群充满激情的开发者——程序员、艺术家、硬件专家,偶尔还有数据科学家——在周末聚在一起,连续 24 或 36 个小时为项目工作。有时会有特定的问题需要解决,但在其他情况下,比如使用 HackCWRU,您可以自由选择您的团队和项目。在有限的时间内完成你的目标,睡觉通常是不鼓励的!
HackCWRU 做了各种各样的项目:手机应用、虚拟现实游戏、动作捕捉程序,而我选择做我最喜欢的事情:数据可视化。我单干了,项目名为排放浏览器,坚持在我的所有项目中添加浏览器的习惯(见股票浏览器和重量浏览器)。我周末的目标是展示数据可视化如何通过构建一个交互式数据探索网站,将数百万个数字转化为有意义的知识。
整个网站在线可用,代码也可以在 GitHub 上免费获得,供任何人使用或改进。(这个网站在桌面上运行得最好,因为我没有时间让它适应移动设备。这对任何人来说都是一个很好的解决方案!).
在我的过程中,我会在下面展示大部分的结果,但是我强烈推荐任何人访问这个网站来获得完整的体验。
显色法
在我们开始制作视觉效果的有趣部分之前,我们必须找到并清理一些数据。在一个正常的数据科学工作流程中,这要花费一个项目 90%的时间。然而,在有限的时间内工作,我需要干净的数据和快速。我从三个来源收集数据: GapMinder ( 由汤姆·卡登策划)气候数据在线工具和世界银行,所有这些都是熟悉的 csv 文件格式。
数据状况良好,但有一些不一致之处,主要与国名有关。我花了很长时间才弄明白,韩国的代码是“Korea,Rep .”而朝鲜的代码是“Korea,Dem”。所有的数据格式化都是用 Python 完成的(在 Jupyter 笔记本中),使用了 Pandas 和 Numpy。数据的最终版本被保存为 json ( Javascript 对象符号),一种机器可读的数据交换格式。
虽然我通常使用 Python 和 R 进行分析和可视化,但数据科学的一部分是了解用于这项工作的正确工具,交互式绘图的最佳选择之一是 D3 . js。D3,数据驱动文档是一个 JavaScript 库,允许您通过一次构建一个元素来控制图表的每个方面。它的学习曲线非常陡峭,但最终结果是值得的!
对于我的第一个图表,我想用地图做些事情,因为我喜欢在地理环境中看到国家之间的比较。我的想法是创建一个世界地图,并在国家上画出与它们排放的二氧化碳量成比例的圆圈。圆圈的颜色将反映该国在排放量方面的排名。由于二氧化碳排放量变化很大,尤其是在过去的几十年里,我加入了一个时间维度,可以选择可视化数据的整个历史(1850 年至 2014 年)和一个选择框,以便用户可以选择特定的年份。最终结果显示在下面的动画中:
You can’t make this in Excel
作为点睛之笔,我添加了工具提示,当你把鼠标放在一个国家上时,它会显示每个国家的确切排放量和该国在给定年份的排名。我喜欢专业制作的图表中像这样的小细节,所以我试着自己做一点!
完成地图后,我想做一个更好的方法来比较随着时间的推移排名靠前的国家。地图动画中隐藏了很多细节,对于可视化随时间变化的轨迹来说不是很好。显示时间序列最常见的方式是简单的线图,我认为没有理由发明不同的解决方案。同样,我在图表中保留了一个交互元素,允许用户选择特定的国家。
制作这个图表最困难的部分是 y 轴上的自动缩放。幸运的是,d3 允许您控制图表的每个方面,所以我能够指定轴的刻度应该更新以匹配排放量最大的国家。我认为这种视觉效果比地图更适合比较排名前 15 位的国家,摆弄它可以揭示出许多真知灼见。例如,中国在 2005 年超过了美国(这不是一个你想成为第一的领域),尽管英国最初是最大的排放国,但到了 2014 年,他们的排放量与工业化国家相比相形见绌。
对我影响最大的数据可视化灵感之一是已故的 GapMinder 创始人汉斯·罗斯林。特别是,在我第一次观看他的演讲后,他展示各国人口统计数据随时间变化的演讲让我记忆犹新,这是任何电子表格都无法做到的。
对于最终的视觉效果,我想尝试重新创建 GapMinder 风格的图表,并在此过程中使用一些额外的社会经济数据。我大量借鉴了迈克·博斯托克的《国家财富与健康图表》( T1 ),制作了自己的动画互动视觉效果。在同一张图上有四个不同的变量,我把它分成如下几个部分
- x 轴显示的是一个国家的对数人口
- y 轴显示人均 GDP,衡量一个国家的富裕程度
- 圆圈的面积与二氧化碳排放量成正比
- 圆圈的颜色代表国家的等级
最终版本需要一些时间来吸收,因为它提供了相当多的信息!
该图表还允许用户通过将鼠标悬停在标签上来更改年份。当我展示这个的时候,我让很多人将它与汉斯·罗斯林的工作进行比较,这可能是我得到的最高的数据可视化补充!
一旦我把所有的图表放在一起,我就通过复制和粘贴现有的 html/css 模板把一个快速主页和 about page 放在一起。然后,我托管了我的文件,并在亚马逊 S3(一种云存储服务)上创建了一个静态网站。(他的指导很有帮助)。我接受的正规机械工程/数据科学教育并不包括任何网页设计方面的指导,所以整体美感显然还需要一些努力。尽管如此,这三个图表实现了我设定的目标:将这些有价值的公共数据从对任何人都没有好处的电子表格中解放出来!
结论
我确保在所有图表中包含的一个元素是交互性。当我看图表时,我喜欢自己摆弄数据,改变参数以发现所有的细微差别。由于这是一个探索性数据分析(EDA)项目,我想让用户自己得出一些结论。虽然总的信息是二氧化碳的排放量无疑随着时间的推移一直在增加,但人们可以在图表中找到其他有趣的信息。我们认为数据包含客观真理,但即使是数字,不同的个人也会带来自己的解释,影响他们从数据中获得的知识。当然,有些时候我们想用数据来证明一个观点,比如医学试验,但在这种公共数据的情况下,我想让人们更容易使用他们认为合适的数据。
尽管我最终赢得了两个奖项——公民赛道奖和亚马逊网络服务最佳使用奖——但这些奖品并没有从事一个很酷的项目重要。此外,黑客马拉松挑战我学习另一项技能 d3.js,我可以将它添加到我用于数据科学的工具箱中。成功的数据科学家总是愿意学习,不存在你已经掌握一切的阶段。D3.js 可能不值得陡峭的学习曲线——plot . ly 可以在 Python 中使用,并基于 d3 构建,Tableau 允许您非常快速地从干净的数据中制作专业的图表——但我仍然喜欢这个项目。黑客马拉松是获得大量实际问题经验的好方法,我向任何喜欢解决问题/创建独特项目的人推荐它们。虽然我选择采用数据科学的方法,但黑客马拉松欢迎来自各种背景的人,我鼓励任何人尝试一下!
如果有人想改进我的网站,或者有任何其他反馈和建设性的批评,可以通过 Twitter @koehrsen_will 联系我。
Python 中的数据可视化,如 R 的 ggplot2
教程 PYTHON 数据可视化
一步一步的教程如何创建一个基本的图表到一个出版就绪的 dataviz 图表
Photo by faaiq ackmerd from Pexels
如果你喜欢用 R 的 ggplot2 来绘制数据,但是你必须使用 Python,那么 plotnine 包作为 matplotlib 的替代包是值得研究的。在这篇文章中,我将向你展示如何开始使用 plotnine 进行高效的输出。
如果你想继续,请在 GitHub 上找到完整的脚本:
[## scheithauer/python-plotnine
python 中的数据可视化,就像 R 的 ggplot2 一样
github.com](https://github.com/scheithauer/python-plotnine)
ggplot2
ggplot2 是一个基于图形语法的声明式创建图形的系统。您提供数据,告诉 ggplot2 如何将变量映射到美学,使用什么图形原语,它负责处理细节。资料来源:http://ggplot2.tidyverse.org/
ggplot output; http://ggplot2.tidyverse.org/reference/figures/README-example-1.png
plotnine 作为 python 的 matplotlib 的替代
根据我的经验,ggplot2 的优势是实现了图形的语法。
plotnine 是由哈桑·基比瑞吉为 python 编写的图形语法,它给 Python 带来了同样的优势:更少的编码和更容易理解(声明性范例)。
安装绘图仪
# Using pip
$ pip install plotnine # 1\. should be sufficient for most
$ pip install 'plotnine[all]' # 2\. includes extra/optional packages
# Or using conda
$ conda install -c conda-forge plotnine
可视化数据
我用的**craft-beers-dataset出自 Jean-Nicholas Hould 。它包含了 2410 种美国精酿啤酒的信息。这些信息包括:**
- abv——酒精的体积含量,0 表示无酒精,1 表示纯酒精
- 国际苦味单位,描述一种饮料有多苦。
- 名称 —啤酒的名称。
- 风格 —啤酒风格(lager、ale、IPA 等。)
- brewery_id —生产该啤酒的啤酒厂的唯一标识符
- 盎司 —啤酒的盎司数。
Data set example entries
安装必要的库
**import pandas as pd
import numpy as np
from plotnine import ***
定义有用的常数
**c_remote_data ='[https://raw.githubusercontent.com/nickhould/craft-beers-dataset/master/data/processed/beers.csv'](https://raw.githubusercontent.com/nickhould/craft-beers-dataset/master/data/processed/beers.csv')
c_col = ["#2f4858", "#f6ae2d", "#f26419",
"#33658a", "#55dde0", "#2f4858",
"#2f4858", "#f6ae2d", "#f26419",
"#33658a", "#55dde0", "#2f4858"]**
有用的功能
**def labels(from_, to_, step_):
return pd.Series(np.arange(from_, to_ + step_, step_)).apply(lambda x: '{:,}'.format(x)).tolist()def breaks(from_, to_, step_):
return pd.Series(np.arange(from_, to_ + step_, step_)).tolist()**
读取数据并设置索引
**data = pd.read_csv(c_remote_data)data = (
data.filter([
'abv',
'ibu',
'id',
'name',
'style',
'brewery_id',
'ounces'
]).
set_index('id')
)**
柱状图
最初的
**fig = (
ggplot(data.dropna(subset = ['abv'])) +
geom_histogram(aes(x = 'abv'))
)**
添加颜色
**fig = (
ggplot(data.dropna(subset = ['abv'])) +
geom_histogram(
aes(x = 'abv'),
**fill = c_col[0], color = 'black'**
)
)**
添加标签
**fig = (
ggplot(data.dropna(subset = ['abv'])) +
geom_histogram(
aes(x = 'abv'),
fill = c_col[0], color = 'black'
) **+
labs(
title ='Distribution of The alcoholic content by volume (abv)',
x = 'abv - The alcoholic content by volume',
y = 'Count',
)**
)**
设置轴缩放比例
**fig = (
ggplot(data.dropna(subset = ['abv'])) +
geom_histogram(
aes(x = 'abv'),
fill = c_col[0], color = 'black'
) +
labs(
title ='Distribution of The alcoholic content by volume (abv)',
x = 'abv - The alcoholic content by volume',
y = 'Count',
) **+
scale_x_continuous(
limits = (0, 0.14),
labels = labels(0, 0.14, 0.02),
breaks = breaks(0, 0.14, 0.02)
) +
scale_y_continuous(
limits = (0, 350),
labels = labels(0, 350, 50),
breaks = breaks(0, 350, 50)
)**
)**
应用一个可用的主题
****theme_set(
theme_538()
)** # one time call**
更改一些主题功能
**theme_set(
theme_538() **+
theme(
figure_size = (8, 4),
text = element_text(
size = 8,
color = 'black',
family = 'Arial'
),
plot_title = element_text(
color = 'black',
family = 'Arial',
weight = 'bold',
size = 12
),
axis_title = element_text(
color = 'black',
family = 'Arial',
weight = 'bold',
size = 6
),
)**
)**
添加一些统计数据
**fig = (
ggplot(data.dropna(subset = ['abv'])) +
geom_histogram(
aes(x = 'abv'),
fill = c_col[0], color = 'black'
) +
labs(
title ='Distribution of The alcoholic content by volume (abv)',
x = 'abv - The alcoholic content by volume (**median = dashed line; mean = solid line)**',
y = 'Count',
) +
scale_x_continuous(
limits = (0, 0.14),
labels = labels(0, 0.14, 0.02),
breaks = breaks(0, 0.14, 0.02)
) +
scale_y_continuous(
limits = (0, 350),
labels = labels(0, 350, 50),
breaks = breaks(0, 350, 50)
) **+
geom_vline(aes(xintercept = data.abv.mean()), color = 'gray') +
geom_vline(aes(xintercept = data.abv.median()), linetype = 'dashed', color = 'gray')**
)**
刻面
**fig = (
ggplot(data.dropna(subset = ['abv', 'style'])[data['style'].dropna().str.contains('American')]) +
geom_histogram(
aes(x = 'abv'),
fill = c_col[0], color = 'black'
) +
labs(
title ='Distribution of The alcoholic content by volume (abv)',
x = 'abv - The alcoholic content by volume',
y = 'Count',
) +
scale_x_continuous(
limits = (0, 0.14),
labels = labels(0, 0.14, 0.07),
breaks = breaks(0, 0.14, 0.07)
) +
scale_y_continuous(
limits = (0, 300),
labels = labels(0, 300, 100),
breaks = breaks(0, 300, 100)
) **+
theme(figure_size = (8, 12)) +
facet_wrap('~style', ncol = 4)**
)**
散点图
最初的
**fig = (
ggplot(data.dropna(subset = ['abv'])) +
geom_point(
aes(x = 'abv',
y = 'ibu'),
fill = c_col[0], color = 'black'
) +
labs(
title ='Relationship between alcoholic content (abv) and int. bittering untis (ibu)',
x = 'abv - The alcoholic content by volume',
y = 'ibu - International bittering units',
) +
scale_x_continuous(
limits = (0, 0.14),
labels = labels(0, 0.14, 0.02),
breaks = breaks(0, 0.14, 0.02)
) +
scale_y_continuous(
limits = (0, 150),
labels = labels(0, 150, 30),
breaks = breaks(0, 150, 30)
)
)**
将磅值更改为变量
**fig = (
ggplot(data.dropna(subset = ['abv'])) +
geom_point(
aes(x = 'abv',
y = 'ibu',
**size = 'ounces'**),
fill = c_col[0], color = 'black'
) +
labs(
title ='Relationship between alcoholic content (abv) and int. bittering untis (ibu)',
x = 'abv - The alcoholic content by volume',
y = 'ibu - International bittering units',
) +
scale_x_continuous(
limits = (0, 0.14),
labels = labels(0, 0.14, 0.02),
breaks = breaks(0, 0.14, 0.02)
) +
scale_y_continuous(
limits = (0, 150),
labels = labels(0, 150, 30),
breaks = breaks(0, 150, 30)
)
)**
将点颜色更改为变量
****data['ounces_str'] = data['ounces']
data['ounces_str'] = data['ounces_str'].apply(str)**fig = (
ggplot(data.dropna(subset = ['abv'])) +
geom_point(
aes(x = 'abv',
y = 'ibu',
**fill = 'ounces_str'**),
**alpha = 0.5**,
color = 'black'
) +
labs(
title ='Relationship between alcoholic content (abv) and int. bittering untis (ibu)',
x = 'abv - The alcoholic content by volume',
y = 'ibu - International bittering units',
) +
scale_fill_manual(
name = 'Ounces',
values = c_col) +
scale_x_continuous(
limits = (0, 0.14),
labels = labels(0, 0.14, 0.02),
breaks = breaks(0, 0.14, 0.02)
) +
scale_y_continuous(
limits = (0, 150),
labels = labels(0, 150, 30),
breaks = breaks(0, 150, 30)
)
)**
添加线性回归线
**fig = (
ggplot(data.dropna(subset = ['abv'])) +
geom_point(
aes(x = 'abv',
y = 'ibu',
fill = 'ounces_str'),
alpha = 0.5,
color = 'black'
) **+
geom_smooth(
aes(x = 'abv',
y = 'ibu')
)** +
labs(
title ='Relationship between alcoholic content (abv) and int. bittering untis (ibu)',
x = 'abv - The alcoholic content by volume',
y = 'ibu - International bittering units',
) +
scale_fill_manual(
name = 'Ounces',
values = c_col) +
scale_x_continuous(
limits = (0, 0.14),
labels = labels(0, 0.14, 0.02),
breaks = breaks(0, 0.14, 0.02)
) +
scale_y_continuous(
limits = (0, 150),
labels = labels(0, 150, 30),
breaks = breaks(0, 150, 30)
)
)**
刻面
**fig = (
ggplot(data.dropna(subset = ['abv'])) +
geom_jitter(
aes(x = 'abv',
y = 'ibu',
fill = 'ounces_str'),
width = 0.0051,
height = 5,
color = 'black'
) +
labs(
title ='Relationship between alcoholic content (abv) and int. bittering untis (ibu)',
x = 'abv - The alcoholic content by volume',
y = 'ibu - International bittering units',
) +
scale_fill_manual(
guide = False,
name = 'Ounces',
values = c_col) +
scale_x_continuous(
limits = (0, 0.14),
labels = labels(0, 0.14, 0.02),
breaks = breaks(0, 0.14, 0.02)
) +
scale_y_continuous(
limits = (0, 150),
labels = labels(0, 150, 30),
breaks = breaks(0, 150, 30)
) **+
facet_wrap('ounces_str')**
)**
热图
**fig = (
ggplot(data.dropna(subset = ['abv'])) +
**geom_bin2d**(
aes(x = 'abv',
y = 'ibu')
) +
labs(
title ='Relationship between alcoholic content (abv) and int. bittering untis (ibu)',
x = 'abv - The alcoholic content by volume',
y = 'ibu - International bittering units',
) +
scale_x_continuous(
limits = (0, 0.14),
labels = labels(0, 0.14, 0.02),
breaks = breaks(0, 0.14, 0.02)
) +
scale_y_continuous(
limits = (0, 150),
labels = labels(0, 150, 30),
breaks = breaks(0, 150, 30)
) **+
theme(figure_size = (8, 8))**
)**
箱线图
通用箱线图
**fig = (
ggplot(data.dropna(subset = ['abv'])) +
**geom_boxplot**(
aes(x = 'ounces_str',
y = 'abv')
) +
labs(
title ='Distribution of alcoholic content (abv) by size',
x = 'size in ounces',
y = 'abv - The alcoholic content by volume',
) +
scale_y_continuous(
limits = (0, 0.14),
labels = labels(0, 0.14, 0.02),
breaks = breaks(0, 0.14, 0.02)
)
)**
小提琴盒图
**fig = (
ggplot(data.dropna(subset = ['abv'])) +
**geom_violin**(
aes(x = 'ounces_str',
y = 'abv'),
fill = c_col[0]
) +
labs(
title ='Distribution of alcoholic content (abv) by size',
x = 'size in ounces',
y = 'abv - The alcoholic content by volume',
) +
scale_y_continuous(
limits = (0, 0.14),
labels = labels(0, 0.14, 0.02),
breaks = breaks(0, 0.14, 0.02)
)
)**
结论
plotnine 提供了各种不同的可视化,很容易适应定制的输出。如果你有在 R 中使用 ggplot 的经验,那么切换到 plotnine 是毫不费力的。
点击此处查看更多我的文章:
- 了解我如何为媒体设计文章
- 了解如何使用链接(或管道)在 Python 中编写干净的代码
- 学习如何使用 R 分析你的 LinkedIn 数据
- 学习如何使用图形语法在 Python 中以描述性的方式创建图表
- 了解如何在两分钟内用 python 数据科学代码设置日志
Gregor Scheithauer 是一名顾问、数据科学家和研究员。他专门研究流程挖掘、业务流程管理和分析。你可以在LinkedInTwitter上和他联系,或者在 中 上这里。谢谢大家!
数据可视化:来自最具创新力的美国城市的 Kickstarter 项目
一种结合自然语言处理、t-SNE 和主成分分析的方法
背景
据福布斯报道,2015 年最具创新力的美国城市是:
加利福尼亚州圣何塞
第 1 位;科罗拉多州博尔德
第 2 位;加利福尼亚州旧金山
第 3 位;科瓦利斯
第 4 位;华盛顿州西雅图
第 5 位;科罗拉多州科林斯堡
第 7 位;犹他州普罗沃
第 8 位;德克萨斯州奥斯汀
第 9 位;佛蒙特州伯灵顿
第 10 位;马萨诸塞州波士顿
受到一个精心组织的关于测谎仪的可视化项目的启发,我们很想知道来自上述最具创新性的美国城市的成功 Kickstarter 项目之间是否有任何差异。数据集是 2016 年 11 月在 Kickstarter 上报废所有可用项目得到的。
让我们先来看看上述城市与美国其他城市相比表现如何。
Screenshot of goal amount vs. pledged amount between innovative cities and other cities
事实上,我们可以观察到,来自创新型城市的项目似乎比他们最初的目标承诺了更多的金额,因为可以在灰色线(斜率=1)以上找到更多的项目。
目标
由于测谎仪的帮助,我们已经知道每个城市的哪些类别更受欢迎,我们很想知道创新城市的成功项目名称是否有任何差异。
方法
我们将使用 Google 开发的一种流行的自然语言处理(NLP)算法 word2vec 来执行文本挖掘任务。由于之前我们已经简单的谈过方法论,所以这次我们将重点讨论 word2vec 的实现。但是,建议在继续下一步之前先回顾一下这些概念。
1…将文本语料库作为输入
2…构建一个词汇表
3…学习单词的矢量表示法
4…生成单词向量作为输出
5…将单词向量应用于项目标题
6…创建平均项目标题向量
7…使用 t-SNE 将项目标题矢量转换为 2D 矢量表示
8…可视化美国顶级创新城市的结果
数据准备
1…修复放错位置的数据
由于数据来自于网络剪报,有些行可能放错了位置,需要做一些调整。
2…仅包括创新的美国城市
我们只想从想要的城市中选择项目,因此我们将删除其他城市。
3…清理项目名称
由于项目名称将是我们将要处理的主要变量,我们需要先做一些清理工作,比如去掉标点符号。
模特培训
我们将使用 R 中的 rword2vec 包来演示模型。
1…产生单词向量
虽然大多数分析会删除停用词,因为它们的高频率会在分析中产生噪声,但出于比较目的,我们将保留它们。
library(rword2vec)#Prepare the dataset
train=text$name
train=gsub("[[:punct:]]", "", train)
write(train,"text_data.txt")#Convert phrases to words
word2phrase(train_file = "text_data.txt",output_file = "vec.txt")#Input words to model
model=word2vec(train_file = "vec.txt",output_file = "vec.bin",binary=1)#Convert binary to text format
bin_to_txt("vec.bin","model1text.txt")#Convert .txt to .cvs
model1 <- read.table("model1text.txt",fill=TRUE)
write.csv(model1,"model1.csv")
m1 <- read.csv("model1.csv")
Screenshot of the word vectors produced
我们还可以找到与搜索单词最接近的单词。
distance("vec.bin","new",num=15)
distance("vec.bin","album",num=15)
Screenshot of the top 15 closest words to “new”
Screenshot of the top 15 closest words to “album”
2…将单词向量应用于项目标题(所有单词向量的平均值)
s <- strsplit(data$name, split = " ")
new <- data.frame(V1 = rep(data$id, sapply(s, length)), V2 = unlist(s))colnames(new) <- c("id","word")
colnames(m1)[1] <- "word"
new <- merge(new,m1,by="word")new2 <- aggregate(V2 ~ id, new, mean)
for (i in 4:102){
new3 <- aggregate(new[,i] ~ id, new, mean)
new2 <- merge (new2,new3,by="id")
}colnames(new2)[1] <- "id"
colnames(new2)[2:101] <- paste("V", 1:100, sep="")
new2$id <- as.factor(new2$id)
write.csv(new,"data.csv")
Screenshot of the project title vectors created
3…使用 t-SNE 将项目标题向量转换为 2D(该过程耗时 1 小时)
library(Rtsne)set.seed(1)
tsne <- Rtsne(new2, dims = 2, perplexity=100, verbose=TRUE, max_iter = 500)t = as.data.frame(tsne$Y)
id <- subset(new2,select="id")
t <- merge(id,t,by=0)city <- submydata1[,c(3,28)]final <- merge(city,t,by="id")final$Row.names <- NULL
4…根据城市的 t-SNE 向量绘制 2D 项目标题
library(ggplot2)p <- ggplot(final,
aes(V1, V2, color = final$location1))+
geom_point(alpha=0.7,size=2)
p
Screenshot of the project title vectors with t-SNE
5…使用 PCA 将项目标题向量转换为 2D
pcadata <- new2
pcadata$id <- NULLpr.out=prcomp(pcadata, scale=TRUE)
pr.out$sdev
pr.var=pr.out$sdev ^2
pve=pr.var/sum(pr.var)
pve
plot(pve, xlab="Principal Component", ylab="Proportion of Variance Explained ", ylim=c(0,1),type="b")
plot(cumsum(pve), xlab="Principal Component ", ylab=" Cumulative Proportion of Variance Explained ", ylim=c(0,1), type="b")
pcadata2 <- scale(pcadata, pr.out$center, pr.out$scale) %*% pr.out$rotationid <- subset(new2,select="id")
p <- merge(id,pcadata2,by=0)city <- submydata1[,c(3,28)]pfinal <- merge(city,p,by="id")
Screenshot of the performance of the PCA based on variance explained
6…根据城市的 PCA 向量绘制 2D 项目标题
plot <- ggplot(pfinal,aes(PC1, PC2, color = pfinal$location1))+
geom_point(alpha=0.7,size=0.5)
plot
Screenshot of the project title vectors with PCA
不幸的是,这两种可视化方法都没有对我们最初的理论产生有意义的结果,即在创新的美国城市中,项目名称存在差异。然而,我们从 PCA 中注意到,这些创新城市可能有类似的项目名称,给出了中间的集群。
接下来,我们将检查某些项目标题是否更有可能成功。但是,由于数据量大,我们将取 20%作为样本。
Screenshot of the project titles with PCA by successful and failed status (20% data points as sample)
让我们看看按照创新城市和其他城市来划分项目名称是否会有所帮助。
Screenshot of the project titles with PCA by innovative cities and other cities
最后,无论是失败与成功,还是创新与其他城市,在项目名称上似乎都没有任何有趣的发现。
我们还能做什么?
1…删除停止词以查看性能是否提高
2…我们可以查看项目描述,而不是项目标题
有什么问题、意见或顾虑吗?
jchen6912@gmail.com
优秀游泳运动员比赛成绩的数据可视化(第一部分——数据集)
这篇文章是数据可视化项目《游泳者的历史》制作笔记的第一部分。
大型游泳比赛中优秀游泳运动员比赛成绩的数据可视化。探索+1500 游泳者的历史…
tany.kim](http://tany.kim/swimmers-history)
游泳是我长期以来的兴趣,我一直想让数据可视化。最近(阅读:一年前:-),我发现一个伟大的网站提供了无数游泳比赛的结果,我试图利用网站上的信息。在这篇文章中,我将讨论我是如何废弃安全的 HTML 页面(用 R) ,提取有用的数据点,最后生成可视化的最佳数据集(用 Python) 。有了数据集,我设计了允许用户选择游泳比赛/事件的可视化,并按游泳者过滤比赛。因此,我在前端包含了用于数据过滤(重新生成数据子集)的 UI 组件设计。为了更好地理解收集到的数据集,我还谈了一下游泳世界。
感兴趣的游泳数据
在 SwimRankings.net 的众多网页中,我关注的是精英游泳运动员渴望参加的国际比赛。目前,自 2007 年以来主要比赛的全部结果都在网站上公开。
五大游泳比赛
从 2007 年到 2016 年,总共报道了 17 场会议。
- 奥运会:每四年一次——2008 年、2012 年、2016 年
- 世界锦标赛:每隔奇数年——2007、2009、2011、2013、2015
- 欧洲锦标赛:每偶数年——2008、2010、2012、2014、2016 年
- 英联邦运动会:每四年一届非奥运会——2010 年、2014 年
- 泛太平洋锦标赛:每非奥运四年一届——2010 年、2014 年
奥运项目
游泳项目大体上分为个人和团体两种。在这个项目中,我包括了引入奥运会的项目。例如,较短距离(50 米)仰泳和蛙泳比赛在世界锦标赛中进行,但在奥运会中没有。男女种族之间,没有完美的对称;男子最长自由泳是 1500 米,而女子是 800 米。
该数据集只包括决赛,这使得总共有 544 场比赛(16 场比赛 X 2 个性别 X 17 场比赛)。下面是我使用的数据集中的事件列表。
- 个人自由泳:50 米、100 米、200 米、400 米、800 米(仅限女子)、1500 米(仅限男子)
- 个人仰泳:100 米,200 米
- 个人蛙泳:100 米、200 米
- 个人蝶泳:100 米,200 米
- 个人混合泳:200 米,400 米
- 团体自由泳:4x 100 米、4x 200 米
- 团体混合泳:4x 100 米
用 R 废弃安全的 HTML 页面
在源网站上,每个事件都在一个单独的页面中提供,该页面在相同的 URL 基础上用参数标识,这些参数包括会议 ID、性别和风格(事件)ID。比如 2016 里约奥运会的(遇见)男子(性别),50 米自由泳项目(风格)页面网址是这样的:
page=meetDetail&meetId=596227&gender=1&styleId=16
为了获得 17 场比赛的 ID,我解析了每场比赛的 meta info 页面(例如,奥运会页面),因为这些页面有到上面 URL 的超链接。**获得正确索引值的保证方法是检查源代码。**在奥运页面,我关注的部分在这里:
A part that I inspected of the Olympics info page.
A link to a specific meet has the meet ID
代码检查显示每届奥运会的比赛 ID。此外,我从这个来源追踪了主办国和主办城市的名称。
Dropdown menu of styles shows style IDs.
现在我们有了所有的会议 id。样式 ID 是从 meet 页面中的标签的代码检查中手工收集的。
提取所有 544 场比赛的 R 脚本在这里可用。有了这些脚本,我只想用将整个网页删除并保存为文件,然后用 Python 做更多的数据烹饪。为什么不用 R 或 Python 做所有的事情?我更喜欢 Python 语法的简单性。我尝试用 Python 解析网页,但是用 Python 解析安全页面(https)很棘手。如果你知道一个方法,请让我知道!
用 Python 烹饪数据
下一步是从废弃的网页中只解析有用的部分。
The exact part of resource that I targeted in a webpage
数据解析
与我对 R 所做的类似,我检查了 HTML 标签,并跟踪了比赛信息,包括比赛日期和决赛的结果(例如,里约奥运会 50 米男子自由泳)。
The hyperlink to a swimmer’s info has theathlete ID.
对于每个游泳者,我追踪他们的名字、国家、游泳时间和分数。此外,通过检查源代码,我能够找到每个游泳者的唯一 ID ,它也用作前端上数据过滤/处理的标识符**。最后,我得出了总共 869 名男子和 779 名女子游泳运动员的比赛结果。**
没有完美的干净数据可以立即满足您的需求。特别是当你想设计独特的和定制的数据可视化,**在前端使用数据集之前,优化数据集以满足你的需求是至关重要的。**这是因为在客户端使用 Javascript 处理大型数据集需要一些时间,这可能会导致大量的加载时间,并最终导致用户受挫。
格式化用于演示的数据
我想在前端以特定的顺序显示比赛和事件,所以我给每个比赛和比赛名称添加了单个字母。
meet_year_letter = {
'2016': 'a',
'2015': 'b',
...
'2007': 'j'
}events_name = {
'1': ['50m Freestyle', 'a50Fr', '0IND'],
'2': ['100m Freestyle', 'b100Fr', '0IND'],
...
'19': ['400m Medley', 'n400IM', '0IND'],
...
'40': ['4 X 100m Medley', 'q4X100M', '1TEAM']
}
我分析了所有游泳者的信息。游泳者的信息结构如下:我将记录信息存储为数组。
{
"id": "4038916",
"name":"Michael Phelps",
"country": "United States",
"records":[
{
"place":"2",
"point":924,
"race_id":"0OG-a2016--0IND-k100Fly",
"swimtime":"51.14"
},
....
]
}
正如我将在下一篇文章中更详细描述的,我想展示游泳者的网络。使用 Python,我创建了包含任何一对在同一场比赛中一起参赛的游泳运动员的关系信息的数据集。
{
"source":"4042367",
"target":"4081509",
"value":[
"0OG-a2016--0IND-a50Fr",
"0OG-e2012--0IND-a50Fr",
"1WC-d2013--0IND-a50Fr",
"1WC-d2013--1TEAM-o4X100Fr"
]
}
在 Python 脚本的最后,我将它保存为前端的一个 JSON 文件**。看 Python 代码这里。**
前端的数据过滤
考虑到这个项目的真实用例,一次呈现所有游泳者的数据并不是最有用的。人们会有特定的需求,比如“我想看迈克尔·菲尔普斯在奥运会上的所有游泳比赛。”为了支持这一点,我设计了 UI 组件,允许用户选择比赛和事件,并按名称指定游泳者。我假设人们想要比较不同会议上的同一事件或同一会议上的多个事件。这样设计:一旦用户选择会议和事件,所选会议和事件的所有组合都包括在内。此外,她还可以选择游泳运动员,以进一步排除所选游泳运动员没有参加的比赛。
Options for filtering races (Among total 17 meets and 16 events)
例如,选择三届奥运会(2008、2012、2016)和男子所有七项自由泳赛事(50 米、100 米、200 米、400 米、800/1500 米、4 X 100 米接力和 4 X 200 米接力)将返回 21 场比赛(3 X 7)和 166 名游泳运动员。然后,如果通过姓名过滤选项选择了迈克尔·菲尔普斯,则游泳运动员的总数将减少到 140 名。
当该选项面板中的选择被更新时,一个新的数据子集被生成,可视化也被重新创建。React-Redux 很好地管理了这种基于前端的数据处理,我在这里不再进一步讨论。如果你感兴趣,去检查我的 GitHub repo 上的代码。
请继续阅读下一篇关于可视化设计和同一项目构思的帖子。也别忘了查看见解上的帖子。
优秀游泳运动员比赛成绩的数据可视化(第二部分——设计)
这个帖子是关于一个数据可视化项目游泳运动员的历史。请查看上一篇关于数据集生成的文章。
大型游泳比赛中优秀游泳运动员比赛成绩的数据可视化。探索+1500 游泳者的历史…
tany.kim](http://tany.kim/swimmers-history)
通过利用 SwimRankins.net的数据采集工作,我从 2006 年到 2007 年的 544 场重大赛事中创建了 1648 名游泳运动员的历史数据集。那么如何处理这个数据集呢?在这篇文章中,我描述了三种可视化的构思过程,以及探索数据集的用户交互设计。这篇文章包括了很多在最终决定之前的可视化设计的图片,我希望用它们来帮助其他设计师发展他们自己的想法,避免常见的错误。通过展示同一数据集的各种可视化类型,我还想解释数据集的哪些方面可以根据可视化设计来关注或必须忽略。请注意,下面的可视化示例是用整个数据集的子集制作的;用户可以使用选项面板设置自己的子集。
游泳主题的颜色
首先,让我谈谈你将在可视化中看到的颜色。对于这个游泳主题的项目,我希望主色接近蓝色,强调色比蓝色稍暖一些。我用这三个作为网站设计的通用调色板。由于可视化不是静态图像,我使用这些颜色来突出显示用户交互触发的视觉元素。
在设计可视化效果时,颜色经常被误用,如下所示。
- 编码不适当的数据维度:在对定量数据进行编码时,颜色不应是首选
- 冗余:仅出于装饰目的使用颜色会导致数据维度的冗余编码(例如,将颜色渐变应用于条形图,以匹配已经通过条形长度呈现的值)。
因为我已经使用了三种主要颜色来通过鼠标悬停或单击来突出显示视觉元素,所以我尽量减少了其他颜色的使用。然而,通过反复的设计,我加入了三种奖牌颜色,事实证明它们对洞察力的发现非常有效。这是为分类数据(金、银和铜)应用颜色的一个很好的例子。
Examples of using two main, accent colors (top) and medal colors (bottom) in CSS
通过普通比赛的游泳者网络
通常游泳成绩是按比赛和比赛列出的(这正是源网站的组织方式),但我认为可视化可以做得很好的一件事是呈现游泳者之间的关系。为了突出数据的方面,我使用了 D3 中的力定向图形库。
Color-coding medalists also helps users to figure out where to start.
我遵循了网络图的一般设计原则。**每个游泳者代表一个圆圈(节点)。**当一名游泳运动员参加一场比赛时,他/她可以获得 700+分,位置更高的游泳运动员可以获得更多分。累积的点与节点的大小(面积,而不是直径)成比例。奖牌获得者用每种匹配的奖牌颜色进行颜色编码。我首先没有想到对奖牌颜色进行编码,但事实证明,除了圆圈的大小之外,添加这些颜色有助于区分成绩更好的游泳运动员。
如果游泳运动员在一场或多场比赛中相互竞争,他们就被联系在一起。**两个游泳者的连线(边缘)呈现半透明的直线。**代表同一个国家在同一个团体项目中一起游泳不被考虑为链接。他们共享的种族越多,线就变得越粗。
下面的四张图片展示了不同的互动状态。
- 在正常状态下,我会突出显示金牌、银牌和铜牌获得者。
- 选定(单击)的节点用强调色填充。
- 对于鼠标悬停效果,使用两种主要颜色来突出显示连接的节点(浅蓝色)和线条(蓝色)。如果链接了以前选择的游泳者,则强调色会被浅蓝色覆盖。
- 当选择多个节点时,用户可以突出显示所有连接的圆(用白色)和边(用强调色)。此视图是 2 的替代视图。
Network graph has various states depending on mouse interactions and highlighting options
以种族为中心的可视化
When a rectangle (as an instance of Ledecky’s single result) is selected, other Ledecky’s rectangles are also highlighted in blue.
在实现了上面的网络图之后,我认为如果有另一种方法来表示游泳运动员参加的每一场比赛,那将会很棒,因为比赛信息没有包含在节点-边图中。基本想法是显示比赛中的游泳运动员(如果一个游泳运动员参加了多场比赛,他/她有多个实例),每个游泳运动员在比赛中被显示为一个细矩形。当一个游泳者被悬停或点击时,所选游泳者的所有实例被突出显示。
Iterations of the radial view show its limitation in scaleability (top) and in showing connected swimmers (dots).
直到上面的最终设计,我经历了许多次迭代。首先,我认为在径向视图中显示比赛有点独特,这也将保持网络视图的方形布局。人们在设计可视化时犯的一个常见错误是**他们忽略了数据集在缩放时的不同形状。**当我想呈现尽可能多的比赛时,我发现在固定大小的画布上很难区分比赛或游泳者。这是我不得不放弃放射状外观的一个原因。
以种族为中心的观点的一个早期想法是通过线条明确地连接同一个游泳者的实例。但是用实际数据实现这个想法并不是很好;游泳运动员并没有参加所有经过筛选的比赛,因此用直线或曲线将它们连接起来会使可视化看起来更加复杂。遗憾的是,我也不得不放弃这个想法,转而接受只用颜色突出显示的想法。
按国家可视化游泳运动员
游泳运动员最重要的比赛是奥运会,我们认为这是国家之间的竞争。人们对了解强大的国家感兴趣,所以我设计了一个视图,通过他们代表的国家来探索游泳运动员。
Early work for the country-based view of swimmers
可视化的第一个想法是在 x 轴上排列国家,并将游泳者列为圆圈,编码他们的总点数(与节点-边图相同)。同样,类似于我上面讨论的径向视图,它的可伸缩性不是很好。我可以垂直列出这些国家,然后如果一个国家有太多的游泳者,它就不适合给定的宽度。为了解决这个问题,我可以把游泳者分成多排,这实际上是个好主意。
但是我想在可视化中显示一个游泳运动员的所有比赛,而不是像网络视图那样;为此,我想了一个方法来呈现游泳运动员在参加的一组比赛。因此,一场比赛是一个正方形,如果一名运动员在多场比赛中游泳,这些正方形被连接起来形成一个宽矩形。矩形可以很宽,因此由这些游泳者组成的国家也会占据很大的空间。
最后,我决定把所有的比赛、游泳者和国家都列在一个方向上,就像我们写文字一样。如果一个游泳者太长而不能适应一条线,它会打断下一条线。这种划分方式可能会令人困惑,因为大多数游泳运动员都在一个完整的矩形中,但我折衷了这一部分,以涵盖一些极端情况(例如,如果您选择男子所有比赛和项目,一些主要的游泳运动员无法在一条线上。)第一名(金牌)、第二名(银牌)和第三名(铜牌)用相应的奖牌颜色填充。我还用这个漂亮的库添加了每个国家的国旗。与其他视图中选择每个游泳者不同,在国家视图中,每个比赛都可以用鼠标悬停,以浅蓝色轮廓突出显示。
The number in the grey circle next to each country name means the number of swimmers.
对游泳运动员比赛成绩的盘问
Swimmers who had the best results a race is highlighted
当用户选择一名游泳者时(通过点击可视化中匹配的可视元素或右边的下拉菜单),该游泳者的比赛结果出现在可视化下方。当选择多个游泳者时,仅显示他们都参加过的比赛(即,比赛的交叉点)。这个额外的表格补充了没有显示详细比赛结果的可视化效果。
带有元数据的登录页面
如前所述,用户可以选择将哪些游泳比赛/事件和游泳者包括在可视化中。为了让用户清楚地熟悉这个特性以及数据集的健壮性,我设计了一个入口点来生成相对更有趣的子数据集。
该数据集包括 10 年间的 17 场游泳比赛。我将会议的**“元数据”可视化为类似时间轴的视图。我**把一条传统的直线时间线修改成了波浪。这样时间线可以区分奇数年和偶数年;大型游泳比赛每隔 2 或 4 年举行一次。此外,我认为海浪符合游泳的主题。对于一个介绍性的可视化,我不想让它太复杂。没有用户交互,但这是一个动画。每年的竞赛名称会随着移动的圆圈到达该年而弹出。我可以添加每次会面的日期,但是过多的文本会使视觉效果更加混乱,所以我省略了它们。****
A subtle variation: the Olympic years are on a higher wave than the non-olympic 4-th years.
感谢阅读!如果你想知道你能从这些可视化图像中学到什么,请看下一篇文章。
优秀游泳运动员比赛成绩的数据可视化(第三部分——洞察)
这个帖子是关于游泳运动员的历史。如果你想了解数据处理和可视化设计的技术方面,请阅读其他帖子。
大型游泳比赛中优秀游泳运动员比赛成绩的数据可视化。探索+1500 游泳者的历史…
tany.kim](http://tany.kim/swimmers-history)
即使你对游泳不感兴趣,你也一定听说过一些世界级的游泳运动员,如迈克尔·菲尔普斯或声名狼藉的瑞安·罗切特。如果你是一个游泳爱好者,你可能会对这两位游泳运动员的竞争历史感到好奇。这是一个你可以用游泳运动员的历史来回答的问题。
The Phelps Face
“菲尔普斯脸”是 2016 年里约奥运会期间的一个迷因。人们可能想知道为什么南非游泳运动员惹恼了历史上获得奖牌最多的游泳运动员。嗯,有一个历史,你可以很容易地看到它与游泳运动员的历史!这里我描述几个洞察的例子。
对手的历史
在选项面板中,我选择了所有奥运会和所有个人项目。然后我选择了菲尔普斯和勒克洛斯来比较他们的结果。是的,勒克洛斯在 2012 年以 0.05 秒的优势击败过菲尔普斯一次。
Le Close beat Phelps once in 2012 at 200M butterfly.
It’s something considering there are only 4 Olympic events that Phelps didn’t win.
当我在观看里约奥运会游泳比赛时,可能是 100 米蝶泳或 200 米蝶泳,我听到解说员说匈牙利的拉斯洛·切赫赢得了四枚奥运奖牌,但没有一枚是金牌,每一枚金牌都被菲尔普斯获得。我觉得这太不可思议了,想看看这是不是真的。在过去的 10 年里,两人都参加了蝶泳和个人混合泳比赛。包括另外两次世界锦标赛,Cseh 从未击败过菲尔普斯。他唯一没有输的一次是在他们的最后一场比赛中——他们在里约的 100 米蝶泳比赛中并列获得银牌。我无法想象在自己的大陆上你是最棒的,但不是全世界最棒的。
History of Phelps VS Cseh
At the European Championships, Laszlo Cseh is absolutely dominating in Butterly and Individual Medley.
占优势的游泳运动员
在网络视图中,由于圆圈(节点)的大小代表游泳运动员获得的分数,您可以轻松识别表现更好的游泳运动员。创建一个与迈克尔·菲尔普斯竞争的游泳运动员网络;总共检索到 369 名游泳运动员,你会发现菲尔普斯的圈子明显更大。第二大国家是瑞安·罗切特。
当你选择所有参加过过去三届奥运会的游泳运动员时,你会看到 213 名男子,253 名女子。按性别比较这两个网络,你会发现一个相当大的差异。在男子网中,菲尔普斯是最大的圆心。相比之下,你会看到许多金牌得主的圆圈大小变化不大。
Men (left) and Women (right) Olympian swimmers
游泳运动员的风格分布
Four styles are completed separated in Women’s 2016 Olympics.
游泳运动员参加多种风格的比赛吗?让我们找出答案。转到女子,选择 2016 年里约奥运会,然后是四种泳姿的 100 米和 200 米项目——自由泳、仰泳、蛙泳、蝶泳。有趣的是,你会发现没有一个游泳运动员参加过一种以上的比赛。同样的项目,但对于男子,你会看到勒克洛斯是唯一一个参加多种类型比赛的游泳运动员——他参加了自由泳和蝶泳比赛。
个人游泳运动员
Highlighted swimmer is Paul Bierdermann of Germany.
你也可以调查一个特定的游泳运动员。例如,我想知道德国的保罗·比德尔曼在 2009 年成为世界冠军后的表现。如果你是一个游泳爱好者,你会记得他的记录太好了,因为冠军赛后被禁的高科技泳衣。也许并不奇怪,他的记录被丢弃了;2009 年后,他从未赢得过奥运会或世界冠军,但仍参加了许多决赛。说到德国,我发现了一件令人惊讶的事情——德国男子游泳运动员在过去的三届奥运会上都没有获得任何奖牌。我记得 1988 年奥运会上东德游泳运动员还是个孩子,这很令人惊讶。
Olympic swimmers at final races — no medalists from Germany….
我还看到荷兰也没有任何奖牌获得者(皮尔特·范·登·霍根班德是我最喜欢的游泳运动员之一!)
Swimmers of high points can be selected from the dropdown menu.
在帖子的前面,我讨论过奥运会上没有明显表现突出的女游泳运动员。但是我们仍然可以看到“勤奋”的游泳运动员——《纽约时报》的这篇文章告诉我们来自匈牙利的 Katinka Hosszu 有些“独特”的训练风格。这是我们可以从游泳运动员的历史中发现的。在奥运会、世界锦标赛和欧洲锦标赛上,Hosszu 总共参加了 47 场比赛,这只是最后一场比赛。
我阐明了你可以从主要游泳比赛数据的可视化中发现什么。我在这里写的只是几个见解的例子。如果你发现了什么有趣的东西,请留下你的评论!
连接印度特大城市的列车数据可视化
在过去的十年里,印度经历了前所未有的城市化发展。其中大部分是作为“智能城市任务”的一部分完成的,在该任务中,预计有 98 个城镇具有巨大的潜力,将被转化为智能城市。这些智能城市将配备最新的技术和创新解决方案,帮助市民引领未来。
当我们概述印度的地理环境时,我们看到了这个国家的纵向和横向延伸。这个国家有四个州府大城市。
Plotting megacities of India
这些特大城市位于该国的四个角落,形成一个四边形。
Connecting of the megacities
交通部门连接这些大城市的计划。最近,埃隆·马斯克(Elon Musk)的公司 Hyperloop 计划在全印度建立最快的公共交通网络。详情请查看他们的网站——https://hyperloopindia.in/
这是一个未来的项目,但截至 2017 年,印度公民只依赖印度铁路,因为它是长途运输中最便宜的方式。
Plotting the new upcoming smartcities dotting the paths connecting the megacities
这些特大城市将与散布在连接走廊上的小型智能城市连接在一起。
Abstracting the quadilateral into a circular visual mapping
从图表中我们可以看到,一个圆可以是一个很好的抽象形式,来形象化这些大小城市的地理位置。
Concept : Plotting according to the relative positions
我们需要将所有的点推出圆圈,但仍然基于它们的实际地理位置保持它们在圆圈上的相对位置。
Concept : Chord chart showing the flow from one megacity to the another
我们可以用多种方式来可视化数据流。但是在这种情况下,弦图似乎是最好的方法,因为它直观地告诉你不同站点之间的流量,以及每个站点的总体统计数据。
对于这个项目,我只对大城市进行了研究,而忽略了较小的智能城市。但是在未来,我想把他们也包括在这个可视化中。所以,我们去了加尔各答、钦奈、孟买和新德里,想象了来往的火车数量。
Finding the number of trains departing from megacities to megacities in all days of week
我首先将 irctc.co.in 中的数据手工制表到 excel 表格中(以便于制表)。你可以自由使用任何电子表格。在“irctc”中输入来源和目的地,然后逐一选择一周中的所有日子,并将其列表在电子表格中。在始发地和目的地相同的单元中,列车数量为零,因为我们看到的不是市内列车,而是城际列车
Converting the data from spreadsheet to a matrix format for vizualization
Assign colors to cities for vizualization
和弦图可视化
点击下面的链接,看上面图表的互动版
[## 弦图
编辑描述
www.arkadesignstudio.in](http://www.arkadesignstudio.in/railway/index.html)
理解编码部分
在一个文件夹中,您需要创建以下四个文件:
chord . js——处理可视化(画圆、圆弧等)、排版(CSS)、交互(工具提示信息、鼠标悬停动作等)
index.html—在 html 网页中嵌入不同的部分
matrix.json —包含以矩阵格式可视化的数据库
neighs.csv —包含分配给城市的颜色代码
为了便于设置,你可以将我的项目克隆/分支/下载到你的驱动器上,并上传到网络服务器上(D3 在离线模式下不工作)。
项目链接如下图
https://github.com/arkamajhi/arkamajhi.github.io
请随时回复这篇博文或直接给我回复关于这个研究项目的建议或关于任何有趣项目的信息**。**
读者好
我是 Arka Majhi,IIT 孟买 IDC 设计学科的硕士研究生。作为学术工作的一部分,我做了一个关于数据可视化的练习。这个故事是关于可视化的火车流穿过印度的大城市。
也可以看看我的作品集和资料库
设计作品集:https://www.behance.net/arkamajhi4d63
建筑作品集:http://spadelhi.org/arkamajhi/
工作室网站:http://arkadesignstudio.in/
通过喜欢和张贴你对我的项目的建设性意见来支持我。提前感谢。将等待您的回复。
用于业务影响的数据可视化软件
技术帮助您优化业务运营并创造更多收入。如果不采用技术,就很难保持业务的增长势头。每次你都需要参考你的业务报告,以了解你的业务的确切状况。相反,您可以依靠商业智能工具来了解 KPI 的表现。这种做法会帮助你做出更好更聪明的决定。
使用可视化商业智能软件(仪表盘)会让你的工作轻松很多。它将以图形方式呈现您的业务统计数据——图表、表格和图形——包括业务的所有关键指标。据观察,在商业中更多地采用最新技术会导致更高的投资回报,而较少的采用会导致商业损失。
数据仪表板软件将帮助你专注于业务的关键领域,而无需付出任何额外的努力。您可以根据您的业务模式和公司目标开发仪表板。大多数公司构建仪表板应用程序是为了做出更好的决策,这是商业智能的重要方面。
开发 data dashboard 软件时,您需要考虑以下提示:
- **确定关键绩效指标:**首先确定将在软件上显示的关键绩效指标,这一点非常重要。很明显,你会看到销售数字,以了解你的业务增长。这是您业务的重要 KPI 之一。销售数字的图表比统计数字更容易理解。明智的做法是在仪表板应用程序中设置大约 3-5 个 KPI。你需要专注于你所寻求的结果的这三到五个方面。
- **策划&执行:**任何企业的成功都取决于策划及其执行。大多数企业失败的原因是执行不力,这同样适用于为您的企业开发应用程序。您需要关注应用程序的规划和执行。仪表板应用程序应该具有您规划的所有功能,它应该帮助您按照生成的报告执行任务。如果您不清楚自己的操作,仪表板应用程序将会失败。
- **需求收集:**当您为您的业务计划一个仪表板应用程序时,您需要了解您的团队的需求。与他们讨论应用程序的设计、功能方面和数据要求。一旦收集了需求,就可以开始开发应用程序了。
- 反应灵敏:仪表盘软件必须反应灵敏。它应该可以在所有设备上访问,如移动设备、平板电脑、个人电脑,以便您的团队可以从任何地方访问它并更新应用程序。这将是有用的,甚至从你的手机获取重要信息。你需要让它变得移动友好,以便随时与应用程序连接,并且你的团队可以随时轻松访问它。
- **最新技术:**大数据和机器学习等最新技术可能会给你的业务带来巨大变化。在仪表板应用程序中使用这些技术可以获得最佳效果。
正确使用该软件将有助于您更有效地管理您的业务。如果你打算考虑一个应用程序,那么上面的提示会很有用。
数据可视化状态 2019
Photo by Lukas Blazek on Unsplash
作为 Sisense 的前端工程师,我需要使用数据可视化库构建多个组件。可视化库的存在是为了帮助我们理解复杂的想法。有大量的库选项可以在网上进行可视化。每一种都有自己的优点和缺点。在我看来,这里有五个最好的可视化库。
首先,我假设您已经知道 React 是什么。如果你对它不熟悉,简短的回答是 React 是一个用于构建用户界面的 JavaScript 库。如果你想要更长的答案,你可以在这里查看更多的。React 由脸书支持,是当今构建 UI 最流行的 Javascript 库。
D3
d3 是一个基于数据操作文档的 javascript 库,这个库使用 web 标准并且是框架不可知的,这意味着 d 3 不关心你是否使用 React、 Vue 或任何其他 javascript 框架,D3 将在任何地方工作,为了证明我所说的,我用不同的库(React、Vue、 Polymer )构建了 3 个应用程序,D3 在所有这些应用程序上都工作得完美无缺。
用 D3 和 React 做的 App。
github.com](https://github.com/leofle/d3app2) [## d3Vue
带有 D3 图形的 Vue 应用程序。
github.com](https://github.com/leofle/d3vue) [## D3 聚合物
聚合物 3.0 应用程序与 D3 图。
github.com](https://github.com/leofle/d3polymer)
D3 使用类似 jQuery 的选择器(对于像我这样的老开发者来说😉)来选择 DOM 元素,通常是 SVG,也可以是 canvas。D3 对 DOM 元素应用操作和事件。
D3 可以操作 DOM 元素,但是因为我们使用 React,React 由于其虚拟 DOM 而在呈现 DOM 方面表现出色,所以我们希望使用 React 来执行该任务。我们将只在计算中使用 D3。
D3 就像所有可视化库之母,不是因为它是最古老的,而是因为许多其他库都是基于 D3 的。这个库继续存在于所有的框架和库中,因为总会有人使用 D3 作为基础创建一个新的库。
D3 graph example
数据可视化的存在是为了帮助我们理解复杂的想法…
对…做出反应
React-vis 是由优步创建的 React 可视化库。有了它你可以轻松地创建常用图表,如****区域条形图饼形图树形图等等。********
React-vis example
GitHub stars:5520
为什么是这个图书馆?
React-vis 库非常容易安装和使用,它有很好的文档,并且由优步支持。事实上,优步是支持数据可视化库的最大公司,这是令人放心的,也是很好的了解。
还有什么可以更好的?
虽然这个库有一个丰富的 API,但是当我们想要添加特定的东西或者扩展它的时候有点困难。(当然可以送个先生!😉).
Photo by Isaac Smith on Unsplash
Chart.js
很棒的库,更好的文档,轻量级,完全响应的图表。7 种图表,包括:条形图、气泡图、圆环图、折线图、极区图、雷达图、散点图。
GitHub stars:43182
为什么是这个图书馆?
尺寸!这个图书馆太小了!!只有 11kb 的 gzipped,在 web 开发规模如此重要的今天,没有比小型库更好的了。
使用原生 API,因此学习曲线很小甚至没有。
还有什么可以更好的?
如果有更多的图表和 svg 选项,这个库会更好。
Chart.js example
VX
这是一个很棒的库,展示了 React 和 D3 的强大功能,快速且轻量级。
GitHub stars:5965
为什么是这个图书馆?
伟大的 API,非常容易制作复杂的图形,vx 在很大程度上是不固执己见的,它提供的开箱即用的图形类型的数量令人难以置信。
VX example
重新 chart
基于 React 组件构建的可组合图表库,包含大量实例的优秀文档。
GitHub stars:11482
为什么是这个图书馆?
小型库,也是可组合的,这意味着您可以在其上构建,并用新组件“组合”不同的图表。
Rechart example
那现在怎么办?
最后,我不得不说,所有这些库都很棒,它们之间的差异很小。它可以是库的大小,或者 API 的不同用法,当然,还有 GitHub 的受欢迎程度。但是最终,在开源世界中,我们知道最受欢迎的库将会更频繁地更新,并且会有一个很棒的社区来添加许多特性。
然而,我也鼓励你们所有人走出去,找到自己的梦想——甚至建造一个!D3 非常强大,允许你用自己的 JS 库包装它。然而,理想的情况是让 D3 进行计算,并让 JS 框架,无论你选择使用哪一个,来进行渲染。这样你就可以制作出令人难以置信的交互式图表。
使用 Matplotlib 实现数据可视化
数据可视化是商业活动的一个重要部分,因为现在的组织收集了大量的数据。世界各地的传感器都在收集气候数据、用户点击数据、预测方向盘的汽车数据等。所有这些收集到的数据都包含了对企业的关键见解,可视化使这些见解易于解释。
数据只有呈现出来才是好的。
为什么可视化很重要?
可视化是分析和吸收信息最简单的方法。视觉有助于轻松理解复杂的问题。它们有助于识别数据中的模式、关系和异常值。它有助于更好、更快地理解业务问题。它有助于建立一个引人注目的视觉故事。从图像中收集的见解有助于制定企业战略。它也是探索性数据分析(EDA)和机器学习(ML)的许多高级数据分析的先驱。
人类是视觉动物。无数的研究表明,我们的大脑是如何适应视觉的,当它通过眼睛时,处理任何事情都更快。
“即使您的角色不直接涉及数据科学的具体细节,了解数据可视化可以做什么以及它在现实世界中是如何实现的也是很有用的。”
-苎麻雅各布森
python 中的数据可视化可以通过许多包来完成。我们将讨论 matplotlib 包。它可以用于 Python 脚本、Jupyter notebook 和 web 应用服务器。
Matplotlib
Matplotlib 是一个二维绘图库,有助于可视化图形。Matplotlib 模拟 Matlab 的图形和可视化。Matlab 不是免费的,难以扩展,并且作为一种编程语言是乏味的。因此,使用 Python 中的 matplotlib,因为它是一个用于数据可视化的健壮、免费和简单的库。
Matplotlib 图形剖析
该图包含发生绘图的整个窗口,包含在该图中的是绘制实际图形的位置。每个轴都有一个 x 轴和 y 轴用于绘图。并且包含在轴内的是与每个轴相关联的标题、记号、标签。matplotlib 的一个重要特点是,我们可以在一个图形中包含多个轴,这有助于构建多个图,如下所示。在 matplotlib 中,pyplot 用于创建图形和改变图形的特征。
安装 Matplotlib
在 Jupyter 笔记本中键入!pip install matplotlib
,或者如果在 cmd 中不起作用,则键入conda install -c conda-forge matplotlib
。这在大多数情况下应该是可行的。
要遵循的东西
Matplotlib 的绘图相当容易。通常,在绘图时,他们在每个绘图中遵循相同的步骤。Matplotlib 有一个名为 pyplot 的模块,可以帮助绘制图形。Jupyter 笔记本用于运行图。我们import matplotlib.pyplot as plt
称它为包模块。
- 使用 Pandas
pd.read_csv()
导入所需的库和数据集进行绘图 - 利用熊猫数据帧上的条件提取地块的重要部分。
plt.plot()
对于绘制折线图,类似地,使用其他功能代替绘图。所有绘图函数都需要数据,数据通过参数在函数中提供。plot.xlabel , plt.ylabel
用于分别标注 x 轴和 y 轴。plt.xticks
、plt.yticks
分别用于标注 x 轴和 y 轴观察刻度点。plt.legend()
用于表示观察变量。plt.title()
用于设置情节的标题。plot.show()
用于显示绘图。
柱状图
直方图接受一系列数据,并将这些数据划分为多个条块。然后,它绘制每个箱中的频率数据点(即点的间隔)。这有助于理解数据范围的计数。
**何时使用:**当我们需要一个图中变量的计数时,应该使用直方图。
商店里出售的特定游戏的数量。
从上面我们可以看到大峡谷游客的直方图。plt.hist()
将第一个参数作为水平轴上的数字数据,即 GrandCanyon visitor.bins=10 用于在 GrandCanyon 的游客值之间创建 10 个箱。
从上图中,我们可以看到构成直方图的分量,n 是直方图每个区间中的最大值,即 5、9 等等。
累积属性为我们提供了最终附加值,并帮助我们了解每个仓位的增值。
范围有助于我们理解指定值之间的值分布。
多个直方图有助于理解两个实体变量之间的分布。我们可以看到大峡谷比布莱斯峡谷有更多的游客。
实现 : 直方图
圆形分格统计图表
这是一个圆形图,它被分成几个部分来说明数字比例。饼图的切片是为了显示部分占整体的比例。
**何时使用:**饼图应该使用很少使用,因为很难比较图表的各个部分。使用柱状图代替,因为比较截面很容易。
电影的市场份额。
注意:饼图不是一个很好的图表来说明信息。
上面,plt.pie()
将数字数据作为第一个参数,即百分比,将标签显示为第二个参数,即扇区。最终,它显示了数据在饼图中的比例分布。
从上面我们可以看到构成饼图的组件,它返回楔形对象、标签中的文本等等。
饼图可以很容易地定制,并从上面的颜色和标签值格式化。
从上方分解用于从饼图中分离出点。就像切披萨一样。
实现 : 饼状图
时间序列线图
时间序列是一个线形图,它基本上是用一条直线连接数据点。这有助于理解长期趋势。可以用趋势来解释点与点之间的相关性。上升趋势意味着正相关,下降趋势意味着负相关。它主要用于预测、监控模型。
**何时使用:**当要绘制单个或多个变量随时间的变化时,应使用时间序列。
公司的股票市场分析,天气预报。
首先,将日期转换为 pandas DateTime,以便于绘制数据。
从上面看,fig.add_axes
用于绘制画布。检查这个add _ axes 和 add_subplot 有什么区别?了解轴线和支线剧情。plt.plot()
将第一个参数作为数字数据,即日期,第二个参数是数字股票数据。AAPL 股票被认为是 ax1,这是外部数字,而在 ax2 上,IBM 股票被认为是用于绘图,这是插图。
在前面的图中,add_axes 用于将轴添加到图形中,而从上面的 add_subplot 将多个 subplot 添加到图形中。无法完成,因为只有 6 个可能的支线剧情。
我们可以看到,科技公司的股票呈上升趋势,显示出交易员投资股票的积极结果。
实施 : 时间序列
箱线图和紫线图
箱线图
箱线图很好地总结了这些数据。这有助于更好地理解我们的分布。
**何时使用:**当我们需要使用关于数据分布的整体统计信息时应该使用。它可用于检测数据中的异常值。
例如:客户的信用评分。我们可以获得关于标记的最大值、最小值和更多信息。
理解箱线图
Source: How to Read and Use a Box-and-Whisker Plot
在上图中,将方框分成两部分的线代表数据的中位数。方框的末端表示上四分位数(75%),方框的起点表示下四分位数(25%)。上四分位数也称为第三四分位数,同样,下四分位数也称为第一四分位数。下四分位数和上四分位数之间的区域称为四分位数间范围(IQR ),用于估计中间数据的 50%分布(75–25 = 50%)。最大值是数据中的最高值,同样最小值是数据中的最低值,也称为上限。方框外以及最大值和最大值之间的点称为触须,它们显示数据中的值的范围。极值点是数据的异常值。一个常用的规则是,如果一个值小于下四分位数-1.5 * IQR 或大于上四分位数+ 1.5* IQR,则该值为异常值。
bp 包含盒状图组件,如盒、须、中线、帽。Seaborn 是另一个绘图库,它比 matplotlib 更容易构建自定义绘图。patch_artist
使定制成为可能。notch
让中间看起来更突出。
使用 boxplot 的一个注意事项是观测值中的唯一值没有定义,Seaborn 中的 Jitter Plot 可以克服这个注意事项,或者 Violinplot 也是有用的
小提琴情节
Violin plot 是比 boxplot 更好的图表,因为它对分布有更广泛的理解。它类似于一把小提琴,密集的区域表示更多的数据分布,否则会被箱线图所隐藏
**何时使用:**它是 boxplot 的扩展。当我们需要更直观地理解数据时,应该使用它。
中间的分数密度似乎更大,因为学生在大多数科目上的得分都接近平均水平。
双轴
双轴有助于可视化绘制相对于 y 轴和同一 x 轴的两个图。
**何时使用:**当我们需要两个图或同一方向的分组数据时使用。
例:人口,GDP 数据在同一个 x 轴(日期)。
在 y 轴和相同的 x 轴上绘制 2 个图
提取重要细节,即 x 轴的日期、TempAvgF 和不同 y 轴的 WindAvgMPH。
正如我们所知,只有一个轴,twinx()
用于缠绕 x 轴,左边的 y 轴用于温度,右边的 y 轴用于风速。
用不同的单位和相同的 x 轴绘制相同的数据
该函数定义为计算不同的数据单位,即从华氏温度转换为摄氏温度。
我们可以看到,左边的 y 轴标绘了华氏温度,右边的 x 轴标绘了摄氏温度。
实现 : 双轴
堆积图和茎图
堆叠图
堆栈图可视化堆栈中的数据,并显示数据随时间的分布。
**何时使用:**用于检查单个地块中的多个可变面积地块。
这有助于理解多个变量在一段时间内的分布变化。
由于堆叠图需要堆叠,所以使用np.vstack()
完成
plt.stackplot
接受第一个参数数字数据,即年份,第二个参数垂直堆叠数据,即国家公园。
百分比堆积图
类似于堆栈图,但每个数据都被转换为其所占分布的百分比。
data_prec
用于将总体百分比划分为单独的百分比分布。s= np_data.sum(axis=1)
沿列计算总和,np_data.divide(s,axis=0)
沿行划分数据。
茎图
Stemplot 甚至采用负值,因此差异是从数据中提取的,并随时间绘制。
**何时使用:**它类似于堆栈图,但区别有助于比较数据点。
diff()
用于查找以前的数据和存储在另一个副本中的数据之间的差异。第一个数据点是 NaN(不是数字),因为它不包含任何用于计算差值的先前数据。
(31n)个子情节被创建以容纳图中的 3 行 1 列子情节。plt.stem()
将第一个参数作为数字数据,即年份,将第二个参数作为国家公园游客的数字数据。
实现: 栈图&茎图
条形图
条形图显示了数据在几个组中的分布。它通常与直方图相混淆,直方图只采用数字数据进行绘制。它有助于比较多个数值。
何时用:用于多组比较时。
学生在考试中的分数。
plt.bar()
将第一个参数作为数字格式的标签,将第二个参数作为它所代表的值的标签。
实现: 柱状图
散点图
散点图有助于可视化 2 个数字变量。它有助于确定数据与每个变量的关系,即相关性或趋势模式。它还有助于检测图中的异常值。
何时使用:用在回归之类的机器学习概念中,其中 x 和 y 是连续变量。它还用于聚类分散点或离群点检测。
plt.scatter()
采用 2 个数值参数来分散图中的数据点。它类似于线图,只是没有相连的直线。我们所说的相关性是指 GDP 与预期寿命的相关性,正如我们所看到的,这是正相关的,这意味着随着一个国家 GDP 的增加,预期寿命也会增加。
通过采用 GDP 的对数,我们可以有更好的相关性,因为我们可以更好地拟合点,它将 GDP 转换为对数标度,即 log(1000 美元)=3。
三维散点图
3D 散点图有助于在三维图中显示 3 个数值变量。
它类似于散点图,只是这次我们添加了 3 个数字变量。通过观察该图,我们可以推断,随着年份和 GDP 的增加,预期寿命也会增加。
实现 : 散点图
在这个Github Repo中找到上面的代码。
结论
总之,我们学习了如何使用一个数字变量和多个变量构建数据可视化图。我们现在可以很容易地构建图表,通过可视化直观地理解我们的数据。
使用 Seaborn 的数据可视化
“turned on flat screen monitor” by Chris Liverani on Unsplash
我回来了,带着 seaborn 教程。上次我们学习了使用 Matplotlib 的数据可视化。
Seaborn 是一个基于 matplotlib 的 Python 数据可视化库。它提供了一个高层次的界面来绘制有吸引力的和信息丰富的统计图形。
关键特征
- Seaborn 是一个统计绘图库
- 它有漂亮的默认风格
- 它还被设计成能很好地处理熊猫数据帧对象。
安装和入门
要安装 seaborn 的最新版本,可以使用 pip:
pip 安装 seaborn
也可以使用 conda 安装发布版本:
康达安装海博
或者,您可以使用 pip 直接从 github 安装开发版本:
pip 安装 git+https://github . com/mwaskom/seaborn . git
另一个选择是克隆 github 库并从您的本地副本安装:
pip 安装。依赖 Python 2.7 或 3.5 以上版本
强制依赖项
numpy(> = 1 . 9 . 3)
scipy(>= 0 . 14 . 0)
matplotlib(>= 1 . 4 . 3)
熊猫(> = 0.15.2)
推荐的依赖项
统计模型(> = 0.5.0)
可选阅读
TestingTesting
要测试 seaborn,在源码发布的根目录下运行 make test。这将运行单元测试套件(使用 pytest,但是许多旧的测试使用 nose asserts)。它还运行函数 docstrings 中的示例代码,对更广泛、更真实的示例用法进行冒烟测试。
全套测试需要一个互联网连接来下载示例数据集(如果它们之前没有被缓存),但是单元测试应该可以离线运行。bug
请通过 github 问题跟踪器报告您遇到的任何错误。在一个示例数据集(通过 load_dataset()访问)中包含一个可重复的示例将会非常有帮助。如果不知道你正在使用的 seaborn 和 matplotlib 的版本,以及你正在使用什么样的 matplotlib 后端来绘制图形,很难调试任何问题,所以请在你的错误报告中包括这些内容。
注意:本文假设您熟悉 python basic 和数据可视化。尽管如此,面对任何问题,评论或电子邮件给我你的问题。
参考我们的— 使用 Matplotlib 进行数据可视化
[## 红米 6 Pro(金色,3GB 内存,32GB 存储)
Redmi 6 Pro(金色,3GB 内存,32GB 存储空间):亚马逊
www .亚马逊. in](https://www.amazon.in/Redmi-Pro-Gold-32GB-Storage/dp/B07DJHV6S7/ref=as_li_ss_tl?_encoding=UTF8&smid=A23AODI1X2CEAE&pf_rd_m=A1VBAL9TL5WCBF&pf_rd_s=&pf_rd_r=50K466P7CMTN9W8Q780N&pf_rd_t=36701&pf_rd_p=e1fc9d07-6588-4865-b544-7a2a6ae17329&pf_rd_i=desktop&linkCode=ll1&tag=themenyouwant-21&linkId=e7387d6c0ffdd6bd50b46b5d1358036b&language=en_IN) [## 实践机器学习与 Scikit-Learn 和张量流:概念,工具和技术…
用 Scikit-Learn 和张量流实践机器学习:概念、工具和技术来建立…
www .亚马逊. in](https://www.amazon.in/gp/product/9352135210/ref=as_li_ss_tl?ie=UTF8&pd_rd_i=9352135210&pd_rd_r=78c1d00c-dee3-11e8-b353-add13b1583b7&pd_rd_w=1ioa9&pd_rd_wg=ctqpm&pf_rd_m=A1VBAL9TL5WCBF&pf_rd_s=&pf_rd_r=50K466P7CMTN9W8Q780N&pf_rd_t=36701&pf_rd_p=6d72b06e-660a-431b-b792-d8ca3a121c2b&pf_rd_i=desktop&linkCode=ll1&tag=themenyouwant-21&linkId=7f475732e6079a0f7c3455271a79dc17&language=en_IN)
在[1]中:
import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
%matplotlib inline
在[2]中:
census_data = pd.read_csv('census_data.csv')
census_data.describe()
Out[2]:
Figure 1
在[3]中:
census_data.head()
Out[3]:
Figure 2
在[4]中:
census_data.info()
Out[4]:
Figure 3
可视化统计关系
统计分析是一个了解数据集中的变量如何相互关联以及这些关系如何依赖于其他变量的过程。可视化可以是这一过程的核心组成部分,因为当数据被适当地可视化时,人类视觉系统可以看到指示关系的趋势和模式。
我们今天将讨论大多数的 seaborn 函数-
散点图
散点图是统计可视化的支柱。它使用点云来描述两个变量的联合分布,其中每个点代表数据集中的一个观察值。这种描绘允许眼睛推断关于它们之间是否有任何有意义的关系的大量信息。
在 seaborn 中绘制散点图有几种方法。当两个变量都是数字时,应该使用的最基本的函数是 scatterplot()函数。
在[5]中:
sns.scatterplot(x='capital_loss',y='capital_gain',data=census_data)
Out[5]:
<matplotlib.axes._subplots.AxesSubplot at 0xaafb2b0>
Figure 4
在[6]中:
sns.set(style="darkgrid")
tips = sns.load_dataset("tips") *#tips is inbuild dataset in seaborn*
sns.relplot(x="total_bill", y="tip", data=tips);
Figure 5
注意:散点图()是 relplot()中的默认种类(也可以通过设置 kind="scatter "来强制):
在[7]中:
*# adding some additional parameters*
sns.scatterplot(x='capital_loss',y='capital_gain',hue='marital_status',data=census_data)*# hue: Can be either categorical or numeric, although color mapping will*
*# behave differently in latter case.*
Out[7]:
<matplotlib.axes._subplots.AxesSubplot at 0xac406a0>
Figure 6
在[8]中:
sns.scatterplot(x='capital_loss',y='capital_gain',hue='marital_status',size='age',data=census_data)
Out[8]:
<matplotlib.axes._subplots.AxesSubplot at 0xadc95c0>
Figure 7
在[9]中:
*# As I said above the scatterplot() is the default kind in relplot() (it can also be forced by setting kind="scatter"):*
*# see difference*
sns.relplot(x='capital_loss',y='capital_gain',hue='marital_status',size='age',data=census_data)
Out[9]:
<seaborn.axisgrid.FacetGrid at 0xacdeb70>
Figure 8
线形图
散点图非常有效,但是没有普遍最佳的可视化类型。相反,可视化表示应适应数据集的具体情况以及您试图通过绘图回答的问题。
对于某些数据集,您可能希望了解某个变量随时间的变化,或者类似的连续变量。在这种情况下,一个好的选择是画一个线图。在 Seaborn 中,这可以通过 lineplot()函数直接完成,或者通过设置 kind=" line ":
在[10]中:
df = pd.DataFrame(dict(time=np.arange(500),
value=np.random.randn(500).cumsum()))
g = sns.relplot(x="time", y="value", kind="line", data=df)
g.fig.autofmt_xdate()*"""*
*Figure-level interface for drawing relational plots onto a FacetGrid.**This function provides access to several different axes-level functions*
*that show the relationship between two variables with semantic mappings*
*of subsets. The ``kind`` parameter selects the underlying axes-level*
*function to use:**- :func:`scatterplot` (with ``kind="scatter"``; the default)*
*- :func:`lineplot` (with ``kind="line"``)*
*"""*
Out[10]:
Figure 9
在[11]中:
age_vs_hours_per_week = sns.relplot(x="age", y="hours_per_week", kind="line", data=census_data
Out[11]:
Figure 10
在[12]中:
age_vs_hours_per_week = sns.relplot(x="age", y="hours_per_week", kind="line",sort=**False**, data=census_data)
Out[12]:
Figure 11
Lineplot()假设您经常尝试将 y 绘制为 x 的函数,默认行为是在绘制之前按 x 值对数据进行排序。但是,这可以禁用:
显示与方面的多重关系
我们在本教程中强调,虽然这些函数可以一次显示几个语义变量,但这样做并不总是有效。但是当你想了解两个变量之间的关系是如何依赖于一个以上的其他变量的时候呢?
最好的方法可能是制作一个以上的情节。因为 relplot()基于 FacetGrid,所以这很容易做到。要显示附加变量的影响,不要将其分配给图中的语义角色之一,而是使用它来“分面”可视化。这意味着您需要制作多个轴,并在每个轴上绘制数据子集:
在[13]中:
sns.relplot(x='capital_loss',y='capital_gain',hue='marital_status',size='age',col='gender',data=census_data)
Out[13]:
<seaborn.axisgrid.FacetGrid at 0xc8a1240>
Figure 12
在[14]中:
sns.relplot(x='capital_loss',y='capital_gain',hue='marital_status',size='age',col='income_bracket',data=census_data)
Out[14]:
<seaborn.axisgrid.FacetGrid at 0xcdc25c0>
Figure 13
您也可以这样显示影响两个变量:一个通过列上的分面,一个通过行上的分面。当您开始向网格中添加更多变量时,您可能希望减小图形大小。请记住,FacetGrid 的大小由每个面的高度和纵横比来参数化:
在[15]中:
sns.relplot(x='capital_loss',y='capital_gain',hue='marital_status',size='age',col='income_bracket',row='race',height=5,data=census_data)
Out[15]:
<seaborn.axisgrid.FacetGrid at 0xcdc2320>
Figure 14
Figure 15
Figure 16
用分类数据绘图
在关系图教程中,我们看到了如何使用不同的可视化表示来显示数据集中多个变量之间的关系。在示例中,我们关注的是两个数值变量之间的主要关系。如果其中一个主要变量是“分类的”(被分成离散的组),那么使用一种更专业的可视化方法可能会有所帮助。
在 seaborn 中,有几种不同的方法来可视化涉及分类数据的关系。类似于 relplot()与散点图()或线图()之间的关系,有两种方法可以制作这些图。有许多轴级别的函数可以以不同的方式绘制分类数据,还有一个图形级别的接口 catplot(),可以对它们进行统一的高级访问。
将不同的分类图种类看作属于三个不同的家族是有帮助的,我们将在下面详细讨论。它们是:
分类散点图:
strip lot()(with kind = " strip ";
默认)【swarm plot】(with kind = " swarm ")
分类分布图:
box plot()(with kind = " box ")
violin plot()(with kind = " violin ")
boxen plot()(with kind = " boxen ")
分类估计图:
point plot()(with kind = " point ")
bar plot()(with kind = " bar ")
count plot()(with kind = " count ")
这些系列使用不同的粒度级别来表示数据。
catplot()中数据的默认表示使用散点图。在 seaborn 实际上有两个不同的分类散点图。他们采用不同的方法来解决用散点图表示分类数据的主要挑战,即属于一个类别的所有点将落在与分类变量对应的轴上的相同位置。stripplot()使用的方法(catplot()中的默认“种类”)是通过少量随机“抖动”来调整分类轴上的点的位置:
在[16]中:
sns.catplot(x="age",y="marital_status",data=census_data)
Out[16]:
<seaborn.axisgrid.FacetGrid at 0xdb18470>
Figure 17
第二种方法使用防止点重叠的算法沿分类轴调整点。它可以更好地表示观察值的分布,尽管它只适用于相对较小的数据集。这种绘图有时称为“蜂群”,由 swarmplot()在 seaborn 中绘制,它是通过在 catplot()中设置 kind="swarm "来激活的:
在[27]中:
*#sns.catplot(x="age",y="relationship",kind='swarm',data=census_data)*
*# or*
*#sns.swarmplot(x="relationship",y="age",data=census_data)*
sns.catplot(x="day", y="total_bill", kind="swarm", data=tips);
Out[27]:
Figure 18
与关系图类似,可以通过使用色调语义向分类图添加另一个维度。(分类图目前不支持大小或样式语义)。每个不同的分类绘图函数以不同的方式处理色调语义。对于散点图,只需改变点的颜色:
在[29]中:
sns.catplot(x="day", y="total_bill", hue="sex", kind="swarm", data=tips);
Out[29]:
Figure 19
箱形图
首先是大家熟悉的 boxplot()。这种图显示了分布的三个四分位值以及极值。“触须”延伸到位于上下四分位数 1.5 IQRs 内的点,然后独立显示超出该范围的观察值。这意味着箱线图中的每个值对应于数据中的一个实际观察值。
在[32]中:
sns.catplot(x="age",y="marital_status",kind='box',data=census_data)
Out[32]:
<seaborn.axisgrid.FacetGrid at 0xd411860>
Figure 20
添加色调语义时,语义变量的每个级别的框将沿分类轴移动,这样它们就不会重叠:
在[37]中:
sns.catplot(x="age",y="marital_status",kind='box',hue='gender',data=census_data)
Out[37]:
<seaborn.axisgrid.FacetGrid at 0xde8a8d0>
Figure 21
小提琴情节
另一种方法是 violinplot(),它将箱线图与分布教程中描述的核密度估计过程结合起来:
在[38]中:
sns.catplot(x="age",y="marital_status",kind='violin',data=census_data)
Out[38]:
<seaborn.axisgrid.FacetGrid at 0x184c4080>
Figure 22
这种方法使用核密度估计来提供对值分布的更丰富的描述。此外,箱线图中的四分位数和 whikser 值显示在 violin 内部。缺点是,因为 violinplot 使用了 KDE,所以有一些其他参数可能需要调整,相对于简单的箱线图增加了一些复杂性:
在[41]中:
sns.catplot(x="age",y="marital_status",kind='violin',bw=.15, cut=0,data=census_data)
Out[41]:
<seaborn.axisgrid.FacetGrid at 0xfdea320>
Figure 23
类别内的统计估计
对于其他应用程序,您可能希望显示值的集中趋势的估计值,而不是显示每个类别中的分布。Seaborn 有两种主要方式来显示这些信息。重要的是,这些函数的基本 API 与上面讨论的 API 是相同的。
条形图
实现这一目标的常见绘图样式是条形图。在 seaborn 中,barplot()函数对完整数据集进行操作,并应用一个函数来获得估计值(默认情况下取平均值)。当每个类别中有多个观察值时,它还使用 bootstrapping 来计算估计值周围的置信区间,并使用误差线绘制:
在[46]中:
sns.catplot(x="income_bracket",y="age",kind='bar',data=census_data)
Out[46]:
<seaborn.axisgrid.FacetGrid at 0x160588d0>
Figure 24
在[47]中:
sns.catplot(x="income_bracket",y="age",kind='bar',hue='gender',data=census_data)
Out[47]:
<seaborn.axisgrid.FacetGrid at 0xdf262e8>
Figure 25
条形图的一个特殊情况是,您希望显示每个类别中的观察值数量,而不是计算第二个变量的统计值。这类似于分类变量而非定量变量的直方图。在 seaborn 中,使用 countplot()函数很容易做到这一点:
在[61]:
ax = sns.catplot(x='marital_status',kind='count',data=census_data,orient="h")
ax.fig.autofmt_xdate()
Out[61]:
Figure 26
点图
pointplot()函数提供了可视化相同信息的另一种方式。该函数也用另一个轴上的高度对估计值进行编码,但它不是显示一个完整的条形图,而是绘制点估计值和置信区间。此外,pointplot()连接来自同一色调类别的点。这样就很容易看出主要关系是如何随着色调语义的变化而变化的,因为你的眼睛非常善于捕捉斜率的差异:
在[67]:
ax = sns.catplot(x='marital_status',y='age',hue='relationship',kind='point',data=census_data)
ax.fig.autofmt_xdate()
Out[67]:
Figure 27
显示与方面的多重关系
就像 relplot()一样,catplot()建立在 FacetGrid 上的事实意味着很容易添加分面变量来可视化更高维的关系:
在[78]:
sns.catplot(x="age", y="marital_status", hue="income_bracket",
col="gender", aspect=.6,
kind="box", data=census_data);
out[78]:
Figure 28
在亚马逊上以最优惠的价格在线预定编码面试问题
www .亚马逊. in](https://www.amazon.in/gp/product/8193245202/ref=as_li_ss_tl?ie=UTF8&pd_rd_i=8193245202&pd_rd_r=78c1d00c-dee3-11e8-b353-add13b1583b7&pd_rd_w=1ioa9&pd_rd_wg=ctqpm&pf_rd_m=A1VBAL9TL5WCBF&pf_rd_s=&pf_rd_r=50K466P7CMTN9W8Q780N&pf_rd_t=36701&pf_rd_p=6d72b06e-660a-431b-b792-d8ca3a121c2b&pf_rd_i=desktop&linkCode=ll1&tag=themenyouwant-21&linkId=830d111966f700de39f4da335646e83e&language=en_IN) [## 用 R 动手编程:编写你自己的函数和模拟
Amazon.in - Buy 与 R 一起动手编程:以最优惠的价格在网上编写自己的函数和模拟书籍…
www .亚马逊. in](https://www.amazon.in/gp/product/9351107280/ref=as_li_ss_tl?ie=UTF8&pd_rd_i=9351107280&pd_rd_r=78c1d00c-dee3-11e8-b353-add13b1583b7&pd_rd_w=1ioa9&pd_rd_wg=ctqpm&pf_rd_m=A1VBAL9TL5WCBF&pf_rd_s=&pf_rd_r=50K466P7CMTN9W8Q780N&pf_rd_t=36701&pf_rd_p=6d72b06e-660a-431b-b792-d8ca3a121c2b&pf_rd_i=desktop&linkCode=ll1&tag=themenyouwant-21&linkId=ea6045b0df68ca9a7c6c6176c53817a8&language=en_IN) [## 有效的 Python 1: 59 编写更好的 Python 的具体方法
Amazon.in - Buy 有效的 Python 1: 59 在印度以最优惠的价格编写更好的 Python 书籍的具体方法
www .亚马逊. in](https://www.amazon.in/gp/product/9332552363/ref=as_li_ss_tl?ie=UTF8&pd_rd_i=9332552363&pd_rd_r=78c1d00c-dee3-11e8-b353-add13b1583b7&pd_rd_w=1ioa9&pd_rd_wg=ctqpm&pf_rd_m=A1VBAL9TL5WCBF&pf_rd_s=&pf_rd_r=50K466P7CMTN9W8Q780N&pf_rd_t=36701&pf_rd_p=6d72b06e-660a-431b-b792-d8ca3a121c2b&pf_rd_i=desktop&linkCode=ll1&tag=themenyouwant-21&linkId=bd492e127284082b0be2349a6405e710&language=en_IN)
全文上 下 …
要分叉,这个笔记本去 GitHub 。
如果你喜欢这篇文章,请与他人分享。
谢谢~
使用 Python 中的散景进行数据可视化,第二部分:交互
超越静态图
在本系列的第一部分中,我们在散景中创建了一个基本的直方图,这是一个强大的 Python 可视化库。最终结果显示了 2013 年从纽约市出发的航班的到达延迟分布,如下所示(带有漂亮的工具提示!):
这张图表完成了工作,但它并不是很吸引人!观众可以看到航班延误的分布几乎是正常的(有轻微的正偏差),但他们没有理由花超过几秒钟的时间看这个数字。
如果我们想创建更引人入胜的可视化,我们可以允许用户通过交互自己探索数据。例如,在这个直方图中,一个有价值的特性是能够选择特定的航空公司进行比较,或者可以选择改变条块的宽度,以便更详细地检查数据。幸运的是,这两个功能我们都可以使用散景添加到现有的绘图之上。直方图的最初发展可能看起来涉及到一个简单的绘图,但现在我们看到了使用像散景这样强大的库的好处!
这个系列的所有代码都可以在 GitHub 上获得。我鼓励任何人查看它的所有数据清理细节(数据科学中令人乏味但必要的部分),并对代码进行实验!(对于交互式散景图,我们仍然可以使用 Jupyter 笔记本来显示结果,或者我们可以编写 Python 脚本并运行散景服务器。对于开发,我通常在 Jupyter 笔记本上工作,因为它更容易快速迭代和改变情节,而不必重启服务器。然后我移动到一个服务器来显示最终结果。你可以在 GitHub 上看到独立的脚本和完整的笔记本。)
积极互动
在散景中有两类交互:被动和主动。第一部分介绍的被动交互也被称为检查器,因为它们允许用户更详细地检查图形,但不改变显示的信息。一个例子是当用户将鼠标悬停在数据点上时出现的工具提示:
Tooltip, a passive interactor
第二类交互称为主动交互,因为它改变了图上显示的实际数据。这可以是从选择数据的子集(例如特定的航空公司)到改变多项式回归拟合的程度的任何事情。在 Bokeh 中有多种类型的主动交互,但这里我们将重点放在所谓的“小部件”上,这些部件可以点击,并让用户控制情节的某些方面。
Example of Widgets (dropdown button and radio button group)
当我查看图表时,我喜欢玩主动交互(比如 FlowingData 上的那些),因为它们允许我自己探索数据。我发现自己从数据中发现结论(在设计师的指导下)比从完全静态的图表中发现结论更有洞察力。此外,给用户一些自由,允许他们带着稍微不同的解释离开,这可以产生关于数据集的有益讨论。
互动大纲
一旦我们开始添加主动交互,我们需要超越单行代码,进入封装特定动作的功能。对于散景小部件交互,有三个主要功能需要实现:
make_dataset()
格式化要显示的具体数据make_plot()
用指定的数据绘制图形update()
根据用户选择更新情节
格式化数据
在绘制图表之前,我们需要规划出将要显示的数据。对于我们的交互式直方图,我们将为用户提供三个可控参数:
- 显示的航空公司(代码中称为承运人)
- 图上的延迟范围,例如:-60 到+120 分钟
- 直方图框的宽度,默认为 5 分钟
对于为绘图生成数据集的函数,我们需要允许指定这些参数中的每一个。为了通知我们将如何在我们的make_dataset
函数中转换数据,让我们加载所有相关的数据并进行检查。
Data for histogram
在这个数据集中,每一行都是一个单独的航班。arr_delay
栏是以分钟为单位的航班到达延迟(负数表示航班提前)。在第一部分中,我们做了一些数据探索,知道有 327,236 个航班的最小延迟为-86 分钟,最大延迟为+1272 分钟。在make_dataset
功能中,我们希望根据数据框中的name
列选择航空公司,并通过arr_delay
列限制航班。
为了生成直方图的数据,我们使用 numpy 函数histogram
,它计算每个面元中数据点的数量。在我们的例子中,这是每个指定的延误间隔中的航班数量。对于第一部分,我们为所有航班制作了一个直方图,但现在我们将按每个承运人制作。由于每个承运人的航班数量差异很大,我们可以按比例而不是原始数量显示延误。也就是说,图上的高度对应于特定航空公司的所有航班在相应仓中有延迟的部分。为了从数量到比例,我们将数量除以航空公司的总数量。
下面是创建数据集的完整代码。该函数接收我们想要包含的载波列表、要绘制的最小和最大延迟以及以分钟为单位的指定 bin 宽度。
(我知道这是一个关于散景的帖子,但是没有格式化的数据是无法做出图形的,所以我附上了演示我的方法的代码!)
对所有载体运行该功能的结果如下:
提醒一下,我们使用散景quad
字形来制作直方图,所以我们需要提供字形的左、右和顶部(底部固定为 0)。这些分别在left
、right
和proportion
栏中。颜色列为每个载体提供了独特的颜色,而f_
列为工具提示提供了格式化的文本。
下一个要实现的功能是make_plot
。该函数应接受一个 column data source(Bokeh 中用于绘图的特定类型的对象),并返回绘图对象:
如果我们传入一个包含所有航空公司的源,该代码会给出以下图表:
这个直方图非常混乱,因为在同一张图上有 16 家航空公司!如果我们想比较航空公司,由于信息重叠,这几乎是不可能的。幸运的是,我们可以添加一些小部件来使情节更加清晰,并实现快速比较。
创建小部件交互
一旦我们在散景中创建了一个基本图形,通过小部件添加交互就相对简单了。我们想要的第一个小部件是一个选择框,允许查看者选择要显示的航空公司。这个控件将是一个复选框,允许尽可能多的选择,在 Bokeh 中称为CheckboxGroup.
来制作选择工具,我们导入CheckboxGroup
类并创建一个带有两个参数的实例,labels
:我们希望显示在每个框旁边的值和active
:被选中的初始框。下面是为所有运营商创建一个CheckboxGroup
的代码。
from bokeh.models.widgets import CheckboxGroup# Create the checkbox selection element, available carriers is a
# list of all airlines in the data
carrier_selection = CheckboxGroup(labels=available_carriers,
active = [0, 1])
CheckboxGroup widget
散景复选框中的标签必须是字符串,而有效值是整数。这意味着在图像中,“穿越航空公司”映射到活动值 0,而“阿拉斯加航空公司”映射到活动值 1。当我们想要将选中的复选框与航空公司匹配时,我们需要确保找到与选中的整数有效值相关联的字符串名称。我们可以使用小部件的.labels
和.active
属性来做到这一点:
# Select the airlines names from the selection values
[carrier_selection.labels[i] for i in carrier_selection.active]**['AirTran Airways Corporation', 'Alaska Airlines Inc.']**
在制作了选择小部件之后,我们现在需要将选中的航空公司复选框链接到图表上显示的信息。这是使用 CheckboxGroup 的.on_change
方法和我们定义的update
函数来完成的。更新函数总是采用三个参数:attr, old, new
并根据选择控件更新绘图。我们改变图表上显示的数据的方法是改变我们传递给make_plot
函数中的字形的数据源。这听起来可能有点抽象,所以这里有一个update
函数的例子,它改变直方图以显示所选的航空公司:
# Update function takes three default parameters
def update(attr, old, new):
# Get the list of carriers for the graph
carriers_to_plot = [carrier_selection.labels[i] for i in
carrier_selection.active] # Make a new dataset based on the selected carriers and the
# make_dataset function defined earlier
new_src = make_dataset(carriers_to_plot,
range_start = -60,
range_end = 120,
bin_width = 5) # Update the source used in the quad glpyhs
src.data.update(new_src.data)
这里,我们根据从 CheckboxGroup 中选择的航空公司检索要显示的航空公司列表。这个列表被传递给make_dataset
函数,该函数返回一个新的列数据源。我们通过调用src.data.update
并传递来自新源的数据来更新字形中使用的源的数据。最后,为了将carrier_selection
小部件中的更改链接到update
函数,我们必须使用.on_change
方法(称为事件处理程序)。
# Link a change in selected buttons to the update function
carrier_selection.on_change('active', update)
每当选择或取消选择一个不同的航线时,这个函数就调用 update 函数。最终结果是,直方图上只绘制了与所选航空公司相对应的图示符,如下所示:
更多控件
现在我们知道了创建控件的基本工作流程,我们可以添加更多的元素。每次,我们创建一个小部件,编写一个更新函数来改变绘图上显示的数据,并用一个事件处理程序将更新函数链接到小部件。我们甚至可以对多个元素使用相同的更新函数,方法是重写该函数,从小部件中提取我们需要的值。为了练习,我们将添加两个额外的控件:一个滑块,用于选择直方图的框宽度;一个 RangeSlider,用于设置要显示的最小和最大延迟。下面是制作这两个小部件和新的更新功能的代码:
标准滑块和范围滑块如下所示:
如果需要,除了使用更新功能显示的数据之外,我们还可以更改绘图的其他方面。例如,要更改标题文本以匹配框的宽度,我们可以:
# Change plot title to match selection
bin_width = binwidth_select.value
p.title.text = 'Delays with %d Minute Bin Width' % bin_width
在散景中还有许多其他类型的交互,但是现在,我们的三个控件允许用户在图表上尽情“玩”!
把所有的放在一起
我们互动剧情的所有元素都已就位。我们有三个必要的函数:make_dataset
、make_plot
和update
来根据控件和小部件本身改变情节。我们通过定义布局将所有这些元素连接到一个页面上。
from bokeh.layouts import column, row, WidgetBox
from bokeh.models import Panel
from bokeh.models.widgets import Tabs# Put controls in a single element
controls = WidgetBox(carrier_selection, binwidth_select, range_select)
# Create a row layout
layout = row(controls, p)
# Make a tab with the layout
tab = Panel(child=layout, title = 'Delay Histogram')
tabs = Tabs(tabs=[tab])
我将整个布局放在一个选项卡上,当我们制作一个完整的应用程序时,我们可以将每个图放在一个单独的选项卡上。所有这些工作的最终结果如下:
你可以在 GitHub 上随意查看代码和情节。
下一步措施和结论
本系列的下一部分将着眼于我们如何制作一个包含多个情节的完整应用程序。我们将能够在服务器上显示我们的工作,并在浏览器中访问它,创建一个完整的仪表板来探索数据集。
我们可以看到最后的互动剧情比原著有用多了!现在,我们可以比较航空公司之间的延迟,并改变箱的宽度/范围,以查看分布是如何受到影响的。增加交互性提高了绘图的价值,因为它增加了与数据的接触,并允许用户通过自己的探索得出结论。尽管设置初始情节很复杂,但我们看到了如何轻松地向现有图形添加元素和控制小部件。与 matplotlib 等快速简单的工具相比,使用 Bokeh 等较重的绘图库的好处是绘图和交互的可定制性。不同的可视化库有不同的优势和用例,但是当我们想要增加额外的交互维度时,散景是一个很好的选择。希望在这一点上,你有足够的信心开始开发自己的可视化,并请分享你创造的任何东西!
我欢迎反馈和建设性的批评,可以通过 Twitter @koehrsen_will 联系到我。
使用 Python 中的散景进行数据可视化,第三部分:制作完整的仪表板
在散景中创建交互式可视化应用
有时我会学习一种数据科学技术来解决一个特定的问题。其他时候,就像使用散景一样,我尝试一种新工具,因为我在 Twitter 上看到一些很酷的项目,然后想:“看起来很棒。我不确定什么时候会用到它,但它可能会派上用场。”几乎每次我这么说的时候,我最终都会找到这个工具的用途。数据科学需要许多不同技能的知识,您永远不知道您将使用的下一个想法来自哪里!
以散景为例,在试用了几周后,我作为一名数据科学研究人员在工作中发现了一个完美的用例。我的研究项目涉及使用数据科学提高商业建筑的能源效率,并且,对于最近在召开的会议,我们需要一种方式来展示我们应用的许多技术的成果。通常的 powerpoint 建议可以完成工作,但并不突出。当大多数与会者看到他们的第三张幻灯片时,他们已经不再注意了。尽管我还不太了解 Bokeh,但我自愿尝试制作一个与该库交互的应用程序,认为这将允许我扩展我的技能,并创建一种引人入胜的方式来展示我们的项目。我们的团队持怀疑态度,准备了一个备份演示,但在我向他们展示了一些原型后,他们给予了全力支持。最终的交互式仪表盘在会议上非常引人注目,将被我们的团队采用以供将来使用:
Example of Bokeh Dashboard built for my research
虽然不是你在 Twitter 上看到的每个想法都可能对你的职业生涯有所帮助,但我认为可以肯定地说,了解更多的数据科学技术不会有什么坏处。沿着这些思路,我开始了这个系列来分享 Bokeh 的功能,这是 Python 中一个强大的绘图库,允许您制作交互式绘图和仪表板。虽然我不能为我的研究分享仪表板,但我可以使用公开可用的数据集展示在散景中构建可视化的基础。这第三个帖子是我的散景系列的延续,第一部分专注于构建一个简单的图形,和第二部分展示了如何向散景图添加交互。在这篇文章中,我们将看到如何建立一个完整的散景应用程序,并运行一个可以在浏览器中访问的本地散景服务器!
本文将关注散景应用程序的结构,而不是情节细节,但所有内容的完整代码都可以在 GitHub 上找到。我们将继续使用 NYCFlights13 数据集,这是 2013 年从纽约 3 个机场起飞的航班的真实信息集合。数据集中有超过 300,000 个航班,对于我们的仪表板,我们将主要关注于探索到达延迟信息。
要自己运行完整的应用程序,确保你已经安装了散景(使用pip install bokeh
),从 GitHub 下载 [bokeh_app.zip](https://github.com/WillKoehrsen/Bokeh-Python-Visualization/blob/master/bokeh_app.zip)
文件夹,解压,在目录中打开一个命令窗口,键入bokeh serve --show bokeh_app
。这将建立一个本地散景服务器并在你的浏览器中打开应用程序(你也可以在线公开散景图,但现在我们将坚持本地托管)。
最终产品
在我们进入细节之前,让我们看一下我们的目标产品,这样我们就可以看到各个部分是如何组合在一起的。下面是一个短片,展示了我们如何与完整的控制面板进行交互:
Final Bokeh Flights Application
这里我在一个运行在本地服务器上的浏览器(Chrome 的全屏模式)中使用了散景应用程序。在顶部,我们看到许多选项卡,每个选项卡包含应用程序的不同部分。仪表板的想法是,虽然每个选项卡可以独立存在,但我们可以将许多选项卡连接在一起,以实现对数据的完整探索。视频展示了我们可以用散景制作的一系列图表,从直方图和密度图,到可以按列排序的数据表,再到完全交互式的地图。除了我们可以在散景中创建的图形范围之外,使用这个库的另一个好处是交互。每个标签都有一个互动元素,让用户参与数据并做出自己的发现。根据经验,当探索数据集时,人们喜欢自己获得洞察力,我们可以通过让他们通过各种控件选择和过滤数据来实现这一点。
现在我们有了一个仪表板的概念,让我们看看如何创建一个散景应用程序。我强烈推荐下载代码让自己跟着做!
散景应用程序的结构
在编写任何代码之前,为我们的应用程序建立一个框架是很重要的。在任何项目中,很容易迷失在编码中,很快就会迷失在一堆半成品脚本和不合适的数据文件中,因此我们希望预先创建一个结构,以便将所有代码和数据放入其中。这种组织将帮助我们跟踪应用程序中的所有元素,并在不可避免地出错时协助调试。此外,我们可以在未来的项目中重复使用这个框架,这样我们在规划阶段的初始投资将会得到回报。
为了建立一个散景应用程序,我创建了一个父目录来保存所有名为bokeh_app
的东西。在这个目录中,我们将有一个数据子目录(称为data
),一个脚本子目录(scripts
),以及一个main.py
脚本来整合所有内容。通常,为了管理所有代码,我发现最好将每个选项卡的代码保存在单独的 Python 脚本中,并从单个主脚本中调用它们。以下是我在散景应用中使用的文件结构,改编自官方文档。
bokeh_app
|
+--- data
| +--- info.csv
| +--- info2.csv
|
+--- scripts
| +--- plot.py
| +--- plot2.py
|
+--- main.py
对于 flights 应用程序,其结构遵循以下一般框架:
Folder structure of flights dashboard
在一个父bokeh_app
目录下有三个主要部分:data
、scripts
和main.py,
。当运行服务器时,我们告诉 Bokeh 服务于bokeh_app
目录,它将自动搜索并运行main.py
脚本。有了大致的结构,让我们来看看main.py
,我喜欢称之为散景应用程序的执行者(不是一个技术术语)!
main.py
main.py
脚本就像一个散景应用程序的执行者。它加载数据,将数据传递给其他脚本,获取结果图,并将它们组织到一个单独的显示中。这将是我完整展示的唯一一个脚本,因为它对应用程序至关重要:
我们从必要的导入开始,包括创建选项卡的函数,每个选项卡都存储在scripts
目录中的一个单独的脚本中。如果您查看文件结构,请注意在scripts
目录中有一个__init__.py
文件。这是一个完全空白的文件,需要放在目录中,以便我们使用相关语句(如from scripts.histogram import histogram_tab
)导入适当的函数。我不太确定为什么需要这样做,但它确实有效(下面是我用来解决这个问题的堆栈溢出答案)。
在库和脚本导入之后,我们在 Python [__file__](https://stackoverflow.com/questions/9271464/what-does-the-file-variable-mean-do/9271617)
属性的帮助下读入必要的数据。在这种情况下,我们使用两个熊猫数据帧(flights
和map_data
)以及包含在散景中的美国各州数据。一旦数据被读入,脚本就开始委托:它将适当的数据传递给每个函数,每个函数绘制并返回一个选项卡,主脚本将所有这些选项卡组织在一个名为tabs
的布局中。作为每个独立选项卡功能的示例,让我们看看绘制map_tab
的功能。
该功能接收map_data
(航班数据的格式化版本)和美国各州数据,并为选定的航空公司生成飞行路线地图:
Map Tab
我们在本系列的第二部分讨论了交互式的情节,这个情节只是那个想法的一个实现。该功能的总体结构是:
def map_tab(map_data, states):
...
def make_dataset(airline_list):
...
return new_src def make_plot(src):
...
return p def update(attr, old, new):
... new_src = make_dataset(airline_list)
src.data.update(new_src.data) controls = ... tab = Panel(child = layout, title = 'Flight Map')
return tab
我们看到熟悉的make_dataset
、make_plot
和update
函数用于绘制带有交互控件的图形。一旦我们建立了情节,最后一行将整个情节返回给主脚本。每个单独的脚本(5 个选项卡有 5 个)遵循相同的模式。
回到主脚本,最后一步是收集选项卡并将它们添加到单个文档中。
# Put all the tabs into one application
tabs = Tabs(tabs = [tab1, tab2, tab3, tab4, tab5])# Put the tabs in the current document for display
curdoc().add_root(tabs)
选项卡出现在应用程序的顶部,就像任何浏览器中的选项卡一样,我们可以轻松地在它们之间切换以浏览数据。
运行散景服务器
在完成了绘制图形所需的所有设置和编码之后,在本地运行散景服务器就非常简单了。我们打开一个命令行界面(我更喜欢 Git Bash,但是任何一个都可以),切换到包含bokeh_app
的目录并运行bokeh serve --show bokeh_app
。假设一切都编码正确,应用程序将自动在我们的浏览器中打开地址http://localhost:5006/bokeh_app
。然后,我们可以访问该应用程序并浏览我们的仪表板!
Final Bokeh Flights Application
在 Jupyter 笔记本中调试
如果出现问题(在我们编写仪表板的最初几次中,毫无疑问会出现这种情况),必须停止服务器,对文件进行更改,然后重启服务器以查看我们的更改是否达到了预期的效果,这可能会令人沮丧。为了快速迭代和解决问题,我通常会在 Jupyter 笔记本上绘制图表。Jupyter 笔记本是一个很好的散景开发环境,因为您可以在笔记本中创建和测试完全交互式的绘图。语法略有不同,但是一旦你有了一个完整的情节,代码只需要稍微修改一下,然后就可以复制并粘贴到一个独立的.py
脚本中。要了解这一点,请看一看我用来开发应用程序的 Jupyter 笔记本。
结论
完全交互式的散景仪表板使任何数据科学项目脱颖而出。我经常看到我的同事做了大量出色的统计工作,但却没有清晰地传达结果,这意味着所有的工作都没有得到应有的认可。从个人经验来看,我也看到了散景应用在交流结果方面的有效性。虽然制作一个完整的仪表板工作量很大(这个有 600 多行代码!)结果是值得的。此外,一旦我们有了一个应用程序,我们可以使用 GitHub 快速共享它,如果我们聪明地使用我们的结构,我们可以在其他项目中重用这个框架。
从本项目中获得的要点通常适用于许多数据科学项目:
- 在开始数据科学任务(散景或任何其他任务)之前,拥有适当的框架/结构至关重要。这样,您就不会发现自己迷失在试图寻找错误的代码森林中。此外,一旦我们开发了一个有效的框架,它就可以用最少的努力被重用,从而带来长期的收益。
- 找到一个允许你快速迭代想法的调试周期是至关重要的。Jupyter Notebook 允许的编写代码—查看结果—修复错误循环有助于提高开发周期的效率(至少对于小规模的项目是如此)。
- 散景中的交互式应用将提升你的项目并鼓励用户参与。仪表板可以是一个独立的探索性项目,也可以突出显示您已经完成的所有棘手的分析工作!
- 你永远不知道你会在哪里找到下一个你将在工作中使用的工具。睁大你的眼睛,不要害怕尝试新的软件和技术!
这就是这篇文章和这个系列的全部内容,尽管我计划在未来发布更多关于散景的独立教程。有了 Bokeh 和 plot.ly 这样的库,制作交互式图形变得越来越容易,拥有一种以令人信服的方式展示数据科学成果的方法至关重要。检查这个 Bokeh GitHub repo 为我所有的工作,并随时分叉,并开始与您自己的项目。现在,我渴望看到其他人能创造什么!
一如既往,我欢迎反馈和建设性的批评。可以通过推特 @koehrsen_will 联系到我。