文章目录

  • 下载数据
    • 制作全球地震散点图:JSON格式
  • end

几个实验结果:

每日最高气温:


地震图绘制:

下载数据

CSV文件格式

在文本文件中存储数据,一个简单方式是将数据作为一系列以逗号分隔的值(comma-separated values)写入文件。这样的文件称为CSV文件。下面是一行CSV格式的天气数据:

"USW00025333","SITKA AIRPORT, AK US","2018-01-01","0.45",,"48","38"

CSV文件对人来说阅读起来比较麻烦,但程序可轻松提取并处理其中的值,有助于加快数据分析过程。

在《python编程从入门到实践》的下载资源中找到data文件夹,下面可以找到如下的csv文件,然后移动到我们的项目文件夹,如下:

分析CSV文件头
csv模块包含在Python标准库中,可用于分析CSV文件中的数据行,让我们能够快速提取感兴趣的值。先来查看这个文件的第一行,其中的一系列文件头指出了后续各行包含的是什么样的信息
sitka_highs.py

import csv
filename = 'data/sitka_weather_2018_simple.csv'with open(filename) as f:reader = csv.reader(f)header_row = next(reader)print(header_row)

导入模块csv后,将要使用的文件的名称赋给filename。接下来,打开这个文件,并将返回的文件对象赋给f。然后,调用csv.reader()并将前面存储的文件对象作为实参传递给它,从而创建一个与该文件相关联的阅读器对象。这个阅读器对象被赋给了reader。

模块csv包含函数next(),调用它并传入阅读器对象时,它将返回文件中的下一行。在上述代码中,只调用了next()一次,因此得到的是文件的第一行,其中包含文件头。将返回的数据存储到header_row中。如你所见,header_row包含与天气相关的文件头,指出了每行都包含哪些数据:

['STATION', 'NAME', 'DATE', 'PRCP', 'TAVG', 'TMAX', 'TMIN']

reader处理文件中以逗号分隔的第一行数据,并将每项数据都作为一个元素存储在列表中。

  • 文件头STATION表示记录数据的气象站的编码。这个文件头的位置表明,每行的第一个值都是气象站编码。
  • 文件头NAME指出每行的第二个值都是记录数据的气象站的名称。其他文件头则指出记录了哪些信息。当前,我们最关心的是日期(DATE)、最高温度(TMAX)和最低温度(TMIN)。

这是一个简单的数据集,只包含降水量以及与温度相关的数据。你自己下载天气数据时,可选择涵盖众多测量值,如风速、风向以及详细的降水量数据。

打印文件头及其位置
为了让文件头数据更容易理解,将列表中的每个文件头及其位置打印出来:

import csvfilename = 'data/sitka_weather_2018_simple.csv'with open(filename) as f:reader = csv.reader(f)header_row = next(reader)for index, column_header in enumerate(header_row):print(index, column_header)

在循环中,对列表调用了enumerate()来获取每个元素的索引及其值。
输出如下,指出了每个文件头的索引:

0 STATION
1 NAME
2 DATE
3 PRCP
4 TAVG
5 TMAX
6 TMIN

从中可知,日期和最高温度分别存储在第三列和第六列。为研究这些数据,我们将处理sitka_weather-2018_simple.csv中的每行数据,并提取其中索引为2和5的值。

提取并读取数据
知道需要哪些列中的数据后,我们来读取一些数据。首先,读取每天的最高温度:

import csvfilename = 'data/sitka_weather_2018_simple.csv'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)

创建一个名为highs的空列表,再遍历文件中余下的各行。

阅读器对象从其停留的地方继续往下读取CSV文件,每次都自动返回当前所处位置的下一行。由于已经读取了文件头行,这个循环将从第二行开始——从这行开始包含的是实际数据。每次执行循环时,都将索引5处(TMAX列)的数据附加到highs末尾。

在文件中,这项数据是以字符串格式存储的,因此在附加到highs末尾前,使用函数int()将其转换为数值格式,以便使用。

得到的最高温度:

