数据可视化 指的是通过可视化表示来探索数据。它与数据分析 紧密相关,而数据分析指的是使用代码来探索数据集的规律和关联。数据集可 以是用一行代码就能表示的小型数字列表,也可以是数千兆字节的数据。
1.1安装Matplotlib本章将首先使用Matplotlib来生成几个图表,为此需要使用 pip 来安装它。 pip 是 一个可用于下载并安装Python包的模块。请在终端提示符下执行如下命令:
python -m pip install --user matplotlib
在你的系统中,如果运行程序或启动终端会话时使用的命令不是 python , 而是python3 ,应使用类似于下面的命令:
python3 -m pip install --user matplotlib
1.2 绘制简单的折线图
下面使用Matplotlib绘制一个简单的折线图,再对其进行定制,以实现信息更丰富 的数据可视化效果。我们将使用平方数序列1、4、9、16和25来绘制这个图表。只需提供如下的数,Matplotlib将完成其他工作:
import matplotlib.pyplot as plt squares = [1, 4, 9, 16, 25] fig, ax = plt.subplots() ax.plot(squares) plt.show()
① 首先导入模块pyplot ,并为其指定别名 plt ,以免反复输入 pyplot。
② 我们创建了一个名为squares 的列表,在其中存储要用来制作图表的数据。
③ 调用函数subplots(),这个函数可在一张图片中绘制一个或多个图表。变量fig 表示整张图片。变 量ax 表示图片中的各个图表,大多数情况下要使用它。
④方法plot() ,它尝试根据给定的数据以有意义的方式绘制图表。
⑤ 函数 plt.show() 打开Matplotlib查看器并显示绘制的图表
1.2.1 修改标签文字和线条粗细
图形表明数是越来越大的,但标签文字太小、线条太细,难以看清 楚。所幸Matplotlib让你能够调整可视化的各个方面。下面通过一些定制来改善这个图表的可读性,如下所示:
import matplotlib.pyplot as plt
squares = [1, 4, 9, 16, 25]
fig, ax = plt.subplots()
ax.plot(squares, linewidth=3)
# 设置图表标题并给坐标轴加上标签。
ax.set_title("平方数", fontsize=24)
ax.set_xlabel("值", fontsize=14)
ax.set_ylabel("值的平方", fontsize=14)
# 设置刻度标记的大小。
ax.tick_params(axis='both', labelsize=14)
plt.show()
①参数linewidth决定了plot() 绘制的线条粗细
②方法set_title() 给图表指定标题。
③方法set_xlabel() 和set_ylabel() 让你能够为每条轴设置标题。
④方 法tick_params()设置刻度的样式,其中指定的实参将影响 轴和 轴 上的刻度(axes='both' ),并将刻度标记的字号设置为14(labelsize=14 )。
1.2.2 校正图形
图形更容易看清后,我们发现没有正确地绘制数据:折线图的终点指出4.0的平方为 25!下面来修复这个问题。向 plot() 提供一系列数时,它假设第一个数据点对应的 坐标值为0,但这里第一 个点对应的值为1。为改变这种默认行为,可向plot() 同时提供输入值和输出值:
import matplotlib.pyplot as plt input_values = [1, 2, 3, 4, 5] squares = [1, 4, 9, 16, 25] fig, ax = plt.subplots() ax.plot(input_values, squares, linewidth=3) # 设置图表标题并给坐标轴加上标签。 --snip1.2.3使用内置样式
Matplotlib提供了很多已经定义好的样式,它们使用的背景色、网格线、线条粗 细、字体、字号等设置很不错,要获悉在你的系统中可使用哪些样式,可在终端会话中执行如下命令:
import matplotlib.pyplot as plt plt.style.available
要使用这些样式,可在生成图表的代码前添加如下代码行:
import matplotlib.pyplot as plt
input_values = [1, 2, 3, 4, 5]
squares = [1, 4, 9, 16, 25]
plt.style.use('seaborn')
fig, ax = plt.subplots()
--snip
方法plt.style.use(样式),置于生成图标的代码前,就可按照自己喜欢的样式来生成图标。
1.2.4 使用scatter() 绘制散点图并设置样式
有时候,绘制散点图并设置各个数据点的样式很有用。要绘制单个点,可使用方法scatter() 。向它传递一对 坐标和 坐标,它将在指定位置绘制一个点:
import matplotlib.pyplot as plt
plt.style.use('seaborn')
fig, ax = plt.subplots()
ax.scatter(2, 4, s=200)
# 设置图表标题并给坐标轴加上标签。
ax.set_title("平方数", fontsize=24)
ax.set_xlabel("值", fontsize=14)
ax.set_ylabel("值的平方", fontsize=14)
# 设置刻度标记的大小。
ax.tick_params(axis='both', which='major', labelsize=14)
plt.show()
①调用scatter() 并使用参数 s 设置绘制图形时使用的点的尺寸。
1.2.5 使用scatter() 绘制一系列点
要绘制一系列的点,可向 scatter() 传递两个分别包含 值和 值的列表,如下所 示:
import matplotlib.pyplot as plt
x_values = [1, 2, 3, 4, 5]
y_values = [1, 4, 9, 16, 25]
plt.style.use('seaborn')
fig, ax = plt.subplots()
ax.scatter(x_values, y_values, s=100)
# 设置图表标题并给坐标轴指定标签。
--snip
列表 x_values 包含要计算平方值的数,列表 y_values 包含前述数的平方值。将 这些列表传递给scatter() 时,Matplotlib依次从每个列表中读取一个值来绘制一个点。
1.2.6 自动计算数据
手工计算列表要包含的值可能效率低下,需要绘制的点很多时尤其如此。我们不必 手工计算包含点坐标的列表,可以用Python循环来完成。
import matplotlib.pyplot as plt
x_values = range(1, 1001)
y_values = [x**2 for x in x_values]
plt.style.use('seaborn')
fig, ax = plt.subplots()
ax.scatter(x_values, y_values, s=10)
# 设置图表标题并给坐标轴加上标签。
--snip--
# 设置每个坐标轴的取值范围。
ax.axis([0, 1100, 0, 1100000])
plt.show()
使用方法axis() 指定了每个坐标轴的取值范围。方法axis() 要求提供4 个值: 和 坐标轴的最小值和最大值。这里将 坐标轴的取值范围设置为0~ 1100,并将 坐标轴的取值范围设置为0~1100 000。
1.2.7 自定义颜色
要修改数据点的颜色,可向 scatter() 传递参数 c ,并将其设置为要使用的颜色 的名称(放在引号内),如下所示:
ax.scatter(x_values, y_values, c='red', s=10)
11.2.8 使用颜色映射
颜色映射 (colormap)是一系列颜色,从起始颜色渐变到结束颜色。在可视化中, 颜色映射用于突出数据的规律。例如,你可能用较浅的颜色来显示较小的值,并使 用较深的颜色来显示较大的值。
import matplotlib.pyplot as plt x_values = range(1, 1001) y_values = [x**2 for x in x_values] ax.scatter(x_values, y_values, c=y_values, cmap=plt.cm.Blues, s=10) # 设置图表标题并给坐标轴加上标签。 --snip
我们将参数 c 设置成了一个 值列表,并使用参数 cmap 告诉 pyplot 使用哪个颜 色映射。这些代码将 值较小的点显示为浅蓝色,并将 值较大的点显示为深蓝色。
1.2.9 自动保存图表
要让程序自动将图表保存到文件中,可将调用plt.show() 替换为调用 plt.savefig()
plt.savefig('squares_plot.png', bbox_inches='tight')
第一个实参指定要以什么文件名保存图表,这个文件将存储到scatter_squares.py 所在的目录。第二个实参指定将图表多余的空白区域裁剪掉。如果要保留图表周围多余的空白区域,只需省略这个实参即可。
1.3 随机漫步
本节将使用Python来生成随机漫步数据,再使用Matplotlib以引人瞩目的方式将这 些数据呈现出来。随机漫步 是这样行走得到的路径:每次行走都是完全随机的、没 有明确的方向,结果是由一系列随机决策决定的。
1.3.1 创建RandomWalk 类
为模拟随机漫步,将创建一个名为 RandomWalk 的类,它随机地选择前进方向。这 个类需要三个属性:一个是存储随机漫步次数的变量,其他两个是列表,分别存储 随机漫步经过的每个点的 坐标和坐标。
from random import choice class RandomWalk: """一个生成随机漫步数据的类。""" def __init__(self, num_points=5000): """初始化随机漫步的属性。""" self.num_points = num_points #所有随机漫步都始于(0, 0)。 self.x_values = [0] self.y_values = [0]
并在每次决策时都使用模块random 中的choice() 来决定使用哪种选择
1.3.2 选择方向
我们将使用方法 fill_walk() 来生成漫步包含的点并决定每次漫步的方向,如下 所示。请将这个方法添加到random_walk.py中:
def fill_walk(self):
"""计算随机漫步包含的所有点。"""
# 不断漫步,直到列表达到指定的长度。
while len(self.x_values) < self.num_points:
# 决定前进方向以及沿这个方向前进的距离。
x_direction = choice([1, -1])
x_distance = choice([0, 1, 2, 3, 4])
x_step = x_direction * x_distance
y_direction = choice([1, -1])
y_distance = choice([0, 1, 2, 3, 4])
y_step = y_direction * y_distance
# 拒绝原地踏步。
if x_step == 0 and y_step == 0:
continue
# 计算下一个点的x值和y值。
x = self.x_values[-1] + x_step
y = self.y_values[-1] + y_step
self.x_values.append(x)
self.y_values.append(y)
①使用choice([1, -1]) 给x_direction 选择一个值,结果要么是表示向右走的 1,要么是表示向左走的-1.
②choice([0, 1, 2, 3, 4]) 随机 地选择一个0~4的整数,告诉Python 沿指定的方向走多(x_distance )。
③将移动方向乘以移动距离,确定沿X轴和Y轴移动的距离。
1.3.3 绘制随机漫步图
下面的代码将随机漫步的所有点都绘制出来:
import matplotlib.pyplot as plt
from random_walk import RandomWalk
# 创建一个RandomWalk实例。
rw = RandomWalk()
rw.fill_walk()
# 将所有的点都绘制出来。
plt.style.use('classic')
fig, ax = plt.subplots()
ax.scatter(rw.x_values, rw.y_values, s=15)
plt.show()
将随机漫步包含的X值和Y传递给scatter() ,并选择合适的点尺寸 。
1.3.4 设置随机漫步图的样式
a. 给点着色
我们将使用颜色映射来指出漫步中各点的先后顺序,并删除每个点的黑色轮 廓,让其颜色更为明显。为根据漫步中各点的先后顺序来着色,传递参数c , 并将其设置为一个列表,其中包含各点的先后顺序。这些点是按顺序绘制的, 因此给参数c 指定的列表只需包含数0~4999,如下所示:
--snip--
while True:
# 创建一个RandomWalk实例。
rw = RandomWalk()
rw.fill_walk()
# 将所有的点都绘制出来。
plt.style.use('classic')
fig, ax = plt.subplots()
point_numbers = range(rw.num_points)
ax.scatter(rw.x_values, rw.y_values, c=point_numbers,
cmap=plt.cm.Blues,
edgecolors='none', s=15)
keep_running = input("Make another walk? (y/n): ")
--snip--
①使用range() 生成了一个数字列表,其中包含的数与漫步包含的点数量相同。
②并传递实参edgecolors='none'
③将参数c 设置为point_numbers ,指定使用颜色映射Blues
b. 重新绘制起点和终点
--snip--
while True:
--snip--
ax.scatter(rw.x_values, rw.y_values, c=point_numbers, cmap=plt.cm.Blues,
edgecolors='none', s=15)
# 突出起点和终点。
ax.scatter(0, 0, c='green', edgecolors='none', s=100)
ax.scatter(rw.x_values[-1], rw.y_values[-1], c='red', edgecolors='none',
s=100)
plt.show()
--snip--
使用绿色绘制点(0, 0),并使其比其他点大(s=100 )。为突出终点,在漫步包含的最后一个 值和 值处绘制一个点,将其颜色设置为红 色,并将尺寸设置为100。务必将这些代码放在调用plt.show() 的代码前面,确保在其他点之上绘制起点和终点。
c. 隐藏坐标轴
# 隐藏坐标轴。 ax.get_xaxis().set_visible(False) ax.get_yaxis().set_visible(False)
使用方法ax.get_xaxis() 和ax.get_yaxis() 将 每条坐标轴的可见性都设置为False 。 随着对数据可视化的不断学习和实践, 你会经常看到这种串接方法的方式。
d 调整尺寸以适合屏幕
--snip--
while True:
# 创建一个RandomWalk实例。
rw = RandomWalk(50_000)
rw.fill_walk()
# 将所有的点都绘制出来。
plt.style.use('classic')
fig, ax = plt.subplots(figsize=(15, 9))
--snip--
可传递参数figsize 以指定生成的图形的尺寸。需要给参数 figsize 指定一个元组,向Matplotlib指出绘图窗口的尺寸.
1.4 使用Plotly模拟掷骰子
本节将使用Python包Plotly来生成交互式图表。
1.4.1 安装Plotly
在终端输入:
python -m pip install --user plotly
即可安装plotiy
1.4.2 创建Die 类
from random import randint
class Die:
"""表示一个骰子的类。"""
def __init__(self, num_sides=6):
"""骰子默认为6面。"""
self.num_sides = num_sides
def roll(self):
""""返回一个位于1和骰子面数之间的随机值。"""
return randint(1, self.num_sides)
①方法__init__() 接受一个可选参数。创建这个类的实例时,如果没有指定任何实
参,面数默认为6;
②方法roll() 使用函数randint() 来返回一个1和面数之间的随机数。这 个函数可能返回起始值1、终止值num_sides 或这两个值之间的任何整数。
有时我们使用这个类会出现错误,此时我们可以只定义roll函数,不去定义类。
1.4.3 掷骰子
使用这个类来创建图表前,先来掷D6,将结果打印出来,并确认结果是合理的:
from die import Die
# 创建一个D6。 ❶ die = Die()
# 掷几次骰子并将结果存储在一个列表中。
results = []
for roll_num in range(100):
result = die.roll()
results.append(result)
print(results)
1.4.4 分析结果
为分析掷一个D6的结果,计算每个点数出现的次数:
--snip--
# 掷几次骰子并将结果存储在一个列表中。
results = []
for roll_num in range(1000):
result = die.roll()
results.append(result)
# 分析结果。
frequencies = []
for value in range(1, die.num_sides+1):
frequency = results.count(value)
frequencies.append(frequency)
print(frequencies)
由于将使用Plotly来分析,而不是将结果打印出来,因此可将模拟掷骰子的次数增 加到1000 。为分析结果,我们创建空列表 frequencies ,用于存储每种 点数出现的次数。在 处,遍历可能的点数(这里为1~6),计算每种点数在 results 中出现了多少次。
1.4.5 绘制直方图
有了频率列表,就可以绘制一个表示结果的直方图了。 直方图 是一种条形图,指出 了各种结果出现的频率。
from plotly.graph_objs import Bar, Layout
from plotly import offline
from die import Die
--snip--
# 分析结果。
frequencies = []
for value in range(1, die.num_sides+1):
frequency = results.count(value)
frequencies.append(frequency)
# 对结果进行可视化。
x_values = list(range(1, die.num_sides+1))
data = [Bar(x=x_values, y=frequencies)]
x_axis_config = {'title': '结果'}
y_axis_config = {'title': '结果的频率'}
my_layout = Layout(title='掷一个D6 1000次的结果',
xaxis=x_axis_config, yaxis=y_axis_config)
offline.plot({'data': data, 'layout': my_layout}, filename='d6.html')
①我们将可能出现的点数 (1到骰子的面数)存储在一个名为x_values 的列表中,Plotly不能直接 接受函数range() 的结果,因此需要使用函数list() 将其转换为列表。
②Plotly类 Bar() 表示用于绘制条形图的数据集,需要一个存储X值的列表和一个存储Y值的列表。这个类必须放在方括号内,因为数据集可能包含多个元素。
③类Layout() 返回一个指定图表布局和配置的对象 (见❹)。这里设置了图表名称,并传入了 轴和 轴的配置字典。
④这个函数需要一个包含 数据和布局对象的字典,还接受一个文件名,指定要将图表保存到哪里。这里将输 出存储到文件d6.html。
第二章 下载数据 本章将从网上下载数据,并对其进行可视化。本章将访问并可视化的数据以两种常见格式存储:CSV和JSON。 2.1CSV文件格式 要在文本文件中存储数据,一个简单方式是将数据作为一系列 以逗号分隔的值(comma-separated values)写入文件。这样的文件成为CVS文件。 2.1.1 分析CSV文件头 csv 模块包含在Python标准库中,可用于分析CSV文件中的数据行,让我们能够快速 提取感兴趣的值。(它相当于一个竖着排列的一列列的列表,而开头一行是列表名)。接下来我们尝试读取这些列表名。import csv
filename = 'data/sitka_weather_07-2018_simple.csv'
with open(filename) as f:
reader = csv.reader(f)
header_row = next(reader)
print(header_row)
将文件名赋给filename,这是打开文件时常用的做法。然后将用到至关重要的函数csv.reader(),括号里包含的是需要读取的文件对象,从而创建一个与该文件相关联的阅读器对象,在这里被赋给了reader。模块csv 包含函数next() ,调用它并传入阅读器对象时,它将返回文件中的下一 行。在上述代码中,只调用了next() 一次,因此得到的是文件的第一行,其中包含文件头。
注意:当阅读器经过next()函数以后,每当调用一次将会自动返回文件的下一行。
2.1.2打印开头及其位置为了得到文件头下包含的数据,我们需要获取文件头的位置。于是接着上面代码的基础上我们再加几行代码:
import csv
filename = 'data/sitka_weather_07-2018_simple.csv'
with open(filename) as f:
reader = csv.reader(f)
header_row = next(reader)
for index,name in enumerate(header_row)
print(index,name)
在这里我们又引用了一个新的函数enumerate(),有点类似于对于字典使用的items()这个函数,不同的是这里返回的是索引和元素。由此我们获得了对应文件的开头,方便我们获得需要的数据。
2.1.3读取并提取文件知道了第一行里对应的数据名以及位置,我们可以回去剩下行里的数据。
with open(filename) as f:
reader = csv.reader(f)
header_row = next(reader)
# 从文件中获取最高温度。
highs = []
for row in reader:
high = int(row[5])
highs.append(high)
print(highs)
紧接着上面的代码我们获取每一行数据的第五个索引位置的数据(最高温度)。
2.1.4绘制温度图表为了将数据可视化,我们使用上面安装的用Matplotlib创建一个显示每日最高温度的简单图 形,如下所示:
import csv
import matplotlib.pyplot as plt
filename = 'data/sitka_weather_07-2018_simple.csv'
with open(filename) as f:
--_snip_—
# 根据最高温度绘制图形。
plt.style.use('seaborn')
fig, ax = plt.subplots()
ax.plot(highs, c='red')
# 设置图形的格式。
ax.set_title("2018年7月每日最高温度", fontsize=24)
ax.set_xlabel('', fontsize=16)
ax.set_ylabel("温度 (F)", fontsize=16)
ax.tick_params(axis='both', which='major', labelsize=16)
plt.show()
使用绘图函数plot(),并传递c="red",以便将数据点绘制为红色,其余函数在上一章均详细介绍过,
2 .1.5 模块datetime根据前面获取的第一行文件名,我们来获取详尽的时间,读取该数据时,获得的是一个字符串,因此需要想办法将字符串"2018-7-1" 转换 为一个表示相应日期的对象。为此我们再此使用新的函数,datetime模块中的的方法strptime(),下面演示此函数作用:
>>> from datetime import datetime
>>> first_date = datetime.strptime('2018-07-01', '%Y-%m-%d')
>>> print(first_date)
2018-07-01 00:00:00
首先导入模块
datetime
中的
datetime
类,再调用方法
strptime()
,并将包 含所需日期的字符串作为第一个实参。第二个实参告诉Python如何设置日期的格 式。在这里,'%Y-'
让Python将字符串中第一个连字符前面的部分视为四位的年 份,'%m-'
让Python将第二个连字符前面的部分视为表示月份的数,
'%d'
让 Python将字符串的最后一部分视为月份中的一天(1~31)。
方法
strptime()
可接受各种实参,并根据它们来决定如何解读日期。下表列出 了这样的一些实参。
| 实参 | 含义 |
| %A | 星期几,,如Monday |
| %B | 月份名,如January |
| %m | 用数表示的月份(01~12) |
| %d | 用数表示的月份中的一天(01~31) |
| % | 四位的年份,如2019 |
| % | 两位的年份,如19 |
| % | 24小时制的小时数(00~23) |
| % | 12小时制的小时数(01~12) |
| % | am或pm |
| % | 分钟数(00~59) |
import csv
from datetime import datetime
import matplotlib.pyplot as plt
filename = 'data/sitka_weather_07-2018_simple.csv'
with open(filename) as f:
reader = csv.reader(f)
header_row = next(reader)
# 从文件中获取日期和最高温度。
dates, highs = [], []
for row in reader:
current_date = datetime.strptime(row[2], '%Y-%m-%d')
high = int(row[5])
dates.append(current_date)
highs.append(high)
# 根据最高温度绘制图形。
plt.style.use('seaborn')
fig, ax = plt.subplots()
ax.plot(dates, highs, c='red')
# 设置图形的格式。
ax.set_title("2018年7月每日最高温度", fontsize=24)
ax.set_xlabel('', fontsize=16)
fig.autofmt_xdate()
ax.set_ylabel("温度 (F)", fontsize=16)
ax.tick_params(axis='both', which='major', labelsize=16)
plt.show()
2.1.7再绘制一个数据系列
虽然改进后的图表已经显示了丰富的数据,但是还能再添加最低温度数据,使其更 有用。为此,需要从数据文件中提取最低温度,并将它们添加到图表中,如下所示:
--snip--
filename = 'sitka_weather_2018_simple.csv'
with open(filename) as f:
reader = csv.reader(f)
header_row = next(reader)
# 从文件中获取日期、最高温度和最低温度。
dates, highs, lows = [], [], []
for row in reader:
current_date = datetime.strptime(row[2], '%Y-%m-%d')
high = int(row[5])
low = int(row[6])
dates.append(current_date)
highs.append(high)
lows.append(low)
# 根据最高温度和最低温度绘制图形。
plt.style.use('seaborn')
fig, ax = plt.subplots()
ax.plot(dates, highs, c='red')
ax.plot(dates, lows, c='blue')
# 设置图形的格式。
ax.set_title("2018年每日最高温度", fontsize=24)
--snip--
添加空列表
lows
,用于存储最低温度。接下来,从每行的第七列 row[6] )提取最低温度并存储
。
添加调用
plot()
的代码,以 使用蓝色绘制最低温度。
2.1.8给图表区域着色
添加两个数据系列后,就可以知道每天的温度范围了。下面来给这个图表做最后的 修饰,通过着色来呈现每天的温度范围。
--snip--
# 根据最低温度和最高温度绘制图形。
plt.style.use('seaborn')
fig, ax = plt.subplots()
ax.plot(dates, highs, c='red', alpha=0.5)
ax.plot(dates, lows, c='blue', alpha=0.5)
ax.fill_between(dates, highs, lows, facecolor='blue', alpha=0.1)
--snip--
我们再此引用函数方法fill_between() 。 它接受一个 值系列和两个 值系列,并填充两个 值系列之间的空间。实参alpha 指定颜色的透明度。alpha 值为0表示完全透明,为1(默认设置表示完全不透明。向fill_between() 传递一个 值系列(列表dates ),以及两个 值 系列(highs 和lows )。实参facecolor指定填充区域的颜色,还将alpha 设置成了较小的值0.1。
2.2制作全球地震散点图:JSON格式 你将下载一个数据集,其中记录了一个月内全球发生的所有地震,再 制作一幅散点图来展示这些地震的位置和震级。这些数据是以JSON格式存储的,因 此要使用模块json 来处理。 2.1.1地震数据 请将文件eq_data_1_day_m1.json复制到存储本章程序的文件夹中。地震是以里氏震 级度量的,而该文件记录了(截至写作本节时)最近24小时内全球发生的所有不低 于1级的地震。 2.2.2 查看JSON数据 如果打开文件eq_data_1_day_m1.json,你将发现其内容密密麻麻,难以阅读,这些数据适合机器而不是人来读取。不过可以看到,这个文件包含一些字典,还有一些我们感兴趣的信息,如震级和位置。 块json 提供了各种探索和处理JSON数据的工具,其中一些有助于重新设置这个 文件的格式,让我们能够更清楚地查看原始数据,继而决定如何以编程的方式来处理。import json
# 探索数据的结构。
filename = 'data/eq_data_1_day_m1.json'
with open(filename) as f:
all_eq_data = json.load(f)
readable_file = 'data/readable_eq_data.json'
with open(readable_file, 'w') as f:
json.dump(all_eq_data, f, indent=4)
首先导入模块
json
,以便恰当地加载文件中的数据,并将其存储到
all_eq_data 中
。函
json.load()
将数据转换为Python能够处理的格式,这里是一 个庞大的字典。
创建一个文件,以便将这些数据以易于阅读的方式写入其 中。函数json.dump()
接受一个JSON数据对象和一个文件对象,并将数据写入这 个文件中
。参数
indent=4
让
dump()
使用与数据结构匹配的缩进量来设 置数据的格式。
2.2.3 创建地震列表
首先,创建一个列表,其中包含所有地震的各种信息:
import json
# 探索数据的结构。
filename = 'data/eq_data_1_day_m1.json'
with open(filename) as f:
all_eq_data = json.load(f)
all_eq_dicts = all_eq_data['features']
print(len(all_eq_dicts))
我们提取与键
'features'
相关联的数据,并将其存储到
all_eq_dicts
中。我 们知道,这个文件记录了158次地震。下面的输出表明,我们提取了这个文件记录的所有地震。
2.2.4 提取震级
有了包含所有地震数据的列表后,就可遍历这个列表,从中提取所需的数据。下面
来提取每次地震的震级:
--snip--
all_eq_dicts = all_eq_data['features']
mags = []
for eq_dict in all_eq_dicts:
mag = eq_dict['properties']['mag']
mags.append(mag)
print(mags[:10])
2.2.5 提取位置数据并绘制震级散点图
位置数据存储在
"geometry"
键下。在
"geometry"
键关联的字典中,有一 个"coordinates" 键,它关联到一个列表,而列表中的前两个值为经度和纬度。有了前面提取的数据,就可以绘制可视化图了。首先要实现一个简单的震级散点图,在确保显示的信息正确无误之后,我们再将注意力转向样式和外观方面。绘制初始散点图的代码如下:
import plotly.express as px
fig = px.scatter(
x=lons,
y=lats,
labels={"x": "经度", "y": "纬度"},
range_x=[-200, 200],
range_y=[-90, 90],
width=800,
height=800,
title="全球地震散点图",
)
fig.write_html("global_earthquakes.html")
fig.show()
导入
plotly.express
,用别名
px
表示。Plotly Express是Plotly的高级接口。
调用
px.scatter
函数 配置参数创建一个fig
实例,分别设置 轴为经度[范围是
[-200, 200]
(扩大 空间,以便完整显示东西经180°附近的地震散点)]、 轴为纬度[范围是[-90, 90] ],设置散点图显示的宽度和高度均为800像素,并设置标题为“全球地震散点图。
2.2.6 另一种指定图表数据的方式
下面是另一种给图表定义数据的等效方式,需要使用pandas数据分析工 具。首先创建一个DataFrame
,将需要的数据封装起来:
import pandas as pd data = pd.DataFrame( data=zip(lons, lats, titles, mags), columns=["经度", "纬度", "位置", "震级"] ) data.head(在这种方式中,所有有关数据的信息都以键值对的形式放在一个字典中。如果在 eq_plot.py中使用这些代码,生成的图表是一样的。相比于前一种格式,这种格式 让我们能够无缝衔接数据分析,并且更轻松地进行定制。 2.2.7 定制标记的尺寸 确定如何改进散点图的样式时,应着重于让要传达的信息更清晰。当前的散点图显 示了每次地震的位置,但没有指出震级。我们要让观察者迅速获悉最严重的地震发生在什么地方。为此,根据地震的震级设置其标记的尺寸:
fig = px.scatter(
data,
x="经度",
y="纬度",
range_x=[-200, 200],
range_y=[-90, 90],
width=800,
height=800,
title="全球地震散点图",
size="震级",
size_max=10,
)
fig.write_html("global_earthquakes.html")
fig.show()
Plotly Express支持对数据系列进行定制,这些定制都以参数表示。这里使用了 size 参数来指定散点图中每个标记的尺寸,我们只需要将前面
data
中的
"
震级
" 字段提供给size 参数即可。标记尺寸默认为20像素,还可以通过size_max=10 将最大显示尺寸缩放到10。
2.2.8 定制标记的颜色
为了让标记的震级按照不同的颜色 显示,只需要配置color="
震级
"
即可。默认的视觉映射图例渐变色范围是从蓝到红再到黄,数值越小则标记越蓝,而数值越大则标记越黄。
filename = 'data/eq_data_30_day_m1.json' --snip-- fig = px.scatter( data, x="经度", y="纬度", range_x=[-200, 200], range_y=[-90, 90], width=800, height=800, title="全球地震散点图", size="震级", size_max=10, color="震级 )



