文章目录
- Study:day13-数据可视化之Matplotlib模块
- 1.1 折线图进阶
- 1.1.1 进阶折线图-双Y轴折线图
- 1.1.2 进阶折线图-双子图
- 1.1.3 进阶折线图-堆叠面积图
- 1.2 柱形图
- 1.2.1 基础柱形图-单数据系列
- 1.2.2 柱形图进阶-圆角柱形图
- 1.2.3 多系列柱形图
- 1.3 柱形图进阶-堆叠柱形图
Study:day13-数据可视化之Matplotlib模块
昨日内容:
- Scienceplot主题的使用
- 主题的使用方法:
- 全局使用: plt.style.use
- 局部使用: with plt.style.context
- 字体从处理:
- 方案1: 全局字体的设定: plt.rcParams[font.sans-serif] = ‘字体’
- 全局字体位置在什么地方找
- 方案2: 全局字体+局部字体设定(重要)
- 方案3: 调用LaTeX绘制图表(了解)
- 图表的存储:
- 存储的格式: png/pdf/svg
- 存储DPI设定(200-300)
- 图表裁剪白边
- 图表背景色设置透明
- 画布的创建: plt.figure
- 画布的大小
- 画布的分辨率
- 子图的创建:
- plt.subplots(重要)
- plt.subplot(重要)
- plt.axes(了解)
- 基本折线图的绘制:
- 折线图绘制方法:
- 折线图参数设定
- plt.fill_bewtten:填充
- plt.legend图例参数的设定
1.1 折线图进阶
1.1.1 进阶折线图-双Y轴折线图
import pandas as pd
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
import sysprint('Python version:', sys.version)
print('Pandas version:', pd.__version__)
print('Numpy version:', np.__version__)
print('Matplotlib version:', matplotlib.__version__)
Python version: 3.12.3 | packaged by conda-forge | (main, Apr 15 2024, 18:20:11) [MSC v.1938 64 bit (AMD64)]
Pandas version: 2.2.2
Numpy version: 1.26.4
Matplotlib version: 3.9.2
data = pd.read_csv('./data/economics.csv')
data.head()
date | pce | pop | psavert | uempmed | unemploy | |
---|---|---|---|---|---|---|
0 | 1967-07-01 | 507.4 | 198712 | 12.5 | 4.5 | 2944 |
1 | 1967-08-01 | 510.5 | 198911 | 12.5 | 4.7 | 2945 |
2 | 1967-09-01 | 516.3 | 199113 | 11.7 | 4.6 | 2958 |
3 | 1967-10-01 | 512.9 | 199311 | 12.5 | 4.9 | 3143 |
4 | 1967-11-01 | 518.1 | 199498 | 12.5 | 4.7 | 3066 |
import matplotxplt.rcParams['font.sans-serif'] = ['STsong']
plt.rcParams['font.size'] = 15
plt.style.use(matplotx.styles.pitaya_smoothie['light'])fig = plt.figure(figsize=(16, 9), dpi=100)plt.plot(data['date'], data['psavert'], label='个人存储率', color='#ff7f0e', linewidth=1.2, linestyle='--')
plt.ylim(0, 18)
plt.ylabel('个人存储率', color='#ff7f0e')
plt.tick_params(axis='y', colors='#ff7f0e') # 设置y轴刻度标签的颜色plt.title('个人存储率与失业人数对比折线图')
# plt.legend(loc='upper right',ncols=2,labelcolor='linecolor')
plt.twinx() # 让两个图标共享x轴plt.plot(data['date'], data['unemploy'], label='失业人数', color='red', linewidth=1.2)
plt.ylim(0, 18000)
plt.ylabel('失业人数', color='red')
plt.tick_params(axis='y', colors='red') # 设置y轴刻度标签的颜色plt.xticks(np.arange(0, len(data), 40), rotation=45)# plt.legend(loc='upper left',ncols=2,labelcolor='linecolor')fig.legend(loc=1, prop={'family': 'STsong'}, bbox_to_anchor=(0.26, 0.87), labelcolor='linecolor', shadow=True,fancybox=True, frameon=True)
plt.show()
-
共享x轴,plt.twinx 可以开启共享x轴,在这个前后分别是两个图表,图一用左边的Y轴,图二用右边的y轴
-
图例的设定,对于一个画布上两个单独的图像,图例设定可以使用画布中的图例对象进行添加,
-
坐标轴刻度标签的设定,plt.tick_params的使用
-
图表中折线颜色一致
-
x轴,y轴,标题,图例,这些都没有
-
字体没处理
-
网格线没有对齐
-
坐标轴很混乱,不知道那个坐标轴对应的是那个折线
1.1.2 进阶折线图-双子图
# 创建一个画布,设置尺寸 20x9 英寸,分辨率 100 DPI
plt.figure(figsize=(20, 9), dpi=100)# 创建第一个子图 (2行1列中的第1个)
plt.subplot(211)
# 绘制个人存储率折线图
plt.plot(data['date'], data['psavert'], label='个人存储率',color='red', linewidth=1.2, linestyle=(0, (3, 1, 1, 1, 1, 1)))# 设置 x 轴刻度标签方向和间距
plt.tick_params(axis='x', direction='out', pad=14) # x 轴刻度标签向外,间距 14
plt.xticks(np.arange(0, data.shape[0], 50)) # x 轴刻度每隔 50 个显示一次# 设置 y 轴范围为 0 到 18
plt.ylim(0, 18)
# 设置 y 轴标签和颜色
plt.ylabel('个人存储率', fontdict={'family': 'STsong'}, color='red')
# 设置 y 轴刻度标签颜色和方向
plt.tick_params(axis='y', labelcolor='red', direction='in')
# 显示网格线
plt.grid()# 设置图表标题
plt.title('个人存储率与失业人数对比折线图', fontdict={'family': 'STsong', 'size': 20})# 创建第二个子图 (2行1列中的第2个)
plt.subplot(212)
# 绘制失业人数折线图
plt.plot(data['date'], data['unemploy'], label='失业人数',color='blue', linewidth=1.2, linestyle=(0, (5, 1)))# 设置 x 轴刻度标签方向和间距
plt.xticks(np.arange(0, data.shape[0], 50)) # x 轴刻度每隔 50 个显示一次
plt.ylim(0, 18000) # 设置 y 轴范围为 0 到 18000
# 设置 y 轴标签和颜色
plt.ylabel('失业人数', fontdict={'family': 'STsong'}, color='blue')
# 设置 y 轴刻度标签颜色和方向
plt.tick_params(axis='y', labelcolor='blue', direction='in')
# 设置 x 轴刻度标签方向和位置
plt.tick_params(axis='x', bottom=False, labelbottom=False, direction='out', top=True)
# 显示网格线
plt.grid()# 显示图表
plt.show()
1.1.3 进阶折线图-堆叠面积图
data = pd.read_csv('./data/store.csv')
data.head()
Day | Union Ads | Video Ads | Direct | Search Engine | ||
---|---|---|---|---|---|---|
0 | 周一 | 120 | 220 | 150 | 320 | 820 |
1 | 周二 | 132 | 182 | 232 | 332 | 932 |
2 | 周三 | 101 | 191 | 201 | 301 | 901 |
3 | 周四 | 134 | 234 | 154 | 334 | 934 |
4 | 周五 | 90 | 290 | 190 | 390 | 1290 |
- 第一条折线很轻松可以绘制出来
- 第二条折线: 是第二条折线本身+第一条折线的数据.
- 第三条折线图: 前三条折线图数据之后
- …
第N条折线图,数据应该为前N条数据之和
data.iloc[:, 1:] = data.iloc[:, 1:].cumsum(axis=1)
lists = list(zip([0, 'Email', 'Union Ads', 'Video Ads', 'Direct'],['Email', 'Union Ads', 'Video Ads', 'Direct', 'Search Engine']))
colors = ['#91a1df', '#c6e8ad', '#fbe79d', '#f3a19e', '#b2dff4']
plt.figure(figsize=(12, 5), dpi=100)for index, item in enumerate(data.columns[1:]):plt.plot(data['Day'], data[item], lw=1)if index == 0:plt.fill_between(data['Day'],y1=0,y2=data[lists[index][1]],color=colors[index])else:plt.fill_between(data['Day'],y1=data[lists[index][0]],y2=data[lists[index][1]],color=colors[index])plt.xticks(fontproperties='STsong')
plt.show()
1.2 柱形图
主要用于多个数据系列对比使用
1.2.1 基础柱形图-单数据系列
data = pd.read_csv('./data/stack_data_bar.csv')
data
Country | Pensions | Income | Health | Other services | |
---|---|---|---|---|---|
0 | Italy | 14 | 5 | 9 | 3 |
1 | Spain | 8 | 6 | 7 | 8 |
2 | United States | 15 | 4 | 7 | 1 |
3 | France | 11 | 5 | 8 | 3 |
4 | Germany | 9 | 7 | 7 | 2 |
5 | Sweden | 6 | 6 | 8 | 4 |
6 | China | 7 | 3 | 8 | 1 |
7 | Britain | 8 | 5 | 6 | 3 |
import matplotxplt.style.use(matplotx.styles.pitaya_smoothie['light'])
plt.rcParams['font.sans-serif'] = ['Times New Roman']
plt.rcParams['font.size'] = 15
plt.figure(figsize=(16, 9), dpi=100)
plt.bar(x=data['Country'], # x轴数据height=data['Pensions'], # 柱子的高度width=0.5, # 柱子的宽度color='#ff7f0e', # 柱子颜色edgecolor='black', # 柱子边框颜色linewidth=1, # 柱子边框宽度alpha=0.8, # 柱子透明度yerr=[0.3] * data.shape[0], # 添加误差线ecolor='red', # 误差线颜色label='Pensions', # 数据标签 align='center', # 柱子的位置# bottom=[2,3,4,6,5,4,2,1] # 数据的起始位置,一般用于绘制瀑布图)
plt.xlabel('Country')
# plt.ylabel('Pensions')
plt.title('The Basic column chart -various parament settings', fontsize=20)
for i in range(len(data)):plt.text(data['Country'][i], # x坐标data['Pensions'][i] / 2, # y坐标data['Pensions'][i], # y的实际值ha='center',va='bottom')
plt.show()
- 每个柱子显示数字
- 柱子上加折线
- 柱子的颜色/柱子的变框/边框的粗细/颜色/柱子的宽度/柱子与柱子之间的间距/透明度
1.2.2 柱形图进阶-圆角柱形图
colors = ['#464ca6','#6472ea','#7fc9da','#eec568','#df8342']
from matplotlib.patches import FancyBboxPatchplt.rcParams['font.sans-serif'] = 'Times New Roman'
plt.rcParams['font.size'] = 14
plt.figure(figsize=(6, 6), dpi=100)
rects = plt.bar(x=data['Country'][:5], # x轴数据height=data['Pensions'][:5], # 柱子的高度width=.4, # 柱子的宽度color=colors, # 柱子的颜色label='Pensions', # 数据标签align='center', # 柱子的位置bottom=[1.5] * 5)ax = plt.gca() # 获取当前的坐标轴对象
for rect in rects:rect.remove()
for index, rect in enumerate(rects):bb = rect.get_bbox()patch = FancyBboxPatch((bb.xmin, bb.ymin), # 左下角的坐标abs(bb.width), abs(bb.height),boxstyle="Round, pad=0, rounding_size=0.1", # 补丁的样式ec=colors[index], fc=colors[index], linewidth=2,mutation_aspect=4,mutation_scale=2.2,)ax.add_patch(patch)
ax = plt.gca()
ax.set_facecolor('#1a1c41')
plt.ylim(0, 26)
plt.text(x=-.34, y=21,color='white',s='Uses Excel, Python, SQL, power BI to share \n the whole process data analysis and correct solutions')
plt.text(x=- 0.34, y=24, s='Doughnut Classification', color='white', fontweight='bold')
plt.tick_params(axis='y', labelleft=False, left=False)
plt.tick_params(axis='x', bottom=False, pad=-18, )
plt.xticks(color='white')
for i in range(5):plt.text(data['Country'][i], # X坐标data['Pensions'][i] + 3, # y坐标data['Pensions'][i], # y的实际值ha='center',va='bottom',color='white')
# plt.savefig('./figure/fig-s-1.png',dpi=200,bbox_inches='tight',pad_inches=0.0)
plt.show()
# 圆角柱形图设置函数
def get_round_rect(rects, ec='black', fc='#96c8d6'):bb = rects.get_bbox()patch = FancyBboxPatch((bb.xmin, bb.ymin), # 左下角的坐标abs(bb.width), abs(bb.height),boxstyle="Round, pad=0, rounding_size=0.05", # 补丁的样式ec=ec, fc=fc, linewidth=1,mutation_aspect=4,mutation_scale=1,)return patch
1.2.3 多系列柱形图
x = np.arange(len(data))
with plt.style.context(matplotx.styles.pitaya_smoothie['light']):plt.figure(figsize=(16, 9), dpi=100)rects1 = plt.bar(x - 0.2, data['Pensions'], width=0.4)rects2 = plt.bar(x, data['Income'], align='edge', width=0.4)ax = plt.gca()for rect in zip(rects1, rects2):rect[0].remove()rect[1].remove()patch1 = get_round_rect(rect[0])patch2 = get_round_rect(rect[1], fc='#ff7f0e')ax.add_patch(patch1)ax.add_patch(patch2)plt.xlabel('Country')plt.ylabel('Value')plt.title('柱形图进阶-分组柱形图',fontdict={'family':'STsong','size':20})plt.xticks(ticks=x, labels=data['Country'],)plt.xticks(x, labels=data['Country'])for i in range(len(data)):plt.text(x[i]-0.2,data['Pensions'][i],data['Pensions'][i],ha='center',va='bottom')plt.text(x[i]+0.2,data['Income'][i],data['Income'][i],ha='center',va='bottom')plt.legend(['Pensions', 'Income'])plt.show()
1.3 柱形图进阶-堆叠柱形图
data = pd.read_csv('./data/奖牌.csv')
x = np.arange(4)
x
array([0, 1, 2, 3])
- 要求绘制最近的四次奥运会,金牌数量,银牌数量,铜牌数量分组柱形图/堆积柱形图
plt.rcParams['font.sans-serif'] = ['STsong']
plt.rcParams['font.size'] = 15
plt.figure(figsize=(16, 9),dpi=100)
rects1 = plt.bar(x,data['金牌'][6:10],color='red',width=0.2)
rects2 = plt.bar(x+0.1,data['银牌'][6:10],color='#ff7f0e',align='edge',width=0.2)
rects3 = plt.bar(x-0.2,data['铜牌'][6:10],color='blue',width=0.2)
plt.show()
plt.figure(figsize=(16, 9),dpi=100)plt.bar(data['赛事'],data['铜牌'])
plt.bar(data['赛事'],data['银牌'],bottom=data['铜牌'])
plt.bar(data['赛事'],data['金牌'],bottom=data['铜牌']+data['银牌'])
plt.xticks(rotation=45)
for i in range(len(data)):plt.text(data['赛事'][i],data['金牌'][i]+data['银牌'][i]+data['铜牌'][i]/2,data['金牌'][i],ha='center',va='bottom')plt.text(data['赛事'][i],data['银牌'][i]+data['铜牌'][i]/2,data['银牌'][i],ha='center',va='bottom')plt.text(data['赛事'][i],data['铜牌'][i]/2,data['铜牌'][i],ha='center',va='bottom')
plt.legend(['铜牌','银牌','金牌'])
plt.show()