[48, 48, 46, 42, 46, 44, 39, 36, 34, 28, 34, 41, 53, 63, 60, 54, 47, 46, 42, 45, 43, 41, 41, 40, 40, 41, 39, 40, 40, 39, 36, 35, 35, 34, 42, 41, 39, 42, 39, 37, 37, 40, 43, 41, 40, 38, 36, 37, 39, 39, 38, 41, 42, 41, 39, 38, 42, 39, 40, 35, 40, 41, 40, 39, 39, 40, 39, 42, 43, 44, 54, 58, 54, 45, 45, 45, 43, 41, 41, 42, 46, 42, 42, 41, 42, 43, 43, 46, 45, 43, 45, 41, 43, 45, 52, 51, 59, 52, 54, 57, 58, 51, 51, 48, 50, 49, 46, 46, 45, 45, 47, 47, 45, 46, 45, 45, 46, 47, 46, 44, 44, 47, 45, 48, 50, 56, 53, 51, 56, 52, 48, 49, 54, 45, 50, 51, 57, 52, 50, 52, 53, 52, 55, 52, 50, 52, 51, 50, 54, 53, 54, 58, 53, 57, 52, 63, 57, 59, 59, 60, 53, 51, 63, 56, 54, 60, 57, 54, 62, 67, 62, 57, 60, 57, 61, 60, 55, 56, 61, 57, 57, 62, 58, 70, 70, 67, 59, 58, 62, 66, 59, 56, 63, 65, 58, 56, 59, 64, 60, 60, 61, 65, 65, 63, 59, 64, 65, 68, 66, 64, 67, 65, 66, 59, 67, 73, 72, 64, 62, 61, 61, 63, 65, 62, 59, 61, 60, 63, 66, 63, 67, 65, 63, 59, 60, 58, 58, 63, 59, 61, 62, 61, 61, 57, 63, 62, 65, 67, 64, 65, 68, 66, 71, 69, 67, 61, 65, 62, 59, 60, 64, 63, 58, 64, 56, 56, 56, 57, 57, 57, 61, 64, 63, 66, 56, 54, 54, 57, 52, 53, 56, 54, 53, 52, 54, 56, 57, 60, 59, 55, 55, 56, 54, 56, 61, 61, 55, 55, 51, 54, 54, 55, 51, 47, 49, 45, 50, 48, 47, 46, 50, 51, 50, 47, 50, 54, 53, 49, 48, 48, 54, 52, 52, 51, 46, 47, 44, 48, 54, 53, 47, 45, 43, 39, 36, 39, 39, 41, 41, 44, 48, 52, 50, 45, 46, 43, 46, 49, 48, 48, 43, 39, 41, 44, 43, 41, 44, 46, 47, 44, 38, 42, 48]

绘制温度图表:
为可视化这些温度数据,首先使用Matplotlib创建一个显示每日最高温度的简单图形,如下所示:上面asv是2018年全年的数据,下面用的是2018年7月的数据:

import csv
import matplotlib.pyplot as pltfilename = 'data/sitka_weather_07-2018_simple.csv'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)# 根据最高温度绘制图形
plt.style.use('seaborn')
plt.rcParams['font.sans-serif'] = ['SimHei']
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’以便将数据点绘制为红色。(这里使用红色显示最高温度,用蓝色显示最低温度。)接下来,设置了一些其他的格式,如名称和字号,这些都在第15章介绍过。鉴于还没有添加日期,因此没有给x轴添加标签,但ax.set_xlabel()确实修改了字号,让默认标签更容易看清。

绘图结果:

模块datatime

下面在图表中添加日期,使其更有用。在天气数据文件中,第一个日期在第二行

USW00025333 SITKA AIRPORT, AK US 2018/1/1 0.45 48 38

读取该数据时,获得的是一个字符串,因此需要想办法将字符串"2018/1/1"转换为一个表示相应日期的对象。为创建一个表示2018年1月1日的对象,可使用模块datetime中的方法strptime()。我们在终端会话中看看strptime()的工作原理:

首先导入模块datetime中的datetime类,再调用方法strptime(),并将包含所需日期的字符串作为第一个实参。第二个实参告诉Python如何设置日期的格式。在这里,’%Y/‘让Python将字符串中第一个连字符前面的部分视为四位的年份,’%m/‘让Python将第二个连字符前面的部分视为表示月份的数,’%d’让Python将字符串的最后一部分视为月份中的一天(1~31)。

需要注意的是:“%Y”后面的符号需要和文件匹配,这里用的是/,而要处理asv文件的时候,这里需要变成“%Y-”. 请参考后面的代码。

方法strptime()可接受各种实参,并根据它们来决定如何解读日期。

