疯狂Python讲义学习笔记(含习题)之数据可视化


Python为数据展示提供了大量优秀的功能包,其中Matplotlib和Pygal是两个极具代表性的功能包。

一、使用Matplotlib生成数据图

Matplotlib是一个非常优秀的Python 2D 绘图库,只要给出符合格式的数据,通过Matplotlib就可以方便地制作折线图、柱状图、散点图等各种高质量的数据图。

(一)、安装Matplotlib包

pip安装

pip install matplotlib

(二)Matplotlib数据图入门

Matplotlib的用法非常简单,对于最简单的折线图来说, 程序只需根据需要给出对应的X 轴、Y 轴数据, 调用pyplot 子模块下的plot()函数即可生成简单的折线图。
示例

import matplotlib.pyplot as plt

# 定义两个列表分别作为X轴、Y轴数据
x_data = ['2011', '2012', '2013', '2014', '2015', '2016', '2017']
y_data = [58000, 60200, 63000, 71000, 84000, 90500, 107000]
# 第一个列表代波啊横坐标的值,第二个列表代表纵坐标的值
plt.plot(x_data, y_data)
# 调用show()函数显示图形
plt.show()

运行效果:

在这里插入图片描述
如果在调用plot()函数时只传入一个list列表,则该列表的数据将作为y轴数据,Matplotlib会自动使用0, 1, 2, 3作为X轴数据。
效果如下图
在这里插入图片描述

plot()函数除了支持创建具有单挑折线的折线图,也支持创建包含多条折线的复式折线图,只要在调用plot()函数时传入多个分别代表x轴和y轴数据的list列表即可。
示例

import matplotlib.pyplot as plt

x_data = ['2011', '2012', '2013', '2014', '2015', '2016', '2017']
# 定义两个列表分别作为两条折线的Y轴数据
y_data = [58000, 60200, 63000, 71000, 84000, 90500, 107000]
y_data1 = [52000, 54200, 51500, 58300, 56800, 59500, 62700]
# 传入两组分别代表X轴,Y轴的数据的list列表
plt.plot(x_data, y_data, x_data, y_data1)
# 调用show()函数显示图形
plt.show()

运行效果:
在这里插入图片描述

