在本章中,你将从网上下载数据,并对这些数据进行可视化。网上的数据多得难以置信,且大多未经过仔细检查。如果能够对这些数据进行分析,你就能发现别人没有发现的规律和关联。

我们将访问并可视化以两种常见格式存储的数据:CSV 和JSON。我们将使用Python模块csv 来处理以CSV(逗号分隔的值)格式存储的天气数据,找出两个不同地区在一段时间内的最高温度和最低温度。然后,我们将使用matplotlib根据下载的数据创建一个图表,展示两个不同地区的气温变化:阿拉斯加锡特卡和加利福尼亚死亡谷。在本章的后面,我们将使用模块json 来访问以JSON格式存储的人口数据,并使用Pygal绘制一幅按国别划分的人口地图。
阅读本章后,你将能够处理各种类型和格式的数据集,并对如何创建复杂的图表有更深入的认识。要处理各种真实世界的数据集,必须能够访问并可视化各种类型和格式的在线数据。

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

2014-1-5,61,44,26,18,7,-1,56,30,9,30.34,30.27,30.15,,,,10,4,,0.00,0,,195

这是阿拉斯加锡特卡2014年1月5日的天气数据,其中包含当天的最高气温和最低气温,还有众多其他数据。CSV文件对人来说阅读起来比较麻烦,但程序可轻松地提取并处理其 中的值,这有助于加快数据分析过程。

