目录
绘制等高线图(contour())
绘制矢量场流线图(streamplot())
绘制棉棒图(stem())
绘制哑铃图
绘制甘特图
绘制人口金字塔图
绘制漏斗图
绘制桑基图(Sankey())
绘制华夫饼图
contour(X,Y, # 表示坐标点的网格数据
Z, # 表示坐标点对应的高度数据
levels, # 表示等高线的数量。若levels为n,则说明绘制n+1条等高线
colors, # 表示不同高度的等高线颜色
cmap, # 表示颜色映射表
linewidths, # 表示等高线的宽度
linestyle # 表示等高线的线型
)
# 绘制等高线图
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
plt.rcParams['font.sans-serif'] = ['KaiTi']
plt.rcParams['axes.unicode_minus'] = False
# 计算高度
def calcu_elevation(x1, y1):
h = (1-x1/2 + x**5 + y1**3) * np.exp(-x1**2 - y1**2) # np.exp(x) 为e的x幂次方, (1-x1/2 + x**5 + y1**3) * np.exp(-x1**2 - y1**2)求高度的公式一致
return h
# 数据
n = 256
x = np.linspace(-2, 2, n)
y = np.linspace(-2, 2, n)
# 利用meshgrid() 函数生成网格数据
x_grid, y_grid = np.meshgrid(x, y) # 将x中每一个数据和y中每一个数据组合生成很多点,然后将这些点的x坐标放入到x_grid中,y坐标放入y_grid 中,并且相应位置是对应的
# 画布
fig = plt.figure()
ax = fig.add_subplot(111)
# 绘制等高线
con = ax.contour(x_grid, y_grid, # 网格数据
calcu_elevation(x_grid, y_grid), # 高度
8, # 等高线数量
colors='black' # 不同高度的等高线颜色
)
# 填充等高线的颜色
ax.contourf(x_grid, y_grid, # 网格数据
calcu_elevation(x_grid, y_grid), # 高度
8, # 等高线数量
alpha=0.75, # 透明度
cmap=plt.cm.copper # 颜色映射表
)
# 为等高线添加文字标签
ax.clabel(con, # 要标记的等高线图
inline=True, # 删除放置标签的基础轮廓。
fmt='%1.1f', # 标签的格式字符串
fontsize=10
)
ax.set_xticks([]) # 空标签
ax.set_yticks([])
ax.set_title('等高线图')
plt.show()
# 常用参数
streamplot([x, y,] # 表示间距均匀的网格数据
u, v, # 表示(x, y)速率的二维数组
density=1, # 表示流线的密度
linewidth=None, # 表示流线的宽度
arrowsize, # 表示箭头的类型
minlength, # 表示流线的最小长度
maxlength # 表示流线的最大长度
)
# 绘制矢量场流线图
y, x = np.mgrid[0:5:50j, 0:5:50j] # 生成两个均匀的50行50列的网格数据是二维数组
u = x
v = y
fig = plt.figure()
ax = fig.add_subplot(111)
# 绘制矢量场流线图
ax.streamplot(x, y, # 间距均匀的网格数据
u, v, # (x, y)速率的二维数组
density=2, # 流线的密度
)
plt.show()
makerline, stemlines, baseline = \n
ax.stem([x,] y, # 表示茎的x值和茎头的y值
linefmt=None, # 表示茎属性的字符串
markerfmt=None, # 表示茎头属性的字符串
basefmt=None, # 表示基线属性的字符串
bottom=0, # 表示基线的y值
label=None, # 表示应用于图例的标签
use_line_collection=False # 若为True,则将棉棒图的所有线段存储到一个LineCollection类对象中;若为False,则将棉棒图的所有线段存储到列表中
)
'''
stem()函数会返回一个形如(markertline,stemlines,basline)的元组,其中元组的第1个元素markerline为代表棉棒图标记的Line2D对象,
第2个元素stemlines为代表棉棒图线段的Line2D对象,第3个元素baseline为代表基线的Line2D对象
'''
# 绘制棉棒图
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
plt.rcParams['font.sans-serif'] = ['KaiTi']
plt.rcParams['axes.unicode_minus'] = False
# 数据
x = np.arange(1, 16)
y = np.array([5.9, 6.2, 6.7, 7.0, 7.0, 7.1, 7.2, 7.4,
7.5, 7.6, 7.7, 7.7, 7.7, 7.8, 7.9])
labels = np.array(['宝骏310', '宝马i3', '致享', '焕驰', '力帆530',
'派力奥', '悦翔V3', '乐风RV', '奥迪A1', '威驰FS',
'夏利N7', '启辰R30', '和悦A13RS', '致炫', '赛欧'])
# 画布
fig = plt.figure(figsize=(10, 6), dpi=80) # dpi指定每个长度单位像素量
ax = fig.add_subplot(111)
# 绘制棉棒图
makerline, stemlines, baseline = ax.stem(x, # 茎值
y, # 茎头值
linefmt='--', # 茎属性字符串为虚线
markerfmt='o', # 茎头标记为o
label='Teststem', # 图例标签
use_line_collection=True # 将棉棒图的所有线段存储到一个LineCollection类对象中
)
# 设置棉棒图线段的属性
# setp()函数:设置元素属性
plt.setp(stemlines, lw=1) # lw=linewidth 线宽度
# 轴和标题设置
ax.set_title('不同品牌轿车的燃料消耗量', fontdict={'size':18})
ax.set_ylabel('燃料消耗量(L/km)')
ax.set_xticks(x)
ax.set_xticklabels(labels, # x轴标签
rotation=60 # 标签呈60度方向
)
ax.set_ylim([0, 10])
# 无指向性注释文本
for temp_x, temp_y in zip(x, y):
ax.text(temp_x, temp_y+0.5, # 注释文本的位置
s='{}'.format(temp_y), # 注释文本
ha='center',
va='bottom', # 上方
fontsize=14 # 字体大小
)
plt.show()
# 绘制哑铃图
import pandas as pd
import matplotlib.lines as mlines
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['KaiTi']
plt.rcParams['axes.unicode_minus'] = False
# 读取数据
df = pd.read_excel('./第八章data/health.xlsx')
# 处理数据
df.sort_values('pct_2014', inplace=True) # 将'pct_2014'排序 # inplace=True即替换
df.reset_index(inplace=True) # 重置索引直接生成一个新DataFrame或Series
df = df.sort_values(by='index') # 按新增列索引排序
# df['排名'] = df['index']+1
def newline(p1, p2, color='black'):
ax = plt.gca() # 获取当前的绘图区域
l = mlines.Line2D([p1[0], p2[0]], [p1[1], p2[1]], color='skyblue')
ax.add_line(l)
# print(ax.add_line)
return l
fig, ax = plt.subplots(1, 1, figsize=(8,6))
# 绘制散点
ax.scatter(y=df['index'], x=df['pct_2013'], # 数据点位置
s=50, # 标记大小
color='#0e668b', # 颜色
alpha=0.7 # 透明度
)
ax.scatter(y=df['index'], x=df['pct_2014'],# 数据点位置
s=50,# 标记大小
color='#a3c4dc', # 颜色
alpha=0.7 # 透明度
)
# 绘制线条
for i, p1, p2 in zip(df['index'], df['pct_2013'], df['pct_2014']):
newline([p1, i], [p2, i]) # 两点之间的线条距离,调用 newline方法绘制哑铃图
# print([p1, i], [p2, i])
ax.set_title('2013年与2014年美国部分城市人口PCT指标的变化率', fontdict={'size':12})
ax.set_xlim(0, .25)
ax.set_xticks([.05, .1, .15, .20]) # 5%,10%,15%,20%
ax.set_xticklabels(['5%', '10%', '15%', '20%'])
ax.set_xlabel('变化率')
ax.set_yticks(df['index'])
ax.set_yticklabels(df['city'])
ax.grid(alpha=0.5, # 网格透明度
axis='x' # 只生成x方轴的网格
)
plt.show()
# 绘制甘特图
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
plt.rcParams['font.sans-serif'] = ['KaiTi']
plt.rcParams['axes.unicode_minus'] = False
# 数据
ticks = np.array(['报告提交','数据分析','数据录入','实地执行',
'问卷确定','试访','问卷设计','项目确定'])
y_data = np.arange(1,9)
x_data = np.array([0.5, 1.5, 1, 3, 0.5, 1, 1, 2])
# 画布
fig, ax = plt.subplots(1, 1)
ax.barh(y_data, # 条形的y坐标值
x_data, # 条形图的长度
tick_label=ticks, # 设置y轴坐标标签
left=[7.5, 6, 5.5, 3, 3, 2, 1.5, 0], # 条形左侧x的左边,默认从0开始,即设置条形到y轴的距离
color='#CD5C5C' # 设置条形图的颜色
)
[ax.spines[i].set_visible(False) for i in ['top', 'right']] # 隐藏上轴脊和右轴脊ax.spines['top'].set_visible(False)
ax.set_title("任务甘特图")
ax.set_xlabel('日期')
ax.grid(alpha=0.5, axis='x')
plt.show()
# 绘制人口金字塔图
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
plt.rcParams['font.sans-serif'] = ['KaiTi']
plt.rcParams['axes.unicode_minus'] = False
# 读数据
df = pd.read_excel('./第八章data/population.xlsx')
df_male = df.groupby(by='Gender').get_group('Male') # 性别按Male分组
list_male = df_male['Number'].values.tolist() # 取出人口数,将ndarray转换为list
df_female = df.groupby(by='Gender').get_group('Female') # 性别按Female分组
list_female = df_female['Number'].values.tolist() # 取出人口数,将ndarray转换为list
df_age = df.groupby('AgeGroup').sum()
count = df_age.shape[0] # 10
y = np.arange(1, 11)
labels = []
for i in range(count):
age = df_age.index[i] # 取出年龄段
labels.append(age)
# 画布
fig = plt.figure()
ax = fig.add_subplot(111)
# 绘制人口金字塔图
ax.barh(y, # 条形的y坐标值
list_male, # 条形图的长度
tick_label=labels, # 设置y轴坐标标签
label='男', # 设置图例标签
color='#6699FF'
)
ax.barh(y, # 条形的y坐标值
list_female, # 条形图的长度
tick_label=labels, # 设置y轴坐标标签
label='女', # 设置图例标签
color='#CC6699'
)
# 设置轴标签和标题
ax.set_ylabel("年龄段(岁)")
ax.set_xticks([-100000, -75000, -50000, -25000,
0, 25000, 50000, 75000, 100000])
ax.set_xticklabels(['100000', '75000',' 50000', '25000',
'0', '25000', '50000', '75000', '100000'])
ax.set_xlabel("人数")
ax.set_title("某城市人口金字塔")
ax.legend() # 执行图例
plt.show()
# 绘制漏斗图
import numpy as np
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = 'SimHei'
plt.rcParams['axes.unicode_minus'] = False
# 数据
num = 5
height = 0.5
x1 = np.array([1000, 500, 300, 200, 150]) # 各环节的客户数量
x2 = np.array((x1.max() - x1) / 2) # [ 0. 250. 350. 400. 425.]
x3 = [i +j for i, j in zip(x1, x2)] # [1000.0, 750.0, 650.0, 600.0, 575.0]
x3 = np.array(x3)
y = -np.sort(-np.arange(num)) # 倒转y轴 [4 3 2 1 0]
# 标签
labels=['访问商品', '加购物车', '生成订单', '支付订单', '完成交易']
# 画布
fig = plt.figure(figsize=(10, 8))
ax = fig.add_subplot(111)
# 绘制条形图
rects1 = ax.barh(y, # 条形的y坐标值
x3, # 条形图的长度
height, # 条形的宽度
tick_label=labels, # 设置y轴坐标标签
color='g', # 设置条形图的颜色
alpha=0.5 # 透明度
)
# 绘制辅助条形图
rects2 = ax.barh(y, # 条形的y坐标值
x2, # 条形图的长度
height, # 条形的宽度
color='r', # 把r变成w也就是白色,将会消失
alpha=1
)
# 绘制右折线
ax.plot(x3,
y,
'black',
alpha=0.7
)
# 绘制左折线
ax.plot(x2,
y,
'black',
alpha=0.7
)
# 添加无指向型注释文本
notes = []
for i in range(0, len(x1)):
notes.append('%.2f%%'%((x1[i] / x1[0]) * 100)) # 百分数
for rect_one, rect_two, note in zip(rects1, rects2, notes):
# rect_one Rectangle(xy=(0, 3.75), width=1000, height=0.5, angle=0)......
# rect_two Rectangle(xy=(0, 3.75), width=0, height=0.5, angle=0)..........
text_x = rect_two.get_width() + (rect_one.get_width() - rect_two.get_width()) / 2 - 30 # 选取每个条形图中间的位置下30
text_y = rect_one.get_y() + height / 2 # 选取y轴坐标加上每个条形宽度的一半
ax.text(text_x, text_y, # 注释文本位置
note, # 注释文本
fontsize=12
)
# 隐藏轴脊和刻度
ax.set_xticks([]) # 空列表即没有值
# 隐藏所有轴脊
for direction in ['top', 'left', 'bottom', 'right']:
ax.spines[direction].set_color('none')
ax.yaxis.set_ticks_position('none') # 隐藏y轴刻度线
plt.show()
'''
from matplotlib.sankey import Sankey
1.创建桑基图
常用参数:
Sankey(ax=None, # 若不提供该参数,则会创建一个新的坐标轴
scale=1.0, # 表示流量比例因子,用于按比例调整分支的宽度
unit='', # 表示与流量相关的物理单位的字符串。若为None,则不会做数量标记
gap=0.25 # 表示进入或离开顶部的分支间距,默认为0.25
)
'''
# 例如,创建一个桑基图的代码如下:
sankey = Sankey(ax=None,gap=0.3)
'''
2.添加桑基图的选项
Sankey类对象可以调用add()方法为桑基图添加数据流量、标签等选项。add()方法的语法格式如下:
常用参数:
add(patchlabel='', # 表示位于图标中心的标签
flows=None, # 表示流量数据的数组,其中投入数据为正值,产生数据为负值
orientations=None, # 表示流的方向列表或用于所有流的单个方向,可以取值为0(从左侧输入、右侧输出)、1(从顶部到顶部)或-1(从底部到底部)
labels, # 表示流的标签列表或用于所有流的单个标签
trunklength # 表示输入组和输出组的基之间的长度
)
'''
# 例如,为刚刚创建的桑基图sankey添加流的数据和标签,具体代码如下:
flows = [0.7, 0.3, -0.3, -0.1, -0.3, -0.1, -0.1, -0.1]
labels = ['工资', '副业', '生活', '购物', '深造', '运动', '其他', '买书']
sankey.add(flows=flows,labels=labels)
'''
Sankey类对象在添加数据之后需要调用finish()方法完成绘制,并返回包含多个桑基子图的列表。桑基子图包含以下字段:
patch:表示桑基子图的轮廓
flows:表示流量值(输入为正,输出为负)
angles:表示箭头角度的列表
tips:表示流路径的尖端或凹陷位置的数组,其中每一行是一个(x, y)
text:表示中心标签的Text实例
texts:表示流分支标签的Text实例
'''
举例
'''
假设现在小明家日常生活的开支主要分为工资、副业、生活、购物、深造、运动、买书和其它几类,
且其中每项投入或产出值分别为0.7, 0.3, -0.3, -0.1, -0.3, -0.1, -0.1, -0.1。下面结合这些日常生活开支的数据绘制一个桑基图,示例代码如下:
'''
import matplotlib.pyplot as plt
from matplotlib.sankey import Sankey
plt.rcParams["font.sans-serif"] = ["SimHei"]
plt.rcParams["axes.unicode_minus"] = False
# 消费收入与支出数据
flows = [0.7, 0.3, -0.3, -0.1, -0.3, -0.1, -0.1, -0.1]
# 流的标签列表
labels = ["工资", "副业", "生活", "购物", "深造", "运动", "其他", "买书"]
# 流的方向
orientations = [1, 1, 0, -1, 1, -1, 1, 0]
# 创建 Sankey 类对象
sankey = Sankey()
# 为桑基图添加数据
sankey.add(flows=flows, # 收入与支出数据
labels=labels, # 数据标签
orientations=orientations, # 标签显示的方向
color="black", # 边缘线条颜色
fc="lightgreen", # 填充颜色
patchlabel="生活消费 ", # 图表中心的标签
alpha=0.7) # 透明度
# 桑基图绘制完成的对象
diagrams = sankey.finish()
diagrams[0].texts[4].set_color("r") # 将下标为 4 的数据标签设为红色
diagrams[0].texts[4].set_weight("bold") # 将下标为 4 的数据标签设为字体加粗
diagrams[0].text.set_fontsize(20) # 将中心标签的字体大小设为20
diagrams[0].text.set_fontweight("bold") # 将中心标签的字体设为加粗
plt.title("日常生活开支的桑基图")
plt.show()
'''
pywaffle的安装
开发者可以直接使用pip命令安装pywaffle包。
打开命令提示符工具,在提示符的后面输入命令:pip install pywaffle
以上命令执行后,若命令提示符窗口出现如下字样,说明pywaffle包安装完成:
Installing collected packages: pywaffle
Successfully installed pywaffle-0.4.1
安装完成后,在提示符的后面输入python,之后输入如下导入语句进行验证:
from pywaffle import Waffle
执行以上语句后,若命令提示符窗口没有出现任何错误信息,说明pywaffle安装成功,否则说明安装失败。
'''
'''
pywaffle的使用
pywaffle是Python中专门绘制华夫饼图的包,它提供了一个继承自Figure的子类Waffle,
通过将Waffle类传递给figure()函数的FigureClass参数即可创建一个华夫饼图。
FigureClass:可以是Figure类或Figure子类。
rows:表示华夫饼图的行数。
columns:表示华夫饼图的列数。
values:表示数据,可以接收数组或字典。若values参数接收一个字典,则将字典的键作为华夫饼图的图例项。
colors:表示每个分类数据的颜色列表。
vertical:表示是否按垂直方向绘制华夫饼图,默认为False。
title:表示标题,可以接收一个字典,其中字典的键为title()函数的关键字参数。
legend:表示图例,可以接收一个字典,其中字典的键为legend()函数的关键字参数。
'''
# 例如,创建一个10行10列的华夫饼图,具体代码如下:
plt.figure(FigureClass=Waffle, # 指定画布类为Waffle
rows=10, # 行数设为10
columns=10, # 列数设为10
values=[45, 55], # 一组数据
)
举例
'''
pywaffle的使用
pywaffle是Python中专门绘制华夫饼图的包,它提供了一个继承自Figure的子类Waffle,
通过将Waffle类传递给figure()函数的FigureClass参数即可创建一个华夫饼图。
FigureClass:可以是Figure类或Figure子类。
rows:表示华夫饼图的行数。
columns:表示华夫饼图的列数。
values:表示数据,可以接收数组或字典。若values参数接收一个字典,则将字典的键作为华夫饼图的图例项。
colors:表示每个分类数据的颜色列表。
vertical:表示是否按垂直方向绘制华夫饼图,默认为False。
title:表示标题,可以接收一个字典,其中字典的键为title()函数的关键字参数。
legend:表示图例,可以接收一个字典,其中字典的键为legend()函数的关键字参数。
'''
# 例如,创建一个10行10列的华夫饼图,具体代码如下:
plt.figure(FigureClass=Waffle, # 指定画布类为Waffle
rows=10, # 行数设为10
columns=10, # 列数设为10
values=[45, 55], # 一组数据
)