通过上一篇谈谈Python实战数据可视化之matplotlib模块(基础篇)的学习,我们初步了解了matplotlib模块的pyplot基础,本节实战将利用CSV模块获取某地的天气数据,并且使用matplotlib模块将天气数据可视化。
鉴于Python编程从入门到实战这本书的配套资源网上难找的悲伤,我深有体会。所以,在此提供链接供下载(有帮助点个赞支持下我哦(●'◡'●)):
百度云链接:https://pan.baidu.com/s/1-XE0pBS8IaDLoUBdO8hDOw 密码:n39g
CSV - 逗号分隔值文件格式,逗号分隔值(Comma-Separated Values,CSV,有时也称为字符分隔值,因为分隔字符也可以不是逗号),其文件以纯文本形式存储表格数据(数字和文本)。纯文本意味着该文件是一个字符序列,不含必须像二进制数字那样被解读的数据。CSV文件由任意数目的记录组成,记录间以某种换行符分隔;每条记录由字段组成,字段间的分隔符是其它字符或字符串,最常见的是逗号或制表符。通常,所有记录都有完全相同的字段序列。通常都是纯文本文件。
例如:
Country,Indicator,Year,Value
AFG,NGDP_R,2002,183.26
AFG,NGDP_R,2003,198.736
AFG,NGDP_R,2004,200.069
AFG,NGDP_R,2005,223.737
AFG,NGDP_R,2006,235.731
AFG,NGDP_R,2007,267.177
AFG,NGDP_R,2008,277.498
AFG,NGDP_R,2009,334.621
AFG,NGDP_R,2010,362.857
AFG,NGDP_R,2011,386.368
AFG,NGDP_R,2012,440.336
AFG,NGDP_R,2013,456.453
.......................
.......................
先将sitka_weather_07-2014.csv文件放到项目同一目录下,然后利用Python标准库提供的CSV模块可以用于分析CSV文件中的数据行(也就是上面提到的记录),让我们能快速提取感兴趣的值。案例代码如下:
import csv
# 包含一个sitka城市七月份天气信息的CSV文件,里面都是用逗号隔开
filename = 'sitka_weather_07-2014.csv'
# 打开csv文件,实例化一个csv模块的reader阅读器对象,是一个可迭代对象,所以可以使用for循环遍历该reader阅读器对象,
# 也可以调用BIF-next函数遍历下一行,需要注意的是reader里面的每行记录只能被遍历一次,其中reader有一个line_num属性返回遍历过程中对应的行号。
with open(filename) as f:
reader = csv.reader(f) # 返回的是一个csv的阅读器对象,直接打印获取不到里面的内容
print(reader) # 打印出的是<_csv.reader object at 0x000002D1B24912B8>
head_row = next(reader) # 返回第一行的记录内容组成的字符串列表
print(head_row) # 打印 ['AKDT', 'Max TemperatureF'...]
for row in reader:
# 根据阅读器对象的记录(一行算一个记录)只能遍历一次的特性,行号从2开始了哦
print(reader.line_num, row) # 打印 2 ['2014-7-1', '64', '56', '50'....]
运行结果如下:
好了,初步获取到了CSV文件的内容,但是我们有一点要注意,就是reader里面的每行记录只能被遍历一次,我们下面添加一行代码更深刻领会:
import csv
filename = 'sitka_weather_07-2014.csv'
with open(filename) as f:
reader = csv.reader(f)
print(reader)
print(list(reader)) # 值得注意的是,当先调用 print(list(reader)),发现遍历到最后了,再执行后面的代码就报错了
head_row = next(reader)
print(head_row)
for row in reader:
print(reader.line_num, row)
运行结果如下:
对上面的结果进行分析:对于list内置函数,内部实现大概可以猜到是先将reader对象里面的记录遍历再添加进一个列表中,然后返回整个列表。调用list内置函数其实已经遍历一次了,遍历指针指向了最后一个记录,并且因为reader的记录(一行算一个记录)只能被遍历一次的特性,所以后面的代码再遍历reader对象就没啥意义了。
我们前面已经知道怎么获取天气数据了,那么我们将使用pyplot模块绘制阿拉斯加锡特卡2014年7月每日最高气温折线图。代码如下(注释有助于理解代码):
# 绘制锡特卡7月份的天气数据
# 导入python支持的csv模块,用来处理csv文件,分析csv文件中的数据行,让我们提取我们感兴趣的值
import csv
# 导入matplotlib包里的pyplot模块,用于可视化获取到的每天最高温度
from matplotlib import pyplot as plt
from datetime import datetime
# 包含一个城市天气信息的CSV文件,里面都是用逗号隔开
filename = 'sitka_weather_07-2014.csv'
# 打开csv文件,实例化一个csv模块的reader阅读器对象
with open(filename) as f:
reader = csv.reader(f)
head_row = next(reader) # 返回第一行的记录内容组成的字符串列表,例如:['1','2'....]
highs = [] # 用于存储每天最高的温度
dates = [] # 用于存储日期
for row in reader: # row也是返回遍历行的记录内容组成的字符串列表
current_date = datetime.strptime(row[0], "%Y-%m-%d") # 讲时间字符串转化为指定格式的datetime对象
dates.append(current_date)
high = int(row[1]) # 由于前面已经next过一次了,根据reader只能被遍历一次的性质,这里for循环就从第二行开始遍历
highs.append(high) # 将每天的最高温度保存在highs列表中,这时候列表存储的元素都是数字而非字符串,那么我们就可以利用这个列表进行可视化处理了
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=14)
plt.show()
运行结果如下:
仔细观察上面的运行结果,X轴还是与书本图片有些出入,其实无碍,这是正确的,因为我们运行的结果也是7月初开始,只不过X轴把6月份也包括进去了。
前面我们绘制了阿拉斯加锡特卡7月份每日最高气温折线图,现在我们将获取阿拉斯加锡特卡2014年整一年的天气数据,再绘制阿拉斯加锡特卡2014年每日最高气温和最低气温折线图。我们先将sitka_weather_2014.csv文件也放到项目同一目录下。代码如下:
# 绘制锡特卡整年的天气数据,未进行错误检查
# 导入python支持的csv模块,用来处理csv文件,分析csv文件中的数据行,让我们提取我们感兴趣的值
import csv
# 导入matplotlib包里的pyplot模块,用于可视化获取到的每天最高温度
from matplotlib import pyplot as plt
from datetime import datetime
# 包含一个城市天气信息的CSV文件,里面都是用逗号隔开
filename = 'sitka_weather_2014.csv'
# 打开csv文件,实例化一个csv模块的reader阅读器对象
with open(filename) as f:
reader = csv.reader(f)
head_row = next(reader) # 返回第一行的记录内容组成的字符串列表,例如:['1','2'....]
highs = [] # 用于存储整年每一天中的最高温度
dates = [] # 用于存储日期
lows = [] # 用于存储整年每一天中的最低温度
for row in reader: # row也是返回遍历行的元素内容组成的字符串列表
current_date = datetime.strptime(row[0], "%Y-%m-%d")
dates.append(current_date)
high = int(row[1]) # 由于前面已经next过一次了,根据reader只能被遍历一次的性质,这里for循环就从第二行开始遍历
highs.append(high) # 将每天的最高温度保存在highs列表中,这时候列表存储的元素都是数字而非字符串,那么我们就可以利用这个列表进行可视化处理了
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.title("Daily high and low temperatures,- 2014", fontsize=24)
plt.xlabel('', fontsize=16)
fig.autofmt_xdate()
plt.ylabel("Temperature (F)", fontsize=16)
plt.tick_params(axis='both', which='major', labelsize=14)
plt.show()
运行结果如下:
由于有些气象站会偶尔出现故障,未能收集全应该收集的数据,所以如果我们还是采用上一个代码例子这样获取某个城市的天气数据,那么就会报错,因为这个城市的csv文件中某一天可能是缺少数据的,所以会报ValueError错误。就如下图这样缺少某天的数据:
所以,鉴于上面的问题,下一节获取死亡谷整年的天气数据将会采用异常处理机制就能预防这种情况。
前面说了可能在实际应用中可能会出现缺少数据等问题,作为一名程序开发者,必须设想到各种可能出现的问题,并且采用实用的方法解决问题。我们将会采用异常处理机制来绘制死亡谷2014年每日最高气温和最低气温折线图。代码如下:
# 导入python支持的csv模块,用来处理csv文件,分析csv文件中的数据行,让我们提取我们感兴趣的值
import csv
# 导入matplotlib包里的pyplot模块,用于可视化获取到的每天最高温度
from matplotlib import pyplot as plt
from datetime import datetime
# 包含一个城市天气信息的CSV文件
filename = 'death_valley_2014.csv'
# 打开csv文件,实例化一个csv模块的reader阅读器对象
with open(filename) as f:
reader = csv.reader(f)
head_row = next(reader) # 返回第一行的记录内容组成的字符串列表,例如:['1','2'....]
highs = [] # 用于存储每天最高的温度
dates = [] # 用于存储日期
lows = [] # 用于存储每天最低的温度
for row in reader: # row也是返回遍历行的记录内容组成的字符串列表
try:
current_date = datetime.strptime(row[0], "%Y-%m-%d")
high = int(row[1]) # 由于前面已经next过一次了,根据reader只能被遍历一次的性质,这里for循环就从第二行开始遍历
low = int(row[3])
except ValueError:
print(current_date,'missing data')
else:
dates.append(current_date)
highs.append(high) # 将每天的最高温度保存在highs列表中,这时候列表存储的元素都是数字而非字符串,那么我们就可以利用这个列表进行可视化处理了
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.title("Daily high and low temperatures,- 2014\nDeath Valley.CA", fontsize=20)
plt.xlabel('', fontsize=16)
fig.autofmt_xdate()
plt.ylabel("Temperature (F)", fontsize=16)
plt.tick_params(axis='both', which='major', labelsize=14)
plt.show()
运行结果如下(两张图):
(1)折线图
(2)终端图
通过上面两个图可以知道,2014-02-16这一天的温度数据是丢失了,所以在折线图其实没有画出2014-02-16这一天的最高和最低气温(由于太密集看不出)。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。