在图表中添加日期

现在,可以通过提取日期和最高温度并将其传递给plot(),对温度图形进行改进,如下所示:

import csv
from datetime import datetimeimport matplotlib.pyplot as pltfilename = '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')
plt.rcParams['font.sans-serif'] = ['SimHei']
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()

我们创建了两个空列表,用于存储从文件中提取的日期和最高温度。然后,将包含日期信息的数据(row[2])转换为datetime对象,并将其附加到列表dates末尾。然后,将日期和最高温度值传递给plot()。调用fig.autofmt_xdate()来绘制倾斜的日期标签,以免其彼此重叠.

涵盖更长的时间
设置好图表后,我们来添加更多的数据,生成一幅更复杂的锡特卡天气图。请将文件sitka_weather_2018_simple.csv复制到本章程序所在的文件夹,该文件包含整年的锡特卡天气数据。

代码

import csv
from datetime import datetimeimport matplotlib.pyplot as plt# filename = 'data/sitka_weather_07-2018_simple.csv'
filename = 'data/sitka_weather_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')
plt.rcParams['font.sans-serif'] = ['SimHei']
fig, ax = plt.subplots()
ax.plot(dates, highs, c='red')# 设置图形格式
ax.set_title("2018年每日最高温度", 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()

再绘制一个数据系列
虽然改进后的图表已经显示了丰富的数据,但是还能再添加最低温度数据,使其更有用。为此,需要从数据文件中提取最低温度,并将它们添加到图表中,如下所示:

sikta_highs_lows.py

import csv
from datetime import datetimeimport matplotlib.pyplot as plt# filename = 'data/sitka_weather_07-2018_simple.csv'
filename = 'data/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')
plt.rcParams['font.sans-serif'] = ['SimHei']
fig, ax = plt.subplots()
ax.plot(dates, highs, c='red')
ax.plot(dates, lows, c='blue')# 设置图形格式
ax.set_title("2018年每日最高温度", 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()

绘制的结果:

给图表区域着色
添加两个数据系列后,就可以知道每天的温度范围了。下面来给这个图表做最后的修饰,通过着色来呈现每天的温度范围。为此,将使用方法fill_between()。它接受一个x值系列和两个y值系列,并填充两个y值系列之间的空间:

import csv
from datetime import datetimeimport matplotlib.pyplot as plt# filename = 'data/sitka_weather_07-2018_simple.csv'
filename = 'data/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')
plt.rcParams['font.sans-serif'] = ['SimHei']
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)# 设置图形格式
ax.set_title("2018年每日最高温度", 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()

ax.plot()处的实参alpha指定颜色的透明度。alpha值为0表示完全透明,为1(默认设置)表示完全不透明。通过将alpha设置为0.5,可让红色和蓝色折线的颜色看起来更浅。

另外,向fill_between()传递一个x值系列(列表dates),以及两个y值系列(highs和lows)。实参facecolor指定填充区域的颜色,还将alpha设置成了较小的值0.1,让填充区域将两个数据系列连接起来的同时不分散观察者的注意力。下图显示了最高温度和最低温度之间的区域被填充后的图表。

错误检查

有些气象站收集的数据种类不同,有些气象站会偶尔出现故障,未能收集部分或全部应收集的数据。缺失数据可能引发异常,如果不妥善处理,可能导致程序崩溃。例如,来看看生成加利福尼亚州死亡谷的温度图时出现的情况。

death_valley_highs.py

import  csvfilename = 'data/death_valley_2018_simple.csv'with open(filename) as f:reader = csv.reader(f)header_row = next(reader)for index, column_header in enumerate(header_row):print(index, column_header)

输出如下

0 STATION
1 NAME
2 DATE
3 PRCP
4 TMAX
5 TMIN
6 TOBS

与前面一样,日期也在索引2处,但最高温度和最低温度分别在索引4和索引5处,因此需要修改代码中的索引,以反映这一点。另外,这个气象站没有记录平均温度,而记录了TOBS,即特定时点的温度。

import csv
from datetime import datetime
from matplotlib import pyplot as pltfilename = 'data/death_valley_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[4])low = int(row[5])dates.append(current_date)

运行上述代码,会报错

Traceback (most recent call last):File "death_valley_highs_lows.py", line 14, in <module>high = int(row[4])
ValueError: invalid literal for int() with base 10: ''

traceback指出,Python无法处理其中一天的最高温度,因为无法将空字符串(’’)转换为整数。我们只要看一下文件death_valley_2018_simple.csv,就知道缺失了哪项数据,但这里不这样做,而是直接对缺失数据的情形进行处理。

下面的代码使用了python的格式化输出:使用 格式化字符串字面值 ,要在字符串开头的引号或三引号前添加 f 或 F 。在这种字符串中,可以在 { 和 } 字符之间输入引用的变量,或字面值的 Python 表达式。

death_valley_highs_lows.py

import csv
from datetime import datetime
from matplotlib import pyplot as pltfilename = 'data/death_valley_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')try:high = int(row[4])low = int(row[5])except ValueError:print(f"Missing data for {current_date}")else:dates.append(current_date)highs.append(high)lows.append(low)# 根据最低气温和最高气温绘制图形
plt.style.use('seaborn')
plt.rcParams['font.sans-serif'] = ['SimHei']fig, ax = plt.subplots()
ax.plot(dates, highs, c='red', alpha=0.5)
ax.plot(dates, lows, c='blue', alpha=0.5)
plt.fill_between(dates, highs, lows, facecolor='blue', alpha=0.1)# 设置图形的格式
title = "2018年每日最高温度和最低温度\n美国加利福尼亚州死亡谷"
ax.set_title(title, fontsize=20)
ax.set_xlabel('', fontsize=16)plt.ylabel("Temperature (F)", fontsize=16)
plt.tick_params(axis='both', which='major', labelsize=16)plt.show()