我们将首先处理少量锡特卡的CSV格式的天气数据,这些数据可在本书的配套资源(https://www.nostarch.com/pythoncrashcourse/ )中找到。请将文件sitka_weather_07-2014.csv复制到 存储本章程序的文件夹中(下载本书的配套资源后,你就有了这个项目所需的所有文件)。
注意 这个项目使用的天气数据是从http://www.wunderground.com/history/ 下载而来的。

16.1.1分析CSV文件头
csv 模块包含在Python标准库中,可用于分析CSV文件中的数据行,让我们能够快速提取感兴趣的值。下面先来查看这个文件的第一行,其中包含一系列有关数据的描述:
highs_lows.py

import  csv
filename  =  'sitka_weather_07-2014.csv'
with  open(filename)  as  f:reader  =  csv.reader(f)header_row  =  next(reader)print(header_row)

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

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

['AKDT', 'Max TemperatureF', 'Mean TemperatureF', 'Min TemperatureF', 'Max Dew PointF', 'MeanDew PointF', 'Min DewpointF', 'Max Humidity', ' Mean Humidity', ' Min Humidity', ' Max Sea Level PressureIn', ' Mean Sea Level PressureIn', ' Min Sea Level PressureIn', ' Max VisibilityMiles', ' Mean VisibilityMiles', ' Min VisibilityMiles', ' Max Wind SpeedMPH', ' Mean Wind SpeedMPH', ' Max Gust SpeedMPH', 'PrecipitationIn', ' CloudCover', ' Events', ' WindDirDegrees']

reader处理文件中以逗号分隔的第一行数据,并将每项数据都作为一个元素存储在列表中。文件头AKDt 表示阿拉斯加时间(Alaska Daylight Time),其位置表明每行的第一个值都是日期或时间。文件头Max temperatureF 指出每行的第二个值都是当天的最高华氏温度。可通过阅读其他的文件头来确定文件包含的信息类型。
注意 文件头的格式并非总是一致的,空格和单位可能出现在奇怪的地方。这在原始数据文件中很常见,但不会带来任何问题。

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

import  csv
filename  =  'sitka_weather_07-2014.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() (见❶)来获取每个元素的索引及其值。(请注意,我们删除了代码行print(header_row) ,转而显示这个更详细的版本。)输出如下,其中指出了每个文件头的索引:

0 AKDT
1 Max TemperatureF
2 Mean TemperatureF
3 Min TemperatureF
4 Max Dew PointF
5 MeanDew PointF
6 Min DewpointF
7 Max Humidity
8  Mean Humidity
9  Min Humidity
10  Max Sea Level PressureIn
11  Mean Sea Level PressureIn
12  Min Sea Level PressureIn
13  Max VisibilityMiles
14  Mean VisibilityMiles
15  Min VisibilityMiles
16  Max Wind SpeedMPH
17  Mean Wind SpeedMPH
18  Max Gust SpeedMPH
19 PrecipitationIn
20  CloudCover
21  Events
22  WindDirDegrees

从中可知,日期和最高气温分别存储在第0列和第1列。为研究这些数据,我们将处理sitka_weather_07-2014.csv中的每行数据,并提取其中索引为0和1的值。

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

import  csv
# 从文件中获取最高气温
filename  =  'sitka_weather_07-2014.csv'
with  open(filename)  as  f:reader  =  csv.reader(f)header_row  =  next(reader)highs = []for  row  in  reader:highs.append(row[1])print(highs)

我们创建了一个名为highs 的空列表(见❶),再遍历文件中余下的各行(见❷)。阅读器对象从其停留的地方继续往下读取CSV文件,每次都自动返回当前所处位置的下一行。由于我们已经读取了文件头行,这个循环将从第二行开始——从这行开始包含的是实际数据。每次执行该循环时,我们都将索引1处(第2列)的数据附加到highs 末尾(见
❸)。
下面显示了highs 现在存储的数据:

['64', '71', '64', '59', '69', '62', '61', '55', '57', '61', '57', '59', '57', '61', '64', '61', '59', '63', '60', '57', '69', '63', '62', '59', '57', '57', '61', '59', '61', '61', '66']

我们提取了每天的最高气温,并将它们作为字符串整洁地存储在一个列表中。下面使用int() 将这些字符串转换为数字,让matplotlib能够读取它们: highs_lows.py

import  csv
# 从文件中获取最高气温
filename  =  'sitka_weather_07-2014.csv'
with  open(filename)  as  f:reader  =  csv.reader(f)header_row  =  next(reader)highs = []for row in reader:high = int(row[1])highs.append(high)print(highs)

在❶处,我们将表示气温的字符串转换成了数字,再将其附加到列表末尾。这样,最终的列表将包含以数字表示的每日最高气温:

[64,  71,  64,  59,  69,  62,  61,  55,  57,  61,  57,  59,  57,  61,  64,  61,  59,  63,  60,  57,
69,  63,  62,  59,  57,  57,  61,  59,  61,  61,  66]

下面来对这些数据进行可视化。

16.1.4绘制气温图表
为可视化这些气温数据,我们首先使用matplotlib创建一个显示每日最高气温的简单图形,如下所示:
highs_lows.py

# import  csv
# filename  =  'sitka_weather_07-2014.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)import  csv
from  matplotlib  import  pyplot  as  plt
# 从文件中获取最高气温
filename  =  'sitka_weather_07-2014.csv'
with  open(filename)  as  f:reader  =  csv.reader(f)header_row  =  next(reader)highs = []for row in reader:high = int(row[1])highs.append(high)print(highs)
# 根据数据绘制图形
fig  =  plt.figure(dpi=128,  figsize=(10,  6))
plt.plot(highs,  c='red')
# 设置图形的格式
plt.title("Daily  high  temperatures,  July  2014",  fontsize=24)
plt.xlabel('',  fontsize=16)
plt.ylabel("temperature  (F)",  fontsize=16)
plt.tick_params(axis='both',  which='major',  labelsize=16)
plt.show()

我们将最高气温列表传给plot() (见❶),并传递c=‘red’ 以便将数据点绘制为红色(红色显示最高气温,蓝色显示最低气温)。接下来,我们设置了一些其他的格式,如字体大小和标签(见❷),这些都在第15章介绍过。鉴于我们还没有添加日期,因此没有给x 轴添加标签,但plt.xlabel() 确实修改了字体大小,让默认标签更容易看清。图 16-1显示了绘制的图表:一个简单的折线图,显示了阿拉斯加锡特卡2014年7月每天的最高气温。

图16-1 阿拉斯加锡特卡2014年7月每日最高气温折线图

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

2014-7-1,64,56,50,53,51,48,96,83,58,30.19,--snip--

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

>>>  from  datetime  import  datetime
>>>  first_date  =  datetime.strptime('2014-7-1',  '%Y-%m-%d')
>>>  print(first_date) 2014-07-01  00:00:00

我们首先导入了模块datetime 中的datetime 类,然后调用方法strptime() ,并将包含所需日期的字符串作为第一个实参。第二个实参告诉Python如何设置日期的格式。在这个示例中,’%Y-’ 让Python将字符串中第一个连字符前面的部分视为四位的年份;’%m-’ 让Python将第二个连字符前面的部分视为表示月份的数字;而’%d’ 让Python将字符串的最后一部分视为月份中的一天(1~31)。
方法strptime() 可接受各种实参,并根据它们来决定如何解读日期。表16-1列出了其中一些这样的实参。表16-1 模块datetime中设置日期和时间格式的实参

实参
含义

%A
星期的名称,如Monday

%B
月份名,如January

%m
用数字表示的月份(01~12)

%d
用数字表示月份中的一天(01~31)
%Y
实参 四位的年份,如2015
含义

%y 两位的年份,如15

%H
24小时制的小时数(00~23)

%i
12小时制的小时数(01~12)

%p
am或pm

%M
分钟数(00~59)

%S
秒数(00~61)

16.1.6在图表中添加日期
知道如何处理CSV文件中的日期后,就可对气温图形进行改进了,即提取日期和最高气温,并将它们传递给plot() ,如下所示:
highs_lows.py

import  csv
from  datetime  import  datetime
from  matplotlib  import  pyplot  as  plt
# 从文件中获取日期和最高气温
filename  =  'sitka_weather_07-2014.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[0],  "%Y-%m-%d")dates.append(current_date)high  =  int(row[1])highs.append(high)# 根据数据绘制图形
fig  =  plt.figure(dpi=128,  figsize=(10,  6))
plt.plot(dates,  highs,  c='red')
# 设置图形的格式
plt.title("Daily  high  temperatures,  July  2014",  fontsize=24)
plt.xlabel('',  fontsize=16)
fig.autofmt_xdate()
plt.ylabel("temperature  (F)",  fontsize=16)
plt.tick_params(axis='both',  which='major',  labelsize=16)
plt.show()

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

图16-2 现在图表的 x 轴上有日期,含义更丰富

16.1.7涵盖更长的时间
设置好图表后,我们来添加更多的数据,以成一幅更复杂的锡特卡天气图。请将文件sitka_weather_2014.csv复制到存储本章程序的文件夹中,该文件包含Weather Underground提供的整年的锡特卡天气数据。
现在可以创建覆盖整年的天气图了:
highs_lows.py

import  csv
from  datetime  import  datetime
from  matplotlib  import  pyplot  as  plt
# 从文件中获取日期和最高气温
filename  =  'sitka_weather_2014.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[0],  "%Y-%m-%d")dates.append(current_date)high  =  int(row[1])highs.append(high)# 根据数据绘制图形
fig  =  plt.figure(dpi=128,  figsize=(10,  6))
plt.plot(dates,  highs,  c='red')
# 设置图形的格式
plt.title("Daily  high  temperatures  -  2014", fontsize=24)
#plt.title("Daily  high  temperatures,  July  2014",  fontsize=24)
plt.xlabel('',  fontsize=16)
fig.autofmt_xdate()
plt.ylabel("temperature  (F)",  fontsize=16)
plt.tick_params(axis='both',  which='major',  labelsize=16)
plt.show()

我们修改了文件名,以使用新的数据文件sitka_weather_2014.csv(见❶);我们还修改了图表的标题,以反映其内容的变化(见❷)。图16-3显示了生成的图形。

图16-3 一年的天气数据

16.1.8再绘制一个数据系列
图16-3所示的改进后的图表显示了大量意义深远的数据,但我们可以在其中再添加最低气温数据,使其更有用。为此,需要从数据文件中提取最低气温,并将它们添加到图表中,如下所示:
highs_lows.py

import  csv
from  datetime  import  datetime
from  matplotlib  import  pyplot  as  plt
# 从文件中获取日期、最高气温和最低气温
filename  =  'sitka_weather_2014.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[0],  "%Y-%m-%d")dates.append(current_date)high  =  int(row[1])highs.append(high)low = int(row[3])lows.append(low)
# 根据数据绘制图形
fig  =  plt.figure(dpi=128,  figsize=(10,  6))
plt.plot(dates,  highs,  c='red')
plt.plot(dates, lows, c='blue')
# 设置图形的格式
plt.title("Daily  high  temperatures  -  2014", fontsize=24)
#plt.title("Daily  high  temperatures,  July  2014",  fontsize=24)
plt.xlabel('',  fontsize=16)
fig.autofmt_xdate()
plt.ylabel("temperature  (F)",  fontsize=16)
plt.tick_params(axis='both',  which='major',  labelsize=16)
plt.show()


在❶处,我们添加了空列表lows ,用于存储最低气温。接下来,我们从每行的第4列(row[3] )提取每天的最低气温,并存储它们(见❷)。在❸处,我们添加了一个对plot() 的调用,以使用蓝色绘制最低气温。最后,我们修改了标题(见❹)。图16-4显示了这样绘制出来的图表。

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

highs_lows.py

import  csv
from  datetime  import  datetime
from  matplotlib  import  pyplot  as  plt
# 从文件中获取日期、最高气温和最低气温
filename  =  'sitka_weather_2014.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[0],  "%Y-%m-%d")dates.append(current_date)high  =  int(row[1])highs.append(high)low = int(row[3])lows.append(low)
# 根据数据绘制图形
fig  =  plt.figure(dpi=128,  figsize=(10,  6))
plt.plot(dates,  highs,  c='red',  alpha=0.5)
plt.plot(dates,  lows,  c='blue',  alpha=0.5)
plt.fill_between(dates,  highs,  lows,  facecolor='blue',  alpha=0.1)
plt.plot(dates,  highs,  c='red')
plt.plot(dates, lows, c='blue')
# 设置图形的格式
plt.title("Daily  high  temperatures  -  2014", fontsize=24)
#plt.title("Daily  high  temperatures,  July  2014",  fontsize=24)
plt.xlabel('',  fontsize=16)
fig.autofmt_xdate()
plt.ylabel("temperature  (F)",  fontsize=16)
plt.tick_params(axis='both',  which='major',  labelsize=16)
plt.show()

❶处的实参alpha 指定颜色的透明度。Alpha 值为0表示完全透明,1(默认设置)表示完全不透明。通过将alpha 设置为0.5,可让红色和蓝色折线的颜色看起来更浅。
在❷处,我们向fill_between() 传递了一个 x 值系列:列表dates ,还传递了两个 y 值系列:highs 和lows 。实参facecolor 指定了填充区域的颜色,我们还将alpha设置成了较小的值0.1,让填充区域将两个数据系列连接起来的同时不分散观察者的注意力。图16-5显示了最高气温和最低气温之间的区域被填充的图表。

图16-5 给两个数据集之间的区域着色
通过着色,让两个数据集之间的区域显而易见。

16.1.10错误检查
我们应该能够使用有关任何地方的天气数据来运行highs_lows.py中的代码,但有些气象站会偶尔出现故障,未能收集部分或全部其应该收集的数据。缺失数据可能会引发异常,如 果不妥善地处理,还可能导致程序崩溃。
例如,我们来看看生成加利福尼亚死亡谷的气温图时出现的情况。将文件death_valley_2014.csv复制到本章程序所在的文件夹,再修改highs_lows.py,使其生成死亡谷的气温图:
highs_lows.py

import  csv
from  datetime  import  datetime
from  matplotlib  import  pyplot  as  plt
# 从文件中获取日期、最高气温和最低气温
filename  =  'death_valley_2014.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[0],  "%Y-%m-%d")dates.append(current_date)high  =  int(row[1])highs.append(high)low = int(row[3])lows.append(low)
# 根据数据绘制图形
fig  =  plt.figure(dpi=128,  figsize=(10,  6))
plt.plot(dates,  highs,  c='red',  alpha=0.5)
plt.plot(dates,  lows,  c='blue',  alpha=0.5)
plt.fill_between(dates,  highs,  lows,  facecolor='blue',  alpha=0.1)
plt.plot(dates,  highs,  c='red')
plt.plot(dates, lows, c='blue')
# 设置图形的格式
plt.title("Daily  high  temperatures  -  2014", fontsize=24)
#plt.title("Daily  high  temperatures,  July  2014",  fontsize=24)
plt.xlabel('',  fontsize=16)
fig.autofmt_xdate()
plt.ylabel("temperature  (F)",  fontsize=16)
plt.tick_params(axis='both',  which='major',  labelsize=16)
plt.show()

运行这个程序时,出现了一个错误,如下述输出的最后一行所示:

traceback  (most  recent  call  last):
File  "highs_lows.py",  line  17,  in  <module> high  =  int(row[1])
ValueError:  invalid  literal  for  int()  with  base  10:  ''

该traceback指出,Python无法处理其中一天的最高气温,因为它无法将空字符串(’ ’ )转换为整数。只要看一下death_valley_2014.csv,就能发现其中的问题:

2014-2-16,,,,,,,,,,,,,,,,,,,0.00,,,-1

其中好像没有记录2014年2月16日的数据,表示最高温度的字符串为空。为解决这种问题,我们在从CSV文件中读取值时执行错误检查代码,对分析数据集时可能出现的异常进行 处理,如下所示:
highs_lows.py

import  csv
from  datetime  import  datetime
from  matplotlib  import  pyplot  as  plt
# 从文件中获取日期、最高气温和最低气温
#filename  =  'sitka_weather_2014.csv'
#filename  =  'sitka_weather_07-2014.csv'
filename  =  'death_valley_2014.csv'
with  open(filename)  as  f:reader  =  csv.reader(f)header_row  =  next(reader)dates, highs, lows = [], [], []for  row  in  reader:try:current_date  =  datetime.strptime(row[0],  "%Y-%m-%d")#dates.append(current_date)high  =  int(row[1])#highs.append(high)low = int(row[3])#lows.append(low)except  ValueError:print(current_date, 'missing  data')else:dates.append(current_date)highs.append(high)lows.append(low)
# 根据数据绘制图形
fig  =  plt.figure(dpi=128,  figsize=(10,  6))
plt.plot(dates,  highs,  c='red',  alpha=0.5)
plt.plot(dates,  lows,  c='blue',  alpha=0.5)
plt.fill_between(dates,  highs,  lows,  facecolor='blue',  alpha=0.1)
plt.plot(dates,  highs,  c='red')
plt.plot(dates, lows, c='blue')
# 设置图形的格式
title  =  "Daily  high  and  low  temperatures  -  2014\nDeath  Valley,  CA"
plt.title(title,  fontsize=20)
#plt.title("Daily  high  temperatures  -  2014", fontsize=24)
#plt.title("Daily  high  temperatures,  July  2014",  fontsize=24)
plt.xlabel('',  fontsize=16)
fig.autofmt_xdate()
plt.ylabel("temperature  (F)",  fontsize=16)
plt.tick_params(axis='both',  which='major',  labelsize=16)
plt.show()

对于每一行,我们都尝试从中提取日期、最高气温和最低气温(见❶)。只要缺失其中一项数据,Python就会引发ValueError 异常,而我们可这样处理:打印一条错误消息,指出缺失数据的日期(见❷)。打印错误消息后,循环将接着处理下一行。如果获取特定日期的所有数据时没有发生错误,将运行else 代码块,并将数据附加到相应列表的末尾(见❸)。鉴于我们绘图时使用的是有关另一个地方的信息,我们修改了标题,在图表中指出了这个地方(见❹)。
如果你现在运行highs_lows.py ,将发现缺失数据的日期只有一个:

2014-02-16  missing  data

图16-6显示了绘制出的图形。

图16-6 死亡谷每日高气温和最低气温

将这个图表与锡特卡的图表对比可知,总体而言,死亡谷比阿拉斯加东南部暖和,这可能符合预期,但这个沙漠中每天的温差也更大,从着色区域的高度可以明显看出这一点。
使用的很多数据集都可能缺失数据、数据格式不正确或数据本身不正确。对于这样的情形,可使用本书前半部分介绍的工具来处理。在这里,我们使用了一个try-except- else 代码块来处理数据缺失的问题。在有些情况下,需要使用continue 来跳过一些数据,或者使用remove() 或del 将已提取的数据删除。可采用任何管用的方法,只要能进行精确而有意义的可视化就好。

16.2制作世界人口地图:JSON格式
在本节中,你将下载JSON格式的人口数据,并使用json 模块来处理它们。Pygal提供了一个适合初学者使用的地图创建工具,你将使用它来对人口数据进行可视化,以探索全球人口的分布情况。

16.2.1下载世界人口数据
将文件population_data.json复制到本章程序所在的文件夹中,这个文件包含全球大部分国家1960~2010年的人口数据。Open Knowledge Foundation(http://data.okfn.org/ )提供了大量可 以免费使用的数据集,这些数据就来自其中一个数据集。

16.2.2提取相关的数据
我们来研究一下population_data.json,看看如何着手处理这个文件中的数据:
population_data.json

[
{
"Country  Name":  "Arab  World", "Country  Code":  "ARB", "Year":  "1960",
"Value":  "96388069"
},
{
"Country  Name":  "Arab  World", "Country  Code":  "ARB", "Year":  "1961",
"Value":  "98882541.4"
},
--snip--
]

这个文件实际上就是一个很长的Python列表,其中每个元素都是一个包含四个键的字典:国家名、国别码、年份以及表示人口数量的值。我们只关心每个国家2010年的人口数量, 因此我们首先编写一个打印这些信息的程序:
world_population.py

import  json
# 将数据加载到一个列表中
filename  =  'population_data.json'
with  open(filename)  as  f:pop_data  =  json.load(f)
# 打印每个国家2010年的人口数量
for  pop_dict  in  pop_data:if  pop_dict['Year']  ==  '2010':country_name  =  pop_dict['Country Name']population  =  pop_dict['Value']print(country_name  +  ":  "  +  population)

我们首先导入了模块json ,以便能够正确地加载文件中的数据,然后,我们将数据存储在pop_data 中(见❶)。函数json.load() 将数据转换为Python能够处理的格式,这里是一个列表。在❷处,我们遍历pop_data 中的每个元素。每个元素都是一个字典,包含四个键—值对,我们将每个字典依次存储在pop_dict 中。
在❸处,我们检查字典的’Year’ 键对应的值是否是2010(由于population_data.json中的值都是用引号括起的,因此我们执行的是字符串比较)。如果年份为2010,我们就将
与’Country Name’ 相关联的值存储到country_name 中,并将与’Value’ 相关联的值存储在population 中(见❹)。接下来,我们打印每个国家的名称和人口数量。
输出为一系列国家的名称和人口数量:

Arab  World:  357868000    Caribbean  small  states:  6880000
East  Asia  &  Pacific  (all  income  levels):  2201536674
--snip--  Zimbabwe:  12571000

我们捕获的数据并非都包含准确的国家名,但这开了一个好头。现在,我们需要将数据转换为Pygal能够处理的格式。

16.2.3将字符串转换为数字值
population_data.json中的每个键和值都是字符串。为处理这些人口数据,我们需要将表示人口数量的字符串转换为数字值,为此我们使用函数int() :
world_population.py

import  json
# 将数据加载到一个列表中
filename  =  'population_data.json'
with  open(filename)  as  f:pop_data  =  json.load(f)
# 打印每个国家2010年的人口数量
for  pop_dict  in  pop_data:if  pop_dict['Year']  ==  '2010':country_name  =  pop_dict['Country Name']population = int(pop_dict['Value'])print(country_name + ":  " + str(population))

在❶处,我们将每个人口数量值都存储为数字格式。打印人口数量值时,需要将其转换为字符串(见❷)。 然而,对于有些值,这种转换会导致错误,如下所示:

Arab  World:  357868000    Caribbean  small  states:  6880000
East  Asia  &  Pacific  (all  income  levels):  2201536674
--snip--
traceback  (most  recent  call  last):
File  "print_populations.py",  line  12,  in  <module> population  =  int(pop_dict['Value'])
❶   ValueError:  invalid  literal  for  int()  with  base  10:  '1127437398.85751'

原始数据的格式常常不统一,因此经常会出现错误。导致上述错误的原因是,Python不能直接将包含小数点的字符串’1127437398.85751’ 转换为整数(这个小数值可能是人口数据缺失时通过插值得到的)。为消除这种错误,我们先将字符串转换为浮点数,再将浮点数转换为整数:
world_population.py

import  json
# 将数据加载到一个列表中
filename  =  'population_data.json'
with  open(filename)  as  f:pop_data  =  json.load(f)
# 打印每个国家2010年的人口数量
for  pop_dict  in  pop_data:if  pop_dict['Year']  ==  '2010':country_name  =  pop_dict['Country Name']population = int(float(pop_dict['Value']))print(country_name + ":  " + str(population))
Arab  World:  357868000    Caribbean  small  states:  6880000
East  Asia  &  Pacific  (all  income  levels):  2201536674
--snip--  Zimbabwe:  12571000

每个字符串都成功地转换成了浮点数,再转换为整数。以数字格式存储人口数量值后,就可以使用它们来制作世界人口地图了。

16.2.4获取两个字母的国别码
制作地图前,还需要解决数据存在的最后一个问题。Pygal中的地图制作工具要求数据为特定的格式:用国别码表示国家,以及用数字表示人口数量。处理地理政治数据时,经常需要用到几个标准化国别码集。population_data.json中包含的是三个字母的国别码,但Pygal使用两个字母的国别码。我们需要想办法根据国家名获取两个字母的国别码。
Pygal使用的国别码存储在模块i18n (internationalization的缩写)中。字典COUNtRiES 包含的键和值分别为两个字母的国别码和国家名。要查看这些国别码,可从模块i18n 中导入这个字典,并打印其键和值:

Python学习:ModuleNotFoundError: No module named ‘pygal.i18n’ 的解决方法
https://www.cnblogs.com/lovesy/p/10804689.html
python工程路径下执行哦

countries.py

from pygal_maps_world.i18n import COUNTRIES
for  country_code  in  sorted(COUNTRIES.keys()):print(country_code,  COUNTRIES[country_code])

在上面的for 循环中,我们让Python将键按字母顺序排序(见❶),然后打印每个国别码及其对应的国家:

ad Andorra
ae United Arab Emirates
af Afghanistan
al Albania
am Armenia
ao Angola
aq Antarctica
ar Argentina
at Austria
au Australia
az Azerbaijan
ba Bosnia and Herzegovina
bd Bangladesh
be Belgium
bf Burkina Faso
bg Bulgaria
bh Bahrain
bi Burundi
bj Benin
bn Brunei Darussalam
bo Bolivia, Plurinational State of
br Brazil
bt Bhutan
bw Botswana
by Belarus
bz Belize
ca Canada
cd Congo, the Democratic Republic of the
cf Central African Republic
cg Congo
ch Switzerland
ci Cote d'Ivoire
cl Chile
cm Cameroon
cn China
co Colombia
cr Costa Rica
cu Cuba
cv Cape Verde
cy Cyprus
cz Czech Republic
de Germany
dj Djibouti
dk Denmark
do Dominican Republic
dz Algeria
ec Ecuador
ee Estonia
eg Egypt
eh Western Sahara
er Eritrea
es Spain
et Ethiopia
fi Finland
fr France
ga Gabon
gb United Kingdom
ge Georgia
gf French Guiana
gh Ghana
gl Greenland
gm Gambia
gn Guinea
gq Equatorial Guinea
gr Greece
gt Guatemala
gu Guam
gw Guinea-Bissau
gy Guyana
hk Hong Kong
hn Honduras
hr Croatia
ht Haiti
hu Hungary
id Indonesia
ie Ireland
il Israel
in India
iq Iraq
ir Iran, Islamic Republic of
is Iceland
it Italy
jm Jamaica
jo Jordan
jp Japan
ke Kenya
kg Kyrgyzstan
kh Cambodia
kp Korea, Democratic People's Republic of
kr Korea, Republic of
kw Kuwait
kz Kazakhstan
la Lao People's Democratic Republic
lb Lebanon
li Liechtenstein
lk Sri Lanka
lr Liberia
ls Lesotho
lt Lithuania
lu Luxembourg
lv Latvia
ly Libyan Arab Jamahiriya
ma Morocco
mc Monaco
md Moldova, Republic of
me Montenegro
mg Madagascar
mk Macedonia, the former Yugoslav Republic of
ml Mali
mm Myanmar
mn Mongolia
mo Macao
mr Mauritania
mt Malta
mu Mauritius
mv Maldives
mw Malawi
mx Mexico
my Malaysia
mz Mozambique
na Namibia
ne Niger
ng Nigeria
ni Nicaragua
nl Netherlands
no Norway
np Nepal
nz New Zealand
om Oman
pa Panama
pe Peru
pg Papua New Guinea
ph Philippines
pk Pakistan
pl Poland
pr Puerto Rico
ps Palestine, State of
pt Portugal
py Paraguay
re Reunion
ro Romania
rs Serbia
ru Russian Federation
rw Rwanda
sa Saudi Arabia
sc Seychelles
sd Sudan
se Sweden
sg Singapore
sh Saint Helena, Ascension and Tristan da Cunha
si Slovenia
sk Slovakia
sl Sierra Leone
sm San Marino
sn Senegal
so Somalia
sr Suriname
st Sao Tome and Principe
sv El Salvador
sy Syrian Arab Republic
sz Swaziland
td Chad
tg Togo
th Thailand
tj Tajikistan
tl Timor-Leste
tm Turkmenistan
tn Tunisia
tr Turkey
tw Taiwan, Province of China
tz Tanzania, United Republic of
ua Ukraine
ug Uganda
us United States
uy Uruguay
uz Uzbekistan
va Holy See (Vatican City State)
ve Venezuela, Bolivarian Republic of
vn Viet Nam
ye Yemen
yt Mayotte
za South Africa
zm Zambia
zw Zimbabwe

为获取国别码,我们将编写一个函数,它在COUNtRiES 中查找并返回国别码。我们将这个函数放在一个名为country_codes 的模块中,以便能够在可视化程序中导入它:
country_codes.py

from  pygal_maps_world.i18n  import  COUNTRIES
def  get_country_code(country_name):"""根据指定的国家,返回Pygal使用的两个字母的国别码"""for  code,name  in  COUNTRIES.items():if name == country_name:return code# 如果没有找到指定的国家,就返回Nonereturn None
print(get_country_code('Andorra'))
print(get_country_code('United Arab Emirates'))
print(get_country_code('Afghanistan'))

get_country_code() 接受国家名,并将其存储在形参country_name 中(见❶)。接下来,我们遍历COUNtRiES 中的国家名—国别码对(见❷);如果找到指定的国家名,就返回相应的国别码(见❸)。在循环后面,我们在没有找到指定的国家名时返回None (见❹)。最后,我们使用了三个国家名来调用这个函数,以核实它能否正确地工作。与预期的一样,这个程序输出了三个由两个字母组成的国别码:

ad
ae
af

使用这个函数前,先将country_codes.py中的print 语句删除。接下来,在world_population.py中导入get_country_code : world_population.py

import  json
from  country_codes  import  get_country_code
# 将数据加载到一个列表中
filename  =  'population_data.json'
with  open(filename)  as  f:pop_data  =  json.load(f)
# 打印每个国家2010年的人口数量
for  pop_dict  in  pop_data:if  pop_dict['Year']  ==  '2010':country_name  =  pop_dict['Country Name']population = int(float(pop_dict['Value']))code = get_country_code(country_name)if code:print(code + ":  " + str(population))else:print('ERROR  -  ' + country_name)

提取国家名和人口数量后,我们将国别码存储在code 中,如果没有国别码,就在其中存储None (见❶)。如果返回了国别码,就打印国别码和相应国家的人口数量(见❷)。如果没有找到国别码,就显示一条错误消息,其中包含无法找到国别码的国家的名称(见❸)。如果你运行这个程序,将看到一些国别码和相应国家的人口数量,还有一些错误消息:

ERROR  -  Arab  World
ERROR  -  Caribbean  small  states
ERROR  -  East  Asia  &  Pacific  (all  income  levels)
--snip--  af: 34385000
al: 3205000
dz:  35468000
--snip--
ERROR  -  Yemen,  Rep. zm:  12927000
zw:  12571000

导致显示错误消息的原因有两个。首先,并非所有人口数量对应的都是国家,有些人口数量对应的是地区(阿拉伯世界)和经济类群(所有收入水平)。其次,有些统计数据使用了不同的完整国家名(如Yemen, Rep.,而不是Yemen)。当前,我们将忽略导致错误的数据,看看根据成功恢复了的数据制作出的地图是什么样的。

16.2.5制作世界地图
有了国别码后,制作世界地图易如反掌。Pygal提供了图表类型Worldmap ,可帮助你制作呈现各国数据的世界地图。为演示如何使用Worldmap ,我们来创建一个突出北美、中美和南美的简单地图:
americas.py

import  pygal
import pygal_maps_world.maps
wm = pygal_maps_world.maps.World()
wm.title  =  'North,  Central,  and  South  America'
wm.add('North  America',  ['ca',  'mx',  'us'])
wm.add('Central  America',  ['bz',  'cr',  'gt',  'hn',  'ni',  'pa',  'sv'])
wm.add('South  America',  ['ar',  'bo',  'br',  'cl',  'co',  'ec',  'gf',
'gy',  'pe',  'py',  'sr',  'uy',  've'])
wm.render_to_file('americas.svg')

在❶处,我们创建了一个Worldmap 实例,并设置了该地图的的title 属性。在❷处,我们使用了方法add() ,它接受一个标签和一个列表,其中后者包含我们要突出的国家的国别码。每次调用add() 都将为指定的国家选择一种新颜色,并在图表左边显示该颜色和指定的标签。我们要以同一种颜色显示整个北美地区,因此第一次调用add() 时, 在传递给它的列表中包含’ca’ 、‘mx’ 和’us’ ,以同时突出加拿大、墨西哥和美国。接下来,对中美和南美国家做同样的处理。
❸处的方法render_to_file() 创建一个包含该图表的.svg文件,你可以在浏览器中打开它。输出是一幅以不同颜色突出北美、中美和南美的地图,如图16-7所示。

图16-7 图表类型Worldmap 的一个简单实例

知道如何创建包含彩色区域、颜色标示和标签的地图后,我们在地图中添加数据,以显示有关国家的信息。

16.2.6在世界地图上呈现数字数据
为练习在地图上呈现数字数据,我们来创建一幅地图,显示三个北美国家的人口数量:
na_populations.py

import pygal_maps_world.maps
wm = pygal_maps_world.maps.World()
wm.title  =  'Populations  of  Countries  in  North  America'
wm.add('North  America',  {'ca':  34126000,  'us':  309349000,  'mx':  113423000})
wm.render_to_file('na_populations.svg')

首先,创建了一个Worldmap 实例并设置了标题。接下来,使用了方法add() ,但这次通过第二个实参传递了一个字典而不是列表(见❶)。这个字典将两个字母的Pygal国别码作为键,将人口数量作为值。Pygal根据这些数字自动给不同国家着以深浅不一的颜色(人口最少的国家颜色最浅,人口最多的国家颜色最深),如图16-8所示。

图16-8 北美国家的人口数量

这幅地图具有交互性:如果你将鼠标指向某个国家,将看到其人口数量。下面在这个地图中添加更多的数据。

16.2.7绘制完整的世界人口地图
要呈现其他国家的人口数量,需要将前面处理的数据转换为Pygal要求的字典格式:键为两个字母的国别码,值为人口数量。为此,在world_population.py中添加如下代码:
world_population.py

import  json
import pygal_maps_world.maps
from  country_codes  import  get_country_code
# 将数据加载到一个列表中
filename  =  'population_data.json'
with  open(filename)  as  f:pop_data  =  json.load(f)# # 打印每个国家2010年的人口数量
# for  pop_dict  in  pop_data:
#     if  pop_dict['Year']  ==  '2010':
#         country_name  =  pop_dict['Country Name']
#         population = int(float(pop_dict['Value']))
#         code = get_country_code(country_name)
#         if code:
#             print(code + ":  " + str(population))
#         else:
#             print('ERROR  -  ' + country_name)
# 创建一个包含人口数量的字典
cc_populations  =  {}
for  pop_dict  in  pop_data:if  pop_dict['Year']  ==  '2010':country  =  pop_dict['Country Name']population  =  int(float(pop_dict['Value']))code = get_country_code(country)if  code:cc_populations[code]  =  population
wm = pygal_maps_world.maps.World()
wm.title  =  'World  Population  in  2010,  by  Country'
wm.add('2010',  cc_populations)
wm.render_to_file('world_population.svg')

我们首先导入了pygal 。在❶处,我们创建了一个空字典,用于以Pygal要求的格式存储国别码和人口数量。在❷处,如果返回了国别码,就将国别码和人口数量分别作为键和值填充字典cc_populations 。我们还删除了所有的print 语句。
在❸处,我们创建了一个Worldmap 实例,并设置其title 属性。在❹处,我们调用了add() ,并向它传递由国别码和人口数量组成的字典。图16-9显示了生成的地图。

图16-9 2010年的世界人口数量

有几个国家没有相关的数据,我们将其显示为黑色,但对于大多数国家,都根据其人口数量进行了着色。本章后面将处理数据缺失的问题,这里先来修改着色,以更准确地反映各国的人口数量。在当前的地图中,很多国家都是浅色的,只有两个国家是深色的。对大多数国家而言,颜色深浅的差别不足以反映其人口数量的差别。为修复这种问题,我们将根据人口数量将国家分组,再分别给每个组着色。
16.2.8根据人口数量将国家分组
印度和中国的人口比其他国家多得多,但在当前的地图中,它们的颜色与其他国家差别较小。中国和印度的人口都超过了10亿,接下来人口最多的国家是美国,但只有大约3亿。下面不将所有国家都作为一个编组,而是根据人口数量分成三组——少于1000万的、介于1000万和10亿之间的以及超过10亿的:
world_population.py

import  json
import pygal_maps_world.maps
from  country_codes  import  get_country_code
# 将数据加载到一个列表中
filename  =  'population_data.json'
with  open(filename)  as  f:pop_data  =  json.load(f)# # 打印每个国家2010年的人口数量
# for  pop_dict  in  pop_data:
#     if  pop_dict['Year']  ==  '2010':
#         country_name  =  pop_dict['Country Name']
#         population = int(float(pop_dict['Value']))
#         code = get_country_code(country_name)
#         if code:
#             print(code + ":  " + str(population))
#         else:
#             print('ERROR  -  ' + country_name)
# 创建一个包含人口数量的字典
cc_populations  =  {}
for  pop_dict  in  pop_data:if  pop_dict['Year']  ==  '2010':country  =  pop_dict['Country Name']population  =  int(float(pop_dict['Value']))code = get_country_code(country)if  code:cc_populations[code]  =  population
# 根据人口数量将所有的国家分成三组
cc_pops_1,  cc_pops_2,  cc_pops_3  =  {},  {},  {}
for  cc,  pop  in  cc_populations.items():if  pop  <  10000000:cc_pops_1[cc] = popelif  pop  <  1000000000:cc_pops_2[cc] = popelse:cc_pops_3[cc] = pop
print(len(cc_pops_1),  len(cc_pops_2),  len(cc_pops_3))
wm = pygal_maps_world.maps.World()
wm.title  =  'World  Population  in  2010,  by  Country'
wm.add('0-10m', cc_pops_1)
wm.add('10m-1bn', cc_pops_2)
wm.add('>1bn', cc_pops_3)
wm.render_to_file('world_population.svg')

为将国家分组,我们创建了三个空字典(见❶)。接下来,遍历cc_populations ,检查每个国家的人口数量(见❷)。if-elif-else 代码块将每个国别码-人口数量对加入到合适的字典(cc_pops_1 、cc_pops_2 或cc_pops_3 )中。

在❸处,我们打印这些字典的长度,以获悉每个分组的规模。绘制地图时,我们将全部三个分组都添加到Worldmap 中(见❹)。如果你现在运行这个程序,首先看到的将是每个分组的规模:

85 69 2

上述输出表明,人口少于1000万的国家有85个,人口介于1000万和10亿之间的国家有69个,还有两个国家比较特殊,其人口都超过了10亿。这样的分组看起来足够了,让地图包 含丰富的信息。图16-10显示了生成的地图。

图16-10 分三组显示的世界各国人口

现在使用了三种不同的颜色,让我们能够看出人口数量上的差别。在每组中,各个国家都按人口从少到多着以从浅到深的颜色。

16.2.9使用Pygal设置世界地图的样式
在这个地图中,根据人口将国家分组虽然很有效,但默认的颜色设置很难看。例如,在这里,Pygal选择了鲜艳的粉色和绿色基色。下面使用Pygal样式设置指令来调整颜色。 我们也让Pygal使用一种基色,但将指定该基色,并让三个分组的颜色差别更大:
world_population.py

import json
import pygal
from country_codes import get_country_codefilename = 'population_data.json'
with open(filename) as f:# 函数json.load()将数据(文件对象)转换为Python能处理的格式,pop_data = json.load(f)  # pop_data是一个列表,每个元素都包含一个四个键的字典cc_populations = {}
for pop_dict in pop_data:if pop_dict['Year'] == '2010':country_name = pop_dict['Country Name']population = int(float(pop_dict['Value']))code = get_country_code(country_name)if code:cc_populations[code] = population# 根据人口数量将所有的国家分成三组
cc_pops_1, cc_pops_2, cc_pops_3 = {}, {}, {}
for cc, pop in cc_populations.items():if pop < 10000000:cc_pops_1[cc] = popelif pop < 1000000000:cc_pops_2[cc] = popelse:cc_pops_3[cc] = popwm = pygal.maps.world.World()  # 创建一个实例
wm.title = 'World Population in 2010,by Country'
wm.add('0-10m', cc_pops_1)
wm.add('10m-1bn', cc_pops_2)
wm.add('>1bn', cc_pops_3)wm.render_to_file('world_population.svg')

Pygal样式存储在模块style 中,我们从这个模块中导入了样式RotateStyle (见❶)。创建这个类的实例时,需要提供一个实参——十六进制的RGB颜色(见❷);Pygal将根据指定的颜色为每组选择颜色。十六进制格式 的RGB颜色是一个以井号(#)打头的字符串,后面跟着6个字符,其中前两个字符表示红色分量,接下来的两个表示绿色分量,最 后两个表示蓝色分量。每个分量的取值范围为00 (没有相应的颜色)~FF (包含最多的相应颜色)。如果你在线搜索hex color chooser(十六进制颜色选择器 ),可找到让你能够尝试选择不同的颜色并显示其RGB值的工具。这里使用的颜色值(#336699)混合了少量的红色(33)、多一些的绿色(66)和更多一些的蓝色(99),它为RotateStyle 提供了一种淡蓝色基色。

RotateStyle 返回一个样式对象,我们将其存储在wm_style 中。为使用这个样式对象,我们在创建Worldmap 实例时以关键字实参的方式传递它(见❸)。更新后的地图如图16-11所示。

85 69 2


图16-11 按人口划分的三个国家编组了统一的颜色主题

前面的样式设置让地图的颜色更一致,也更容易区分不同的编组。

16.2.10加亮颜色主题
Pygal通常默认使用较暗的颜色主题。为方便印刷,我使用LightColorizedStyle 加亮了地图的颜色。这个类修改整个图表的主题,包括背景色、标签以及各个国家的颜色。要使用这个样式,先导入它:

from  pygal.style  import  LightColorizedStyle

然后就可独立地使用LightColorizedStyle 了,例如:

wm_style  =  LightColorizedStyle

然而使用这个类时,你不能直接控制使用的颜色,Pygal将选择默认的基色。要设置颜色,可使用RotateStyle ,并将LightColorizedStyle 作为基本样式。为此,导入LightColorizedStyle 和RotateStyle :

from  pygal.style  import  LightColorizedStyle,  RotateStyle

再使用RotateStyle 创建一种样式,并传入另一个实参base_style :

wm_style  =  RotateStyle('#336699',  base_style=LightColorizedStyle)

这设置了较亮的主题,同时根据通过实参传递的颜色给各个国家着色。使用这种样式时,生成的图表与本书的屏幕截图更一致。尝试为不同的可视化选择合适的样式设置指令时,在import 语句中指定别名会有所帮助:

from  pygal.style  import  LightColorizedStyle  as  LCS,  RotateStyle  as  RS

这样,样式定义将更短:

wm_style  =  RS('#336699',  base_style=LCS)

通过使用几个样式设置指令,就能很好地控制图表和地图的外观。

import json
import pygal
from country_codes import get_country_code
from pygal.style import LightColorizedStyle as LCS,RotateStyle as RS  # 导入RotateStyle和 LightColorizedStyle,并取了别名,后面调用就采用别名,方便多了filename = 'population_data.json'
with open(filename) as f:# 函数json.load()将数据(文件对象)转换为Python能处理的格式,pop_data = json.load(f)  # pop_data是一个列表,每个元素都包含一个四个键的字典cc_populations = {}
for pop_dict in pop_data:if pop_dict['Year'] == '2010':country_name = pop_dict['Country Name']population = int(float(pop_dict['Value']))code = get_country_code(country_name)if code:cc_populations[code] = population# 根据人口数量将所有的国家分成三组
cc_pops_1, cc_pops_2, cc_pops_3 = {}, {}, {}
for cc, pop in cc_populations.items():if pop < 10000000:cc_pops_1[cc] = popelif pop < 1000000000:cc_pops_2[cc] = popelse:cc_pops_3[cc] = popwm_style = RS('#336699',base_style=LCS)  # 一个样式对象,参数指定一个十六进制的RGB颜色
wm = pygal.maps.world.World(style=wm_style)  # 创建一个实例,并传入一个指定了颜色的样式对象wm_style
wm.title = 'World Population in 2010,by Country'
wm.add('0-10m', cc_pops_1)
wm.add('10m-1bn', cc_pops_2)
wm.add('>1bn', cc_pops_3)wm.render_to_file('world_population.svg')

16.3小结
在本章中,你学习了:如何使用网上的数据集;如何处理CSV和JSON文件,以及如何提取你感兴趣的数据;如何使用matplotlib来处理以往的天气数据,包括如何使用模块datetime ,以及如何在同一个图表中绘制多个数据系列;如何使用Pygal绘制呈现各国数据的世界地图,以及如何设置Pygal地图和图表的样式。
有了使用CSV和JSON文件的经验后,你将能够处理几乎任何要分析的数据。大多数在线数据集都可以以这两种格式中的一种或两种下载。学习使用这两种格式为学习使用其他格 式的数据做好了准备。

在下一章,你将编写自动从网上采集数据并对其进行可视化的程序。如果你只是将编程作为业余爱好,学会这些技能可以增加乐趣;如果你有志于成为专业程序员,就必须掌握这些技能。

第 16 章 下载数据相关推荐

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

    文章目录 下载数据 制作全球地震散点图:JSON格式 end 几个实验结果: 每日最高气温: 地震图绘制: 下载数据 CSV文件格式 在文本文件中存储数据,一个简单方式是将数据作为一系列以逗号分隔的值 ...

  2. 16 使用Python下载数据

    在本章中,你将从网上下载数据,并对这些数据进行可视化.网上的数据多得难以置信,且大多未经过仔细检查.如果能够对这些数据进行分析,你就能发现别人没有发现的规律和关联. 我们将访问并可视化以两种常见格式存 ...

  3. 《Python编程:从入门到实践》第十六章:下载数据

    下载数据 我们将访问并可视化以两种常见格式存储的数据:CSV和JSON.我们将使用Python模块csv来处理以CSV(逗号分隔的值)格式存储的天气数据,找出两个不同地区在一段时间内的最高温度和最低温 ...

  4. python编程从入门到实战16章x轴刻度_PYTHON编程:从入门到实践之数据可视化

    数据可视化是指的通过可视化来表示探索数据,与数据挖掘紧密相关,数据挖掘是指的使用代码来探索数据集的规律和关联.可视化的目的是为了简洁的展示给观看者数据的规律和意义. 本文中使用的可视化模块为matpl ...

  5. 云计算与大数据第16章 分布式内存计算平台Spark习题

    第16章 分布式内存计算平台Spark习题 16.1 选择题 1.Spark是Hadoop生态(  B  )组件的替代方案. A. Hadoop     B. MapReduce        C. ...

  6. python--从入门到实践--chapter 15 16 17 生成数据/下载数据/web API

    1.随机漫步 random_walk.py from random import choice class RandomWalk():def __init__(self, num_points=500 ...

  7. 复现经典:《统计学习方法》​第16章 主成分分析

    第16章 主成分分析 本文是李航老师的<统计学习方法>一书的代码复现.作者:黄海广 备注:代码都可以在github中下载.我将陆续将代码发布在公众号"机器学习初学者", ...

  8. 《asp.net夜话》一书视频ASP.NET夜话视频1-17章下载(ASP.NET夜话2009年5月9日更新)

    asp.net夜话教学视频说明 本 系列视频是笔者著作<asp.net夜话>的配套视频教程.<asp.net夜话>是根据在csdn论坛里经常问到的问题结合本人多年的网站开发经验 ...

  9. 第五章 存储数据 web scraping with python

    第五章.存储数据 尽管在终端打印是有很多乐趣的,但是当谈到数据汇总和分析时候这不是非常有用的.为了使大部分的爬虫有用,你需要能够保存它们抓取的信息. 在本章中,我们将着眼于的三个数据管理的方法满足任何 ...

  10. 《asp.net夜话》一书视频ASP.NET夜话视频1-14章下载(ASP.NET夜话2009年5月8日更新)

    <asp.net夜话>一书视频1-12章下载(2009年4月13日更新) asp.net夜话教学视频说明 本系列视频是笔者著作<asp.net夜话>的配套视频教程.<as ...

最新文章

  1. python中str和int区别_Python中的string方法和str方法有什么区别?
  2. 使用 Azure Container Registry 储存镜像
  3. android 生成二维码_Java 生成二维码实战
  4. Spring MVC处理用户请求的完整流程
  5. beeline-导出csv
  6. FusionCharts图表右键菜单的各种典型示例
  7. 如何将Safari中保存的密码导入Chrome ?
  8. 制作ecc证书(linux命令行)
  9. Linux修改默认静态IP
  10. vue 在线答题功能
  11. Deepin 手动安装显卡驱动
  12. 西安适合计算机专业的研究所,计算机类专业比较厉害的6所大学,适合于中等偏上的学生报考...
  13. 有服务器还需要网站空间吗,有服务器还需要空间吗
  14. 2022年秋,工程伦理期末考试答案(仅供参考)
  15. c语言中查重,体验CCleaner查重功能,快速找出电脑中的重复文件
  16. 使用OpenSSL生成自己服务器的证书
  17. 反编译微信小程序,win电脑解析获取微信小程序源码
  18. 穿越洪荒之鸿蒙紫气系统,洪荒:吾乃鸿蒙至尊
  19. [Java学习之路篇] 设计原则与设计模式
  20. 学习笔记(1):EXCEL VBA编程进阶-2.6 工作表与工作簿结合应用(拆分工作表到工作簿)...

热门文章

  1. 外贸工具WhatsApp
  2. 职场菜鸟捕食指北【相亲篇】
  3. 从战略到执行:业务领先模型 BLM 战略篇「市场洞察」
  4. 关于JFrame添加背景图片,setbounds的小知识
  5. Region Proposal by Guided Anchoring 阅读笔记
  6. oracle peoplesoft enterprise,Solix实现与Oracle PeopleSoft Enterprise9.1整合
  7. 【综述】(MIT博士)林达华老师-概率模型与计算机视觉”
  8. 贼好玩!我用Python写了一个AI玩星际争霸2!
  9. 嵌入式系统 ---> 程序存储器和数据存储器
  10. 听说你有10年的工作经验?还是你把1个经验反复用了10年?(文末赠书)