如何用 Choropleth 图显示疫情冠状病毒
关于 Choropleth 地图的介绍和教程
图片来自皮克斯拜的米洛丝拉娃·克里斯诺娃
介绍
我非常支持数据可视化,因为我相信这是以简单易懂的方式说明和解释复杂信息,尤其是数字数据的最有效方法。此外,当正确执行时,可视化数据可以减少或帮助减轻数据解释中的偏差。
我最喜欢的可视化类型之一是动画 choropleth 地图。鉴于疫情正在进行,我认为现在是展示动画 choropleth 地图威力的好时机。
在本文中,您将了解以下内容:
- 什么是 choropleth 地图
- 何时以及为什么使用它们最有效
- Python 代码来创建您自己的 choropleth 地图,如下所示:
Choropleth 地图
choropleth 地图是一种专题地图,其中区域或地区按照给定数据变量的比例进行着色。
当您想要按区域比较所需变量时,静态 choropleth 图最有用。例如,如果你想比较某一时刻美国各州的犯罪率,你可以用一个静态的 choropleth 来显示。
一个动画或动态弦线图类似于一个静态弦线图,除了你可以随时间按区域比较一个变量。这增加了第三维度的信息,也是这些可视化变得如此有趣和强大的原因。
可视化冠状病毒疫情
我用来创建以下可视化效果的数据是 Kaggle 的新 Corona Virus 2019 数据集,可以在这里找到。该数据集由多个来源组成,包括世界卫生组织、中华人民共和国国家卫生委员会和美国疾病控制中心。
注意:如果这些来源中的任何一个未能提供准确和及时的数据,可视化可能会失真或不准确。
静态 Choropleth
以下是截至 2020 年 3 月 28 日各国冠状病毒确诊病例总数的静态分布图。你可以看到,病例数量最多的国家包括美国、中国、意大利以及其他几个欧洲国家。
冠状病毒确诊病例的静态霍乱弧菌
创建它的代码如下:
**# Import libraries**
import numpy as np
import pandas as pd
import plotly as py
import plotly.express as px
import plotly.graph_objs as go
from plotly.subplots import make_subplots
from plotly.offline import download_plotlyjs, init_notebook_mode, plot, iplot
init_notebook_mode(connected=True)**# Read Data**
df = pd.read_csv("../input/novel-corona-virus-2019-dataset/covid_19_data.csv")**# Rename columns**
df = df.rename(columns={'Country/Region':'Country'})
df = df.rename(columns={'ObservationDate':'Date'})**# Manipulate Dataframe** df_countries = df.groupby(['Country', 'Date']).sum().reset_index().sort_values('Date', ascending=False)
df_countries = df_countries.drop_duplicates(subset = ['Country'])
df_countries = df_countries[df_countries['Confirmed']>0]**# Create the Choropleth**
fig = go.Figure(data=go.Choropleth(
locations = df_countries['Country'],
locationmode = 'country names',
z = df_countries['Confirmed'],
colorscale = 'Reds',
marker_line_color = 'black',
marker_line_width = 0.5,
))fig.update_layout(
title_text = 'Confirmed Cases as of March 28, 2020',
title_x = 0.5,
geo=dict(
showframe = False,
showcoastlines = False,
projection_type = 'equirectangular'
)
)
请注意,您真正做的只是设置几个参数来引用数据集中的特定变量,如位置、位置模式和 z 。代码的其余部分用于更改 choropleth 地图的外观。
动画 Choropleth 地图
你可以看到动画的 choropleth 地图比静态地图更有效,更吸引人。在这里,我们正在查看一段时间内各国确诊的冠状病毒病例总数。你可以看到,直到最近,中国的病例数一直是最多的。
创建它的代码如下:
**# Manipulating the original dataframe**
df_countrydate = df[df['Confirmed']>0]
df_countrydate = df_countrydate.groupby(['Date','Country']).sum().reset_index()
df_countrydate**# Creating the visualization**
fig = px.choropleth(df_countrydate,
locations="Country",
locationmode = "country names",
color="Confirmed",
hover_name="Country",
animation_frame="Date"
)fig.update_layout(
title_text = 'Global Spread of Coronavirus',
title_x = 0.5,
geo=dict(
showframe = False,
showcoastlines = False,
))
fig.show()
感谢阅读!
如果你喜欢我的工作,想支持我…
- 支持我的最好方式就是在Medium这里关注我。
- 在 Twitter 这里成为第一批关注我的人之一。我会在这里发布很多更新和有趣的东西!
- 此外,成为第一批订阅我的新 YouTube 频道 这里!
- 在 LinkedIn 上关注我这里。
- 在我的邮箱列表 这里报名。
- 看看我的网站,terenceshin.com。
相关文章
新型冠状病毒 2019 数据集分析及代码
towardsdatascience.com](/coronavirus-data-visualizations-using-plotly-cfbdb8fcfc3d) [## 9 种有趣的新型冠状病毒统计和数据可视化
以下是你应该知道的关于冠状病毒的知识
towardsdatascience.com](/9-fascinating-novel-coronavirus-statistics-and-data-visualizations-710cfa039dfd)
资源
如何用 Plotly 在 Python 中制作 choropleth 地图?
plotly.com](https://plotly.com/python/choropleth-maps/) [## 新型冠状病毒 2019 数据集
新冠肺炎受影响病例的日水平信息
www.kaggle.com](https://www.kaggle.com/sudalairajkumar/novel-corona-virus-2019-dataset)
在美国可视化新冠肺炎
跟踪美国各县冠状病毒爆发的交互式 choropleth 地图和仪表板
我们最新的地图追踪证实了美国各县每平方英里的新冠肺炎病例
随着冠状病毒(新冠肺炎)爆发现已成为疫情,出现了许多工具来跟踪该病毒的新确诊病例,从在线数字地图到详细的仪表板。这些工具有助于对抗这种疫情。他们帮助公共卫生官员协调应对工作,并让公民更好地了解病毒的影响范围,以便他们能够做好相应的准备。
尽管这些地图无疑是重要的,但许多地图缺乏必要的粒度,无法将新确诊的病毒病例置于“大范围”的背景中。在像加利福尼亚这样的大州,观察全州范围内的病例对国家卫生官员来说可能是有价值的,但对州官员、地方官员或普通公民来说就没那么有帮助了。此外,由于人口密度高,病例往往偏向较大的城市地区,而不利于农村和郊区。
我们的目标是创造几个互动的可视化场景,将疫情的方方面面融入其中。
- 累积地图-可视化每个县的案例总数
- 每平方英里地图-可视化每个县每平方英里的案例
- 人均-可视化每 100,000 人中的人均病例数
还应注意的是,由于选择性检测和无症状个体,数据无疑遗漏了许多病例。这些想象虽然不完整,但对我们理解和抗击疫情的集体努力仍然很重要。
约翰·霍普金斯大学的可视化技术过于具体,使得数据难以掌握
health map的可视化过于宽泛,使得数据难以解读
考虑到这些因素,我和我的团队试图在这些现有的地图上进行构建。我们的目标是创建一组视觉效果,为普通市民和当地卫生官员更好地呈现适当规模的疫情。我们认为,郡尺度的 choropleth 地图是准确显示美国各地新冠肺炎新增确诊病例的最佳方式。
早期发展
该团队目前由来自卡内基梅隆大学和纽约大学的三名成员组成。如果你认为你能帮忙,请联系我们!
Jason Zhu——项目和设计负责人
;陈家——开发负责人
;Miranda Luong——研究设计&
在最初的地图开发之前,我们注意到许多大学生开始编制他们自己的高等教育机构和被关闭事件的列表。通过最少的开发,我们很快就建立了一个由受疫情影响的机构和事件组成的众包知识库。这项工作由社区众包,并成为产生更全面的地图兴趣的工具。例如,一个的 reddit 帖子在 NYU 的 subreddit 上吸引了超过 1000 个独立访客,并在 Reddit 和 Twitter 上转发。
截至 3 月 16 日,已经上线的大学初步名单。
初始累积地图可视化
使用 Mapbox GL JS 和公共数据集,我们开发了一个显示确诊病例的美国地图——类似于上面提到的 HealthMap 可视化。然后,我们将每个坐标标绘到相关的县上。我们认为这是一个适当的粒度——对各级政府和普通公民都有用。为了不忽略查看各州数据的重要性,我们还将美国各州的数据显示在左侧。
以公开可用的美国各县 GeoJSON 边界文件为例,我们使用 Node.js 为每个县添加属性,记录每个日期的确诊病例数。这些数据来源于 UW GitHub 知识库,其中概述了每个案例、确认日期和坐标。
我们数据可视化的初始版本
在一天多的时间里,我们能够创建一个 choropleth 地图,将每个确诊病例坐标与其相关的县进行映射。虽然还处于初级阶段,但这是我们所知的第一次在县一级成功绘制美国冠状病毒病例的努力。我们认为,由于难以找到必要的数据,以前没有这样做过。
该地图的一个缺点是,它可能会歪曲新冠肺炎是如何在美国蔓延和增长的。随着美国的测试能力刚刚开始提升,随着时间的推移,这是可视化数据的必然结果。
从右到左:我们的累积 choropleth 图的三次迭代。
每平方英里和人均地图可视化
随着初始地图的发布,我们开始着手解决累积氯图所呈现的一些问题。举例来说,累积地图可能会忽略新冠肺炎是如何影响农村地区的,因为它倾向于容易进行测试和人口众多的地方。
每平方英里地图
每 10 万人地图
虽然这项工作仍在进行中,但我们会邀请您在 coronashutdown.com 参观我们的可视化项目。
如果您想参与或有任何反馈,请联系我。
非常感谢 Lucy Zhu 和其他人的编辑和反馈
可视化新冠肺炎曲线
每个人都知道我们需要使曲线变平。我们进展如何?
图片: navy.mil
《纽约时报》发布了一组数据,让我们可以查看美国各州、各县的新冠肺炎和相关死亡病例的传播情况。
我们将利用这些数据来观察病毒传播迅速的两个地方:纽约和加利福尼亚。这些数据意义重大,不仅因为它们是最大的州,还因为这些数据可以让我们深入了解社会隔离和就地安置等“曲线拉平”程序有多有效。
但是,由于这只是对数据的快速回顾和可视化,我们将尽量不要得出太多的结论。事实上,我们可以从数据中得出的一个结论是,基于简单的分析就自满太容易了。另一个结论是,即使在加州,我们的情况也很糟糕。除此之外,我邀请你检查数据并得出你自己的结论。
用 Python 提取数据
如果您对提取数据的技术方面不感兴趣,请随意跳到下一节,我们将在这里查看线图。
首先,我们从纽约时报的 github 账号 *中提取数据。*一旦我们建立了这个过程,我们可以简单地重新运行相同的代码,每天重新提取数据,以获得最新的数据集。本页结果完成于 2020 年 3 月 29 日。毫无疑问,接下来的几天和几周,剧情会有所不同。
一个文件是县的,一个是州的,两者都包括累积的(不是新的,而是总数)病例和死亡。
import pandas as pdcounties_url = '[https://raw.githubusercontent.com/nytimes/covid-19-data/master/us-counties.csv'](https://raw.githubusercontent.com/nytimes/covid-19-data/master/us-counties.csv')
df = pd.read_csv(counties_url)
cal_counties_df = df[df['state'] == 'California']
ny_counties_df = df[df['state'] == 'New York']states_url = '[https://raw.githubusercontent.com/nytimes/covid-19-data/master/us-states.csv'](https://raw.githubusercontent.com/nytimes/covid-19-data/master/us-states.csv')
df = pd.read_csv(states_url)
ny_df = df[df['state'] == 'New York']
cal_df = df[df['state'] == 'California']
请注意,第一次感染发生在纽约(3 月 1 日)晚于加州(1 月 25 日),因此纽约的数据集不包括任何更早的日期。您可以通过运行以下命令来验证这一点:
cal_df['date'].min()
ny_df['date'].min()
为了使折线图正确排列,我们需要将那些具有零值的较早日期添加到纽约数据帧中。
ny_add_dates = pd.date_range(start=cal_df['date'].min(), end=ny_df['date'].min()).sort_values(ascending=True)[0:-1]ny_append_list = []for dt in ny_add_dates:
ny_append_list.append([dt.strftime("%Y-%m-%d"), 'New York', 36, 0, 0])
new_ny = pd.DataFrame(
ny_append_list,
columns = ["date", "state", "fips", "cases", "deaths"])ny_extended_df = pd.concat([ny_df, new_ny]).sort_values(by='date')
现在,让我们设置 Python 方法,这将允许我们进行一些绘图:
import matplotlib.pyplot as plt# Plot a single line/location
def plot_loc(loc_df, name, col_name):
fig, ax = plt.subplots()
loc_df.plot(ax=ax, x='date', y=col_name, label=name, kind = 'line')
plt.setp(ax.get_xticklabels(), rotation=30, horizontalalignment='right')
plt.show()# Plot multiple lines/locations
def plot_locs(loc1, loc2, loc1_name, loc2_name, col_name):
ax = loc1.plot(x='date', y=col_name, label=loc1_name, kind='line')
loc2.plot(ax=ax, x='date', y=col_name, label=loc2_name, kind='line')
plt.setp(ax.get_xticklabels(), rotation=30, horizontalalignment='right')
plt.show()
看着这些数据
首先,我们将看看加利福尼亚州与纽约州的比赛:
plot_locs(cal_df, ny_extended_df, 'CA', 'NY', 'cases')
纽约(橙色线)和加州(蓝色线)的感染情况
如果你想对纽约和加州的感染情况做一个简单的比较,那就是了。如果你想知道纽约的情况有多糟糕,那就再考虑几件事情。首先,纽约比加州晚了一个多月才出现第一例感染。其次,加州的面积是纽约的两倍多。
换句话说,纽约的情况很糟糕。
但是我们加州人不应该如此自满。这可能不是因为我们在控制病毒方面比纽约做得更好(尽管也许我们的行动有所帮助),这可能只是因为纽约受到的打击要严重得多。加州早期的就地安置行动可能已经产生了影响(虽然我们不能仅仅通过查看这些数据来说),但加州的情况仍然非常糟糕。
让我们来看看纽约和加州各自的地块,而不是将加州的景色挤进纽约旁边的地块:
plot_loc(cal_df, 'CA', 'cases')
plot_loc(ny_extended_df, 'NY', 'cases')
纽约(左)和加州(右)的感染情况
注意 y 轴(每个图左侧的数字)。左侧图中纽约的最大值为 40,000。对于右边的加利福尼亚,最大值是 5000。换句话说,纽约的感染人数是加州的近十倍。这与我们看到的第一个联合地块非常一致。
但是曲线并没有完全不同。纽约和加州的感染率都呈指数级增长。换句话说,加州落后于纽约,但以这种速度,我们将很快赶上他们现在的水平。
现在,让我们问一个不同的问题:为什么纽约如此糟糕?从这些数据中很难回答这个问题,但是我们可以问*纽约哪里这么糟糕?*这个就好回答多了,应该很明显:纽约市。
我们可以用下面的代码提取纽约市的数据:
nyc_df = ny_counties_df[ny_counties_df['county']=='New York City'].sort_values(by='date')
nyc_add_dates = pd.date_range(start=cal_df['date'].min(), end=nyc_df['date'].min()).sort_values(ascending=True)[0:-1]nyc_append_list = []for dt in nyc_add_dates:
nyc_append_list.append([dt.strftime("%Y-%m-%d"),'New York City', 'New York', 36, 0, 0])
new_nyc = pd.DataFrame(
nyc_append_list,
columns = ["date", "county", "state", "fips", "cases", "deaths"])nyc_extended_df = pd.concat([nyc_df, new_nyc]).sort_values(by='date')
请注意,纽约时报数据将所有纽约市列在一个名为“纽约市”的县下,而不是五个区中的每一个区下。
将纽约市与纽约州的其他城市相比较,我们会看到以下情况:
纽约市所有五个区(蓝线)和整个纽约州的感染情况
蓝线是纽约市,蓝线以上到橙线的所有区域都是州内城市以外的额外感染,包括附近和接壤的县。所以我们可以看到,不出所料,纽约市占了该州感染人数的很大一部分。考虑到纽约州的人口集中在纽约市,这是意料之中的。
但是,为了了解纽约市的情况有多糟糕,让我们将它与加州进行比较:
同样,我们不应该在加州过于自满,但要注意的是,仅纽约市的情况就相当糟糕。
最后,关于指数增长的一个注记。如果你已经学习了计算机科学的入门理论,不仅仅是编程,还有算法分析,一个很大的收获就是指数增长率是不好的。我们经常听到这个词*棘手,*也就是说,一个非常难以处理的问题,即使对于相对较小的指数曲线也是如此。
与纽约相比,加州的感染增长率可能相对较小,但仍呈指数增长,这仍然是一个非常糟糕的预兆。
可视化新冠肺炎对零售的影响
零售业是受疫情影响最大的行业之一,而且可能永远不会恢复
来源:作者使用人口普查局月度零售报告的数据制作的图表
由于新冠肺炎造成的全球疫情现在已经延伸到 2020 年上半年之后,几个国家仍然每天报告数千例病例。最初的行动旨在遏制病毒的传播并使曲线变平以拯救生命,但也产生了严重限制经济活动的不幸影响,因为大多数人都呆在家里以遵守封锁措施。严重依赖人流量的部门被派往 UCI,数量空前的企业要么在有限的产能下工作,要么完全停止运营。尚不清楚一些行业是否会从冲击中恢复过来。
根据美国人口普查局(Census Bureau)的数据,零售业就是这样一个行业,在两个月内,调整后的零售额从 2 月份的 5273 亿美元增加到 4 月份的 4128 亿美元。这意味着总销售额下降了约 22%,也意味着许多企业关门,也许是永远关门。
数据
人口普查局定期发布全国零售数据,这些数据可以直接从官方网站下载。excel 文件包含自 1992 年以来所有月份的数据,每张工作表都以年份命名。从那里,我提取了调整后的数据(如果你对这个过程感兴趣,欢迎你访问Github 项目并查看转换和代码,对于情节复杂的情节使用 NBViewer )。
我选择了调整后的数据,因为显示的估计值是针对季节变化、假日和交易日差异进行调整的,这意味着图表中显示的影响将仅对应于新冠肺炎。使用调整后的数据的一个缺点是,未调整数据的一些细节会丢失,如下图所示。
来源:作者照片。数据来自人口普查局月度零售报告
来源:作者照片。数据来自人口普查局月度零售报告
调整后的切片中有更少的 NAICs,这意味着我们将使用组成每个代码的聚合。总的来说,调整后的数据有 30 个部门,这足以了解每个部门的总体情况。
疫情之前的现实
来源:作者使用人口普查局月度零售报告的数据制作的图表
在上图中,调整后的数据中确定的 30 个地区中的大多数都报告说 1 月份的销售额有所增长,只有一些例外。五个行业的利润率下降到 2%以下,只有燃油经销商似乎表现出“挣扎”的迹象,与 2019 年 12 月相比,下降了约 7.5%。
来源:作者使用人口普查局月度零售报告的数据制作的图表
2 月份几乎所有的零售行业都遇到了一些困难,行业整体下降了 0.44%,在 3 月份灾难降临之前,大多数行业的销售额都减少了相对较小的一部分。
封锁
来源:作者使用人口普查局月度零售报告的数据制作的图表
虽然一些地区在封锁措施下蓬勃发展,如杂货店、药店和非商店零售商;其他公司遭受了不成比例的冲击,比同行受到的伤害大得多。其中一个例子就是仅在三月份就损失了高达 50%的鞋店。
这种情况在 4 月份开始恶化,当时距离措施开始生效。4 月份只有两个行业出现增长,因为整个行业的销售额下降了创纪录的 14.71%。
来源:作者使用人口普查局月度零售报告的数据制作的图表
受封锁影响最大的是服装店、家具和家电商店、餐饮服务和饮酒场所、运动和爱好商店以及加油站。
仅凭直觉,这些结果并不令人惊讶,因为这些商店严重依赖流量来确保其大部分销售。它们还具有非必需品的性质,这意味着公众可以放弃这些支出,转而将资金用于购买危机情况下的必需品。
复苏的开始
随着 5 月初,一些州取消了限制,允许人们回到日常生活中。这些行动转化为大多数行业的销售增长,尤其是受疫情影响最大的行业。仅鞋店销售额就恢复了 200%以上,服装店恢复了 176.88%。
来源:作者使用人口普查局月度零售报告的数据制作的图表
然而,这些数字仍低于新冠肺炎封锁前的水平,如下图所示。
来源:作者使用人口普查局月度零售报告的数据制作的图表
结论
从冠状病毒的初始休克中恢复的小步骤正在进行中。令人高兴的是,在 2020 年 6 月月度报告的预览中看到了进一步改善的迹象,这标志着零售销售的总体增长约为 7.5%,正如华尔街日报所报道的那样。
然而,随着美国的病例数量日益增加,恢复封锁措施的可能性增加,5 月和 6 月取得的成果可能会付诸东流。
[1]人口普查局,零售业月度报告,(2020)
【2】h . Torry,美国随着商店重新开业,6 月份零售额增长 7.5%, (2020),华尔街日报
[3]世界计量仪,美国冠状病毒,(2020)。
视觉化虚无
如何用 Python 可视化数据集的不完整性
很难知道如何处理数据中的空值。大多数时候,放下它们,继续做剩下的事情会更容易。
但它们最终会有意义,可以被研究。花些时间好好看看它们,通常可以更好地理解数据是如何收集的,甚至可以揭示其中的一些模式。
空值矩阵
在本文中,我们将探索如何可视化数据集中的所有空值,并看看我们可以从中获得什么样的见解。
我将在 Jupyer Lab 中运行代码,对于这个例子,我将使用 Pandas 、 Numpy 、 Missingno 和 Matplotlib 。
数据集将是加州监狱概况调查,包含 1995 年至 2018 年每月县级数据。
import pandas as pdf = 'data/california_jail_county_monthly_1995_2018.csv'
df = pd.read_csv(f)
将数据集加载到 Pandas 之后,我们可以看看它处理空值的一种方便的方法。
我们可以利用。isnull 后跟一个. sum,并获取缺失值的个数。
df.isnull().sum()
空值按列计数
这已经很有用了,因为它让我们知道我们可以依赖哪些字段,但是有更好的方式来可视化它,让我们尝试使用 Missingno。
Missingno 是一个用于可视化数据集中不完整性的库,它工作在 Matplotlib 和 Seaborn 之上,使用起来毫不费力。
import missingno as msno
我们将从一个简单的条形图开始。我们将使用矩形和它们的大小,而不是比较大量的数字。
条形图
msno.bar(df)
空值的条形图表示
太好了!在一个方法中,仅仅传递数据帧,我们就已经有了丢失值的可视化表示。
此条形图代表每列中的记录数。这里我们有两个刻度,一个表示字段中值的确切数量(右),另一个表示占总行数的比例。
从条形图开始可以让我们快速判断是否需要花更多的时间来分析空值。
我们的数据并非如此,但如果您有一个没有任何空值或空值数量可接受的数据集,您现在可以停下来继续您的分析。
让我们尝试一种不同的可视化方法来显示缺失的值。
[数]矩阵
msno.matrix(df)
数据集的空值矩阵
矩阵告诉我们丢失值的确切位置,在我们的例子中,数据被排序,最新的记录在最上面。
通过查看矩阵并了解我们的数据是如何排列的,我们已经可以获得一些有价值的见解。在这里,我们可以看到收集的数据在某个时间点发生了变化,矩阵右侧的“*平均囚犯获得心理健康床位”*等字段被终止,其他字段被添加。
突出显示列组的矩阵
非常酷,矩阵的右边还有一个小的 viz,代表行的完整性——它们甚至标记了缺失值的最大和最小数量。
现在让我们来看看。热图,这将有助于我们理解关于不完整性的领域是如何相互关联的。
热图
msno.heatmap(df)
具有空值相关性的热图
好吧,事情变得复杂了——让我们简化一下。
此图按列表示空值之间的相关性。
A 列有一个值,B 也有一个值,这意味着强正相关或图表中的蓝色 1。
A 列有一个值,但 B 列有一个空值,这意味着强负相关,或者在图表中为红色-1。
突出显示的热图
我们之前注意到数据收集方式发生了一些变化,在这里我们可以再次看到这一点。新变量与自身正相关,但与旧字段负相关。
尽管我们可以通过查看矩阵来可视化这种关系,但热图使它们更加明显。为了实现这种模式,我们并不总是以一种方便的方式对行进行排序。
在这个数据集中,我们可以看到调查的字段几乎是分组的。
因此,如果回答了一个问题,我们很可能会得到该组中所有项目的答案。
突出显示各组的热图
好的,我想通过另一种方式,来形象化地展示场在空值问题上的关系。
系统树图
msno.dendrogram(df)
数据集的树状图
我们在热图中看到了一些群体行为,但主要是因为数据集的排列。
如果对行进行排序,我们可以使用矩阵图表注意到字段之间的一些相关性,但是如果它们是随机放置的,这将更加困难。
同样的事情也发生在热图上。如果列是随机放置的,我们将会有一段更具挑战性的时间来找出变量组之间的模式。
树状图使用分层聚类算法根据字段的相关性对其进行分类。*我们看到的与热图的关系。
因此,这就像找出哪些字段在无效性问题上高度相关,然后测试这些变量组如何相互关联等等。
突出显示各组的树状图
同样,我们可以注意到不连续的字段,但我们可以更清楚地看到哪些变量可能更可靠。
该图说明了各组之间的联系,其中离零越远的联系表示无效性不太相似的变量的组合。
过滤器和 Matplotlib
Missingno 是快速可视化缺失值的优秀工具;我们对每个图表只使用了一行代码,得到了一个相当不错的结果。
该工具具有一些过滤功能,可以选择和排列我们想要绘制的变量。它允许我们自定义图表的某些方面,所有这些都在同一个语句中。
对于任何你不能直接用 Missingno 定制的东西,你都可以去 Matplotlib。
from IPython.core.display import display, HTML
import matplotlib.pyplot as plt
import numpy as np# define matrix for the 13 columns with most nulls
**m** = msno.matrix(df, figsize=(25, 14),
**filter='bottom', n=13**,
color=(0.3, 0.3, 0.5))# get ticks names and positions
cols = [i.get_text() for i in **m.axes.get_xticklabels()**]
ticks = np.arange(0,len(cols))# plot new ticks
**plt.xticks**(ticks, labels=ticks+1, rotation=0, ha='center')# title n plot
**plt.title**('Null values matrix\n'.upper(), loc='left', fontsize=22)
plt.show()# empty string for the HTML and template for div
html_table = ''
template = '<div style="border-style:solid; display: inline-block; width: 325px; padding-left: 5px; border-width: thin" >{} - {}</div>'table_order = [1, 6, 10,
2, 7, 11,
3, 8, 12,
4, 9, 13,
5]# draw table
for i in table_order:
html_table += template.format(i, cols[i-1])HTML(html_table)
空值最多的 13 列的空值矩阵
很好,我们了解了可视化和分析数据集完整性的基础知识。有趣的是,我们可以通过可视化数据缺失的值来了解这些数据。
感谢阅读我的文章。我希望你喜欢它。
在这里你可以找到更多关于 Python 和数据可视化的教程。
资源:
https://pandas . pydata . org/pandas-docs/stable/reference/API/pandas . is null . html;
https://github.com/ResidentMario/missingno;
想象新冠肺炎对全球经济的影响
理解四种数据可视化中的疫情效应
凯尔·格伦在 Unsplash 上的照片
目录
数据和代码可以在这里找到:https://github.com/terenceshin/Covid_Impact_on_Economy
介绍
随着我们接近近 400 万例冠状病毒病例、近 25 万例死亡和数月的隔离,我们都同意它极大地影响了我们的日常生活。但这不是唯一受影响的事情。
全球经济中断如此之多,以至于有些人想知道第二次大萧条是否正在向我们走来。虽然目前这只是一种猜测,但我们可以通过客观数字看到,疫情确实正在影响我们的经济。下面是一些统计数据和可视化数据,让你更好地理解目前的经济状况。
冠状病毒和股票市场
标准普尔 500 指数
S&p500 正在下跌。简单来说,标准普尔 500 指数基本上代表了美国 500 家最大的上市公司。今年早些时候,标准普尔 500 指数从最高点下跌了 30%以上——上次标准普尔 500 指数下跌这么多是在 2008 年的经济衰退期间。
你可能会问,“为什么疫情会导致股市下跌这么多?”从理论上讲,股票市场是我们经济运行状况的反映,并且受到许多因素的影响,比如利率。但实际上,股票市场反映了我们对经济在不久的将来会有多好的预期。由于这场疫情引发了很多对未来的不确定性,投资者一直在抛售股票套现,这反过来又降低了股市的价值。
当然,不确定性不是唯一的因素。还有许多其他指标,如失业率和消费者信心,表明经济放缓。这让我们有了下一个洞见…
冠状病毒和失业率
历史失业率
失业率正在上升。2008 年经济衰退后,失业率从 10%一路稳步下降到今年 2 月的 3.5%。然而,从 2 月到 3 月,失业率从 3.5%增加到 4.4%,增幅超过 25%。这可能只是个开始……高盛预测今年失业率可能达到 15%的峰值。
举个例子,2008 年衰退期间的最高失业率是 10%。这既可怕又糟糕,因为失业率影响到每个人。更高的失业率意味着家庭的可支配收入将减少,这意味着公司的收入将下降,从而导致更多的裁员,这一循环还在继续。
冠状病毒和黄金
GLD 信托价格
黄金正在增值。当经济形势恶化时,黄金往往会升值,这种情况也不例外。对那些感兴趣的人来说,从技术上讲,黄金没有内在价值。你不能去杂货店用黄金买食品杂货。但黄金在古代文明中是一种货币,从那时起,它就被社会建构并被视为价值储存手段。因此,这可能是另一个迹象,表明我们的经济正在走下坡路。
冠状病毒与消费者信心
消费者信心下降。经合组织对消费者信心的定义如下:
「这个消费者信心指标提供了家庭消费和储蓄未来发展的指标,是根据对他们预期的财务状况、对整体经济状况的看法、失业情况和储蓄能力的回答而得出的。高于 100 的指标表明消费者对未来经济形势的信心增强,因此他们不太倾向于储蓄,而更倾向于在未来 12 个月内花钱购买大件商品。低于 100 的数值表明对经济未来发展的悲观态度,可能导致更多储蓄和更少消费的趋势。”
从上面的图片来看,消费者信心指数已经下降到 100 以下,我预计在接下来的几个月里会继续下降。这是什么意思?报告称,数值低于 100 表明对未来经济发展持悲观态度。这与我们在上面看到的其他指标是一致的。
如果消费者认为近期前景黯淡,并决定增加储蓄,这意味着经济中流通的货币会减少,这意味着企业赚钱会减少,裁员会增多。
奖金
- 世界上 90%以上的人生活在有旅行限制的国家。这对航空业产生了重大影响,因为许多航空公司已经解雇了数千名员工。点击 这里 如果你想了解更多。
- 从更积极的方面来看,世界各地的空气污染正在急剧下降。呆在室内意味着路上的汽车更少,经济放缓意味着产量减少。一月和二月,中国的 NO₂水平下降了 40%。点击 这里 如果你想了解更多。
感谢阅读!
如果你喜欢我的工作并想支持我,我会非常感谢你在我的社交媒体频道上关注我:
- 支持我的最好方式就是在媒体这里关注我。
- 在推特上关注我这里。
- 点击这里订阅我的新 YouTube 频道 。
- 在 LinkedIn 这里关注我。
- 在我的邮箱列表 这里注册。
- 查看我的网站terenceshin.com。
编者注: 走向数据科学 是一份以数据科学和机器学习研究为主的中型刊物。我们不是健康专家或流行病学家,本文的观点不应被解释为专业建议。想了解更多关于疫情冠状病毒的信息,可以点击 这里 。
可视化冠状病毒爆发的进程
由章节
前几天我发表了一篇文章,分析了冠状病毒(新冠肺炎)在中国的社会影响。然而,总的来说,一些人仍然对这次疫情缺乏充分的了解。我认为从一个更客观的角度来想象这种情况会很有趣。
如何开始
首先,我从网络搜集开始,从中国国家卫生委员会提取数据,并使用表格从空间上可视化疫情进展。我还创建了一个 仪表板 ,我们可以在其中轻松地切换日期和省份,以便更仔细地查看。
冠状病毒进展仪表板由 Ashley
免责声明:
请注意,我收集的数据截止到 2 月 11 日。当你读到这篇文章的时候,这些数据可能已经跑偏了,不能反映这次疫情的现状。我将在本文的后面解释有一种简单的方法来跟上实时数据。我使用了一个 网页抓取工具 来提取数据,而不是编码,因为它可以将数据转换为可行的格式,而无需清理数据。
选择数据源:
如果你谷歌冠状病毒数据,我相信你会找到很多资源。像 Kaggle 这样的来源是其他人收集的二手数据,这些数据落后于像中国官方健康网站这样的主要来源的最新数据。如果你是一个对准确性和及时性有严格标准的数据分析师,你应该避免用二手数据下结论。那么你应该使用什么来源呢?原始数据是你选择的。此时,我选择了冠状病毒更新源,因为它被保存为 JSONs,使我们能够通过 API 管道将各个城市的数据传输到我们的系统。(阅读这个 JSON 文件的指南)
刮模板
另一种提取实时数据的方法是使用一个抓取模板,就像我在上一篇文章中做的那样。对于不会编码的人来说,这是一个现成的解决方案(观看此视频了解详情)。您可以设置任务计划程序来获取最新数据。这是我收集的数据,可以随意使用。
用 Tableau 实现数据可视化
在获得大量数据后,我们可以将其上传到 Tableau。我首先创建一个地图层,只需将省/州拖放到拖放字段中。之后,我添加时间序列并累加数值,以全面展示每个省的数据趋势。我把湖北省画出来,因为我可以特别注意它的数据趋势。该地图显示了自 1 月 22 日以来过去 20 天冠状病毒的历史传播情况。截至 2 月 11 日,仅湖北一地的确诊感染人数就达到了 33366 人。
阿什利冠状病毒爆发
我们可以看出,除了湖北,这次疫情对广东、浙江、湖南和河南的影响也很大。
不同省份报告的病例
请注意,湖北报告的病例明显多于所有其他病例的总和。我创建一个群,把他们分成两类:湖北和其他。为了更好地了解此次疫情的发展方向,我还添加了趋势线来分析当前形势。
湖北和其他地区都开始下滑到趋势线之下,这表明确诊病例呈下降趋势。然而,死亡人数并没有显示出积极的变化,因为数字仍然高于趋势线。
冠状病毒爆发湖北 vs .其他
冠状病毒爆发湖北 vs .其他
除了湖北以外,各省的复苏速度似乎是一些令人高兴的消息,因为随着时间的推移,趋势线变得更加强硬,更多的地方向上移动,表明复苏有所倾斜。恢复率将继续增长,因为人们现在正在迅速采取行动击败病毒。
回收率增长
最终想法:
我制作了动画,因为这是一个很好的方式来理解大画面,我们能够看到这次疫情的进展。一旦我们将数据可视化,分析就变得容易多了。数据分析中最大的挑战是数据收集。我通常会把大部分时间投资在无需动脑的劳动上。通常,我还需要手动修复数据格式。我发现网页抓取工具可以大大提高工作效率。但是,我不会建议过度滥用和刮擦任何网站。这将导致严重的法律后果。查看这篇文章了解更多信息:网络爬行合法吗?
我会努力提高可视化,并随时分享你的想法和电子邮件给我。
原载于 2020 年 2 月 14 日 https://www.octoparse.com*。*
用 Python 散景可视化股票市场
创建交互式股票价格仪表板的初学者指南。
为什么可视化很重要
要建立你的交易平台,你还需要有一个可视化你的股市数据的方法。最简单的方法之一你可以选择 TradingView ,它有一个极好的分析金融市场数据的想法。
但是,您可能有特定的需求,比如在某种程度上比较两只股票的价格。大部分网络平台都支持不了这种情况。或者,如果你已经有一些自动化,你需要一个工具来可视化你的交易策略。
在这篇文章中,我将向你展示我如何开始在我的每日交易平台中建立我的可视化。在过去的几年里,我尝试了很多可视化框架,并且散景可以支持我的大多数用例。
也许你对 Python 中绘图的matplotlib
和seaborn
比较熟悉。然而,金融数据,尤其是价格历史可视化在交互时更好。 散景可以用多个复杂的图表创建丰富的交互式仪表盘。
如果你对我如何尝试其他框架感兴趣,请查看附录。
什么是散景?
散景是一个可视化库,可以很容易地创建功能强大的交互式绘图。
散景图可以导出为静态图像,或者嵌入到网页中。该库有一个内置的应用服务器,可以作为交互式仪表板的后端。
另一方面,散景也是一个低级的库,因为它允许我们控制一个情节的所有方面,包括交互和样式。
但是,散景也是简单易用和强大的,因为在几行代码中,你可以有多种多样的互动情节。为了对散景图有所了解,让我们来看看 MSFT 股票的一个简单图:
MSFT 每日股票价格烛台
开始前,数据
从可视化开始,我们需要先谈谈数据。
在本文中,我们将使用从使用雅虎金融 API 的 Python 的免费股票数据中提取的 OHLCV 数据。先看看这个帖子,你应该能得到你想要的数据。或者你已经有了自己的 OHLC 股票数据。
数据格式如下:
这里我们将使用 MSFT 日报 OHLCV 数据作为例子,并建立一个与历史股票价格相关的仪表板。你可以把它应用到任何金融符号上。
你可以在这里下载我的示例数据。
入门指南
根据您的设置,使用conda install bokeh
或pip install bokeh
安装散景很简单。
该库不仅提供了 Python 包,还提供了一个名为bokeh
的 CLI,用于运行bokeh
app server。你可以通过命令行bokeh serve — show xxx.py
轻松运行散景。
基本概念
编译后,JavaScript 客户端库将在浏览器中呈现可视元素并处理散景图的 UI 交互。不需要控制 JavaScript 部分。
注意,使用bokeh.plotting
界面创建的散景图图带有一组默认的基本字形。字形有多种形式:圆字形、线字形、*文字、*和其他。对于主要用途,散景图就足够了。
每个散景图由一组**模型组成。**构成散景“场景图”的最低级别对象。这些都存在于bokeh.models
接口中。最终,所有的散景图都由模型集合组成,这给了你对图的绝对控制,它通常不会被直接使用。
散景服务器用于将散景图作为静态页面共享和发布,或者在浏览器中部署应用。
基于以上所掌握的知识,我们应该能够用市场数据画出一个图来。
使用股票历史价格数据源绘图
为了使绘图更加简单和清晰,我们使用了ColumnDataSource
。ColumnDataSource
是散景的基本数据结构。大多数图、数据表等。将由一辆ColumnDataSource
驱动。可以像字典一样定义ColumnDataSource
,然后从pandas.dataframe
导入。
使用基本的字形如vbar
来渲染基于ColumnDataSource
的烛台。
基本代码如下所示:
运行bokeh serve — show xxx.py
显示图形:
自定义日期标签
到目前为止,我们只处理了标准数据。这个情节有很多问题。有一点是 x 轴索引不正确。通常,我们可以显示索引号。然而,股票价格是按日期排序的时间序列数据,我们需要绘制一个时间范围并显示确切的日期。我们需要建立一个从索引到日期字符串的映射。
默认情况下,一个图中只有五个分笔成交点。为了显示每一天,我们必须设置刻度数。
更新了代码:
更改后,现在日期 x 轴清晰多了。
自定义货币
这里我们再次使用 Bokeh 的货币格式:($ 0.00 a)
,它将以百万为单位输出数值。对于其他预定义的格式和各种格式化程序,请参见格式化程序文档。
自定义绘图工具悬停工具
你可能已经注意到,散景为每个图提供了一个工具栏。工具允许缩放、平移、选择数据并执行其他动作。
悬停工具是一种检查工具。它通常一直处于打开状态,但可以在与默认隐藏的工具栏相关联的检查器菜单中进行配置。默认情况下,悬停工具将生成一个工具提示,其中每行包含一个标签和相关值。
通过添加带有标签的工具提示更新了代码:日期时间、打开、关闭、体积。可以根据自己的选择添加更多。
下面是修改后的工具提示:
包裹
到目前为止,您已经学会了如何:
- 基于 OHLCV 股票数据创建带有字形的图。
- 用日期时间标签配置图。
- 配置自定义布局和工具提示。
现在你应该可以开始建立你的仪表板,开始你的算法交易分析。如果你想知道更多关于这个话题的信息,请留下你的评论,让我知道。
代码和数据
下面附上我的代码,示例数据是这里是。
附录:其他框架
以下是我对其他框架的评论:
- Matplotlib 财务-> mpl_finance -> mplfinance
- Viser
Matplotlib finance,已被弃用,已被移到一个名为mpl_finance
的模块中。还有,mpl_finance
是贬义,会有新版本 mplfinance (估计 2020 年年中替换)。
与我去年使用的相比,新的打印机相当不错。
价格和成交量图
相比于散景,很难做到交互。如果对于基本用例。这应该是一个快速的解决方案。由于它仍在开发中,我建议在 2020 年中期使用它。
我尝试过的另一个框架是 Viser 。如果你喜欢 JavaScript 技术栈。我做了一个 Viser 的投资组合图。然而,Viser 的社区支持非常差。您必须知道许多技巧,才能使它与其他 JavaScript 库一起工作。
可视化白宫新冠肺炎疫情
作者图片
新闻充斥着 COVID 在白宫行政部门的传播,所以让我们立即进入下图的代码和可视化。数据集在此。 此处代码。
方法论
使用《纽约时报》的文章追踪白宫冠状病毒爆发,我们可以创建一个快速的 excel 表格,列出特朗普总统宣布 COVID 检测呈阳性之前与他在一起的所有人。
作者图片
作者图片
最无聊的部分是,又多了一个数据集来匹配缩写名和全名。数据集在这里所以你可以跳过这个过程。
为了创建可视化效果,我使用 Python 将 events 数据集转换成网络可视化格式的数据集,并使用 Gephi 来可视化网络。
作者图片
关于网络可视化和 Python 的说明
在我们开始为 Gephi 准备这些数据之前,我只想简单谈谈网络可视化数据集和 Python 的准备工作。网上很多教程提到*“网络可视化”*这几个字就会带进 NetworkX 。然而,我发现 NetworkX 对于很少或没有接触过网络分析的初学者来说是不直观的,尤其是与 TidyText ®之类的东西相比,它真的可以指导您完成网络分析+基于文档/文本的关系提取和分析。
因此,如果您打算深入研究——在编写任何代码之前,先读一点资料,并尝试一下网络可视化。对你能运行的统计数据和你能创建的网络感兴趣。一个很棒的资源是网络知识库,它有一个交互式图形 Vis 页面,可以立即将你吸引到你可以从一个网络中学到的奇妙的东西,而不仅仅是 Twitter 上谁关注谁的基础知识。
当您准备好之后,请认真考虑如何创建您一直在尝试的网络数据集格式。对于小型网络,您可以用不到 20 行的代码编写必要的脚本,使用您已经熟悉的库和函数来准备数据集。
准备数据
使用 pandas,导入数据集并使用 ast.literal_eval 将出席特朗普总统活动的人员列表的字符串表示转换为列表。
import pandas as pd
import os
from path import Path
import ast
import itertools# set directory to where this file is located
folder_loc = os.path.dirname(os.path.realpath(__file__))
os.chdir(Path(folder_loc))events_df = pd.read_excel('events.xlsx')
ppl_df = pd.read_excel('ppl.xlsx')output_name = 'edges.csv'# convert str list to list -- please excuse the following these
# apply(lambda x)'s.. this quick script isn't industrial strength in
# efficiency
events_df['ppl'] = events_df['ppl'].apply(lambda x: ast.literal_eval(x))
我们的目标是创建两列: Source 和 Target ,它们表示任何给定的两个人之间的联系,前提是他们都与 Donald Trump 参加了同一个活动。
因此,我们首先获得列表的所有可能组合,每个组合代表一个事件的参与者。然后,我们分解刚刚创建的元组列表,以创建源和目标列。
# new column of all combinations possible
# whats cool about itertools combos is that it doesn't do duplicates
# e.g. (DT, KM) (KM, DT)
events_df['combos'] = events_df['ppl'].apply(
lambda x: list(itertools.combinations(x, 2)))# reshape dataframe with source target
events_df_exploded = events_df.explode('combos')# create source and target rows
def src_targ(combo):
lst = list(combo)
return pd.Series([lst[0], lst[1]])events_df_exploded[['src', 'tar']
] = events_df_exploded['combos'].apply(src_targ)
接下来,我们用全名替换姓名缩写,清理我们的列,并为 Gephi 导出我们的 csv 文件。我还添加了代码来导出单个数据集,每天一个,以防对您自己的项目有所帮助。
# add in the real names of everyone
events_df_exploded = pd.merge(events_df_exploded, ppl_df, how='left',
left_on='src', right_on='abbrev')
events_df_exploded = pd.merge(events_df_exploded, ppl_df, how='left',
left_on='tar', right_on='abbrev')# clean up
events_df_exploded.rename(columns={'name_x': 'Source',
'name_y': 'Target'},
inplace=True)events_df_exploded = events_df_exploded.drop([
'ppl', 'combos', 'abbrev_x', 'abbrev_y', 'src', 'tar'],
axis=1)# export file
events_df_exploded.to_csv(output_name)# export batches by day
df_grouped = events_df_exploded.groupby('date')# iterate and export
for group_name, df_group in df_grouped:
print(group_name)
out_name = output_name.replace(
'.csv', '') + '_' + str(str(group_name).split(' ')[0]) + '.csv'
df_group.to_csv(out_name)
基于 Gephi 的网络可视化
关于 Gephi 要知道的第一件事是,它对你导入的数据集的格式和列标题非常特别。虽然我已经很多年没有使用 Gephi 了,但我很高兴地看到今天网上有更多的文章和视频解释 Gephi 的怪癖。一定要在谷歌上搜索一下,看看 Gephi 的插件,寻找新的想法和未来的项目。
使用 Data Laboratory 屏幕将节点和边数据集导入 Gephi 后,使用概览屏幕左侧的外观选项卡中的参数,以及屏幕右侧和底部的过滤和布局。当您对可视化效果感到满意时,单击预览选项卡并导出您的图像。我用 photopea 把出口和标题放在一起。
就是这样!
还有两件事。如果你或你的学生有热情,但不知道如何或何时,找一个安静的地方,用一支不起眼的笔(转述自保罗·西蒙)。实际上,尝试一下 NodeXL 吧——每份学生许可证 39 美元,在 Twitter 抓取、网络可视化(虽然很慢)和数据集准备(如果你愿意,可以将其导入 Gephi)方面,它包含了一些非常强大的功能。对于非编码人员来说,这是一个轻松的好方法。
作者图片
对于跟随本教程的每个人来说,这里有一些你可能想不到在 Gephi 上看的地方,它们对于创建视觉效果非常关键,而不需要在论坛上寻找答案。整个项目花了我大约 2 个小时,最大的时间消耗(除了开始输入 excel 表格)是记住东西在 Gephi 中的位置。所以,确保你对你想要想象的东西有一个清晰的画面(一直到调色板),放上一些高保真的音乐来放松/学习,然后投入进去。
**关于我:**Basil Labs 的创始人,Basil Labs 是一家大数据消费者智能初创公司,帮助组织量化消费者的去向和价值。
热爱音乐,开放数据政策和数据科学。更多文章请关注我的媒体。
如果你对数据伦理、开放数据和/或音乐充满热情,欢迎在 Twitter 上加我。
使用 Python 可视化三维数据-热点图、等值线和 3D 绘图
Python 科学绘图
使用 Python 绘制热点图、等值线图和 3D 图
当您测量属性对多个独立变量的依赖性时,您现在需要绘制三维数据。这种例子通常发生在空间测量中,其中存在与每个(x,y)点相关联的强度,类似于光栅显微镜测量或空间衍射图案。为了可视化这些数据,我们有几个选项可供选择——我们将探索创建热图、等高线图(未填充和填充)和 3D 图。
我将在这个例子中使用的数据集是来自原子力显微镜(AFM)的一张 2 m x 2 m 的显微照片。首先,我们导入包——我们这次添加的两个新包是make_axes_locatable
,它将帮助我们管理我们的绘图的色条,以及我们的 3D 绘图所需的Axes3D
:
# Import packages
%matplotlib inline
import matplotlib as mpl
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1.axes_divider import make_axes_locatable
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
我们现在将加载我们的 AFM 数据,再次使用numpy.loadtxt
将我们的数据直接加载到 2D numpy
数组中。
# Import AFM data
afm_data = np.loadtxt('./afm.txt')
然后,我们可以检查我们加载的数据中的几行:
# Print some of the AFM data
print(afm_data[0:5])>>> [[4.8379e-08 4.7485e-08 4.6752e-08 ... 6.0293e-08 5.7804e-08 5.4779e-08]
[5.0034e-08 4.9139e-08 4.7975e-08 ... 5.7221e-08 5.4744e-08 5.1316e-08]
[5.2966e-08 5.2099e-08 5.1076e-08 ... 5.4061e-08 5.0873e-08 4.7128e-08]
[5.7146e-08 5.6070e-08 5.4871e-08 ... 5.1104e-08 4.6898e-08 4.1961e-08]
[6.2167e-08 6.0804e-08 5.9588e-08 ... 4.7038e-08 4.2115e-08 3.7258e-08]]
我们有一个 256 x 256 的点数组,每个值对应于该位置的测量高度(以米为单位)。因为我们知道如果用纳米表示,我们的数据会更有意义,所以我们可以用这个常数来衡量我们所有的值:
# Convert data to nanometers (nm)
afm_data *= (10**9)
现在我们可以开始可视化我们的数据了。我们从设置一些全局参数开始(随意编辑这些参数,但这些是我使用的设置):
# Edit overall plot parameters# Font parameters
mpl.rcParams['font.family'] = 'Avenir'
mpl.rcParams['font.size'] = 18# Edit axes parameters
mpl.rcParams['axes.linewidth'] = 2# Tick properties
mpl.rcParams['xtick.major.size'] = 10
mpl.rcParams['xtick.major.width'] = 2
mpl.rcParams['xtick.direction'] = 'out'
mpl.rcParams['ytick.major.size'] = 10
mpl.rcParams['ytick.major.width'] = 2
mpl.rcParams['ytick.direction'] = 'out'
热图
对于热图可视化,我们将使用imshow
函数将我们的数据显示为图像。首先,我们创建一个图形并添加一个主轴来显示我们的图像。此外,我们将删除刻度线,因为我们将添加一个比例尺。
# Create figure and add axis
fig = plt.figure(figsize=(4,4))
ax = fig.add_subplot(111)# Remove x and y ticks
ax.xaxis.set_tick_params(size=0)
ax.yaxis.set_tick_params(size=0)
ax.set_xticks([])
ax.set_yticks([])
现在我们用下面的命令显示我们的图像:
# Show AFM image
img = ax.imshow(afm_data, origin='lower', cmap='YlGnBu_r', extent=(0, 2, 0, 2), vmin=0, vmax=200)
origin
—图像通常显示为其原点在左上角,因此通过使用origin='lower'
我们强制原点在左下角
我们图像的色彩映射表。所有可用的matplotlib
色彩映射表都可以在中找到,在任何色彩映射表名称中添加_r
都会将其反转。
extent
——imshow
将使用像素绘制我们的图像,除非我们告诉它这些像素对应的范围。在这种情况下,我们知道我们的图像是 2 m x 2 m,所以我们让我们的extent=(x_min, x_max, y_min, y_max)
等于(0, 2, 0, 2)
vmin
—设置为颜色图最小值的值
vmax
—设置为色彩映射表最大值的值
我们的 AFM 显微照片的图像绘图
现在,我们应该添加我们的比例尺,这样任何查看该图的人都会对大小比例有一个概念。我们将使用plt.fill_between
创建一个填充的矩形,然后在顶部添加一个文本标签。
# Create scale bar
ax.fill_between(x=[1.4, 1.9], y1=[0.1, 0.1], y2=[0.2, 0.2], color='white')
x
—我们的填充形状的 x 范围(因为我们的图像从[0,2]到指定的范围[1.4,1.9]是 0.5 米或 500 纳米)
y1
—我们填充形状的底部 y 值(对应于x
的值)
y2
—我们填充形状的顶部 y 值(对应于x
的值)
ax.text(x=1.65, y=0.25, s='500 nm', va='bottom', ha='center', color='white', size=20)
x
—文本的 x 轴位置
y
—文本的 y 轴位置
s
—文本字符串
va
—垂直对齐(bottom
表示y
对应文本底部)
ha
—水平对齐(center
表示x
对应文本中心)
添加比例尺的 AFM 显微照片
最后,我们可以添加一个颜色条来显示图像中的颜色与高度值的对应关系。首先,我们为 colorbar 创建一个新的 axis 对象,这是通过使用make_axes_locatable().append_axes
函数在原始轴的右侧追加一个新轴来实现的。我们将原始轴对象ax
传递给函数:
# Create axis for colorbar
cbar_ax = make_axes_locatable(ax).append_axes(position='right', size='5%', pad=0.1)
position
—添加下一个轴的位置,在本例中为原始图像的右侧
size
—新轴沿position
方向的尺寸,相对于原始轴(图像宽度的 5%)
pad
—两轴之间的填充(在绝对坐标中)
现在,我们把这个新的轴对象变成一个颜色条:
# Create colorbar
cbar = fig.colorbar(mappable=img, cax=cbar_ax)
mappable
—映射到颜色条的图像/绘图(我们在前面使用imshow
时创建了img
cax
—用于颜色条的轴
最后,我们调整色条的刻度线和标签:
# Edit colorbar ticks and labels
cbar.set_ticks([0, 50, 100, 150, 200])
cbar.set_ticklabels(['0', '50', '100', '150', '200 nm'])
带有比例尺和颜色条的 AFM 显微照片
等高线图
就像在大多数徒步旅行路线中发现的地形图一样,我们也可以用恒定强度的等高线来呈现三维数据。我们现在将使用等高线图绘制相同的 AFM 数据。
我们使用与之前相同的代码,更改了以下代码行(我添加了zorder=1
以确保等值线图位于比例尺下方,因为首先绘制的是较低的 z 顺序数字):
# Show AFM contour plot
ax.contour(afm_data, extent=(0, 2, 0, 2), cmap='YlGnBu_r', vmin=0, vmax=200, zorder=1)
AFM 显微图像轮廓图,带比例尺和颜色条
如果我们使用contourf
而不是contour
,我们可以创建填充轮廓,而不仅仅是轮廓线:
# Show AFM filled contour plot
ax.contourf(afm_data, extent=(0, 2, 0, 2), cmap='YlGnBu_r', vmin=0, vmax=200)
AFM 显微照片填充的轮廓图,带有比例尺和颜色条
在这种情况下,来自imshow
的许多更精细的细节在contour
或contourf
中没有被很好地捕捉到。如果您的数据相当平滑,没有很多较小的细节,等值线图像可能比热图更好看。最终,您希望以尽可能透明和直观的方式呈现数据,因此在这种情况下,带有颜色条的热图可能是最好的。
3D 绘图
到目前为止,我们已经将我们的图限制为二维,并使用色标让读者推断强度。如果我们想更好地理解这些强度值,我们实际上可以用 3D 来绘制数据。
我们首先用下面的代码创建一个 3D 轴,这里的关键是我们在生成轴对象时使用了projection=’3d'
:
# Create figure and add axis
fig = plt.figure(figsize=(8,6))
ax = plt.subplot(111, projection='3d')
空 3D 轴对象
灰色窗格和轴网格给我们的绘图增加了混乱,所以让我们删除它们。此外,我将再次为高度添加颜色条,因为透视视图的原因,z 轴将被压缩,所以我将删除它。
# Remove gray panes and axis grid
ax.xaxis.pane.fill = False
ax.xaxis.pane.set_edgecolor('white')
ax.yaxis.pane.fill = False
ax.yaxis.pane.set_edgecolor('white')
ax.zaxis.pane.fill = False
ax.zaxis.pane.set_edgecolor('white')
ax.grid(False)# Remove z-axis
ax.w_zaxis.line.set_lw(0.)
ax.set_zticks([])
没有背景窗格和 z 轴的空三维轴
对于表面图,我们需要 x 和 y 值的 2D 数组来对应强度值。我们通过用np.meshgrid
创建一个 mesh-grid 来做到这一点——我们对这个函数的输入是一个要在网格中重复的 x 值和 y 值的数组,我们将使用np.linspace
来生成这个数组。
# Create meshgrid
X, Y = np.meshgrid(np.linspace(0, 2, len(afm_data)), np.linspace(0, 2, len(afm_data)))
现在我们有了网格,我们可以绘制三维数据:
# Plot surface
plot = ax.plot_surface(X=X, Y=Y, Z=afm_data, cmap='YlGnBu_r', vmin=0, vmax=200)
X
—x 值网格
Y
—y 值的网格
Z
-z 值的网格
AFM 显微照片的 3D 绘图
现在,我们可以调整绘图视图——我们为此控制三个参数:仰角、方位角(在 x-y 平面中)和离轴的距离,它们分别大致对应于球坐标系值 φ 、 *θ、*和 r 。我将方位角设置为 225,因为我们希望 x 轴和 y 轴在(0,0)处相交。
# Adjust plot view
ax.view_init(elev=50, azim=225)
ax.dist=11
添加颜色栏:
# Add colorbar
cbar = fig.colorbar(plot, ax=ax, shrink=0.6)
cbar.set_ticks([0, 50, 100, 150, 200])
cbar.set_ticklabels(['0', '50', '100', '150', '200 nm'])
shrink
—相对于其默认大小将颜色条缩小多少
最后,我们编辑一些美感——x 和 y 轴上的刻度线、轴限制和轴标签。
# Set tick marks
ax.xaxis.set_major_locator(mpl.ticker.MultipleLocator(0.5))
ax.yaxis.set_major_locator(mpl.ticker.MultipleLocator(0.5))# Set axis labels
ax.set_xlabel(r'$\mathregular{\mu}$m', labelpad=20)
ax.set_ylabel(r'$\mathregular{\mu}$m', labelpad=20)# Set z-limit
ax.set_zlim(50, 200)
带彩条的 AFM 显微图的 3D 绘图
这个图让读者除了用颜色表示强度值之外,还能看到高度的波动。然而,噪声更大的数据集可能会导致非常混乱的 3D 绘图。
结论
我希望本教程有助于解决绘制三维数据集的不同方法。在这个 Github 资源库中可以找到例子。感谢阅读!
可视化时间序列生存数据
Geran de Klerk 在 Unsplash 上拍摄的照片
卡普兰-迈耶曲线
让我们想象一下,你有关于你的研究对象“存活”了多久的数据。生存可以是字面意义上的(如在临床试验中)或比喻意义上的(如果你正在研究客户保持,当人们停止阅读一篇文章,或当一台机器坏了)。为了可视化数据,我们想要绘制一条生存曲线,叫做卡普兰-迈耶曲线,如下图所示。
具有 95%置信区间的药物耐受性和使用的存活曲线(人工生成的数据,n ≈ 300)
左边的曲线(使用人工生成的数据创建)旨在显示开始服药几天后仍在服药的人的百分比。在这种情况下,他们会停下来,因为药物不再控制疾病,或者因为它引起了太多的副作用。
理想情况下,通过简单地考虑在开始服药后的给定天数内服药的人的百分比,很容易计算出这条曲线。
然而,一些人(本例中约 25%)仍在服药。他们可能只是服用了很长一段时间(在这种情况下接近 10 年)而没有问题,或者他们可能只是刚刚开始服用。这种观察被称为“右删截”,因为我们不能及时观察到它们(向右)。
对此最简单的解决方案是卡普兰-迈耶曲线,也称为乘积极限估计量。还有其他解决方案,但它们需要对数据做出假设,并为数据提供一个模型。另一方面,我们通常的第一步是只看数据,卡普兰-迈耶曲线允许我们在不做假设的情况下这样做。
在本文中,我们将讨论如何计算卡普兰-迈耶曲线,最重要的是,显示的置信区间。更重要的是,我们将探讨计算置信区间(有时称为“对数”和“对数-对数”/指数格林伍德置信区间)的两种方法之间的差异。
卡普兰·迈耶的估计
如果你还没猜到,这种生存曲线起源于医学和精算界,字面上的关注是某人是否真的会死亡。因此,我们将采用这样的术语:研究中给定的受试者(比如说一个人)可能仍然活着,在这种情况下,观察是经过审查的(我们没有观察到一个事件),或者他们可能已经在特定的时间点死亡(我们观察到了该事件)。
请注意,当我们说“时间”时,我们不是指字面上的日期,而是相对于参与者进入研究的时间。在人寿保险的例子中,那只是他们出生的时间。在上面的医学例子中,它是当某人开始服用药物时。
上世纪 50 年代的卡普兰-迈耶估计,用文字表述比用公式表述更容易。规则是:
- 一开始,100%的人都是活着的。
- 在每个时间点(以 i 为索引),计算存活的人的百分比,作为已知活了那么久的人的百分比。
- 为了创建曲线,假设在时间 i 幸存者的百分比是该时间和每个先前时间的生存机会百分比的乘积。
例如,假设我们有三个人的记录。一个活到了 92 岁,一个死于 90 岁,一个死于 95 岁。90 岁时,66.7%的人口存活下来。92 岁时,100%存活。在 95 岁时,100%的人(不是 50 岁)会死亡。这是因为 92 岁的人没有计入 95 岁的人口中。
注意,某人被审查的次数(在我们的例子中是 92 次)不会影响曲线。事实上,只有我们观察到某人死亡的次数才算数。
现在让我们用方程式来做。
- 让 i 索引某事发生的时间(即某人死亡)。
- 设 d 为在时间 i. 停止的人数
- 设 n 是在时间 i. 时人口中(已知幸存)的人数
生存函数的卡普兰-迈耶估计量为
生存函数的 Kaplan-Meier 估计
换句话说,生存百分比与当前时间 t 之前所有时间的产品的乘积。
卡普兰-迈耶估计量是生存函数的最大似然估计量,这使得它成为快速可视化的自然选择。
一般来说,你可以发现这是大多数处理时间序列数据的统计软件包。对于 python 来说,[statsmodels](https://www.statsmodels.org/stable/generated/statsmodels.duration.survfunc.SurvfuncRight.html#statsmodels.duration.survfunc.SurvfuncRight)
或[lifelines](https://lifelines.readthedocs.io/en/latest/)
是一些不错的选择。[survival](https://cran.r-project.org/web/packages/survival/index.html)
作 R。
格林伍德置信区间
棘手的部分在于计算置信区间。首先,我们假设在时间 i. 有一个真实的“风险率”,换句话说,我们假设 d 遵循一个二项式分布,概率 h 和样本量 *n、*在时间 i. 各不相同,这意味着它有均值和方差 nh 和 nh(1-h) 。
d 的均值和方差
下一个技巧是,由于 S 的估计量是一个乘积,所以处理 S 的对数会更容易,因为它是一个和。
现在我们需要转移话题,谈谈泰勒级数近似,它将使我们能够进行一系列的计算。
德尔塔法
Delta 方法是处理随机变量(如对数)转换的一种方便而严格的方法。假设我们有一个随机变量 X 和一个函数 f (你应该认为它是对数)。如果我们假设 X 只是一个正则数(不是随机的),那么我们可以写下关于一个点 c 的一阶泰勒展开式:
f 的一阶泰勒展开
delta 方法的本质洞见是,假设 X 是一个像样本均值或我们对 s 的估计一样的统计量,如果 c 是 X 的期望值,E[X],那么在大样本量的极限下,X 将接近 c 并呈正态分布(由中心极限定理),逼近将非常好。这让我们可以计算 f 的期望值:
delta——期望值的方法近似值
更好的是,我们可以应用大一微积分的中值定理。假设我们已经测量了 X 的值,我们可以找到位于 c 和 X 之间的值 d,因此
泰勒展开的中值定理
同样,在大样本量的限制下,X 更接近 c,因此 d 被挤压在它们之间,也更接近 c。因此,在大样本量的限制下非正式地工作,我们可以将上面的近似等式视为等式。
现在假设我们知道 X 的方差取决于样本大小 n :
根据中心极限定理,x 关于其期望值是正态分布的
回到我们最初的泰勒展开,重新排列各项并乘以 n 的平方根:
f(X)的泰勒展开的重排
这意味着我们已经计算出 f(X)的方差是 x 乘以 fʹ(c 平方的方差。
运用德尔塔法
请回忆一下,在我们离题进入德尔塔法之前,我们说过
让我们考虑使用 Delta 方法计算总和中每一项的方差。期望值是 1–h,所讨论的函数是导数为 1/x 的对数 log(x)(当然,我们只使用自然对数)。因此:
我们还可以计算每一项的方差。log(1-h)项没有方差(是常数),第二项减去 h 也不影响方差。
各项的方差
现在,一个简单的技术问题。通常,我们可以把方差加起来,来计算总和的方差。然而,从技术上讲,这两项并不独立,因为时间 I 的死亡会影响后面时间的分母 n。另一方面,感兴趣的项(d/n–h)具有均值 0,条件是知道所有以前的死亡,这使得这些项成为一个鞅差(或者它们的和是一个鞅)。反过来,鞅中心极限定理告诉我们,方差实际上只是个体方差之和。
最后,我们得到了 S 的对数的方差
最后,我们可以再次应用德尔塔法
最后
我们可以反过来估计为:
这又让我们通过假设 S 的估计量是正态分布(如果样本量足够大,就会是这种情况)来计算格林伍德置信区间。
唷。
指数格林伍德置信区间
现在,使用上面的格林伍德置信区间会导致一个问题,即您的置信区间可能会落在 0-1 边界之外。如果有一个图表,在这个图表上,你的置信区间允许有时候存活率是负的,这将是非常尴尬的。
这里的解决方案是注意我们使用了 log,因为它强制 S 为正。如果我们计算变换后的对数 S 的置信区间,我们至少可以保证得到的置信区间将大于 0(但也可以大于 1)。我们为此付出的“代价”是拥有一个不对称的置信区间。但是,如果我们要这样做,我们不妨一路走下去。如果我们用
那么我们将得到保证位于 0–1 区间内的置信区间,因为 log(–log(X))只接受 0–1 范围内的参数;逆变换将确保我们在该范围内结束。
我不会给你数学;经过变换的 S 的最终方差为
计算变换后的 s 的置信区间,然后用 x ⟼指数(-exp(x))撤消变换,以获得 s 的非对称置信区间
我的目标是写(相对)易懂的数据科学概念的解释,而不回避有时涉及的复杂数学。如果你喜欢这个,你我还有类似风格的解释**困惑中心极限定理 ,或者 期望最大化 。**
如果你不喜欢这个,多考虑一下 回归 ,奇异值分解,或者* 傅立叶变换 。***
笔记
[1]很明显,如果 fʹ©为 0,事情会变得非常糟糕,所以这是一个很好的时机来说明这是一个额外的假设。查阅维基百科的文章,获得完全严格的处理方法。
基于广播交通新闻的交通状况可视化
美声网刮
背景
这个项目发生在 2019 年 10 月,当时我的老板要求我们的团队在网络运营中心(NOC)的大屏幕上可视化我们的网络质量。作为移动运营商,我们经常全天候监控我们的网络质量和状况。开发了许多重要网络 KPI 的仪表板,我的老板希望我们增强所获得的信息,让 NOC 员工“知道/猜测”正在发生的事情。
我们的网络流量可能会受到许多外部因素的影响,我们可以想到的一般信息之一是流量状况,我指的是道路上的实际流量。当出现拥堵、交通堵塞或其他特殊路况时,该特定蜂窝基站的 KPI 可能会爆仓。因此,我们希望在地图上可视化交通状况,让我们的工作人员知道哪个位置有情况。
使用 BeautifulSoup 进行网页抓取
Radio news provides a very good source of detail traffic conditions as they are very useful for the Taxi drivers to choose their route (especially before the birth of Google Map). Besides the radio broadcast, all this information is online. The one we are choosing is the official radio station of Hong Kong RTHK: http://programme.rthk.hk/channel/radio/trafficnews/index.php (Sorry, only Chinese version available). If you know Chinese, you may figure out that the news is well-formatted. If the news is about traffic congestion, the format is the name of the road, the direction, and the queue end position (龍尾:)
HTML 结构也非常好。我们可以看到所有单独的新闻都有一个无序列表
- 。
新闻网站的 HTML 结构
有了请求和 BeautifulSoup,我们很容易获得并解析网页。感谢标准格式,我们可以在一秒钟内看到所有的故事。
import requestsfrom bs4
import BeautifulSoup
r = requests.get("http://programme.rthk.hk/channel/radio/trafficnews/index.php")
if r.status_code == requests.codes.ok:
r.encoding='utf-8'
soup = BeautifulSoup(r.text, 'html.parser')
stories = soup.find_all('li', class_='inner')
我们将每条新闻分为标题(新闻内容)和发布时间。我们用“%Y-%m-%d HKT %H:%M”来格式化发布时间。
titles = []
times = []
for s in stories:
title, time = list(filter(None, re.split(r'**\t**|**\n'**, s.text)))
titles.append(title)
times.append(time)
The most difficult part is to extract the location. Here we search for the particular phrase (龍尾:), which means the queue end in Chinese. If this phrase does not include in the news, we search for our location database. We will discuss how we obtain this database later. And now we have this DataFrame with title, publish time and location.
交通新闻的数据框架
接下来,我们需要对新闻进行分类。经过长时间的观察,我们发现新闻的类型属于这几类:
交通新闻类别
**服务暂停:**部分公共交通服务停止,
**受阻:**部分道路因各种原因受阻:附近道路维修或特殊事件,
**繁忙:**道路繁忙但仍可行驶;
**拥堵:**道路严重拥堵;
**事故:**那条路上发生了交通事故;
**正常:**被封锁或拥堵的道路恢复通行;
Info: 只是一些大概的信息。
而且那些措辞曾经重复出现过很多次。因此,我们可以通过识别词语来明确地划分不同的类别。
# set category
df.loc[df.title.str.contains('關閉'), 'category'] = 'service paused'
df.loc[df.title.str.contains('暫停'), 'category'] = 'service paused'
df.loc[df.title.str.contains('間封'), 'category'] = 'blocked'
df.loc[df.title.str.contains('繁忙'), 'category'] = 'busy'
df.loc[df.title.str.contains('多車'), 'category'] = 'busy'
df.loc[df.title.str.contains('車多'), 'category'] = 'busy'
df.loc[df.title.str.contains('慢車'), 'category'] = 'busy'
df.loc[df.title.str.contains('龍尾'), 'category'] = 'busy'
df.loc[df.title.str.contains('塞車'), 'category'] = 'congestion'
df.loc[df.title.str.contains('擠塞'), 'category'] = 'congestion'
df.loc[df.title.str.contains('意外'), 'category'] = 'accident'
df.loc[df.title.str.contains('回復暢順'), 'category'] = 'normal'
df.loc[df.title.str.contains('回復正常'), 'category'] = 'normal'
df.loc[df.title.str.contains('恢復運作'), 'category'] = 'normal'
df.loc[df.title.str.contains('禁止'), 'category'] = 'blocked'
df.loc[df.title.str.contains('受阻'), 'category'] = 'blocked'
df.loc[df.title.str.contains('不能通車'), 'category'] = 'blocked'
df.loc[df.title.str.contains('封閉'), 'category'] = 'blocked'
df.loc[df.title.str.contains('封路'), 'category'] = 'blocked'
df.loc[df.title.str.contains('恢復'), 'category'] = 'normal'
df.loc[df.title.str.contains('回復'), 'category'] = 'normal'
df.loc[df.title.str.contains('重開'), 'category'] = 'normal'
df.loc[df.title.str.contains('間封措施取消'), 'category'] = 'normal'
df.loc[df.category.isnull(), 'category'] = 'info'
为了定位交通新闻场景,我们需要纬度和经度。幸运的是,我们找到了一个 API GeoPy。你可能会找到一个关于如何使用它的很好的书面教程,从 Geocode with Python,到数据科学。这将物理地址转换为地理位置(即纬度和经度)。乍一看,我们怀疑这个 python 库是否支持中文地址。但事实证明它有着相当不错的性能。我们使用的是基于 OpenStreetMap 数据构建的 nomist 地理编码服务。
locator = Nominatim(user_agent=’myGeocoder’, timeout=3)
try:
location = locator.geocode(record)
except GeocoderTimedOut as e:
print(“Error: geocode failed on input {} with message {}”.format(record, e))
过了一段时间,我们收集了一堆新闻,可以选择经常出现的道路手动查询其经纬度(相信我,交通拥堵每天都在同一条道路上重复重复!)
这是我们 NOC 中使用的仪表板。也请访问 Tableau 创建的演示站点。
交通状况仪表板
使用 Tableau 的可视化
结论
感谢互联网上的丰富资源和那些已经建立了重要有用模块的巨人,我们可以在他们的基础上建立一个交通新闻可视化仪表板。
要了解这个项目的更多信息,请点击这里查看我的 Github 链接。
使用 ggplot2 可视化 R 中多元数据的趋势
由字云生成
数据可视化是通过图形元素表示数据的艺术,是任何研究或数据分析项目的重要组成部分。可视化在探索性数据分析和展示研究结果中是必不可少的。良好的可视化有助于讲述您的数据故事,并传达您的分析的重要信息,因为它允许我们快速查看趋势和模式,找到异常值,并获得洞察力。
通常,要么不容易找到最能描述数据的可视化类型,要么不容易找到生成感兴趣的图的简单工具。例如,可视化具有多个因变量和自变量(以及它们之间的相互作用)的高维数据集中的趋势可能是乏味的。
在这篇文章中,我决定介绍一种我认为非常有效的 3D 数据可视化技术。如果你是第一次接触 R 或者你从未在 R 中使用过 ggplot2 库,这会很有帮助。ggplot2 有几个内置的函数和功能,带来了显示复杂数据所需的灵活性。
此外,在这个博客中,将会有一些例子来说明如何使用函数设置来创建发布就绪的图形,并以高分辨率保存它们。你也可以在我的 Github 页面的一个地方找到所有代码。
概要:
第一部分:数据解释和准备
第二部分:使用 facet_grid() 函数可视化 3D 数据
第三部分:用其他 ggplot2 内置函数可视化 3D 数据
第 4 部分:可视化多因变量数据
第一部分:数据解释和准备
这里,我将使用来自真实世界问题的内部数据集,我们希望根据图像采集时设置的三个关键参数来表征一组对象图像中的噪声。我们不会深入讨论这些参数的细节,为了简单起见,我们将其命名为 Var1、Var2、Var3。图像中的噪声由标准偏差计算得出,命名为 SD。
Var1: Categorical at four levels of 100, 50, 25, 10Var2: Categorical at three levels of k1, k2, k3Var3: Categorical at three levels of st0.6, st1.0, st2.0SD: Continuous in the range of (0, 500)
这些参数有 4x3x3 = 36 种组合。所有这些参数的组合存在于数据集中,这意味着对于每个对象,存在 36 幅图像。每个图像都是参数集的不同组合(见下表)。
# set csv_file name
# set working directory
# set output_path# import libraries
library(ggplot2)
library(stringr)
library(ggpubr)
读取数据并准备数据列。准备工作的一个例子是数据转换:这里 Var1 是一个四层分类变量。在读取数据后,我们必须首先将该列转换为具有四个级别的数字列,然后对其进行排序,以便它在我们的图中按顺序出现。
# Read data
data = read.csv(csv_file,header = TRUE)
#prepare data
data$Var1 <- as.numeric(data$Var1,levels =data$Var1)
data$Var1 <- ordered(data$Var1)
data$Parameter_Set <- factor(data$Parameter_Set)
几行数据。每个对象(由唯一 ID 确定)有 36 个参数集的 36 幅图像
出于可视化的目的,我们将取每个参数集中图像的噪声平均值:
mean_SD = c()
mean_intensity = c()
Var1 = c()
Var2 = c()
Var3 = c()
for (ParamSet in levels(data$Parameter_Set)){
data_subset = data[which(data$Parameter_Set==ParamSet),]
mean_SD = c(mean_SD, mean(data_subset$SD))
mean_intensity = c(mean_intensity, mean(data_subset$intensity))
Var1 = c(Var1,str_split(ParamSet, “_”)[[1]][1])
Var2 = c(Var2,str_split(ParamSet, “_”)[[1]][2])
Var3 = c(Var3,str_split(ParamSet, “_”)[[1]][3])
}
Mean_DF = data.frame(Parameter_Set = levels(data$Parameter_Set),Var1 = Var1, Var2 = Var2, Var3 = Var3 ,mean_SD = mean_SD, mean_intensity = mean_intensity)
来自 Mean_DF 的几个样本行。注意:该数据框有 36 行,用于 36 个参数集
####### Prepare the Mean_DF dataframe
data = Mean_DF
data$Var3 <- factor(data$Var3)
data$Var1 <- as.numeric(data$Var1,levels =data$Var1)
data$Var1 <- ordered(data$Var1)
data$Parameter_Set <- factor(data$Parameter_Set)
第 2 部分:使用 facet_grid()函数可视化 3D 数据
让我们看看剧情
最后,我们将跨 3 个参数可视化图像中平均噪声的 3D 数据!ggplot 2 库中的 facet_grid() 函数是关键函数,它允许我们跨越多个自变量的所有可能组合来绘制因变量。ggplot2 可灵活添加各种功能,通过“+”改变绘图格式。下面我们添加 facet_grid() , geom_point() , labs() , ylim()
ggplot(data, aes(y = mean_SD, x = Var1))+ geom_point(size = 3)+facet_grid(Var3 ~ Var2, scales = "free_x",space = "free")+labs(title =" SD across all parameter sets",x = "Var1 ", y= "Mean SD")+ ylim(0, 500)
看起来在这个情节中发生了很多事情,所以让我们回顾一下:我们有一个有九个街区的情节。每个模块都是 Var2 和 Var3 特定级别的一个参数集。(九块:三级 Var2 和三级 Var3 的组合)。Var3 显示在行上,Var2 显示在列上。在每个块中,横轴是 Var1,纵轴是因变量 mean_SD,范围为 0–500(由 ylim()确定)。
在这里使用 facet_grid()函数的好处是,随着我们的数据变得越来越复杂,变量越来越多,在自变量的不同组合下解开数据并可视化因变量的趋势将变得非常直观。例如,在这里,通过比较右上方的块(k3,st0.6)和左下方的块(k1,st2.0),我们可以看到明显的差异。在(k1,st2.0)处,当 Var1 从 10 变到 100 时,mean_SD 是恒定的,但是在(k3,st0.6)处,当 Var1 变化时,mean_SD 显示出显著的变化。正如你所看到的,这张图可以显示自变量之间的相互作用以及它们各自对因变量的影响。
如果我们只想根据两个参数(Var1 和 Var3)绘图,facet_grid 的输入将更改如下:
…+facet_grid(Var3 ~ . , scales = “free_x”,space = “free”)+ …
在 facet_grid()中,如果将 space 和 scale 参数设置为“自由”而不是默认值“固定”,则很有帮助,这样变量的比例和面板的大小可以根据行和列中每个变量的比例自由变化。
如果你计划发表你的结果或在会议上发表,你必须注意你的绘图格式字体/字体大小/颜色,点和线的颜色/大小等。这里有一些关于如何使上面的情节看起来更好的帮助。我们简单地添加了 theme() 函数来处理 axis 和块元素的一些细节。
ggplot(data, aes(y = mean_SD, x = Var1))+
geom_point(size = 4)+facet_grid(Var3 ~ Var2, scales = "free_x",space = "free")+labs(title =" SD across all parameter sets",x = "Var1 ", y= "Mean SD")+ ylim(0, 500)+
theme(axis.text=element_text(size=16,face= "bold"), axis.text.x = element_text(colour = "blue3"),
axis.title.y=element_text(size=18,face="bold", colour = "black"),
axis.title.x=element_text(size=18,face="bold", colour = "blue3"),
strip.text = element_text(size=18, colour = "blue3",face="bold"))
如果您想以高分辨率保存 R 图,可以使用下面这段代码。
myplot <- ggplot2(data, aes(y = mean_SD, x = Var1))+ ...tiff(mytitle, units=”in”, width=8, height=5, res=300)
myplot
dev.off()
第 3 部分:使用其他 ggplot2 内置函数可视化 3D 数据
假设我们不想使用 facet_grid():
绘制高维数据的另一种方式是简单地为 Var2 和 Var3 的每个不同级别分配不同的颜色和线型。在下面的代码中,我们为不同级别的 Var2 分配不同的颜色,为不同级别的 Var3 分配不同的线型。
在这里,我们将创建三个具有 3 个不同 Var2 值的数据帧。我们将为每个数据帧生成一个图,并将使用 ggarrange() 将这些图合并成一个图。
在下面的图中,我们有意使用了背景颜色和网格线(panel.background 和 panel.grid 作为 theme() 函数中的选项)。
将上面的图与有九个块的图(通过 facet_grid())进行比较,我们可以看到它们各有利弊;一个将数据合并到一个图表中,而另一个展示了允许单独和分别检查数据的 3D 数据面板。我本人更喜欢参数集面板的版本。
下面是上图中的代码:
#separate data frames based on Var2
data_k1 = data[which(data$Var2 == “k1”),]
data_k2 = data[which(data$Var2 == “k2”),]
data_k3 = data[which(data$Var2 ==”k3"),]
第 4 部分:用多个因变量可视化数据
假设我们希望不仅通过图像中的噪声,而且通过图像的亮度值范围来可视化数据的趋势。所以我们现在有了第二个因变量,叫做强度。在第一部分中,与“mean_SD”类似,我们计算了所有参数集的强度平均值(“mean_intensity”)。
首先,让我们看一下“mean_SD”和 Var1 之间的简单图表,其中我们通过颜色渐变显示了“mean_intensity”值的范围(参见图例)
上图的代码:
ggplot(data, aes(x = Var1, y = mean_SD , group = interaction(Var3, Var2)))+ geom_point(size = 3, aes(color = mean_intensity))+
geom_line(lwd = 1.5, aes(color = mean_intensity))+ scale_colour_gradient(low = “yellow”, high = “red3”)+
labs( x = “Var1 “, y = “Mean_SD”)+
theme(strip.text = element_text(size = 20,face=”bold”, colour = “red3”),axis.text=element_text(size=20, face=”bold”),
axis.title=element_text(size=20,face=”bold”, colour = “red3”),
legend.text = element_text(size = 10,face=”bold” ),
panel.grid = element_line(colour= “white”),
panel.background = element_rect(fill = “gray64”),
legend.background = element_rect(fill = “gray64”))
现在,我们可以使用这个想法再次生成一个用块来可视化高维数据的图,并演示三个自变量对两个因变量的影响!
ggplot(data, aes(y = mean_SD, x = Var1))+
geom_point(size = 4,aes(color = mean_intensity))+facet_grid(Var3 ~ Var2, scales = “free_x”,space = “free”)+ scale_colour_gradient(low = “yellow”, high = “red3”)+
labs(title =” SD across all parameter sets”,x = “Var1 “, y= “Mean SD”)+ ylim(0, 500)+
theme(axis.text=element_text(size=16,face= “bold”), axis.text.x = element_text(colour = “blue3”),
axis.title.y=element_text(size=18,face=”bold”, colour = “black”),
axis.title.x=element_text(size=18,face=”bold”, colour = “blue3”),
strip.text = element_text(size=18, colour = “blue3”,face=”bold”),
panel.grid = element_line(colour= “grey”),
panel.background = element_rect(fill = “gray64”))
清晰的可视化有助于从数据中获得洞察力。在高维数据中,理解模式和交互尤其困难。 R 及其库如 ggplot 2 为研究人员、数据爱好者和工程师处理数据和执行知识发现提供了一个有用的框架。
R 和 ggplot2 有更多创建有洞察力的可视化的能力,所以我邀请你探索这些工具。我希望这个简短的教程有助于熟悉一个对数据分析有用的强大绘图工具。
纳斯塔兰·埃玛尼贾德
在 Twitter 上关注我:@ N _ Emaminejad和 LinkedIn:Nastaran _ Emaminejad
基于主成分分析和 t-SNE 的可视化单词嵌入
实践教程
在 2D 或 3D 中创建单词嵌入的交互式可视化
当你听到*‘茶’和‘咖啡’这两个词,你会怎么想?大概你会说它们都是饮料,都含有一定量的咖啡因。关键是,我们可以很容易地识别出这两个词是相互关联的。然而,当我们向计算机提供单词‘茶’和‘咖啡’*时,它无法像我们一样识别这两个单词之间的关联。
Word 不是计算机会自然理解的东西。为了让计算机理解单词背后的含义,需要将单词编码成数字形式。这就是单词嵌入背后的技术有用的地方。
单词嵌入是自然语言处理中常用的一种技术,用于将单词转换成向量形式的数值。这些向量将占据一定维数的嵌入空间。
如果两个单词具有相似的上下文,如*‘茶’和‘咖啡’*那样,那么这两个单词在嵌入空间中的距离将会彼此接近,而与具有不同上下文的其他单词的距离将会更远。
在这篇文章中,我将一步一步地向你展示如何可视化单词嵌入。由于本文的重点不是详细解释单词 embedding 背后的基本理论,您可以在本文和中阅读更多关于理论的内容。
为了可视化单词嵌入,我们将使用常见的降维技术,如 PCA 和 t-SNE。为了将单词映射到它们在嵌入空间中的向量表示,将实现预先训练的单词嵌入手套。
加载预先训练的单词嵌入模型
在可视化单词嵌入之前,通常我们需要首先训练模型。然而,训练单词嵌入在计算上是非常昂贵的。因此,通常使用预先训练的单词嵌入模型来代替。它包含嵌入空间中的记号及其相关向量表示。
除了 Google 开发的 word2vec 之外,GloVe 是一个由斯坦福研究人员开发的流行的预训练单词嵌入模型。本文实现了 GloVe 预训练单词嵌入,你可以在这里下载。同时,我们可以使用 Gensim 库来加载预先训练好的单词嵌入模型。您可以使用 pip 命令安装该库,如下所示。
pip install gensim
作为第一步,我们需要将 GloVe 文件格式转换为 word2vec 文件格式。使用 word2vec 文件格式,我们可以使用 Gensim 库将预先训练好的单词嵌入模型加载到内存中。由于每次调用该命令时,文件加载都会花费一些时间,因此如果我们使用一个单独的 Python 文件来实现这个目的,效果会更好。
创建输入单词并生成相似的单词
现在我们有了一个 Python 文件来加载预训练的模型,接下来我们可以在另一个 Python 文件中调用它,根据输入的单词生成最相似的单词。根据您的喜好,输入的单词可以是任何单词。
在我们键入输入的单词后,下一件事就是创建一个代码来读取它。然后,我们需要根据模型将生成的每个输入单词指定相似单词的数量。最后,我们将相似单词的结果存储在一个列表中。下面是实现这一目的的代码。
例如,假设我们想要找出与*“学校”相关的 5 个最相似的单词。因此,‘学校’将是我们的输入单词。使用上面的代码,我们将得到单词、、、【学校】、、【小学】、、【学生】、和、【学生】、作为结果。*
用主成分分析可视化单词嵌入
到目前为止,我们已经有了输入单词和基于它生成的相似单词。接下来,是时候让我们在嵌入空间中可视化它们了。
有了预训练的模型,每个单词现在可以用它的向量表示法映射到嵌入空间。然而,单词嵌入具有非常高的维数,这意味着不可能可视化单词如何占据嵌入空间。
通常实现诸如主成分分析(PCA)的方法来降低单词嵌入的维度。简而言之,PCA 是一种特征提取技术,它结合变量,然后丢弃最不重要的变量,同时仍然保留变量中有价值的部分。如果你想深入研究 PCA,我推荐这篇文章。
使用 PCA,我们可以在 2D 或 3D 中可视化单词嵌入。因此,让我们使用我们在上面的代码块中调用的模型创建代码来可视化单词嵌入。在下面的代码中,只显示了 3D 可视化。为了使 2D 的认证后活动形象化,只需稍加改动。您可以在代码的注释部分找到需要更改的部分。
例如,假设我们想要可视化与*、【球】、、【学校】、、【食物】、相关联的前 5 个最相似的单词。使用我们到目前为止创建的代码,下面是 2D 的可视化示例。*
基于主成分分析的 2D 词嵌入可视化
下面是同样一组单词的三维可视化。
基于主成分分析的三维单词嵌入可视化
从可视化中,现在我们可以看到这些单词所占空间的模式。与*‘ball’相关联的单词被放置得彼此靠近,因为它们具有相似的上下文。同时,它们和与【学校】**【食物】*相关的词之间的距离更远,因为它们有不同的上下文。
用 t-SNE 可视化单词嵌入
除了 PCA 之外,另一种常用的降维技术是 t 分布随机邻居嵌入或 t-SNE。主成分分析和 t-SNE 之间的区别是它们都实现了降低维数的基本技术。
PCA 是一种线性降维方法。高维空间中的数据被线性映射到低维空间,同时最大化数据的方差。同时,t-SNE 是一种非线性降维方法。利用 t-SNE,该算法计算高维空间和低维空间的相似度。接下来,使用优化方法,例如梯度下降方法,最小化两个空间中的相似性差异。
使用 t-SNE 可视化单词嵌入的代码与使用 PCA 的代码非常相似。在下面的代码中,只显示了 3D 可视化。为了使 2D 的 SNE 霸王龙形象化,只需要做一些小的改动。您可以在代码的注释部分找到需要更改的部分。
对于与 PCA 可视化中相同的例子,即与*‘球’、‘学校’和‘食物’*相关联的前 5 个最相似单词的可视化,下面是在 2D 的可视化结果。
基于 t-SNE 的 2D 单词嵌入可视化
下面是同样一组单词的三维可视化。
基于 t-SNE 的三维单词嵌入可视化
与主成分分析的方法相同,注意如何将具有相似上下文的单词放在彼此靠近的位置,而将具有不同上下文的单词放在较远的位置。
创建一个 Web 应用程序来可视化单词嵌入
到目前为止,我们已经成功地创建了一个 Python 脚本,使用 PCA 或 t-SNE 在 2D 或 3D 中可视化单词嵌入。接下来,我们可以创建一个 Python 脚本来构建一个 web 应用程序,以获得更好的用户体验。
web 应用程序使我们能够通过许多功能和交互性来可视化单词嵌入。例如,用户可以键入他们自己的输入单词,并且他们还可以选择与将被返回的每个输入单词相关联的前 n 个最相似的单词。
可以使用 Dash 或 Streamlit 创建 web 应用程序。在本文中,我将向您展示如何构建一个简单的交互式 web 应用程序,用 Streamlit 可视化单词嵌入。
首先,我们将使用我们之前创建的所有 Python 代码,并将它们放入一个 Python 脚本中。接下来,我们可以开始创建如下几个用户输入参数:
- 降维技术,用户可以选择是应用 PCA 还是 t-SNE。因为只有两个选项,所以我们可以使用 Streamlit 的
selectbox
属性。 - 可视化的维度,其中用户有一个选项,他们是否希望在 2D 或 3D 中可视化单词嵌入。和以前一样,我们可以使用
selectbox
属性。 - 输入单词。这是一个用户输入参数,要求用户键入他们想要的输入单词,例如*‘球’、‘学校’和‘食物’*。因此,我们可以使用
text_input
属性。 - 前 n 个最相似的单词,其中用户需要指定将返回多少个与每个输入单词相关联的相似单词。由于我们可以选择任何数字,那么
slider
属性将是最好的选择。
接下来,我们需要考虑在我们决定使用 SNE 霸王龙时会出现的参数。在 t-SNE 中,我们可以调整一些参数来获得最佳的可视化结果。这些参数是困惑度、学习率和优化迭代次数。在每种情况下,这些参数都没有单一的最佳值,因此最好的解决方案是让用户指定这些值。
由于我们使用的是 Scikit-learn,我们可以参考文档来找出这些参数的默认值。困惑的默认值是 30,但是我们可以在 5 到 50 之间调整这个值。学习率的默认值是 300,但是我们可以在 10 到 1000 之间调整这个值。最后,迭代次数的默认值是 1000,但是我们可以将这个值调整为 250。我们可以使用slider
属性来创建这些参数值。
现在我们已经涵盖了构建 web 应用程序的所有必要部分。最后,我们可以将所有的东西打包成一个完整的脚本,如下所示。
您现在可以使用 Conda 提示符运行 web 应用程序。在提示符下,转到 Python 脚本的目录,然后输入以下命令:
$ streamlit run your_script_name.py
接下来,会自动弹出一个浏览器窗口,您可以在这里本地访问您的 web 应用程序。下面是您可以使用 web 应用程序做些什么的快照。
就是这样!您已经创建了一个简单的 web 应用程序,它具有很多交互性,可以用 PCA 或 t-SNE 可视化单词嵌入。
如果你想看这个单词嵌入可视化的完整代码,可以在我的 GitHub 页面这里访问。
用交互式地图可视化世界幸福
哪些国家最幸福?这个问题极难回答。然而,《世界幸福报告》尽力报道这个话题,对 156 个国家的公民认为自己有多幸福进行了排名。分析《世界幸福报告》数据的一个有趣的方法是观察各国的幸福分数与地图上与它们相近的国家的幸福分数之间的关系。
在本教程结束时,您将拥有一张交互式地理地图,可以用来调查世界各地不同国家的幸福程度——或者,您可以交换数据并可视化一些您自己的有趣地理数据!
安装软件包
以下是完成本教程所需的先决条件,可能有,也可能没有:
- 地质公园。GeoPandas 是一个软件包,它使得使用 Python 处理地理空间数据变得更加容易。你可以在这里找到安装说明。
- 形状文件。为了绘制世界地图或城市地图,我们需要一个 shapefile,用于存储地理信息。我们在这个例子中使用的 shapefile 可以在我的 Github 上获得,或者你可以在这里找到它。
- 散景。散景有助于快速轻松地制作交互式绘图、仪表盘和数据应用。
- 世界幸福报告数据。我在 Kaggle 上找到了数据。
# basic modules
import geopandas as gpd
import pandas as pd
import json
import glob
import os # visualizaztion modules
from bokeh.resources import INLINE
from bokeh.io import output_notebook, show, output_file
from bokeh.plotting import figure
from bokeh.models import GeoJSONDataSource, LinearColorMapper, ColorBar
from bokeh.palettes import brewer,mpl # interactive visualization models
from bokeh.io import curdoc, output_notebook
from bokeh.models import Slider, HoverTool
from bokeh.layouts import widgetbox, row, column
导入和清理数据
shapefile 包含了所有的坐标,这些坐标将有助于以后绘制世界地图。可以重命名这些列,以便它们对分析更有意义。
shapefile = 'ne_110m_admin_0_countries/ne_110m_admin_0_countries.shp'
# Read shapefile using Geopandas
gdf = gpd.read_file(shapefile)[['ADMIN', 'ADM0_A3', 'geometry']]
# Rename columns.
gdf.columns = ['country', 'country_code', 'geometry']
《世界幸福报告》提供的数据来自 2015 年至 2019 年间每年的一个文件。有些文件具有不同的形状和列名。我们必须确保所有感兴趣的列都有匹配的名称,以防止以后出现问题。
此外,在使用 pd.concat()函数将每个文件合并到一起之前,文件名中的年份必须附加到数据框中名为 year 的新列中。否则,我们将在每个国家的数据框架中有 5 行,完全不知道数据来自哪一年。
最后,发现在 shapefile 中,US 被标记为美利坚合众国。在世界幸福报告数据中,美国被标注为美国。为了在后面的操作中使两者相匹配,我们必须更新国家数据框,将美国替换为美利坚合众国。
datafiles_1 = ['2019.csv', '2018.csv']
datafiles_2 = ['2015.csv', '2016.csv']
df = pd.concat((pd.read_csv(f).assign(Year=os.path.basename(f[0:4])) for f in datafiles_1), sort=False)
df2 = pd.concat((pd.read_csv(f).assign(Year=os.path.basename(f[0:4])) for f in datafiles_2), sort=False)
df3 = pd.read_csv('2017.csv').assign(Year="2017")
df['Country'] = df['Country or region']
df2['Score'] = df2['Happiness Score']
df3['Score'] = df3['Happiness.Score']
countries = pd.concat([df[['Country', 'Score', 'Year']], df2[['Country', 'Score', 'Year']], df3[['Country', 'Score', 'Year']]], sort=False)
countries = countries.replace('United States', 'United States of America')
创建交互性功能
我们将需要两个功能,使我们的地理地图互动和动态。
- 获取快乐数据的函数。该函数将接受选择的年份作为参数;今年可以用滑块选择。快乐数据将以 JSON 的形式返回,无论是哪一年。
- 滑块更新时触发的函数。这个函数的工作是获取滑块保存的任何新值,并将其传递给从数字 1 开始的函数。无论滑块设置为什么,此功能都会使地图数据保持最新。
# 1\. Define function that returns json_data for the year selected by slider.
def json_data(selectedYear):
yr = selectedYear
df_yr = countries[countries['Year'] == yr]
merged = gdf.merge(df_yr, left_on ='country', right_on ='Country', how ='left')
merged['Score'] = merged.Score.fillna("N/A")
merged_json = json.loads(merged.to_json())
json_data = json.dumps(merged_json)
return json_data
# 2\. Define the callback function.
# This is what will be called when the slider value changes.
def update_plot(attr, old, new):
yr = slider.value
new_data = json_data(str(yr))
geosource.geojson = new_data
p.title.text = 'Happiness Score by Country (%d)' %yr
渲染地图
现在终于可以在地图上看到所有这些数据了!
鉴于颜色可以在可视化中产生或破坏,我对散景的调色板做了一些研究,并选择了一个与我的数据有意义的调色板。在这种情况下,悬停工具提示很有帮助,因为有些人(像我一样)苦于地理知识,可能无法说出地图上一半国家的名称。
创建了 slider 对象,注意它的回调函数是上面创建的函数之一。国家之间的线条被设置为白色,以便更好地匹配配色方案。
# Input GeoJSON source that contains features for plotting.
# Select a default year to show on first display.
geosource = GeoJSONDataSource(geojson = json_data("2016"))
# Define a sequential multi-hue color palette.
# I chose the Plasma theme because 10 would map to yellow :)
palette = mpl['Plasma'][10]
# Instantiate LinearColorMapper that maps numbers to a sequence of colors.
color_mapper = LinearColorMapper(palette = palette, low = 0, high = 10)
# Add the hovering tooltips.
hover = HoverTool(tooltips = [ ('Country','@country'),('Score', '@Score')])
# Create the color bar.
color_bar = ColorBar(color_mapper=color_mapper, label_standoff=8,width = 500, height = 20, border_line_color=None,location = (0,0), orientation = 'horizontal')
# Create the figure object.
p = figure(title = 'World Happiness by Country (2016)', plot_height = 600 , plot_width = 950, toolbar_location = None, tools = [hover])
# Remove the grid lines.
p.xgrid.grid_line_color = None
p.ygrid.grid_line_color = None
# Increase the title font size.
p.title.text_font_size = '12pt'
# Add the patch renderer to the figure.
# Notice that this is where you provide the Score column from the json_data and the color mapper.
p.patches('xs','ys', source = geosource,fill_color = {'field' :'Score', 'transform' : color_mapper}, line_color = 'white', line_width = 0.5, fill_alpha = 1)
# Place the color bar below the map.
p.add_layout(color_bar, 'below')
# Make a slider object.
slider = Slider(title = 'Year',start = 2015, end = 2019, step = 1, value = 2016)
slider.on_change('value', update_plot)
# Make a column layout of widgetbox (slider) and plot, and add it to the current document
layout = column(p,widgetbox(slider))
curdoc().add_root(layout)
# Show the figure.
output_notebook(INLINE)
show(layout)
只需最后一步,你就可以看到你创建的美丽的地图。因为我们使用 on_change()函数,所以我们需要地图是交互式的,否则,当您移动滑块时,地图不会更新。要以交互模式查看此应用程序,您需要设置一个本地散景服务器。不要烦恼!您可以在一行中完成这项工作,并且您可以在命令行中完成这项工作,并且感觉自己已经是一名成熟的黑客了。
打开你的命令行,输入:bokeh serve-show your file name . ipynb
这是最终产品的样子:
嘣!你刚刚做了一个互动地图来分析世界幸福。我希望你喜欢。如果是这样,可以看看我的其他教程,比如我写的关于用单词云可视化 Kickstarter 数据的文章。也许这篇文章提醒了您,您需要复习数据框架知识…别担心,前往我的数据帧 101 。
原载于 2020 年 5 月 12 日https://data dreamer . io。
使用 Jupyter 可视化全球冠状病毒传播
创建你自己的新冠肺炎传播的可视化
编者按: 走向数据科学 是一份以数据科学和机器学习研究为主的中型刊物。我们不是健康专家或流行病学家,本文的观点不应被解释为专业建议。想了解更多关于疫情冠状病毒的信息,可以点击 这里 。
有很多关于新冠肺炎和冠状病毒在世界各地传播的公共数据集。 Corona Data Scraper 从经过验证的来源提取新冠肺炎案例数据,找到相应的 GeoJSON 特征,并添加人口信息。Corona Data Scraper 提供了奇妙的可视化效果,比如经过速率调整的 2D 国家级地图和 Antonio Piccolboni 对平滑后的新冠肺炎趋势和预测的可视化效果。
如果你想尝试对冠状病毒数据进行自己的分析,你也可以使用 Jupyter 和 Python 小部件创建一些自己的漂亮的全局可视化,我们将在本文中进行讨论。这里有一个完整的交互式可视化的截图。可以拖动滑块查看从 2020 年 1 月 22 日开始的不同日期的新冠肺炎案例。
导入依赖项和数据集
我们将使用的数据集是冠状病毒数据刮刀的时间序列数据。首先导入依赖项并读入数据集。如果尚未安装底图、Networkx 和 Shapely 包,您可能需要安装它们。
import numpy as np
import pandas as pd
import networkx as nx
import matplotlib.pyplot as plt
from mpl_toolkits.basemap import Basemap as Basemap
from shapely.geometry import Point, MultiPoint
from ipywidgets import interact, widgets
from IPython.display import display
您可以下载 CSV 格式的数据集并在本地读取,也可以在https://coronadatascraper.com/timeseries.csv读取最新更新的数据集。
df = pd.read_csv(‘[https://coronadatascraper.com/timeseries.csv'](https://coronadatascraper.com/timeseries.csv'), parse_dates=[‘date’])
查看数据集和列信息。
我们的分析将只使用一些数据,特别是国家、纬度、经度和案例列。
# Get Country, Lat, Long, Cases, Date
case_df = df[[‘country’, ‘lat’, ‘long’, ‘cases’, ‘date’]]
Jupyter 笔记本截图
使用底图绘制地图
接下来,我们从包含边列表的 Pandas 数据帧创建一个 NetworkX 图。我们的目标是简单地在冠状病毒出现的位置标绘点。使用底图 Matplotlib 工具包,我们可以在地图背景上绘制点。
为了使世界形象化,我们将使用墨卡托投影,一种圆柱形的保形投影。这种投影在高纬度地区产生很大的失真,并且不能完全覆盖极地区域。
创建底图墨卡托投影。参数 llcrnrlon 和 llcrnrlat 代表右下角经度和纬度。参数 urcrnrlon 和 urcrnrlat 代表右下角经度和纬度。右下角(西经 150 度,南经 50 度)到左上角(东经 160 度,北纬 75 度)似乎很适合我们的显示。
m = Basemap(llcrnrlon=-150., llcrnrlat=-50., urcrnrlon=160., urcrnrlat=75., rsphere=(6378137.00,6356752.3142), resolution=’l’, projection=’merc’, lat_0=0,lon_0=0., lat_ts=20.)
接下来,创建一个没有节点和边的空图。初始化 Matplotlib 图形以显示地图。
G=nx.Graph()plt.figure(figsize = (20,10))
用 Matplotlib 画空图 G。
nx.draw_networkx(G, node_size=200, node_color=’blue’)
绘制冠状病毒病例
在地图上用点标出冠状病毒病例的位置。
# Create a scatter plot of cases on a single date *d*.one_date_df = case_df[case_df[‘date’]== *d*]
map_points = pd.Series([Point(m(mapped_x, mapped_y)) for mapped_x, mapped_y in zip(one_date_df[‘long’], one_date_df[‘lat’])])
在地图上画出病例的散点图。
# Create a scatterplot on the mapdev = m.scatter( [geom.x for geom in map_points], [geom.y for geom in map_points], 20, marker=’o’, lw=.25, facecolor=’#33ccff’, edgecolor=’w’, alpha=0.9,antialiased=True, zorder=3)
最后,画地图。
# Now draw the map
m.drawcountries()
m.drawstates()
m.bluemarble()
plt.title(‘Coronavirus’)
2020 年 1 月 22 日冠状病毒图谱
使地图互动
将单个地图制作代码组合到一个名为 create_map 的函数中,以在任意给定日期执行上述地图绘制。
def create_map(date_d):
m = Basemap(
llcrnrlon=-150.,
llcrnrlat=-50.,
urcrnrlon=160.,
urcrnrlat=75.,\
rsphere=(6378137.00,6356752.3142),\
resolution='l',projection='merc',\
lat_0=0,lon_0=0.,lat_ts=20.)G=nx.Graph()fig = plt.figure(figsize = (20,10))nx.draw_networkx(G,node_size=200,node_color='blue')# Draw scatter
one_date_df = case_df[case_df['date']== date_d]
map_points = pd.Series([Point(m(mapped_x, mapped_y)) for mapped_x, mapped_y in zip(one_date_df['long'], one_date_df['lat'])])# Scatterplot on the map
dev = m.scatter(
[geom.x for geom in map_points],
[geom.y for geom in map_points],
20, marker='o', lw=.25,
facecolor='#33ccff', edgecolor='w',
alpha=0.9,antialiased=True,
zorder=3)# Draw the map
m.drawcountries()
m.drawstates()
m.bluemarble()
plt.title('Global Coronavirus Cases Starting From 1/22/2020')
return (date_d, fig)
现在,为每个感兴趣的日期画一张地图。
all_dates = list(case_df['date'].unique()) all_maps = [ ]
for date_d in all_dates:
all_maps.append(create_map(date_d))
定义一个功能 f 用于选择对应于其各自日期的地图。
def f(index):
img = all_maps[index][1]
display(img)
现在创建交互式滑块和地图。
interact(f, index=widgets.IntSlider(min=0,max=68,step=1,value=1,
description=’Date Starting From 1/22/2020:’ ))
就是这样!这里有一张 gif 图,可以看到交互式滑块在整个时间序列中的样子。
通过 imgflip.com 创建的 Gif
参考文献
[1]https://coronadatascraper.com/
[3] NetworkX 文档https://networkx.github.io/documentation/stable/index.html
[4]底图文档https://matplotlib.org/basemap/
使用 Python Plotly 地图可视化全球新冠肺炎数据
埃德温·胡珀在 Unsplash 上的照片
编者按: 走向数据科学 是一份以数据科学和机器学习研究为主的中型刊物。我们不是健康专家或流行病学家,本文的观点不应被解释为专业建议。想了解更多关于疫情冠状病毒的信息,可以点击 这里 。
2019 年 12 月 31 日,世界卫生组织(世卫组织)驻中国国家办事处首次报告了一种未知的肺炎类型疾病。这种未知的疾病后来在 2020 年 2 月 11 日被命名为新冠肺炎,因为它与导致 2003 年 SARS 爆发的冠状病毒有遗传关系。新冠肺炎很快在世界范围内广泛传播,直到世卫组织于 2020 年 1 月 30 日宣布该疫情为国际关注的突发公共卫生事件。
在这篇文章中,我将介绍使用 Python Plotly 库 绘制地图的两种方法,以显示新冠肺炎病例在世界各地的分布。
你需要什么
先决条件 Python 库
python Plotly—https://plotly.com/python/
蟒蛇熊猫—https://pandas.pydata.org/
安装指南可以在官方网页上找到。
数据集
第 1 部分:地图上的散点图
在本节中,我们将使用来自 plotly 库的 plotly.graph_objects 在世界地图上创建一个散点图,以显示新冠肺炎确诊病例在世界各地的分布。
步骤 1:探索新的冠状病毒数据集
探索新冠肺炎数据集的 Python 代码
代码解释
**第 1–2 行:**导入熊猫和 Plotly 库
**第 3 行:**世界范围内的新冠肺炎数据可以在 小说电晕病毒数据集 的一个 CSV 文件中找到。 我们可以使用熊猫 read_csv 方法来读取文件。
第 4 行:使用 Pandas head 方法显示前 5 行记录。
数据集记录的前五行
从上面的结果中,我们可以观察到数据集包括从 2020 年 1 月 22 日到 2020 年 4 月 13 日(截至本文撰写时)每个国家报告的新冠肺炎病例数。该数据集每天都会更新。不幸的是,数据集中缺少省/州的详细信息。我们可以看到在省/州列中有很多 NaN 值。
为了简化我们操作列和绘制地图的后续任务,建议简化一些列名(如国家/地区)。
Python 代码重命名列
代码解释
第 5 行:我们可以使用熊猫重命名的方法,将列名“国家/地区”改为“国家”,“省/州”改为“省”。
第 6 行:重命名列后,我们使用熊猫头方法再次查看记录。
重命名的列
步骤 2:在地图上创建散点图
我们现在可以继续使用 Python Plotly 库,使用Plotly . graph _ objects在地图上创建散点图。
用于在地图上创建散点图的 Python 代码
这些代码(第 8 - 39 行)一开始看起来让人望而生畏。不要担心,它们只是我们需要为地图设置的参数,关于这些参数的信息可以在 Plotly 参考页面中找到。这里我只讨论几个重要的参数。
代码解释
第 8 行:设置将出现在数据点上的文本元素。这意味着当我们将鼠标悬停在地图上的数据点上时,预定义的文本(例如,国家名称+20 年 4 月 4 日的病例数)将会弹出。
Line 10–11:lon和 lat 是我们为地图上每个数据点设置的经纬度参数。
第 14–23 行 : 标记是地图上数据点的表示。这里我们将符号(第 19 行)设置为正方形。这将在地图上将每个数据点呈现为一个正方形。我们可以将 reversescale 和 autocolorscale 保留为 True,以使标记的颜色根据报告的新冠肺炎病例数自动改变。
第 24–26 行 : cmin 和 cmax 是数据点色域的下限和上限。
第 31–37 行:这是我们为整个地图设置参数值的部分,比如地图标题(第 32 行),更重要的是范围(第 34 行)。如果我们打算在地图上显示世界范围的数据,我们需要将范围设置为“world ”, Plotly 将生成一个世界地图。如果我们的目的只是只显示美国的数据点,我们可以将范围设置为“美国”。我们可以选择以下范围选项之一:
- 世界
- 美国
- 欧洲
- 非洲
- 北美洲
- 南美洲
第 39 行 : fig.write_html 将生成一个显示散点图的 html 页面。
注 : 可以在 Jupyter 笔记本或 Jupyter Lab 上显示地图,而不是在单独的 HTML 页面上。为此,我们必须为我们的 Jupyter 笔记本/ Jupyter 实验室安装一个扩展(【https://plotly.com/python/getting-started/】)。
地图上的散布图
上面的散点图让我们大致了解了 2020 年 4 月 13 日世界各地报告的新冠肺炎病例。与深色标记相比,黄色标记反映的报告病例相对较少。从地图上,我们可以看到美国是报告病例最多的国家,其次是欧洲的一些国家,如意大利、英国、法国等。当我们将鼠标悬停在地图上的一个数据点上时,我们可以看到一个预定义的弹出文本,显示与该数据点相关的国家名称和已报告病例数。
弹出信息
第 2 部分:Choropleth 地图
我们也可以使用同一个数据集,通过 *plotly.graph_objects 绘制 choropleth 图。*但是,我们需要对数据进行预处理,然后才能创建 choropleth 图。
第一步:数据预处理
为了创建 choropleth 图,我们需要从我们的数据集中获得两条信息:
- 独特的国家列表
- 每个国家报告的新冠肺炎病例总数(2020 年 4 月 13 日)
不幸的是,我们无法从原始数据集中直接提取出这两条所需的信息。通过预览一些记录,再次仔细查看我们的数据集。
原始数据集中的两个问题
我们可以从我们的数据集中得到如下两个观察结果:
- 我们的记录中有重复的国家名称。这是因为给定数量的已报告新冠肺炎病例被分解到可能属于同一个国家的几个省/州。
- 2020 年 4 月 13 日报道的新冠肺炎案例的每一行都只是发生在一个国家的每个省或州的案例的小计。
当我们逐个国家地遍历记录时,可以断断续续地看到上面的两个观察结果。这意味着原始数据集中的记录不一致。有些记录需要对一个国家的州进行细分,而有些记录只包含整个国家的单行数据。
幸运的是,这里有一个简单的修复方法。我们可以使用熊猫图书馆来重组我们的数据。
用于重构数据的 Python 代码
代码解释
第 1–5 行:这是导入必要的 Plotly 和 Pandas 库,读取 CSV 文件以及重命名一些列的步骤。
第 7 行:我们可以使用 Pandas groupby 方法根据国家对我们的数据进行分组,并应用 sum 方法计算每个国家报告的病例总数。结果是一个总和列表,我们将它赋给一个名为 total_list 的变量。
每个国家报告病例总数系列
第 9–13 行:我们将清理国家列表并生成一个唯一的国家列表。
- 首先,使用 tolist 方法将 Country 列转换为 list 对象,并将其赋给变量 country_list (第 9 行)。
- 接下来,使用 set 方法将 country_list 转换成 Python set 对象。set 方法将自动从 country_list 中删除所有重复的国家名称。只有唯一的国家名称会存储在国家设置(第 10 行)中。
- 接下来,再次将 country_set 转换为列表,并将其分配回 country_list (第 11 行)。
- 使用排序方法按照字母顺序重新排列国家列表(第 12 行)。*这一步是必需的,因为之前使用的 set 方法会使国家/地区的顺序随机化。
第 14 行:最后,我们使用前面步骤生成的 country_list 和 total_list 作为新数据帧中仅有的两列,创建一个新数据帧。
重组原始数据后的新数据框架
我们已经成功地重组了我们的数据,并将其存储到一个新的数据帧中, new_df 。 new_df 包含了我们生成 choropleth 地图所需的数据(唯一的国家列表和每个国家的总病例数),我们现在准备进入下一步。
步骤 2:生成 Choropleth 图
choropleth 地图是一种由彩色多边形组成的地图,用于表示数量的空间变化。我们将使用 go。Choropleth graph 对象创建一个 Choropleth 图,显示全球已报告新冠肺炎病例的分布。
创建 Choropleth 地图的 Python 代码
同样,这些代码一开始看起来令人望而生畏。然而,它们只不过是设置参数来构建 choropleth 图。我们可以参考官方网站上的参考页面来获得更多关于参数的信息。
代码解释
第 17–19 行:我们可以为我们的 choropleth 贴图定义一个色域。要定义一个色域,我们只需创建一个六色代码列表。(*颜色代码可在此处获得)。
第 22–33 行:这是我们可以设置位置列表、色域、地图上显示的文本信息、标记线颜色等参数的部分。
- 因为我们绘制地图来显示世界各地的新冠肺炎病例,所以我们将位置模式设置为“国家名称”。这使我们能够将国家列从 new_df 设置为地点参数(第 23–24 行)。这是使 Plotly 能够将我们的新冠肺炎数据映射到 choropleth 地图上各自国家位置的重要一步。(请注意,这里没有坐标,lat & long,均为必填)。
- 我们将来自 new_df 的 Total_Cases 数据设置为参数 z (第 25 行)*。*这是使 Plotly 能够根据应用于 choropleth 图的色域揭示报告病例频率的另一个关键步骤。
- 我们还可以将“ Total_Cases ”设置为文本参数(第 26 行)。每当我们将鼠标悬停在地图上的某个国家/地区上方时,就会在弹出文本中显示病例总数。
- 由于我们已经定义了自己的色域(第 17–19 行),我们可以将参数 autocolorscale 设置为 false(第 28 行)。
- 我们还为颜色栏设置了一个标题(第 30 行)。
Line 33–37:这里,我们简单地为地图设置一个标题,并启用地图上显示的海岸线。
第 40 行:将地图输出到 HTML 页面。
等值区域图
最后,我们成功创建了一个 Choropleth 地图,显示了全球冠状病毒爆发的流行水平。当我们将鼠标放在一个国家地区的上方时,我们可以看到以弹出文本显示的报告病例数。
Choropleth 地图上的弹出文本
第 3 部分:在线发布 Plotly 地图
你有没有想过我们可以在线发布我们的地图?Plotly 为我们提供了一个免费与公众分享地图的选项。为此,我们只需遵循以下几个简单的步骤:
第一步:安装 chart_studio
打开您的终端(Mac)或命令提示符(Windows),点击
**pip install chart_studio
or
sudo pip install chart_studio**
第二步:注册一个 Chart Studio 的免费账户
访问图表工作室页面,注册一个免费账户。这个过程只需要不到 3 分钟。免费帐户允许我们与公众分享最多 100 张图表。
步骤 3:在 Python 代码中设置凭证
注册一个免费的 Chart Studio 帐户后,访问设置页面并寻找 API 键。复制 API 键并将其粘贴到我们之前的 Python 代码(散点图或 Choropleth 图)的顶部。
设置 Chart Studio 凭据的 Python 代码
**第 1–2 行:**这两行代码提供凭证信息,使我们的 Python 程序能够访问 Chart Studio 特性。
步骤 4:将地图共享给公众
为了将我们的地图分享给公众,我们所需要的只是在现有 Python 程序的最后一行(第 42 行)添加一行代码。
将地图共享给公众的 Python 代码
运行代码,Plotly 将返回一个 URL,将我们重定向到托管我们地图的网站。
您可以在此链接 1 查看我的共享散点图,在此链接 2 查看 Choropleth 地图。
结束语
Python Plotly 是一个易于使用的图表绘图库,使我们能够创建令人惊叹的图表并与公众分享。这绝对值得我们花时间学习 Plotly,并使用它来完成我们的数据可视化任务。如果你有兴趣了解更多关于 Plotly 库的知识,可以在这篇博客文章中找到有用的教程。
我希望这篇文章能对你有所帮助。
为了与我联系,你可以
开源代码库
本文中的所有源代码都可以在 GitHub 资源库中找到。