对于每一行,都尝试从中提取日期、最高温度和最低温度。

只要缺失其中一项数据,Python就会引发ValueError异常。我们这样进行处理:打印一条错误消息,指出缺失数据的日期。

打印错误消息后,循环将接着处理下一行。如果获取特定日期的所有数据时没有发生错误,就运行else代码块,将数据附加到相应列表的末尾。

这里绘图时使用的是有关另一个地方的信息,因此修改标题以指出这个地方。因为标题更长,所以我们缩小了字号。

下面是遗失数据产生的错误信息,这里可以看出,上面的数据集中只有1条有误的数据。

Missing data for 2018-02-18 00:00:00

使用的很多数据集都可能缺失数据、格式不正确或数据本身不正确。对于这样的情形,在这里,使用了一个try-except-else代码块来处理数据缺失的问题。在有些情况下,需要使用continue来跳过一些数据,或者使用remove()或del将已提取的数据删除。只要能进行精确而有意义的可视化,采用任何管用的方法都是可以的。

制作全球地震散点图:JSON格式

数据集中记录了一个月内全球发生的所有地震,再制作一幅散点图来展示这些地震的位置和震级。其中,这些数据是json数据,需要用到的是json模块。

地震数据
打开json数据之后,我们发现这些数据格式统一,但是不适合人来阅读,其实,这样格式化的数据特别适合机器来读。

模块json提供了各种探索和处理JSON数据的工具,其中一些有助于重新设置这个文件的格式,让我们能够更清楚地查看原始数据,继而决定如何以编程的方式来处理。
eq_explore_data.py

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_json_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()使用与数据结构匹配的缩进量来设置数据的格式。

我们来查看现在的json文件,部分内容如下:

