• 「Matplotlib」全球疫情数据可视化


    本文写于2020.3

    目标

    使用Python中的Matplotlib库对全球各国的日新增确诊病例进行数据可视化。

    正文

    读取数据

    进行数据可视化,首先,我们需要获取全球各国的日新增确诊病例的数据。

    我在Our World In Data上下载了从ECDC获取的CSV数据。

    CSV数据

    CSV:逗号分隔值,其文件以纯文本形式存储表格数据,便于程序对其进行分析。

    要在Python程序中使用csv文件内储存的数据,可以使用自带的csv库,也可以使用pandas,在这里,我选择的是pandas。

    import pandas as pd
    
    data = pd.read_csv("daily-cases-covid-19.csv")
    print(data)
    print(type(data))
    

    这样就完成了读取文件的工作,简单粗暴。我们使用print来查看data现在储存的数据。

               Entity Code          Date  Daily confirmed cases (cases)
    0     Afghanistan  AFG  Dec 31, 2019                              0
    1     Afghanistan  AFG   Jan 1, 2020                              0
    2     Afghanistan  AFG   Jan 2, 2020                              0
    3     Afghanistan  AFG   Jan 3, 2020                              0
    4     Afghanistan  AFG   Jan 4, 2020                              0
    ...           ...  ...           ...                            ...
    7600     Zimbabwe  ZWE  Mar 25, 2020                              0
    7601     Zimbabwe  ZWE  Mar 26, 2020                              1
    7602     Zimbabwe  ZWE  Mar 27, 2020                              0
    7603     Zimbabwe  ZWE  Mar 28, 2020                              2
    7604     Zimbabwe  ZWE  Mar 29, 2020                              2
    
    [7605 rows x 3 columns]
    <class 'pandas.core.frame.DataFrame'>
    

    DataFrame是pandas的表格型数据结构,包含一组有序的列,每列可以是不同的值类型。DataFrame有行索引和列索引,可以看成由Series组成的字典(Series只含有列索引)。

    我们会发现,现在我们读取的数据是以0开始的序号来作为索引的,但是,为了我们后面能更好的处理数据,使用国家作为索引会更好。

    Entity这一列储存了数据所对应的国家,index_col='Entity'使国家这一列成为了数据的索引。

    data = pd.read_csv("daily-cases-covid-19.csv", index_col='Entity')
    

    再来查看我们的输出。

                Code          Date  Daily confirmed cases (cases)
    Entity                                                       
    Afghanistan  AFG  Dec 31, 2019                              0
    Afghanistan  AFG   Jan 1, 2020                              0
    Afghanistan  AFG   Jan 2, 2020                              0
    Afghanistan  AFG   Jan 3, 2020                              0
    Afghanistan  AFG   Jan 4, 2020                              0
    ...          ...           ...                            ...
    Zimbabwe     ZWE  Mar 25, 2020                              0
    Zimbabwe     ZWE  Mar 26, 2020                              1
    Zimbabwe     ZWE  Mar 27, 2020                              0
    Zimbabwe     ZWE  Mar 28, 2020                              2
    Zimbabwe     ZWE  Mar 29, 2020                              2
    
    [7605 rows x 3 columns]
    

    注意两者的差异,现在,国家成为了索引。

    使用plt绘制表格,我们需要的是纵坐标数据是新增病例数组成的列表,即Daily confirmed cases (cases)列,横坐标则为日期,即为Date列,另外,还需要对国家进行筛选。

    要想从DataFrame中获取这些数据并将其组成列表,我们可以使用loc对行、列进行筛选,并使用values将这些数据组成列表。这里,国家以中国为例。

    va = data.loc["China", ["Date", "Daily confirmed cases (cases)"]].values
    

    此时的va是一个二维列表,为了将x坐标和y坐标分离出来,我使用了map函数。

    va_x = list(map(lambda x: x[0], va))
    va_y = list(map(lambda x: x[1], va))
    

    绘制

    我们首先用最简单的绘制函数来看看效果。

    plt.plot(va_x, va_y)
    plt.show()
    

    Figure_1.png

    这样,我们就能知道我们需要改进的问题:

    • 标题及对y轴所表示数据的说明
    • x坐标上的日期需要倾斜显示,并且需要一定间隔
    • 增加图例

    标题及对y轴所表示数据的说明

    这个比较简单,直接上代码。

    import matplotlib.pyplot as plt
    import pandas as pd
    
    data = pd.read_csv("daily-cases-covid-19.csv", index_col='Entity')
    va = data.loc["China", ["Date", "Daily confirmed cases (cases)"]].values
    va_x = list(map(lambda x: x[0], va))
    va_y = list(map(lambda x: x[1], va))
    plt.title("Global outbreak data - covid-19")
    plt.ylabel("Daily confirmed cases (cases)")
    plt.plot(va_x, va_y)
    plt.show()
    

    来看看效果。

    Figure_1.png

    x坐标上的日期需要倾斜显示,并且需要一定间隔

    为了实现这个目的,我们在对画布进行初始化时,使用fig, ax = plt.subplots(),这一行代码的作用是方便我们在一张画布上呈现多个图表,在这里,我只需要一张图标,使用它是为了能够调用ax.set_xticks(xticks)

    修改后的代码如下。

    import matplotlib.pyplot as plt
    import pandas as pd
    
    data = pd.read_csv("daily-cases-covid-19.csv", index_col='Entity')
    va = data.loc["China", ["Date", "Daily confirmed cases (cases)"]].values
    va_x = list(map(lambda x: x[0], va))
    va_y = list(map(lambda x: x[1], va))
    fig, ax = plt.subplots()
    fig.autofmt_xdate()
    xticks = list(range(0, 90, 10))
    ax.set_xticks(xticks)
    plt.title("Global outbreak data - covid-19")
    plt.ylabel("Daily confirmed cases (cases)")
    plt.plot(va_x, va_y)
    plt.show()
    

    Figure_1.png

    控制x轴间隔的值为xticks = list(range(0, 90, 10))中的10,另外,这里的90指x坐标上的日期共有90个,这里要依照你下载下来的疫情数据而定。

    增加图例

    增加图例需要用到的函数是plt.legend()

    在我们的程序中,实现增加图例的功能,只需要在plt.show()这一行之前加上plt.legend(labels=["China"], loc=0)

    labels就是图例上的文字,这里需要传递的是一个列表,legend函数会按照绘制线条的先后顺序自动匹配文字。

    loc为图例的显示位置,0指代的是best,程序会自动为你选择最合适的放置图例的位置。

    Figure_1.png

    绘制多个国家的数据

    至此,我们的图标已经完成的差不多了,我们还需要让程序能够同时显示多个国家的数据。

    我们可以将多个国家的名称储存在列表countrys,并利用for循环,分别匹配对应的数据。

    import matplotlib.pyplot as plt
    import pandas as pd
    
    data = pd.read_csv("daily-cases-covid-19.csv", index_col='Entity')
    countrys = ["China", "United States"]
    fig, ax = plt.subplots()
    fig.autofmt_xdate()
    xticks = list(range(0, 90, 10))
    ax.set_xticks(xticks)
    plt.title("Global outbreak data - covid-19")
    plt.ylabel("Daily confirmed cases (cases)")
    for country in countrys:
        va = data.loc[country, ["Date", "Daily confirmed cases (cases)"]].values
        va_x = list(map(lambda x: x[0], va))
        va_y = list(map(lambda x: x[1], va))
        plt.plot(va_x, va_y)
    plt.legend(labels=countrys, loc=0)
    plt.show()
    

    用户输入

    以上的代码,需要对源代码进行改动才能修改显示的国家,而我更希望让用户能够输入他们想要查看的国家数据。

    使用input()我认为并不好,单词输错可能会让他们很头疼,所以,我更加倾向于用「Tkinter」完成一个图形化界面,不过,用「EasyGUI」可能会更方便一些。

    我们首先要做的事是将所有国家汇总于一个列表中。

    # 这里将所有的索引放到了total列表里
    total = list(data.index)
    index = 0
    # 这里对total列表进行了删去重复项的操作
    while True:
        if index >= len(total):
            break
        elif total.count(total[index]) > 1:
            del total[index]
        else:
            index += 1
    

    制作一个复选框就很容易了。

    import easygui
    # --snip--
    countrys = easygui.multchoicebox(msg="Please select the country outbreak data to view:", title="", choices=total)
    

    复选框

    Figure_1.png

    源代码

    import matplotlib.pyplot as plt
    import pandas as pd
    import easygui
    
    data = pd.read_csv("daily-cases-covid-19.csv", index_col='Entity')
    total = list(data.index)
    index = 0
    while True:
        if index >= len(total):
            break
        elif total.count(total[index]) > 1:
            del total[index]
        else:
            index += 1
    countrys = easygui.multchoicebox(msg="Please select the country outbreak data to view:", title="", choices=total)
    fig, ax = plt.subplots()
    fig.autofmt_xdate()
    xticks = list(range(0, 90, 10))
    ax.set_xticks(xticks)
    plt.title("Global outbreak data - covid-19")
    plt.ylabel("Daily confirmed cases (cases)")
    for country in countrys:
        va = data.loc[country, ["Date", "Daily confirmed cases (cases)"]].values
        va_x = list(map(lambda x: x[0], va))
        va_y = list(map(lambda x: x[1], va))
        plt.plot(va_x, va_y)
    plt.legend(labels=countrys, loc=0)
    plt.show()
    

    资料库

  • 相关阅读:
    centos文件与权限
    python执行centos命令
    Centos下新建用户及修改用户目录
    微信现金红包 python
    图像直方图
    十三种基于直方图的图像全局二值化算法原理、实现、代码及效果。
    图像处理之常见二值化方法汇总
    OpenCV中对图像进行二值化的关键函数——cvThreshold()。
    cvLoadImage
    cvGet2D的用法
  • 原文地址:https://www.cnblogs.com/liuxizai/p/13765301.html
Copyright © 2020-2023  润新知