zoukankan      html  css  js  c++  java
  • 第 16 章 下载数据

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

        我们将访问并可视化以两种常见格式存储的数据:CSV和JSON.我们将使用Python模块csv来处理CSV格式存储的天气数据,找出两个不同地区在一段时间内的最高温度和最低温度。然后,我们将使用matplotlib根据下载的数据创建一个图表,展示两个不同地区的气温变化:阿拉斯加和加利福尼亚死亡谷。在本章的后面,我们将使用模块json来访问以JSON格式存储的人口数据,并使用Pygal绘制一副按国别划分的人口地图。

        阅读本章后,我们将能够处理各种类型和格式的数据集,并对如何创建复杂的图表有更深入的认识。要处理各种真实世界的数据集,必须能够访问并可视化各种类型和格式的在线数据。

    16.1 CSV文件格式

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

        2014-1-5,64,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格式的天气数据。

    16.1.1  分析CSV文件头

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

      highs_lows.py

      import csv

      filename = 'sitka_weather_07-2014.csv'

      with open(filename) as f:                                     --(1)

        reader = csv.reader(f)                                    --(2)

        header_row = next(reader)                                 --(3)

        print(header_row)

        导入模块csv后,我们将要使用的文件的名称存储在filename中。接下来,我们打开这个文件,并将结果文件对象存储在f中.然后,我们调用csv.reader()

    ,并将前面存储的文件对象作为实参传递给它,从而创建一个于该文件相关联的阅读器(reader)对象。我们将这个阅读器对象存储在reader中。

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

        reader处理文件中以逗号分隔的第一行数据,并将每项数据都作为一个元素存储在列表中。文件头AKDT表示阿拉斯加时间.

    注意:文件头的格式并非总是一致的,空格和单位可能出现在奇怪的地方。这在原始数据文件中很常见,但不会带来任何问题。

    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):          --(1)

          print(index,column_header)

      我们对列表调用了enumerate()来获取每个元素的索引及其值。

      输出如下,其中指出了每个文件头的索引:

      从中可知,日期和最高气温分别存储在第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处的数据附加到highs末尾。

        我们提取了每天的最高气温,并将它们作为字符串整洁地存储在一个列表中。

        下面使用int将表示气温的字符串转换成了数字,再将其附加到列表末尾。这样,最终的列表将包含以数字表示的每日最高气温:

        下面来进行可视化。

    16.1.4  绘制气温图表

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

      highs_lows.py

      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:

          highs.append(row[1])

      #根据数据绘制图形

      fig = plt.figure(dpi=128,figsize=(10,6))

      plt.plot(highs,c='red')

      #设置图形格式

      plt.title("Daliy high temperatures,July 2014",fontsize=24)

      plt.x_laber("",fontsize=16)

      plt.y_laber("Temperature(F)",fontsize=16)

      plt.tick_params(axis='both',which='major',labersize=16)

        plt.show()

        我们将最高气温列表传递给plot(),并传递c="red"以便将数据点绘制为红色(红色显示最高气温,蓝色显示最低气温)。接下来,我们设置了一些其他格式,如字体大小和标签。鉴于我们还没有添加日期,因此没有给x轴添加标签,但plt.xlaber()确实修改了字体大小,让默认标签更容易看清。

    16.1.5  模块datentime

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

        读取该数据时,获得的时一个字符串,因为我们需要想办法将字符串'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()可接受各种实参,并根据它们来决定如何读取reified。

    实参 含义
    %A 星期的名称,如Monday
    %B 月份名,如January
    %m 用数字表示月份(01~12)
    %d 用数字表示月份中的一天(01~31)
    %Y 四位的年份,如2017
    %y 两位的年份,如17
    %H 24小时制的小时数(00-23)
    %I 12小时制的小时数(01~12)
    %p am或pm
    %M 分钟数(00~59)
    %s 秒数(00~61)

    16.1.6   在图表中添加日期

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

    import csv
    from datetime import datetime
    from matplotlib import pyplot as plt
    '''导入模块csv以打开CSV格式的文件'''

    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.ylaber("Temperature(F)",fontsize=16)
    plt.tick_params(axis='both',which='major',labelsize=16)

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

    16.1.7 涵盖更长的时间
    设置好图表后,我们来添加更多的数据,以成一副更复杂的天气图。
    import csv
    from datetime import datetime
    from matplotlib import pyplot as plt
    '''导入模块csv以打开CSV格式的文件'''

    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.xlabel("",fontsize=16)
    fig.autofmt_xdate()
    plt.ylaber("Temperature(F)",fontsize=16)
    plt.tick_params(axis='both',which='major',labelsize=16)

    plt.show()

    16.1.8 再绘制一个数据系列
    改进后的图表显示了大量意义深远的数据,但我们可以在其中添加最低气温数据,使其更有用。为此,需要从数据文件中提取最低气温,并将它们添加到图
    表中,如下所示:
    import csv
    from datetime import datetime
    from matplotlib import pyplot as plt
    '''导入模块csv以打开CSV格式的文件'''

    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='bule')
    #设置图形的格式
    plt.title("Daily high temperatures - 2014",fontsize=24)
    plt.xlabel("",fontsize=16)
    fig.autofmt_xdate()
    plt.ylaber("Temperature(F)",fontsize=16)
    plt.tick_params(axis='both',which='major',labelsize=16)

    plt.show()
      在上面,我们添加了空列表lows,用于存储最低气温。接下来,我们从每行的第4列row[3]提取每天的最低气温,并存储它们。我们添加了一个对plot()
    的调用,以使用蓝色绘制最低气温。最后,我们修改了标题。

    16.1.9 给图表区域着色
    添加两个数据系列后,我们就可以了解每天的气温范围了。下面来给这个图表做最后的修饰,通过着色来呈现每天的天气范围。为此,我们将使用方法
    fill_between(),它接受一个x值系列和两个y值系列,并填充两个值系列之间的空间:
    import csv
    from datetime import datetime
    from matplotlib import pyplot as plt
    '''导入模块csv以打开CSV格式的文件'''

    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='bule',alpha=0.5)
    plt.fill_between(dates,highs,lows,facecolor='blue',alpha=0.1)
    #设置图形的格式
    plt.title("Daily high temperatures - 2014",fontsize=24)
    plt.xlabel("",fontsize=16)
    fig.autofmt_xdate()
    plt.ylaber("Temperature(F)",fontsize=16)
    plt.tick_params(axis='both',which='major',labelsize=16)

    plt.show()

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

    16.1.10 错误检查
    我们应该能够使用有关任何地方的天气数据来运行highs_lows.py中的代码,但有些气象站会偶尔出现故障,未能收集部分或全部其应该收集的数据。缺失
    数据可能会引发异常,如果不妥善地处理,还可能导致程序崩溃。
    例如,我们来看看生成加利福尼亚死亡股的气温图时出现的情况。
    import csv
    from datetime import datetime
    from matplotlib import pyplot as plt
    '''导入模块csv以打开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')
    high = int(row[1])
    low = int([row[3]])
    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='bule',alpha=0.5)
    plt.fill_between(dates,highs,lows,facecolor='blue',alpha=0.1)
    #设置图形的格式
    plt.title("Daily high and low temperatures - 2014 Death Dalley,CA",fontsize=24)
    plt.xlabel("",fontsize=16)
    fig.autofmt_xdate()
    plt.ylaber("Temperature(F)",fontsize=16)
    plt.tick_params(axis='both',which='major',labelsize=16)

    plt.show()
      对于每一行,我们都尝试从中提取日期、最高气温和最低气温。只要缺失其中一项数据,python就会引发ValueError错误,而我们可这样处理:打印一
    条消息,指出缺失数据的日期。打印错误消息后,循环将继续执行下一行处理。如果获取特定日期的所有数据时没有发生错误,将运行else代码块,并将数据
    附加到列表的末尾。鉴于我们绘图时使用的是有关另一个地方的信息,我们修改了标题,在图表中指出了这个地方。
    将这个图表与阿拉斯加的图表对比可知,总体而言,死亡谷比阿拉斯加东南部暖和,这可能符合预期,但这个沙漠中每天的温差也更大,从着色区域的高度
    可以明显看出这一点。
    使用的很多数据集都可能缺失数据、数据格式不正确或数据本身不正确。对于这样的情形,可使用本书前半部分介绍的工具来处理。在这里,我们使用了
    一个try_ecxept_else代码块来处理数据缺失的问题。在有些情况下,需要使用continue来跳过一些数据,或者使用remove()或del将已提取的数据删除。可
    采用任何管用的方法,只要进行精确而有意义的可视化就好。

    16.2 制作世界人口地图:JSON格式
    在本节中,我们将下载JSON格式的人口数据,并使用json模块来处理它们。Pyagl提供了一个适合初学者使用的地图创建工具,我们将使用它来对人口数据
    进行可视化,以探索全球人口的分布情况。
    16.2.1 下载世界人口数据
    将文件population_data.json复制到本章程序所在的文件夹中,这个文件包含全球大部分国家1960~2010年的人口数据。




     
  • 相关阅读:
    Idea 代码编辑错误不飘红提示
    Java序列化机制和原理
    tomcat 启动报错org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalin
    idea tomcat 怎样出现update classes and resources
    Java List序列化的实现
    Spring管理的bean初始化方法的三种方式,以及@PostConstruct不起作用的原因
    Tomcat 启动或者发布项目时提示Publishing failed:Resource /xxxx does not exist
    spring中的context:include-filter和context:exclude-filter的区别
    oracle字符集修改
    VML、SVG、Canvas简介
  • 原文地址:https://www.cnblogs.com/gengcx/p/6675576.html
Copyright © 2011-2022 走看看