{"type": "FeatureCollection","metadata": {"generated": 1550361461000,"url": "https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/1.0_day.geojson","title": "USGS Magnitude 1.0+ Earthquakes, Past Day","status": 200,"api": "1.7.0","count": 158},"features": [

这个文件的开头是一个键为"metadata"的片段(第二行),指出了这个数据文件是什么时候生成的,以及能够在网上的什么地方找到。它还包含适合人类阅读的标题以及文件中记录了多少次地震:在过去的24小时内,发生了158次地震。

这个geoJSON文件的结构适合存储基于位置的数据。数据存储在一个与键"features"相关联的列表中。这个文件包含的是地震数据,因此列表的每个元素都对应一次地震。这种结构可能有点令人迷惑,但很有用,让地质学家能够将有关每次地震的任意数量信息存储在一个字典中,再将这些字典放在一个大型列表中。

下图是feature列表中的一项,含义是一次具体的地震。

键"properties"关联到了与特定地震相关的大量信息。我们关心的主要是与键"mag"相关联的地震震级以及地震的标题,因为后者很好地概述了地震的震级和位置。

键"geometry"指出了地震发生在什么地方,我们需要根据这项信息将地震在散点图上标出来。在与键"coordinates"相关联的列表中,可找到地震发生位置的经度和纬度。

这里有一点值得注意的地方,《python编程从入门到实践》指出:

注意:说到位置时,我们通常先说纬度、再说经度,这种习惯形成的原因可能是人类先发现了纬度,很久后才有经度的概念。然而,很多地质学框架都先列出经度、后列出纬度,因为这与数学约定(x,y)一致。geoJSON格式遵循(经度, 纬度)的约定,但在使用其他框架时,获悉其遵循的约定很重要。

创建地震列表

首先,创建一个列表,其中包含所有地震的各种信息:

我们提取与键’features’相关联的数据,并将其存储到all_eq_dicts中。我们知道,这个文件记录了158次地震。下面的输出表明,我们提取了这个文件记录的所有地震:

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_json_data.json'
with open(readable_file, 'w') as f:json.dump(all_eq_data, f, indent=4)
"""
all_eq_dicts = all_eq_data['features']
print(len(all_eq_dicts))

运行之,程序会输出158,表示这个文件中总共记录了158次地震信息。

提取震级

有了包含所有地震数据的列表后,就可遍历这个列表,从中提取所需的数据。下面来提取每次地震的震级:

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_json_data.json'
with open(readable_file, 'w') as f:json.dump(all_eq_data, f, indent=4)
"""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])

我们创建了一个空列表,用于存储地震震级,再遍历列表all_eq_dicts。每次地震的震级都存储在相应字典的’properties’部分的’mag’键下。我们依次将地震震级赋给变量mag,再将这个变量附加到列表mags末尾。

为确定提取的数据是否正确,打印前10次地震的震级:

[0.96, 1.2, 4.3, 3.6, 2.1, 4, 1.06, 2.3, 4.9, 1.8]

提取位置数据

