在今天晚上的学习中,我将继续完善昨晚所做的天气图。
设置好图表后,我们来添加更多的数据,以成一幅更复杂的天气图:
现在可以创建覆盖整年的天气图了:
# -*- coding:utf-8 -*- import csv from matplotlib import pyplot as plt from datetime import datetime # 从文件中获取日期和最高气温 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) print(highs) # 根据数据绘制图形 fig = plt.figure(dpi=127, figsize=(10, 6)) plt.plot(dates,highs, c='red') # 设置图形的格式 plt.title('Daily high temperature - 2014', fontsize=23) plt.xlabel('', fontsize=17) fig.autofmt_xdate() plt.ylabel('Temperature(F)', fontsize=17) plt.tick_params(axis='both', which='major', labelsize=17) plt.show()我们修改了文件名,以使用新的数据文件sitka_weather_2014.csv(见第9行);我们还修改了图表的标题,以反映其内容的变化(见第30行)。下图显示了生成的图形:
上图所示的改进后的图表显示了大量意义深远的数据,但我们可以在其中再添加最低气温数据,使其更有用。为此,需要从数据文件中提取最低气温,并将它们添加到图表中,如下所示:
# -*- coding:utf-8 -*- import csv from matplotlib import pyplot as plt from datetime import datetime # 从文件中获取日期和最高气温 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) print(highs) print(lows) # 根据数据绘制图形 fig = plt.figure(dpi=127, figsize=(10, 6)) plt.plot(dates,highs, c='red') plt.plot(dates,lows, c='blue') # 设置图形的格式 plt.title('Daily high and low temperature - 2014', fontsize=23) plt.xlabel('', fontsize=17) fig.autofmt_xdate() plt.ylabel('Temperature(F)', fontsize=17) plt.tick_params(axis='both', which='major', labelsize=17) plt.show()在第14行处,我们添加了空列表lows ,用于存储最低气温。接下来,我们从每行的第4列(row[3] )提取每天的最低气温,并存储它们(见23-24行)。在第32行处,我们添加了一个对plot() 的调用,以使用蓝色绘制最低气温。最后,我们修改了标题(见第35行)。下图显示了这样绘制出来的图表:
添加两个数据系列后,我们就可以了解每天的气温范围了。下面来给这个图表做最后的修饰,通过着色来呈现每天的气温范围。为此,我们将使用方法fill_between() ,它接受一个 x 值系列和两个 y 值系列,并填充两个 y 值系列之间的空间:
# -*- coding:utf-8 -*- import csv from matplotlib import pyplot as plt from datetime import datetime # 从文件中获取日期和最高气温 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) print(highs) print(lows) # 根据数据绘制图形 fig = plt.figure(dpi=127, 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='green', alpha=0.2) # 设置图形的格式 plt.title('Daily high and low temperature - 2014', fontsize=23) plt.xlabel('', fontsize=17) fig.autofmt_xdate() plt.ylabel('Temperature(F)', fontsize=17) plt.tick_params(axis='both', which='major', labelsize=17) plt.show()31-32行处的实参alpha 指定颜色的透明度。Alpha 值为0表示完全透明,1(默认设置)表示完全不透明。通过将alpha 设置为0.5,可让红色和蓝色折线的颜色看起来更浅。 在第33行处,我们向fill_between() 传递了一个 x 值系列:列表dates ,还传递了两个 y 值系列:highs 和lows 。实参facecolor 指定了填充区域的颜色,我还将alpha 设置成了较小的值0.2,让填充区域将两个数据系列连接起来的同时不分散观察者的注意力。下图显示了最高气温和最低气温之间的区域被填充的图表,通过着色,让两个数据集之间的区域显而易见:
我们应该能够使用有关任何地方的天气数据来运行highs_lows.py中的代码,但有些气象站会偶尔出现故障,未能收集部分或全部其应该收集的数据。缺失数据可能会引发异常,如果不妥善地处理,可能导致程序崩溃。例如,我们来看看下面这个例子出现的情况:
# -*- coding:utf-8 -*- import csv from matplotlib import pyplot as plt from datetime import datetime # 从文件中获取日期和最高气温 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) print(highs) print(lows) # 根据数据绘制图形 fig = plt.figure(dpi=127, 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='green', alpha=0.2) # 设置图形的格式 plt.title('Daily high and low temperature - 2014', fontsize=23) plt.xlabel('', fontsize=17) fig.autofmt_xdate() plt.ylabel('Temperature(F)', fontsize=17) plt.tick_params(axis='both', which='major', labelsize=17) plt.show()运行这个程序时,出现了一个错误,如上述输出的最后一行所示:该traceback指出,Python无法处理其中一天的最高气温,因为它无法将空字符串(' ' )转换为整数。只要看一下death_valley_2014.csv,就能发现其中的问题:
其中好像没有记录2014年2月16日的数据,表示最高温度的字符串为空。为解决这种问题,我们在从CSV文件中读取值时执行错误检查代码,对分析数据集时可能出现的异常进行处理,如下所示:
# -*- coding:utf-8 -*- import csv from matplotlib import pyplot as plt from datetime import datetime # 从文件中获取日期和最高气温 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") low = int(row[3]) high = int(row[1]) except ValueError: print(current_date, 'missing data') else: dates.append(current_date) highs.append(high) lows.append(low) # 根据数据绘制图形 fig = plt.figure(dpi=127, 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='green', alpha=0.2) # 设置图形的格式 plt.title('Daily high and low temperature - 2014', fontsize=23) plt.xlabel('', fontsize=17) fig.autofmt_xdate() plt.ylabel('Temperature(F)', fontsize=17) plt.tick_params(axis='both', which='major', labelsize=17) plt.show()对于每一行,我们都尝试从中提取日期、最高气温和最低气温(见第17行)。只要缺失其中一项数据,Python就会引发ValueError 异常,而我们可这样处理:打印一条错误消息, 指出缺失数据的日期(见22-23行)。打印错误消息后,循环将接着处理下一行。如果获取特定日期的所有数据时没有发生错误,将运行else 代码块,并将数据附加到相应列表的末尾(见第25-28行)。如果现在运行highs_lows.py ,如上图所示,将发现缺失数据的日期只有一个。
使用的很多数据集都可能缺失数据、数据格式不正确或数据本身不正确。在这里,我们使用了一个try-except- else 代码块来处理数据缺失的问题。在有些情况下,需要使用continue 来跳过一些数据,或者使用remove() 或del 将已提取的数据删除。