也可以将以上代码中的 `` plt.plot(x_data, y_data, x_data, y_data1) ```改为多次调用plot()的方式:

plt.plot(x_data, y_data)
plt.plot(x_data, y_data1)

同样可以在调用plot()函数时传入额外的参数来指定折线的样子、如线宽、颜色、样式等。
示例

import matplotlib.pyplot as plt

x_data = ['2011', '2012', '2013', '2014', '2015', '2016', '2017']
# 定义两个列表分别作为两条折线的Y轴数据
y_data = [58000, 60200, 63000, 71000, 84000, 90500, 107000]
y_data1 = [52000, 54200, 51500, 58300, 56800, 59500, 62700]
# 指定折线的颜色、线宽和样式
plt.plot(x_data, y_data, color='red', linewidth=2.0, linestyle='--')
plt.plot(x_data, y_data1, color='blue', linewidth=3.0, linestyle='-.')
# 调用show()函数显示图形
plt.show()

运行效果:

在这里插入图片描述
样式字符串支持如下参数值:

参数值描述
-代表实线,默认值
代表虚线
:代表点线
-.代表短线、点相间的虚线

(三)管理图例

可以通过legend()函数来为折线添加图例,为该函数传入两个list参数,其中第一个list参数(handles参数)用于引用折线图上的每条折线,第二个list参数(labels)代表为每条折线所添加的图例。
示例

import matplotlib.pyplot as plt

x_data = ['2011', '2012', '2013', '2014', '2015', '2016', '2017']
# 定义两个列表分别作为两条折线的Y轴数据
y_data = [58000, 60200, 63000, 71000, 84000, 90500, 107000]
y_data1 = [52000, 54200, 51500, 58300, 56800, 59500, 62700]
# 指定折线的颜色、线宽和样式
ln1, = plt.plot(x_data, y_data, color='red', linewidth=2.0, linestyle='--')
ln2, = plt.plot(x_data, y_data1, color='blue', linewidth=3.0, linestyle='-.')
# 调用legend()函数设置图例
plt.legend(handles=[ln2, ln1],
           labels=['示例2年销售量', '示例1年销售量'],
           loc='lower right')
# 调用show()函数显示图形
plt.show()

运行效果:

在这里插入图片描述
以上代码中的loc参数指定图例添加位置,该参数支持如下参数值:

参数值描述
best自动选择最佳位置
upper right将图例放在右上角
upper left将图例放在左上角
lower left将图例放在左下角
lower right将图例放在右下角
right将图例放在右边
center left将图例放在左边居中的位置
center right将图例放在右边居中的位置
lower center将图例放在底部居中的位置
upper center将图例放在顶部居中的位置
center将图例放在中心

中文乱码解决方案
① 使用matplotlib.font_manager子模块下的FontProperties类加载中文字体。
② 在调用legend()函数时通过prop属性指定使用中文字体。

示例

import matplotlib.pyplot as plt
import matplotlib.font_manager as fm

x_data = ['2011', '2012', '2013', '2014', '2015', '2016', '2017']
# 定义两个列表分别作为两条折线的Y轴数据
y_data = [58000, 60200, 63000, 71000, 84000, 90500, 107000]
y_data1 = [52000, 54200, 51500, 58300, 56800, 59500, 62700]
# 指定折线的颜色、线宽和样式
ln1, = plt.plot(x_data, y_data, color='red', linewidth=2.0, linestyle='--')
ln2, = plt.plot(x_data, y_data1, color='blue', linewidth=3.0, linestyle='-.')
# 使用Matplotlib的字体管理器加载中文字体
my_font = fm.FontProperties(fname="C:\Windows\Fonts\msyh.ttc")
# 调用legend()函数设置图例
plt.legend(handles=[ln2, ln1],
           labels=['示例2年销售量', '示例1年销售量'],
           loc='lower right',
           prop=my_font)
# 调用show()函数显示图形
plt.show()

运行效果:
在这里插入图片描述

以上程序使用FontProperties类加载c:\windows\Fonts\msyh.ttc文件所对应的中文字体。
legend()函数可以不指定handles参数,只传入labels参数,这样该labels参数将按顺序为直线图中的多条折线添加图例。
Matplotlib也允许在调用plot()函数时为每条折线分别传入label参数,这样程序在调用legend()函数时就无须传入labels、handles参数了。

永久改变Matplotlib的默认字体
在Python的交互解释器中输入如下命令:
在这里插入图片描述
编辑配置文件,找到如下行:
在这里插入图片描述
将此行代码修改为如下形式,并去掉前面的#号:
在这里插入图片描述

(四)管理坐标轴

可以调用xlable()和ylabel()函数分别设置X轴、Y轴的名称,也可以通过title()函数设置整个数据图的标题,还可以调用xticks()、yticks()函数分别改变X轴、Y轴的刻度值(允许使用文本作为刻度值)。
示例

import matplotlib.pyplot as plt

x_data = ['2011', '2012', '2013', '2014', '2015', '2016', '2017']
# 定义两个列表分别作为两条折线的Y轴数据
y_data = [58000, 60200, 63000, 71000, 84000, 90500, 107000]
y_data1 = [52000, 54200, 51500, 58300, 56800, 59500, 62700]
# 指定折线的颜色、线宽和样式
plt.plot(x_data,
         y_data,
         color='red',
         linewidth=2.0,
         linestyle='--',
         label='图例1年销量')
plt.plot(x_data,
         y_data1,
         color='blue',
         linewidth=3.0,
         linestyle='-.',
         label='图例2年销量')
# 调用legend()函数设置图例
plt.legend(loc='best')
# 设置两个坐标轴的名称
plt.xlabel("年份")
plt.ylabel("销量")
# 设置数据图的标题
plt.title("历年销量图")
# 设置Y轴上的数值文本
# 第一个参数是点的位置,第二个参数是点的文字提示
plt.yticks([50000, 70000, 100000], [r'挺好', r'优秀', r'火爆'])
# 调用show()函数显示图形
plt.show()

运行效果:
在这里插入图片描述

若要对X轴、Y轴进行更细致的控制,可以调用gca()函数来获取坐标轴信息对象,然后对坐标轴进行控制。

示例

import matplotlib.pyplot as plt

x_data = ['2011', '2012', '2013', '2014', '2015', '2016', '2017']
# 定义两个列表分别作为两条折线的Y轴数据
y_data = [58000, 60200, 63000, 71000, 84000, 90500, 107000]
y_data1 = [52000, 54200, 51500, 58300, 56800, 59500, 62700]
# 指定折线的颜色、线宽和样式
plt.plot(x_data,
         y_data,
         color='red',
         linewidth=2.0,
         linestyle='--',
         label='图例1年销量')
plt.plot(x_data,
         y_data1,
         color='blue',
         linewidth=3.0,
         linestyle='-.',
         label='图例2年销量')
# 调用legend()函数设置图例
plt.legend(loc='best')
# 设置两个坐标轴的名称
plt.xlabel("年份")
plt.ylabel("销量")
# 设置数据图的标题
plt.title("历年销量图")
# 设置Y轴上的数值文本
# 第一个参数是点的位置,第二个参数是点的文字提示
plt.yticks([50000, 70000, 100000], [r'挺好', r'优秀', r'火爆'])
ax = plt.gca()
# 设置将x轴的刻度值放在底部X轴上
ax.xaxis.set_ticks_position('bottom')
# 设置将Y轴的刻度值放在左边Y轴上
ax.yaxis.set_ticks_position('left')
# 设置右边坐标轴线的颜色(设置为none表示不显示)
ax.spines['right'].set_color('none')
# 设置顶部坐标轴线的颜色(设置为none表示不显示)
ax.spines['top'].set_color('none')
# 定义底部坐标轴线的位置(放在70000数值处)
ax.spines['bottom'].set_position(('data', 70000))
# 调用show()函数显示图形
plt.show()

运行效果:
在这里插入图片描述

以上代码中使用plt.gca()获取了一个AxesSubplot对象,然后调用该对象的xaxis属性的set_ticks_position()方法设置X轴刻度值的位置。通过spines属性可以访问数据图四周的坐标轴线(Spine对象)

(五)管理多个子图

使用Matplotlib 除可以生成包含多条折线的复式折线图之外,它还允许在一张数据图上包含多个子图。
调用subplot()函数可以创建一个子图,然后程序就可以在子图上进行绘制。subplot(nrows, ncols, mdex, **kwargs)函数的时ows 参数指定将数据图区域分成多少行; ncols 参数指定将数据图区域分成多少列: index参数指定获取第几个区域。

示例

import matplotlib.pyplot as plt
import numpy as np

plt.figure()
# 定义从-pi到pi之间的数据,平均去64个数据点
x_data = np.linspace(-np.pi, np.pi, 64, endpoint=True)
# 将整个figure分成两行两列,第三个参数表示将该图形放在第1个网格中
plt.subplot(2, 2, 1)
# 绘制正弦曲线
plt.plot(x_data, np.sin(x_data))
plt.gca().spines['right'].set_color('none')
plt.gca().spines['top'].set_color('none')
plt.gca().spines['bottom'].set_position(('data', 0))
plt.gca().spines['left'].set_position(('data', 0))
plt.title('正弦曲线')

# 将整个figure分成两行两列,并将该图形房子啊第2个网格中
plt.subplot(222)
# 绘制余弦曲线
plt.plot(x_data, np.cos(x_data))
plt.gca().spines['right'].set_color('none')
plt.gca().spines['top'].set_color('none')
plt.gca().spines['bottom'].set_position(('data', 0))
plt.gca().spines['left'].set_position(('data', 0))
plt.title('余弦曲线')

# 将整个figure分成两行两列,并将该图形放在第3个网格中
plt.subplot(223)
# 绘制正切曲线
plt.plot(x_data, np.tan(x_data))
plt.gca().spines['right'].set_color('none')
plt.gca().spines['top'].set_color('none')
plt.gca().spines['bottom'].set_position(('data', 0))
plt.gca().spines['left'].set_position(('data', 0))
plt.title('正切曲线')

plt.show()

运行效果:
在这里插入图片描述

还可以让某个子图占用多个网格,例如将以上代码中的plt.subplot(2, 2, 1)改为 plt.subplot(2, 1, 1),然后依次修改另外两个子图的位置。
还可以使用GridSpec对绘图区域进行分割。
示例

import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec
import numpy as np

plt.figure()
# 定义从-pi到pi之间的数据,平均去64个数据点
x_data = np.linspace(-np.pi, np.pi, 64, endpoint=True)

# 将绘图区域分成两行三列
gs = gridspec.GridSpec(2, 3)
# 指定ax1占用第一行(0)整行
ax1 = plt.subplot(gs[0, :])
# 指定ax2占用第二行(1)的第一格(第二个参数0代表)
ax2 = plt.subplot(gs[1, 0])
# 指定ax3占用第二行(1)的第二、三格(第二个参数用1:3代表)
ax3 = plt.subplot(gs[1, 1:3])

# 绘制正弦曲线
ax1.plot(x_data, np.sin(x_data))
ax1.spines['right'].set_color('none')
ax1.spines['top'].set_color('none')
ax1.spines['bottom'].set_position(('data', 0))
ax1.spines['left'].set_position(('data', 0))
ax1.set_title('正弦曲线')

# 绘制余弦曲线
ax2.plot(x_data, np.cos(x_data))
ax2.spines['right'].set_color('none')
ax2.spines['top'].set_color('none')
ax2.spines['bottom'].set_position(('data', 0))
ax2.spines['left'].set_position(('data', 0))
ax2.set_title('余弦曲线')

# 绘制正切曲线
ax3.plot(x_data, np.tan(x_data))
ax3.spines['right'].set_color('none')
ax3.spines['top'].set_color('none')
ax3.spines['bottom'].set_position(('data', 0))
ax3.spines['left'].set_position(('data', 0))
ax3.set_title('正切曲线')

plt.show()

运行效果:
在这里插入图片描述

功能丰富的数据图

(一)饼图

使用Matplotlib提供的pie() 函数来绘制饼图。
示例数据表 TIOBE2019年6月编程语言指数排行榜前10名

语言排名
Java15.004%
C13.300%
Python8.530%
C++7.384%
Visual Basic.NET4.624%
C#4.483%
JavaScript2.716%
PHP2.567%
SQL2.224%
Assembly language1.479%

饼图示例

import matplotlib.pyplot as plt

# 准备数据
data = [
    0.15004, 0.13300, 0.08530, 0.07384, 0.04624, 0.04483, 0.02716, 0.02567,
    0.02224, 0.01479, 0.37689
]
# 准备标签
labels = [
    'Java', 'C', 'Python', 'C++', 'Visual Basic.NET', 'C#', 'JavaScript',
    'PHP', 'SQL', 'Assembly language', '其他'
]
# 将排在第3位的语言(Python)分离出来
explode = [0, 0, 0.3, 0, 0, 0, 0, 0, 0, 0, 0]
# 使用自定义颜色
colors = ['red', 'pink', 'magenta', 'purple', 'orange']
# 将横、纵坐标轴标准化处理,保证饼图是一个正圆,否则为椭圆
plt.axes(aspect='equal')
# 控制X轴和Y轴的范围(用于控制饼图的圆心、半径)
plt.xlim(0, 8)
plt.ylim(0, 8)

# 绘制饼图
plt.pie(x=data, # 绘图数据
        labels=labels, # 添加编程语言标签
        explode=explode, # 突出显示Python
        colors=colors, # 设置饼图的自定义填充色
        autopct='%.3f%%', # 设置百分比的格式,此处保留3位小数
        pctdistance=0.8, # 设置百分比标签与圆心的距离
        labeldistance=1.05, # 设置标签与圆心的距离
        startangle=180, # 设置饼图的初始角度
        center=(4, 4), # 设置饼图的圆心(相当于X轴和Y轴的范围)
        radius=3.8, # 设置饼图的半径(相当于X轴和Y轴的范围
        counterclock=False, # 是否为逆时针方向,这里为顺时针
        wedgeprops={
            'linewidth': 1,
            'edgecolor': 'green'
        }, # 设置饼图内外边界的属性值
        textprops={
            'fontsize': 12,
            'color': 'black'
        }, # 设置文本标签的属性值
        frame=1) # 是否显示饼图的圆圈,此处设置为显示
# 不显示X轴和Y轴的刻度值
plt.xticks(())
plt.yticks(())
# 添加图形标题
plt.title('TIOBE2019年6月编程语言指数排行榜前10名')
# 显示图形
plt.show()

运行效果:
在这里插入图片描述

(二)柱状图

使用Matplotlib提供的bar()函数来绘制柱状图。与前面介绍的plot()函数类似, 程序每次调用bar()函数时都会生成一组柱状图, 如果希望生成多组柱状图,则可通过多次调用bar()函数来实现。
示例

import matplotlib.pyplot as plt

# 构建数据
x_data = ['2011', '2012', '2013', '2014', '2015', '2016', '2017']
y_data = [58000, 60200, 63000, 71000, 84000, 90500, 107000]
y_data2 = [52000, 54200, 51500, 58300, 56800, 59500, 62700]
# 绘图
plt.bar(x=x_data, height=y_data, label='产品1', color='steelblue', alpha=0.8)
plt.bar(x=x_data, height=y_data2, label='产品2', color='indianred', alpha=0.8)
# 在柱状图上显示具体数值,ha参数控制水平对齐方式,va参数控制垂直对齐方式
for x, y in enumerate(y_data):
    plt.text(x, y + 100, '%s' % y, ha='center', va='bottom')
for x, y in enumerate(y_data2):
    plt.text(x, y + 100, '%s' % y, ha='center', va='top')
# 设置标题
plt.title("产品对比")
# 为两个坐标轴设置名称
plt.xlabel("年份")
plt.ylabel("销量")
# 显示图例
plt.legend()
plt.show()

运行效果:
在这里插入图片描述

使用bar()函数绘制柱状图时,默认不会在柱状图上显示具体的数值。程序可以通过调用text()函数在数据图上输出文字。text()函数前两个参数控制输出文字的X、Y坐标,第三个参数控制输出的内容,va控制文字的垂直对齐方式,ha控制文字的水平对齐方式。
如果不希望两组数据重叠在一起,那么就需要对X轴进行设置,因为两组柱状图使用的是同一组list列表数据,为了将多个柱状图的条柱并列显示,程序需要为这些柱状图重新计算不同的X轴数据。为了精确控制条柱的宽度,程序可以在调用bar()函数时传入width参数,这样可以更好地计算条柱的并列方式。
示例

import matplotlib.pyplot as plt
import numpy as np

# 构建数据
x_data = ['2011', '2012', '2013', '2014', '2015', '2016', '2017']
y_data = [58000, 60200, 63000, 71000, 84000, 90500, 107000]
y_data2 = [52000, 54200, 51500, 58300, 56800, 59500, 62700]
bar_width = 0.3
# 将X轴数据改为使用range(len(x_data)),就是0、1、2……
plt.bar(x=range(len(x_data)),
        height=y_data,
        label='产品1',
        color='steelblue',
        alpha=0.8,
        width=bar_width)
# 将X轴数据改为使用np.arange(len(x_data)) + bar_width
# 就是bar_width、1 + bar_width、2 + bar_width……这样就和第一个图并列了
plt.bar(x=np.arange(len(x_data)) + bar_width,
        height=y_data2,
        label='产品2',
        color='indianred',
        alpha=0.8,
        width=bar_width)
# 在柱状图上显示具体的数值,ha参数控制水平对齐方式,va参数控制垂直对齐方式
for x, y in enumerate(y_data):
    plt.text(x, y + 100, '%s' % y, ha='center', va='bottom')
for x, y in enumerate(y_data2):
    plt.text(x + bar_width, y + 100, '%s' % y, ha='center', va='top')
# 设置标题
plt.title('产品对比')
# 为两个坐标轴设置名称
plt.xlabel("年份")
plt.ylabel("销量")
# 显示图例
plt.legend()
plt.show()

运行效果:
在这里插入图片描述

以上程序有一个不足之处,就是X轴的刻度值变成了0,1,2……而不再显示年份,为了让柱状图的X轴刻度显示年份,可以调用xticks()函数重新设置X轴的刻度值。如:
plt.xticks(np.arange(len(x_data)) + bar_width/2, x_data)

(三)水平柱状图

调用Matplotlib的barh()函数可以生成水平柱状图。barh()函数的用法与bar()函数的用法基本一样,只是在调用barh()函数时使用y 参数传入Y 轴数据,使用width 参数传入代表条柱宽度的数据。
示例

import matplotlib.pyplot as plt
import numpy as np

# 构建数据
x_data = ['2011', '2012', '2013', '2014', '2015', '2016', '2017']
y_data = [58000, 60200, 63000, 71000, 84000, 90500, 107000]
y_data2 = [52000, 54200, 51500, 58300, 56800, 59500, 62700]
bar_width = 0.3
# Y轴数据使用range(len(x_data)),也就是0、1、2、……
plt.barh(y=range(len(x_data)),
         width=y_data,
         label='产品1',
         color='steelblue',
         alpha=0.8,
         height=bar_width)
# Y轴数据使用np.arange(len(x_data)) + bar_width,也就是bar_width、1+bar_width、2+bar_width……
plt.barh(y=np.arange(len(x_data)) + bar_width,
         width=y_data2,
         label='产品2',
         color='indianred',
         alpha=0.8,
         height=bar_width)
# 在柱状图上显示具体的数值,ha参数控制水平对齐方式,va参数控制垂直对齐方式
for y, x in enumerate(y_data):
    plt.text(x + 5000,
             y - bar_width / 2,
             '%s' % x,
             ha='center',
             va='bottom')
for y, x in enumerate(y_data2):
    plt.text(x + 5000,
             y + bar_width / 2,
             '%s' % x,
             ha='center',
             va='bottom')
# 设置Y轴刻度
plt.yticks(np.arange(len(x_data)) + bar_width / 2, x_data)
# 设置标题
plt.title("产品比较")
# 为两个坐标轴设置名称
plt.xlabel("销量")
plt.ylabel("年份")
# 显示图例
plt.legend()
plt.show()

运行效果
在这里插入图片描述

(四)散点图

实际上,散点图和折线图类似,区别是折线图会将各个点用线连接起来,而散点图不会。调用Matplotlib的scatter()函数可以绘制散点图,该函数接收如下参数:

  • x:指定X轴数据。
  • y:指定Y轴数据。
  • s:指定散点的大小。
  • c:指定散点的颜色。
  • alpha:指定散点的透明度。
  • linewidths:指定散点边框线的宽度。
  • edgecolors:指定散点边框的颜色。
  • marker:指定散点的图形样式。
  • cmap:指定散点的颜色映射,会使用不同的颜色来区分散点的值。

散点样式表

样式字符样式
‘.’点标记
‘,’像素标记
‘o’圆形标记
‘v’向下三角形标记
‘^’向上三角形标记
‘<’向左三角形标记
‘>’向右三角形标记
‘1’向下三叉标记
‘2’向上三叉标记
‘3’向左三叉标记
‘4’向右三叉标记
‘s’正方形标记
‘p’五边形标记
‘*’星号标记
‘h’八边形标记
‘H’另一种八边形标记
‘+’加号标记
‘x’x标记
‘D’菱形标记
‘d’尖菱形标记
‘|’竖线标记
‘_’横线标记

示例

import matplotlib.pyplot as plt
import numpy as np

plt.figure()
# 定义从-pi到pi之间的数据,平均取64个数据点
x_data = np.linspace(-np.pi, np.pi, 64, endpoint=True)
# 将整个figure分成两行两列,第三个参数表示将图形放在第1个网格中
# 沿着正弦曲线绘制散点图
plt.scatter(x_data,
            np.sin(x_data),
            c='purple',
            s=50,
            alpha=0.5,
            marker='p',
            linewidths=1,
            edgecolors=['green', 'yellow'])
# 绘制第二个散点图(只包含一个起点),突出起点
plt.scatter(x_data[0], np.sin(x_data)[0], c='red', s=150, alpha=1)
# 绘制第三个散点图(只包含一个结束点),突出结束点
plt.scatter(x_data[63], np.sin(x_data)[63], c='black', s=150, alpha=1)
plt.gca().spines['right'].set_color('none')
plt.gca().spines['top'].set_color('none')
plt.gca().spines['bottom'].set_position(('data', 0))
plt.gca().spines['left'].set_position(('data', 0))
plt.title('正弦曲线的散点图')
plt.show()

运行效果:
在这里插入图片描述

(五)等高线图

等高线图需要三维数据,其中X、Y轴数据决定坐标点,还需要对应的高度数据(相当于Z轴)来决定不同坐标点的高度。程序调用contour()函数绘制等高线,调用contourf()函数为等高线图填充颜色。
contour()、contourf()函数常用参数如下:

  • X:指定X轴数据
  • Y:指定Y轴数据
  • Z:指定X、Y坐标对应点的高度数据
  • colors:指定不同高度的等高线的颜色
  • alpha:指定等高线的透明度
  • cmap:指定登高线的颜色映射,即自动使用不同的颜色来区分不同的高度区域
  • linewidths:指定等高线的宽度
  • linestyles:指定等高线的样式

示例

import matplotlib.pyplot as plt
import numpy as np

delta = 0.025
# 生成代表x轴数据的列表
x = np.arange(-3.0, 3.0, delta)
# 生成代表y轴数据的列表
y = np.arange(-2.0, 2.0, delta)
# 对X、y数据进行网格化
X, Y = np.meshgrid(x, y)
Z1 = np.exp(-X**2 - Y**2)
Z2 = np.exp(-(X - 1)**2 - (Y - 1)**2)
# 计算Z轴数据(高度数据)
Z = (Z1 - Z2) * 2
# 为等高线图填充颜色,16指定将等高线分为几部分
plt.contourf(x, y, Z, 16, alpha=0.75, cmap='rainbow') # 使用颜色映射来区分不同高度的区域
# 绘制等高线
c = plt.contour(x, y, Z, 16, colors='black', linewidths=0.5)
# 绘制等高线数据
plt.clabel(c, inline=True, fontsize=10)
# 去除坐标轴
plt.xticks(())
plt.yticks(())
# 设置标题
plt.title('等高线图')
# 为两个坐标轴设置名称
plt.xlabel("纬度")
plt.ylabel("经度")
plt.show()

运行效果:
在这里插入图片描述

以上代码中要注意一个地方,很多书里都将c = plt.contour(x, y, Z, 16, colors='black', linewidths=0.5)中的linewidths写成了linewidth。

(六)3D图形

调用Axes3D对象的plot_surface()方法来绘制3D图形。
示例

import matplotlib.pyplot as plt
import numpy as np
from mpl_toolkits.mplot3d import Axes3D

fig = plt.figure(figsize=(12, 8))
ax = Axes3D(fig)

delta = 0.125
# 生成代表X轴数据的列表
x = np.arange(-3.0, 3.0, delta)
# 生成代表Y轴数据的列表
y = np.arange(-2.0, 2.0, delta)
# 对x、y数据进行网格化
X, Y = np.meshgrid(x, y)
Z1 = np.exp(-X**2 - Y**2)
Z2 = np.exp(-(X - 1)**2 - (Y - 1)**2)
# 计算Z轴数据(高度数据)
Z = (Z1 - Z2) * 2
# 绘制3D图形
ax.plot_surface(X, Y, Z, rstride=1, cstride=1, cmap=plt.get_cmap('rainbow'))
# 设置Z轴范围
ax.set_zlim(-2, 2)
# 设置标题
plt.title("3D图")
plt.show()

运行效果:
在这里插入图片描述

三、使用Pygal生成数据图

Pygal是另一个简单易用的数据图库,它以面向对象的方式来创建各种数据图,而且使用Pygal可以非常方便地生成各种格式的数据图,包括PNG 、SVG 等。使用Pygal也可以生成XML etree、HTML 表格(这些都需要安装其他包)。

(一)安装Pygal包

pip安装
pip install pygal

查看文档

python -m pydoc -p 8899

(二)Pygal数据图入门

使用Pygal生成数据图步骤如下:
① 创建Pygal数据图对象。有pygal.Bar,pygal.Pie,Pygal.Line等对象类型。
② 调用数据图对象的add()方法添加数据。
③ 调用Config对象的属性配置数据图。
④ 调用数据图对象的render_to_xxx()方法将数据图渲染到指定的输出节点——可以是PNG图片、SVG文件等。

示例

import pygal

x_data = ['2011', '2012', '2013', '2014', '2015', '2016', '2017']
# 定义两个列表分别作为两组柱状图的Y轴数据
y_data = [5800, 60200, 63000, 71000, 84000, 90500, 107000]
y_data2 = [52000, 54200, 51500, 58300, 56800, 59500, 62700]
# 创建pygal.Bar对象
bar = pygal.Bar()
# 添加两组代表条柱的数据
bar.add('产品1', y_data)
bar.add('产品2', y_data2)
# 设置X轴的刻度值
bar.x_labels = x_data
bar._title = '产品历年销售量'
# 设置X,Y轴的标题
bar._x_title = '年份'
bar._y_title = '销量'
# 指定将数据图输出到SVG文件中
bar.render_to_file('pygal_bar_test.svg')

运行后生成pygal_bar_test.svg文件,用浏览器打开效果如下:
在这里插入图片描述

(三)配置Pygal数据图

Pygal模块下有一个config模块,该模块包含了BaseConfig、CommonConfig、Config、SerieConfig等配置类。
部分配置属性示例

import pygal

x_data = ['2011', '2012', '2013', '2014', '2015', '2016', '2017']
# 定义两个列表分别作为两组柱状图的Y轴数据
y_data = [5800, 60200, 63000, 71000, 84000, 90500, 107000]
y_data2 = [52000, 54200, 51500, 58300, 56800, 59500, 62700]
# 创建pygal.Bar对象(柱状图)
bar = pygal.Bar()
# 添加两组代表条柱的数据
bar.add('产品1', y_data)
bar.add('产品2', y_data2)
# 设置X轴的刻度值
bar.x_labels = x_data
bar.title = '产品历年销量'
# 设置X、Y轴的标题
bar.x_title = '年份'
bar.y_title = '销量'
# 设置X轴的刻度值旋转45°
bar.x_label_rotation = 45
# 设置将图例放在底部
bar.legend_at_bottom = True
# 设置数据图四周的页边距
# 也可通过margin_bottom、margin_left、margin_right、margin_top只设置单独一边的页边距
bar.margin = 35
# 隐藏Y轴上的网络线
bar.show_y_guides = False
# 显示X轴上的网格线
bar.show_x_guides = True
# 指定将数据图输出到SVG文件中
bar.render_to_file('pygal_bar_config.svg')

pygal_bar_config.svg文件效果:
在这里插入图片描述

四、Pygal支持的常见数据图

(一)折线图

使用pygal.Line 类来表示折线图,程序创建pygal.Line对象就是创建折线图。
示例

import pygal

x_data = ['2011', '2012', '2013', '2014', '2015', '2016', '2017']
# 定义两个列表分别作为两组柱状图的Y轴数据
y_data = [5800, 60200, 63000, 71000, 84000, 90500, 107000]
y_data2 = [52000, 54200, 51500, 58300, 56800, 59500, 62700]
# 创建pygal.Line对象(折线图)
line = pygal.Line()
# 添加两组代表折线的数据
line.add('产品1', y_data)
line.add('产品2', y_data2)
# 设置X轴的刻度值
line.x_labels = x_data
# 重新设置Y轴的刻度值
line.y_labels = [20000, 40000, 60000, 80000, 100000]
line._title = '产品历年销量'
# 设置X,Y轴的标题
line.x_title = '年份'
line.y_title = '销量'
# 设置将图例放在底部
line.legend_at_bottom = True
# 指定将数据图输出到SVG文件中
line.render_to_file('pygal_line_test.svg')

SVG图形效果:
在这里插入图片描述

(二)水平柱状图和水平折线图

使用pygal.HorizontalBar类来表示水平柱状图。使用pygal.HorizontalBar生成水平柱状图的步骤与创建普通柱状图的步骤基本相同。
示例

import pygal

x_data = ['2011', '2012', '2013', '2014', '2015', '2016', '2017']
# 定义两个列表分别作为两组柱状图的Y轴数据
y_data = [5800, 60200, 63000, 71000, 84000, 90500, 107000]
y_data2 = [52000, 54200, 51500, 58300, 56800, 59500, 62700]
# 创建pygal.HorizontalBar对象
horizontal_bar = pygal.HorizontalBar()
# 添加两组数据
horizontal_bar.add('产品1', y_data)
horizontal_bar.add('产品2', y_data2)
# 设置Y轴的刻度值
horizontal_bar.x_labels = x_data
# 重新设置X轴的刻度值
horizontal_bar.y_labels = [20000, 40000, 60000, 80000, 100000]
horizontal_bar._title = '产品历年销量'
# 设置X、Y轴的标题
horizontal_bar.x_title = '销量'
horizontal_bar.y_title = '年份'
# 设置将图例放在底部
horizontal_bar.legend_at_bottom = True
# 指定将数据图输出到SVG文件中
horizontal_bar.render_to_file('pygal_horizontal_bar_test.svg')

SVG效果图:
在这里插入图片描述

与水平柱状图类似的还有水平折线图,水平折线图使用pygal.HorizontalLine 类来表示,水平折线图的X 轴刻度值同样使用y_labels属性来设置,而Y轴刻度值才使用x_labels属性来设置。

(三)叠加柱状图和叠加折线图

叠加柱状图使用pygal.StackedBar 类来表示,程序使用pygal.StackedBar 创建叠加柱状图的步骤与创建普通柱状图的步骤基本相同。
示例

import pygal

x_data = ['2011', '2012', '2013', '2014', '2015', '2016', '2017']
# 定义两个列表分别作为两组柱状图的Y轴数据
y_data = [5800, 60200, 63000, 71000, 84000, 90500, 107000]
y_data2 = [52000, 54200, 51500, 58300, 56800, 59500, 62700]
# 创建pygal.StackedBar对象
stacked_bar = pygal.StackedBar()
# 添加两组数据
stacked_bar.add('产品1', y_data)
stacked_bar.add('产品2', y_data2)
# 设置X轴的刻度值
stacked_bar.x_labels = x_data
# 重新设置Y轴的刻度值
stacked_bar.y_labels = [20000, 40000, 60000, 80000, 100000]
stacked_bar.title = '产品历年销量'
# 设置X、Y轴的标题
stacked_bar.y_title = '年份'
stacked_bar.x_title = '销量'
# 设置将图例放在底部
stacked_bar.legend_at_bottom = True
# 指定将数据图输出到SVG文件中
stacked_bar.render_to_file('pygal_stacked_bar_test.svg')

SVG效果图:
在这里插入图片描述

(四)饼图

Pygal提供了pygal.Pie 类来支持饼图,支持如下两个特有的属性。

  • inner_radius:设置饼图内圈的半径。通过设置该属性可以实现环形数据图。
  • half_pie:将该属性设置为True,可以实现半圆的饼图。
    示例
import pygal

# 准备数据
data = [
    0.16881, 0.14966, 0.07471, 0.06992, 0.04762, 0.03541, 0.02925, 0.02411,
    0.02316, 0.01409, 0.36326
]
# 准备标签
labels = [
    'Java', 'C', 'C++', 'Python', 'Visual Basic.NET', 'c#', 'PHP',
    'JavaScript', 'SQL', 'Assembly langugage', '其它'
]
# 创建pygal.Pie对象
pie = pygal.Pie()
# 采用循环为饼图添加数据
for i, per in enumerate(data):
    pie.add(labels[i], per)
pie.title = '2018年8月编程语言排行'
# 设置将图例放在底部
pie.legend_at_bottom = True
# 设置内圈的半径长度
pie.inner_radius = 0.4
# 创建班员数据图
pie.half_pie = True
# 指定将数据图输出到SVG文件中
pie.render_to_file('language_percent.svg')

SVG效果图:
在这里插入图片描述

(五)点图

点图使用点( 圆) 的大小来表示数值的大小。Pygal 使用pygal.Dot 类表示点图,创建点图的方式与创建柱状图的方式基本相同。
示例

import pygal

x_data = ['2011', '2012', '2013', '2014', '2015', '2016', '2017']
# 定义两个列表分别作为两组柱状图的Y轴数据
y_data = [5800, 60200, 63000, 71000, 84000, 90500, 107000]
y_data2 = [52000, 54200, 51500, 58300, 56800, 59500, 62700]
# 创建pygal.Dot对象
dot = pygal.Dot()
dot.dots_size = 5
# 添加两组数据
dot.add('产品1', y_data)
dot.add('产品2', y_data2)
# 设置X轴的刻度值
dot.x_labels = x_data
# 重新设置Y轴的刻度值
dot.y_labels = ['产品1', '产品2']
# 设置Y轴刻度值的旋转角度
dot.y_label_rotation = 45
dot.title = '产品历年销量'
# 设置X轴的标题
dot.x_title = '年份'
# 设置将图例放在底部
dot.legend_at_bottom = True
# 指定将数据图输出的SVG文件中
dot.render_to_file('pygal_dot_test.svg')

SVG效果图:
在这里插入图片描述

(六)仪表(Gauge)图

仪表图类似于一个仪表盘,在仪表盘内使用不同的指针代表不同的数据。Pygal使用pygal.Gauge类表示仪表图。程序在创建pygal.Gauge对象之后,为pygal.Gauge 对象添加数据的方式与为pygal.Pie对象添加数据的方式相似。pygal.Gauge对象有一个特别的属性:range ,该属性用于指定仪表图的最小值和最大值。
示例

import pygal

# 准备数据
data = [
    0.16881, 0.14966, 0.07471, 0.06992, 0.04762, 0.03541, 0.02925, 0.02411,
    0.02316, 0.01409, 0.36326
]
# 准备标签
labels = [
    'Java', 'C', 'C++', 'Python', 'Visual Basic.NET', 'c#', 'PHP',
    'JavaScript', 'SQL', 'Assembly langugage', '其它'
]
# 创建pygal.Gauge对象
gauge = pygal.Gauge()
gauge.range = [0, 1]
# 采用循环为仪表图添加数据
for i, per in enumerate(data):
    gauge.add(labels[i], per)
gauge.title = '2018年8月编程语言'
# 设置将图例放在底部
gauge.legend_at_bottom = True
# 指定将数据图输出到SVG文件中
gauge.render_to_file('pygal_gauge_test.svg')

SVG效果图:
在这里插入图片描述

(七)雷达图

雷达图适合用于分析各对象在不同维度的优势和劣势,通过雷达图可对比每个对象在不同维度的得分。
假如我们从下表所示的5个方面(平台健壮性、语法易用性、社区活跃度、市场份额和未来趋势)的得分来评价各编程语言的优势。

平台健壮性语法易用性社区活跃度市场份额未来趋势
Java54.0555
C4.82.84.84.84.9
C++4.52.94.64.04.9
Python4.04.84.94.05
C#3.04.22.33.52
PHP4.84.33.93.04.5

雷达图示例

import pygal

# 准备数据
data = [[5, 4.0, 5, 5, 5], [4.8, 2.8, 4.8, 4.8, 4.9],
        [4.5, 2.9, 4.6, 4.0, 4.9], [4.0, 4.8, 4.9, 4.0, 5],
        [3.0, 4.2, 2.3, 3.5, 2], [4.8, 4.3, 3.9, 3.0, 4.5]]
# 准备标签
labels = ['Java', 'C', 'C++', 'Python', 'C#', 'PHP']
# 创建pygal.Radar对象
rader = pygal.Radar()
# 采用循环为雷达图添加数据
for i, per in enumerate(labels):
    rader.add(labels[i], data[i])
rader.x_labels = ['平台健壮性', '语法易用性', '社区活跃度', '市场份额', '未来趋势']
rader.title = '编程语言对比图'
# 控制各得分点的大小
rader.dots_size = 8
# 设置将图例放在底部
rader.legend_at_bottom = True
# 指定将数据图输出的SVG文件中
rader.render_to_file('language_compare.svg')

SVG效果图:
在这里插入图片描述

五、处理数据

(一)CSV文件格式

csv文件格式的本质是一种以文本存储的表格数据(使用Excel工具即可读写csv 文件) 。csv文件的每行代表一行数据,每行数据中每个单元格内的数据以逗号隔开。
Python提供了csv模块来读写csv文件。由于csv 文件的格式本身比较简单( 通常第一行是表头,用于说明每列数据的含义, 接下来每行代表一行数据) , 因此使用csv模块读取csv文件也非常简单。
① 创建CSV模块的读取器
② 循环调用CSV读取器的next()方法逐行读取CSV文件内容即可。next()方法返回一个list列表代表一行数据,list列表的每个元素代表一个单元格数据。
CSV数据读取示例

import csv

filename = 'guangzhou-2017.csv'
# 打开文件
with open(filename) as f:
    # 创建CSV读取器
    reader = csv.reader(f)
    # 读取第一行,这行是表头数据
    header_row = next(reader)
    print(header_row)
    # 读取第二行,这行是真正的数据
    first_row = next(reader)
    print(first_row)

使用Matplotlib结合CSV文件读取展示图表示例

import csv
from datetime import datetime
from matplotlib import pyplot as plt

filename = 'guangzhou-2017.csv'
# 打开文件
with open(filename) as f:
    # 创建CSV读取器
    reader = csv.reader(f)
    # 读取第一行,这行是表头数据
    header_row = next(reader)
    print(header_row)
    # 定义读取起始日期
    start_date = datetime(2017, 6, 30)
    # 定义读取结束日期
    end_date = datetime(2017, 8, 1)
    # 定义三个list列表作为展示的数据
    dates, highs, lows = [], [], []
    for row in reader:
        # 将第一列的值格式化为日期
        d = datetime.strptime(row[0], '%Y-%m-%d')
        # 只展示2017年7月的数据
        if start_date < d < end_date:
            dates.append(d)
            highs.append(int(row[1]))
            lows.append(int(row[2]))
# 配置图形
fig = plt.figure(dpi=128, figsize=(12, 9))
# 绘制最高气温的折线
plt.plot(dates,
         highs,
         c='red',
         label='最高气温',
         alpha=0.5,
         linewidth=2.0,
         linestyle='-',
         marker='v')
# 绘制最低气温的折线
plt.plot(dates,
         lows,
         c='blue',
         label='最低气温',
         alpha=0.5,
         linewidth=3.0,
         linestyle='-.',
         marker='o')
# 为两个数据的绘图区填充颜色
plt.fill_between(dates, highs, lows, facecolor='blue', alpha=0.1)
# 设置标题
plt.title("2017年7月广州最高气温和最低气温")
# 为两个坐标轴设置名称
plt.xlabel("日期")
# 该方法绘制歇着的日期标签
fig.autofmt_xdate()
plt.ylabel("气温(℃)")
# 显示图例
plt.legend()
ax = plt.gca()
# 设置右边坐标轴线的颜色
ax.spines['right'].set_color('none')
# 设置顶部坐标轴线的颜色
ax.spines['top'].set_color('none')
plt.show()

运行效果:
在这里插入图片描述
使用Pygal结合CSV读取展示数据图示例

import csv
import pygal

filename = 'guangzhou-2017.csv'
# 打开文件
with open(filename) as f:
    # 创建CSV读取器
    reader = csv.reader(f)
    # 读取第一行数据的表头信息
    header_row = next(reader)
    print(header_row)
    # 准备展示的数据
    shades, sunys, cloudys, rainys = 0, 0, 0, 0
    for row in reader:
        if '阴' in row[3]:
            shades += 1
        elif '晴' in row[3]:
            sunys += 1
        elif '云' in row[3]:
            cloudys += 1
        elif '雨' in row[3]:
            rainys += 1
        else:
            print(row[3])
# 创建pygal.pei对象
pie = pygal.Pie()
# 为饼图添加数据
pie.add("阴", shades)
pie.add("晴", sunys)
pie.add("多云", cloudys)
pie.add("雨", rainys)
pie.title = '2017年广州天气汇总'
# 设置图例放在底部
pie.legend_at_bottom = True
# 指定将数据图输出到SVG文件中
pie.render_to_file('pygal_guangzhou_weather.svg')

SVG效果:
在这里插入图片描述

(二)JSON数据

示例1

import json
from matplotlib import pyplot as plt
import numpy as np

filename = 'gdp_json.json'
# 读取JSON格式的GDP数据
with open(filename) as f:
    gdp_list = json.load(f)
# 使用list列表依次保存中国、美国、日本、俄罗斯、加拿大的GDP值
country_gdps = [{}, {}, {}, {}, {}]
country_codes = ['CHN', 'USA', 'JPN', 'RUS', 'CAN']
# 遍历列表的每个元素,每个元素都是一个GDP数据项
for gdp_dict in gdp_list:
    for i, country_code in enumerate(country_codes):
        # 只读取指定国家的数据
        if gdp_dict['Country Code'] == country_code:
            year = gdp_dict['Year']
            # 值读取从2001年到2016年的数据
            if 2017 > year > 2000:
                country_gdps[i][year] = gdp_dict['Value']
country_gdp_list = [[], [], [], [], []]
# 构建时间数据
x_data = range(2001, 2017)
for i in range(len(country_gdp_list)):
    for year in x_data:
        # 除以1e8,让数值变成以亿为单位
        country_gdp_list[i].append(country_gdps[i][year] / 1e8)
bar_width = 0.15
fig = plt.figure(dpi=128, figsize=(15, 9))
colors = ['indianred', 'steelblue', 'gold', 'lightpink', 'seagreen']
# 定义国家名称列表
countries = ['中国', '美国', '日本', '俄罗斯', '加拿大']
# 采用循环绘制5组柱状图
for i in range(len(colors)):
    # 使用自定义的X坐标将数据分开
    plt.bar(x=np.arange(len(x_data)) + bar_width * i,
            height=country_gdp_list[i],
            label=countries[i],
            color=colors[i],
            alpha=0.8,
            width=bar_width)
    # 仅在中国、美国的条柱上绘制GDP值
    if i < 2:
        for x, y in enumerate(country_gdp_list[i]):
            plt.text(x, y + 100, '%.0f' % y, ha='center', va='bottom')
# 为X轴设置刻度值
plt.xticks(np.arange(len(x_data)) + bar_width * 2, x_data)
# 设置标题
plt.title("从2001年到2016年各国GDP对比")
# 为两个坐标轴设置名称
plt.xlabel("年份")
plt.ylabel("GDP(亿美元)")
# 显示图例
plt.legend()
plt.show()

运行效果:
在这里插入图片描述

(三)数据清洗

当程序使用Python 进行数据展示时,经常发现数据存在以下两种情况。

  • 数据丢失
  • 数据格式错误
    对于数据丢失的情况,程序应i亥生成报告:对于数据格式发生错误的情况, 程序应该能略过发生错误的数据,继续处理后面的程序,并报告发生错误的数据。

(四)读取网络数据

示例 爬取并展示http://lishi.tianqi.com站点的数据

import re
from datetime import datetime
from datetime import timedelta
from matplotlib import pyplot as plt
from urllib.request import *


# 定义一个函数读取http://lishi.tianqi.com站点的数据
def get_html(city, year, month):
    url = 'http://lishi.tianqi.com/' + city + '/' + str(year) + str(
        month) + '.html'
    # 创建请求
    request = Request(url)
    # 添加请求头
    request.add_header(
        'User-Agent', 'Mozilla/5.0 (Windows NT 10.0; WOW64)' +
        'AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36'
    )
    response = urlopen(request)
    # 获取服务器响应
    return response.read().decode('utf-8')


# 定义三个list列表作为展示的数据
dates, highs, lows = [], [], []
city = 'chongqing'
year = '2018'
months = [
    '01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12'
]
prev_day = datetime(2017, 12, 31)
# 循环读取每个月的天气数据
for month in months:
    html = get_html(city, year, month)
    # 将HTML响应拼接起来
    text = "".join(html.split())
    # 定义包含天气信息的div的正则表达式
    patten = re.compile(r'<ulclass="lishitable_contentclearfix">(.*?)</ul>')
    table = re.findall(patten, text)
    patten1 = re.compile(r'<li.*?>(.*?)</li>')
    uls = re.findall(patten1, table[0])
    # 去除最后一个包含“查看更多”的<li>
    uls = uls[:-1]
    for ul in uls:
        # 定义解析天气信息的正则表达式
        patten2 = re.compile(r'<div.*?>(.*?)</div>')
        lis = re.findall(patten2, ul)
        print(lis)
        # 解析得到日期数据
        d_str = re.findall(r'">(.*?)</a>', lis[0])[0]
        try:
            # 将日期字符串格式化为日期
            cur_day = datetime.strptime(d_str, '%Y-%m-%d')
            # 解析得到最高气温和最低气温
            high = int(lis[1])
            low = int(lis[2])
        except ValueError:
            print(cur_day, '数据出现错误')
        else:
            # 计算前、后两天数据的时间差
            diff = cur_day - prev_day
            # 如果前、后两天数据的时间差不是相差一天,则说明数据有问题
            if diff != timedelta(days=1):
                print('%s之间少了%d天的数据' % (cur_day, diff.days - 1))
            dates.append(cur_day)
            highs.append(high)
            lows.append(low)
            prev_day = cur_day
# 配置图形
fig = plt.figure(dpi=128, figsize=(12, 9))
# 绘制最高气温的折线
plt.plot(dates, highs, c='red', label='最高气温', alpha=0.5, linewidth=2.0)
# 绘制最低气温的折线
plt.plot(dates, lows, c='blue', label='最低气温', alpha=0.5, linewidth=2.0)
# 为两个数据的绘图区域填充颜色
plt.fill_between(dates, highs, lows, facecolor='blue', alpha=0.1)
# 设置标题
plt.title("%s年重庆最高气温和最低气温" % year)
# 为两个坐标轴设置名称
plt.xlabel("日期")
# 该方法绘制斜着的日期标签
fig.autofmt_xdate()
plt.ylabel("气温(℃)")
# 显示图例
plt.legend()
ax = plt.gca()
# 设置右边坐标线不显示
ax.spines['right'].set_color('none')
# 设置顶部坐标线不显示
ax.spines['top'].set_color('none')
plt.show()

运行效果:
在这里插入图片描述

练习

1.使用Matplotlib生成折线图,分析自己在两个月内体重变化与运动时间之间的关系。

import matplotlib.pyplot as plt

# 定义两个列表分别作为X轴、Y轴数据
# Y轴代表运动时间,X轴代表体重
y_data = [
    '60分钟', '30分钟', '45分钟', '60分钟', '30分钟', '45分钟', '60分钟', '30分钟', '45分钟',
    '60分钟', '30分钟', '45分钟', '60分钟', '30分钟', '45分钟', '60分钟', '30分钟', '45分钟',
    '60分钟', '30分钟', '45分钟', '60分钟', '30分钟', '45分钟', '60分钟', '30分钟', '45分钟',
    '60分钟', '30分钟', '45分钟'
]
x_data = [
    68, 67.5, 67, 66, 66.5, 66, 65.5, 65, 64.5, 64, 64.5, 64, 63.5, 63, 64, 63,
    62.5, 62, 61.5, 61, 61.5, 60, 59.5, 59, 58.5, 58, 57.5, 57, 56.5, 56
]
# 第一个列表代表横坐标的值,第二个列表代表纵坐标的值
plt.plot(x_data, y_data)
# 调用show()函数显示图形
plt.show()

2.使用Pygal生成饼图,分析本年度自己在生活、教育学习、健身、旅游、娱乐各方面的时间投入和金钱投入。

import pygal

# 准备数据
data = [191400, 50000, 1000, 30000, 110000]
data1 = [365, 100, 125, 30, 200]
# 准备标签
labels = ['生活', '教育学习', '健身', '旅游', '娱乐']
# 创建pygal.Pie对象
pie = pygal.Pie()
# 采用循环为饼图添加数据
for i, per in enumerate(data):
    pie.add(labels[i], per)
pie.title = '2019年消费投入图'
# 设置将图例放在底部
pie.legend_at_bottom = True
# 设置内圈的半径长度
pie.inner_radius = 0.4
# 指定将数据图输出到SVG文件中
pie.render_to_file('my.svg')

# 创建pygal.Pie对象
pie1 = pygal.Pie()
# 采用循环为饼图添加数据
for i, per in enumerate(data1):
    pie1.add(labels[i], per)
pie1.title = '2019年时间投入图'
# 设置将图例放在底部
pie1.legend_at_bottom = True
# 设置内圈的半径长度
pie1.inner_radius = 0.5
# 指定将数据图输出到SVG文件中
pie.render_to_file('my1.svg')

3.使用随机数生成5000 个(-3, -3 )~(3,3 )范围的点,并使用散点图绘制它们。

import matplotlib.pyplot as plt
import random

plt.figure()
x_data, y_data = [], []
for i in range(5000):
    x_data.append(random.uniform(-3, 3))
for i in range(5000):
    y_data.append(random.uniform(-3, 3))
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.scatter(x_data,
            y_data,
            c='purple',
            s=50,
            alpha=0.5,
            marker='p',
            linewidths=1,
            edgecolors=['green', 'yellow'])
# 绘制第二个散点图(只包含一个起点),突出起点
plt.scatter(x_data[0], y_data[0], c='red', s=150, alpha=1)
# 绘制第三个散点图(只包含一个结束点),突出结束点
plt.scatter(x_data[4999], y_data[4999], c='black', s=150, alpha=1)
plt.gca().spines['right'].set_color('none')
plt.gca().spines['top'].set_color('none')
plt.gca().spines['bottom'].set_position(('data', 0))
plt.gca().spines['left'].set_position(('data', 0))
plt.title('随机数的散点图')
plt.show()

4.从https://www.tiobe.com/tiobe-index/网站查找2018年各月Python和Java两门语言的市场份额,并绘制它们的柱状图进行对比。

import csv, pygal

filename = 'exercise\language.csv'
x_data = ['0' + str(i + 1) for i in range(12)]
java_data = [0] * 12
python_data = [0] * 12
# 打开文件
with open(filename) as f:
    reader = csv.reader(f)
    header_row = next(reader)
    for row in reader:
        # Java的数据
        if row[0] == 'java':
            java_data[int(row[2][5:]) - 1] = float(row[1])
        # Python的数据
        elif row[0] == 'python':
            python_data[int(row[2][5:]) - 1] = float(row[1])
bar = pygal.Bar()
bar.add('Java', java_data)
bar.add('python', python_data)
bar.x_labels = x_data
bar.title = '2018年各月Java与Python市场份额对比图'
bar.x_title = '月份'
bar.y_title = '份额'
bar.legend_at_bottom = True
bar.render_to_file('language.svg')

5.从https://datahub.io网站下载世界各国的人口数据,并绘制中国、印度历年人口变化的折线图。

import json
import pygal

pop_filename = 'exercise\\population-figures-by-country.json'
# 读取JSON格式的人口数据
with open(pop_filename) as f:
    pop_list = json.load(f)

# 构建时间数据
x_data = range(1970, 2017)
# 使用list列表依次保存中国、印度的人口
country_pops_list = [[], []]
for pop_dict in pop_list:
    # 获取中国的人口数据
    if pop_dict['Country_Code'] == 'CHN':
        for year in x_data:
            country_pops_list[0].append(pop_dict['Population_in_%d' % year] /
                                        10000)
    # 获取印度的人口数据
    if pop_dict['Country_Code'] == 'IND':
        for year in x_data:
            country_pops_list[1].append(pop_dict['Population_in_%d' % year] /
                                        10000)
# 定义国家名称列表
countries = ['中国', '印度']
# 创建pygal.Bar对象
bar = pygal.Bar()
# 采用循环添加代表条柱的数据
for i in range(len(countries)):
    bar.add(countries[i], country_pops_list[i])
bar.width = 1100
# 设置X轴的刻度值
bar.x_labels = x_data
bar.title = '1970-2016年中国印度人口对比'
bar.x_title = '年份'
bar.y_title = '人口(万)'
# 设置X轴的刻度值旋转45度
bar.x_label_rotation = 45
# 设置将图例放在底部
bar.legend_at_bottom = True
# 将数据图输出到文件
bar.render_to_file('population.svg')

6.从http://lishi.tianqi.com网站读取深圳的2017年历史天气数据,并绘制最高气温、最低气温的折线图。

import re
from datetime import datetime
from datetime import timedelta
from matplotlib import pyplot as plt
from urllib.request import *


# 定义一个函数读取http://lishi.tianqi.com站点的数据
def get_html(city, year, month):
    url = 'http://lishi.tianqi.com/' + city + '/' + str(year) + str(
        month) + '.html'
    # 创建请求
    request = Request(url)
    # 添加请求头
    request.add_header(
        'User-Agent', 'Mozilla/5.0 (Windows NT 10.0; WOW64)' +
        'AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36'
    )
    response = urlopen(request)
    # 获取服务器响应
    return response.read().decode('utf-8')


# 定义三个list列表作为展示的数据
dates, highs, lows = [], [], []
city = 'shenzhen'
year = '2017'
months = [
    '01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12'
]
prev_day = datetime(2016, 12, 31)
# 循环读取每个月的天气数据
for month in months:
    html = get_html(city, year, month)
    # 将HTML响应拼接起来
    text = "".join(html.split())
    # 定义包含天气信息的div的正则表达式
    patten = re.compile(r'<ulclass="lishitable_contentclearfix">(.*?)</ul>')
    table = re.findall(patten, text)
    patten1 = re.compile(r'<li.*?>(.*?)</li>')
    uls = re.findall(patten1, table[0])
    # 去除最后一个包含“查看更多”的<li>
    uls = uls[:-1]
    for ul in uls:
        # 定义解析天气信息的正则表达式
        patten2 = re.compile(r'<div.*?>(.*?)</div>')
        lis = re.findall(patten2, ul)
        print(lis)
        # 解析得到日期数据
        d_str = re.findall(r'">(.*?)</a>', lis[0])[0]
        try:
            # 将日期字符串格式化为日期
            cur_day = datetime.strptime(d_str, '%Y-%m-%d')
            # 解析得到最高气温和最低气温
            high = int(lis[1])
            low = int(lis[2])
        except ValueError:
            print(cur_day, '数据出现错误')
        else:
            # 计算前、后两天数据的时间差
            diff = cur_day - prev_day
            # 如果前、后两天数据的时间差不是相差一天,则说明数据有问题
            if diff != timedelta(days=1):
                print('%s之间少了%d天的数据' % (cur_day, diff.days - 1))
            dates.append(cur_day)
            highs.append(high)
            lows.append(low)
            prev_day = cur_day
# 配置图形
fig = plt.figure(dpi=128, figsize=(12, 9))
# 绘制最高气温的折线
plt.plot(dates, highs, c='red', label='最高气温', alpha=0.5, linewidth=2.0)
# 绘制最低气温的折线
plt.plot(dates, lows, c='blue', label='最低气温', alpha=0.5, linewidth=2.0)
# 为两个数据的绘图区域填充颜色
plt.fill_between(dates, highs, lows, facecolor='blue', alpha=0.1)
# 设置标题
plt.title("%s年重庆最高气温和最低气温" % year)
# 为两个坐标轴设置名称
plt.xlabel("日期")
# 该方法绘制斜着的日期标签
fig.autofmt_xdate()
plt.ylabel("气温(℃)")
# 显示图例
plt.legend()
ax = plt.gca()
# 设置右边坐标线不显示
ax.spines['right'].set_color('none')
# 设置顶部坐标线不显示
ax.spines['top'].set_color('none')
plt.show()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值