位置数据存储在"geometry"键下。在"geometry"键关联的字典中,有一个"coordinates"键,它关联到一个列表,而列表中的前两个值为经度和纬度。下面演示了如何提取位置数据:

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_json_data.json'
with open(readable_file, 'w') as f:json.dump(all_eq_data, f, indent=4)
"""all_eq_dicts = all_eq_data['features']mags, titles, lons, lats = [], [], [], []
for eq_dict in all_eq_dicts:mag = eq_dict['properties']['mag']title = eq_dict['properties']['title']lon = eq_dict['geometry']['coordinates'][0]lat = eq_dict['geometry']['coordinates'][1]mags.append(mag)titles.append(title)lons.append(lon)lats.append(lat)print(mags[:10])
print(titles[:2])
print(lons[:5])
print(lats[:5])

我们创建了用于存储位置标题的列表titles,来提取字典’properties’里’title’键对应的值,以及用于存储经度和纬度的列表。代码eq_dict['geometry']访问与"geometry"键相关联的字典。第二个键(‘coordinates’)提取与"coordinates"相关联的列表,而索引0提取该列表中的第一个值,即地震发生位置的经度。

输出结果

[0.96, 1.2, 4.3, 3.6, 2.1, 4, 1.06, 2.3, 4.9, 1.8]
['M 1.0 - 8km NE of Aguanga, CA', 'M 1.2 - 11km NNE of North Nenana, Alaska']
[-116.7941667, -148.9865, -74.2343, -161.6801, -118.5316667]
[33.4863333, 64.6673, -12.1025, 54.2232, 35.3098333]

对应的代码是

print(mags[:10]) # 地震等级
print(titles[:2]) # 地震名称
print(lons[:5]) # 经度
print(lats[:5]) # 纬度

绘制震级散点图
首先要实现绘制一个简单的散点图。

# plotly express 是Plotly的高级接口
import plotly.express as px
import json
import pandas as pdfilename = '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']
mags, titles, lons, lats = [], [], [], []
for eq_dict in all_eq_dicts:mag = eq_dict['properties']['mag']title = eq_dict['properties']['title']lon = eq_dict['geometry']['coordinates'][0]lat = eq_dict['geometry']['coordinates'][1]mags.append(mag)titles.append(title)lons.append(lon)lats.append(lat)# 调用px.scatter函数配置参数创建一个fig实例
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 可以将可视化图保存为html文件
fig.write_html("global_earthquakes.html")
fig.show()

运行书中代码得到的图形:

这和书上显示的不太一样啊,晕,我还以为我做错了!后来才发现,根据书中的代码,这才是绘制出来的结果,因为根本没用地图。

书上的图:(坑了我!)

另一种指定图表数据的方式

使用pandas数据分析工具。创建一个DataFrame,将需要的数据封装起来:

# plotly express 是Plotly的高级接口
import plotly.express as px
import json
import pandas as pdfilename = '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']
mags, titles, lons, lats = [], [], [], []
for eq_dict in all_eq_dicts:mag = eq_dict['properties']['mag']title = eq_dict['properties']['title']lon = eq_dict['geometry']['coordinates'][0]lat = eq_dict['geometry']['coordinates'][1]mags.append(mag)titles.append(title)lons.append(lon)lats.append(lat)
# 使用DataFrame将数据封装
# 所有有关数据的信息都以键值对的方式存在字典中。
data = pd.DataFrame(data = zip(lons, lats, titles, mags), columns = ["经度","纬度","位置","震级"],
)data.head()# 调用px.scatter函数配置参数创建一个fig实例
fig = px.scatter(data,x="经度",y="纬度",labels = {"x": "经度", "y": "纬度"},range_x = [-200, 200],range_y = [-90, 90],width = 800,height = 800,title = "全球地震散点图"
)# fig.write_html 可以将可视化图保存为html文件
fig.write_html("global_earthquakes.html")
fig.show()

运行代码,我们得到的是和上面绘图同样的结果:

然后根据参考博客:《Python 编程:从入门到实践》16章 地图部分练习 提供的绘制方式:将px.scatter替换成px.density_mapbox,然后就得到下面的绘制结果:

# 调用px.scatter函数配置参数创建一个fig实例
"""
fig = px.scatter(data,x="经度",y="纬度",labels = {"x": "经度", "y": "纬度"},range_x = [-200, 200],range_y = [-90, 90],width = 800,height = 800,title = "全球地震散点图"
)"""fig = px.density_mapbox(data, lat='纬度', lon='经度', z='震级', hover_name='位置', radius=5,center=dict(lat=0, lon=180), zoom=0, mapbox_style="stamen-terrain")

代码如下:

# plotly express 是Plotly的高级接口
import plotly.express as px
import json
import pandas as pdfilename = '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']
mags, titles, lons, lats = [], [], [], []
for eq_dict in all_eq_dicts:mag = eq_dict['properties']['mag']title = eq_dict['properties']['title']lon = eq_dict['geometry']['coordinates'][0]lat = eq_dict['geometry']['coordinates'][1]mags.append(mag)titles.append(title)lons.append(lon)lats.append(lat)data = pd.DataFrame(data = zip(lons, lats, titles, mags), columns = ["经度","纬度","位置","震级"],
)data.head()# 调用px.scatter函数配置参数创建一个fig实例
"""
fig = px.scatter(data,x="经度",y="纬度",labels = {"x": "经度", "y": "纬度"},range_x = [-200, 200],range_y = [-90, 90],width = 800,height = 800,title = "全球地震散点图"
)"""fig = px.density_mapbox(data, lat='纬度', lon='经度', z='震级', hover_name='位置', radius=5,center=dict(lat=0, lon=180), zoom=0, mapbox_style="stamen-terrain")# fig.write_html 可以将可视化图保存为html文件
fig.write_html("global_earthquakes.html")
fig.show()

定制标记的颜色

定制颜色,以呈现地震的严重程度。这里换成了更大的数据集,用的是30天的。

未定制标记之前

加了颜色定制之后的运行结果

了让标记的震级按照不同的颜色显示,只需要配置color="震级"即可。默认的视觉映射图例渐变色范围是从蓝到红再到黄,数值越小则标记越蓝,而数值越大则标记越黄。

代码:

# plotly express 是Plotly的高级接口
import plotly.express as px
import json
import pandas as pdfilename = 'data/eq_data_30_day_m1.json'
with open(filename) as f:all_eq_data = json.load(f)all_eq_dicts = all_eq_data['features']
mags, titles, lons, lats = [], [], [], []
for eq_dict in all_eq_dicts:mag = eq_dict['properties']['mag']title = eq_dict['properties']['title']lon = eq_dict['geometry']['coordinates'][0]lat = eq_dict['geometry']['coordinates'][1]mags.append(mag)titles.append(title)lons.append(lon)lats.append(lat)data = pd.DataFrame(data = zip(lons, lats, titles, mags), columns = ["经度","纬度","位置","震级"],
)data.head()# 调用px.scatter函数配置参数创建一个fig实例fig = px.scatter(data,x="经度",y="纬度",labels = {"x": "经度", "y": "纬度"},range_x = [-200, 200],range_y = [-90, 90],width = 800,height = 800,title = "全球地震散点图",size_max = 10,color = '震级',
)"""fig = px.density_mapbox(data, lat='纬度', lon='经度', z='震级', hover_name='位置', radius=5,center=dict(lat=0, lon=180), zoom=0, mapbox_style="stamen-terrain")"""# fig.write_html 可以将可视化图保存为html文件
fig.write_html("global_earthquakes.html")
fig.show()

使用绘制地图的api:

# plotly express 是Plotly的高级接口
import plotly.express as px
import json
import pandas as pdfilename = 'data/eq_data_30_day_m1.json'
with open(filename) as f:all_eq_data = json.load(f)all_eq_dicts = all_eq_data['features']
mags, titles, lons, lats = [], [], [], []
for eq_dict in all_eq_dicts:mag = eq_dict['properties']['mag']title = eq_dict['properties']['title']lon = eq_dict['geometry']['coordinates'][0]lat = eq_dict['geometry']['coordinates'][1]mags.append(mag)titles.append(title)lons.append(lon)lats.append(lat)data = pd.DataFrame(data = zip(lons, lats, titles, mags), columns = ["经度","纬度","位置","震级"],
)data.head()# 调用px.scatter函数配置参数创建一个fig实例
"""
fig = px.scatter(data,x="经度",y="纬度",labels = {"x": "经度", "y": "纬度"},range_x = [-200, 200],range_y = [-90, 90],width = 800,height = 800,title = "全球地震散点图",size_max = 10,color = '震级',
)"""fig = px.density_mapbox(data, lat='纬度', lon='经度', z='震级', hover_name='位置', radius=5,center=dict(lat=0, lon=180), zoom=0, mapbox_style="stamen-terrain")# fig.write_html 可以将可视化图保存为html文件
fig.write_html("global_earthquakes.html")
fig.show()

使用density_mapbox运行结果:

关于density_mapbox的官方文档:https://plotly.com/python/mapbox-density-heatmaps/

https://plotly.com/python-api-reference/generated/plotly.express.density_mapbox

plotly.express.density_mapbox(data_frame=None, lat=None, lon=None, z=None, hover_name=None, hover_data=None, custom_data=None, animation_frame=None, animation_group=None, category_orders=None, labels=None, color_continuous_scale=None, range_color=None, color_continuous_midpoint=None, opacity=None, zoom=8, center=None, mapbox_style=None, radius=None, title=None, template=None, width=None, height=None)

end

python基础学习[python编程从入门到实践读书笔记(连载五)]:数据可视化项目第16章相关推荐

  1. python基础学习[python编程从入门到实践读书笔记(连载二)]:外星人入侵项目

    第一版游戏demo 添加计分系统:中间是最高得分,右边是本次得分. 显示余下的飞船数 主函数如下,完整程序将上传到笔者的github:https://github.com/shizhengLi/lea ...

  2. python基础学习[python编程从入门到实践读书笔记(连载一)]

    写在前面:本文来自笔者关于<python编程从入门到实践>的读书笔记与动手实践记录. 程序员之禅 文章目录 02变量和简单数据类型 03 列表简介 04 操作列表 05 if语句 06 字 ...

  3. python基础学习[python编程从入门到实践读书笔记(连载三)]:django学习笔记web项目

    文章目录 Django项目:学习笔记web网页 项目部署 参考 自己部署的网站,还是小有成就感的,毕竟踩过很多坑,实战技能也有些许进步. 网站链接:http://lishizheng.herokuap ...

  4. python基础学习[python编程从入门到实践读书笔记(连载四)]:数据可视化项目第15章

    文章目录 matplotlib初学 基础绘图用法 随机漫步 使用Plotly模拟掷骰子 matplotlib初学 基础绘图用法 import matplotlib.pyplot as pltsquar ...

  5. python基础学习[python编程从入门到实践读书笔记(连载六)]:数据可视化项目第17章

    文章目录 使用API end 项目结果: 使用plotly可视化github最受欢迎的python仓库: 修改后的可视化图表: 使用API 编写独立的程序,实现对获取的数据可视化.我们使用Web AP ...

  6. python编程从入门到实践读书笔记-《Python编程:从入门到实践》项目部分读书笔记(二)...

    鸽了一个暑假没有更新,现在趁着还没开学更一下.咕咕咕 上期作业: 请创建一个Django项目,命名为Blog,建不建立虚拟环境随便你,最后本地跑成了就行. 步骤: ①在需要创建工程的文件夹下打开cmd ...

  7. Python基础学习-Python中最常见括号()、[]、{}的区别 2015-08-13 07:54 by xuxiaoxiaoxiaolu, 1138 阅读, 0 评论, 收藏, 编辑 Pytho

    Python基础学习-Python中最常见括号().[].{}的区别 2015-08-13 07:54 by xuxiaoxiaoxiaolu, 1138 阅读, 0 评论, 收藏, 编辑 Pytho ...

  8. python编程从入门到精通读书笔记(基础知识)

    第一部分:基础知识 学习python想要做的软件  1.开机答题软件,(电脑一开机的输入密码,改为答题,初步设定为选择题,答对了才可以进入.)  2.   第二章 2.1第一个程序:  print(& ...

  9. Python基础学习——面向对象编程(第一讲:面向对象概述、面向对象三个基本特征(封装性、继承性、多态性)、类和对象(定义类、创建和使用对象、实例变量、类变量、构造方法、实例方法、类方法、静态方法))

    面向对象是Python最重要的特性,在Python中一切数据类型都是面向对象的. 1.面向对象概述 面向对象的编程思想是,按照真实世界客观事物的自然规律进行分析,客观世界中存在什么样的实体,构建软件系 ...

最新文章

  1. 耶鲁大学等机构提出的脑机接口软硬件协同设计,增加脑机的更大潜力
  2. 大学python实训总结-千锋Python实训总结 学好基础才能走的更远
  3. salt 执行命令等待_saltstack异步执行命令
  4. v-for 循环 绑定对象 和数组
  5. 8192 oracle,ORA-39095: 转储文件空间已耗尽: 无法分配 8192 字节
  6. 依赖反转原则(DIP)
  7. std::thread的常用参数传递总结
  8. Atitit 工作手册之班委会工作法 班级管理法 目录 1.1. 班级管理工作规范 1 1.2. 班长、学习委员、生活委员、纪律委员、宣传委员、文体委员组成的班委会 1 2. 班委会职责 1 2.
  9. xx.net可能会出现的小bug(Ipv6篇)
  10. xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
  11. mysql插入微信名称中的特殊字符
  12. 什么是服务器、云服务的优缺点是什么、为什么要使用云服务器?
  13. html可以简写的属性,css有哪些缩写属性?
  14. 大专计算机知识,大专计算机应用基础试题及答案
  15. 基于MATLAB/Simulink软件的单相光伏并网逆变器仿真,仿真中使用两级电路,前级BOOST升压后级光伏逆变并网
  16. 【HTML】基础,入门先学会这些知识点
  17. ueditor编辑器遇到的问题
  18. java笔试完一般多久给通知_笔试之后多久收到面试通知?
  19. 计算机网络技术(二)——数据通信
  20. 如何去使用Python分析股票数据?学到就是赚到

热门文章

  1. Big Data, Hadoop and StreamInsight™
  2. Extjs--FormPanel(2)
  3. C# HttpHelper帮助类,真正的Httprequest请求时无视编码,无视证书,无视Cookie,网页抓取...
  4. rgb565和rgb555的文件头区别_Windows可执行文件格式
  5. python选课系统_【精选】在Monash读Data Science,人人都拥有这样一份选课指南。
  6. 安卓 buttontext怎么居中_三星发布会汇总,同样是Note 20,差距怎么就那么大呢?...
  7. 3.10 程序示例--神经网络设计-机器学习笔记-斯坦福吴恩达教授
  8. 独立于三大FPGA平台采用modelsim仿真
  9. android编译全过程
  10. 时域和频域的麦克斯韦方程组