最近阅读学习了林骥老师的《数据化分析 Python 实战》,书中讲好的技能应该刻意的练习,而不是简单的重复。
学习林骥老师的数据可视化的每种图表时,原来代码略微修改,使其适用于自己工作业务中的数据可视化。
林骥老师将数据可视化分析源代码分享在他的GitHub空间https://github.com/linjiwx/mp
子弹图,它的样子有点像子弹,能够表达比较丰富的信息,例如表现好、中、差的取值范围,并突出显示实际值与目标值的差异情况。
林骥老师在数据可视化分析中提到改进折线图的 12 个细节:
1、把标题变成左对齐,更加符合设计的审美;
2、把标题颜色换成深灰色,让观察者更加关注数据;
3、删除不必要的边框和网格线,避免它们消耗观察者的精力;
4、只保留最大值和最小值的标记,让对比更加明显;
5、去掉图例,直接在线条的附近标注,避免观察者在图例和数据之间来回移动;
6、去掉平均值线,让图表显得更加简洁;
7、更加谨慎而且有策略地使用颜色,去掉那些花花绿绿的颜色,换成只有蓝色和灰色,这样反而能够让重要的信息显得更加突出;
8、坐标轴和标签文字统一换成深灰色,让它们更自然地融入背景,在视觉上不与数据进行竞争;
9、把竖直的日期标签,换成横向的简化日期格式,以便提高阅读的体验,有研究表明,阅读 90 度角倾斜的文字,速度比阅读正常方向的文字平均慢 205%;
10、去掉最大值和最小值的具体数字,因为这里更加关心的是数据背后的事件,而不是数字本身;
11、增加 X 轴的标题「日期」,让它与最左侧的标签对齐;
12、增加 Y 轴的标题「PM2.5」,让它与最上方的标签对齐,为了更加方便阅读,采用换行的方法,把 Y 轴的标题文字变成竖直的方向。
现在我们对比一下改进前后的折线效果:
改进前如下图:
改进后如下:
数据格式如下:
代码语言:text复制date value
2018年1月1日 205.1764706
2018年1月2日 131.7916667
2018年1月3日 43.5
2018年1月4日 34.95833333
......
2018年12月30日 65.625
2018年12月31日 83.25
代码如下:
代码语言:python代码运行次数:0复制# 导入所需的库
import numpy as np
import pandas as pd
import matplotlib as mpl
import matplotlib.pyplot as plt
from datetime import timedelta
# 正常显示中文标签
mpl.rcParams['font.sans-serif'] = ['SimHei']
# 自动适应布局
mpl.rcParams.update({'figure.autolayout': True})
# 正常显示负号
mpl.rcParams['axes.unicode_minus'] = False
# 定义颜色,主色:蓝色,辅助色:灰色,互补色:橙色
colors = {'蓝色':'#00589F', '深蓝色':'#003867', '浅蓝色':'#5D9BCF','绿色':'green',
'灰色':'#999999', '深灰色':'#666666', '浅灰色':'#CCCCCC','红色':'red',
'橙色':'#F68F00', '深橙色':'#A05D00', '浅橙色':'#FBC171'}
# 数据源路径
filepath='./data/PM25.xlsx'
# 读取 Excel文件
df = pd.read_excel(filepath,1)
# 定义画图用的数据
x = [x.strftime('%m-%d') for x in df.date]
y = df.value
# 使用「面向对象」的方法画图,定义图片的大小
fig, ax=plt.subplots(figsize=(10, 6))
# 设置标题
ax.text(-3.9, y.max() 6, 'n郑州市2018年PM2.5变化趋势n', fontsize=26, color=colors['深灰色'])
# 绘制折线图
ax.plot(x, y, marker='*', ms=16,color=colors['蓝色'], markevery=[y.idxmin(), y.idxmax()], mfc='w')
maxDate=df.date[y.idxmax()].strftime('%m月%d日')
minDate=df.date[y.idxmin()].strftime('%m月%d日')
# 标注最大值对应的事件
ax.annotate('(%s)最高值:%.2f'%(maxDate,y.max()), xy=(x[y.idxmax()], y.max()), color=colors['红色'],
xytext=(y.idxmax()-4.2, y.max()),
arrowprops=dict(arrowstyle='->', color=colors['红色']), fontsize=16)
# 标注最小值对应的事件
ax.annotate('(%s)最低值:%.2f'%(minDate,y.min()), xy=(x[y.idxmin()], y.min()), color=colors['绿色'],
xytext=(y.idxmin()-3.6, y.min()),
arrowprops=dict(arrowstyle='->', color=colors['绿色']), fontsize=16)
# 计算 7 天移动平均
y2 = y.rolling(7).mean()
# 绘制趋势线
ax.plot(x, y2, ls='-', color=colors['灰色'], label='七天移动平均')
# 绘制趋势线末端的箭头
plt.annotate('', xy=(x[-1:], y2[-1:]), xytext=(x[-2:-1], y2[-2:-1]),
arrowprops=dict(arrowstyle='->', color=colors['灰色'], shrinkB=0))
# 文字说明移动平均
ax.text(len(x)-7.8, y2[-8:-7], '七天移动平均', color=colors['深灰色'], fontsize=12, bbox=dict(facecolor='w', edgecolor='w'))
# 隐藏边框
ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)
ax.spines['bottom'].set_color(colors['灰色'])
ax.spines['left'].set_color(colors['灰色'])
# 隐藏 X 轴的刻度线
ax.tick_params(axis='x', which='major', length=0)
xticks=[i if i[-2:]=='01' else '' for i in x]
xticks[-1]=x[-1]
ax.set_xticks(xticks)
# 设置 X、Y 轴的标题,适当留白
ax.text(len(x)/2, -55, '日期', ha='left', fontsize=20, color=colors['深灰色'])
ax.text(-50, y.max()/2, 'PM2.5日均值', va='top', fontsize=20, color=colors['深灰色'])
# 设置坐标标签字体大小和颜色
ax.tick_params(labelsize=16, colors=colors['深灰色'])
# 设置 y 轴的刻度范围
ax.set_ylim(0, y.max() 6)
fig.autofmt_xdate()
plt.show()
为了体现数据的上下浮动范围,可以在折线的基础上添加填充区域。
数据如下:
代码语言:text复制date mean amax amin
20180101 205.1764706 286 74
20180102 131.7916667 206 85
20180103 43.5 73 22
20180104 34.95833333 49 25
20180105 72.16666667 136 42
20180106 120.5416667 146 100
20180107 135 169 93
20180108 29.875 87 19
20180109 20.79166667 27 15
20180110 19.875 25 15
20180111 30.25 50 22
20180112 79.875 120 37
20180113 125 154 84
......
20181230 65.625 83 53
20181231 83.25 118 61
代码如下:
代码语言:python代码运行次数:0复制# 导入所需的库
import numpy as np
import pandas as pd
import matplotlib as mpl
import matplotlib.pyplot as plt
from datetime import datetime
from pandas.plotting import register_matplotlib_converters
register_matplotlib_converters()
# 正常显示中文标签
mpl.rcParams['font.sans-serif'] = ['SimHei']
# 自动适应布局
mpl.rcParams.update({'figure.autolayout': True})
# 正常显示负号
mpl.rcParams['axes.unicode_minus'] = False
# 定义颜色,主色:蓝色,辅助色:灰色,互补色:橙色
colors = {'蓝色':'#00589F', '深蓝色':'#003867', '浅蓝色':'#5D9BCF',
'灰色':'#999999', '深灰色':'#666666', '浅灰色':'#CCCCCC',
'橙色':'#F68F00', '深橙色':'#A05D00', '浅橙色':'#FBC171'}
# 数据源路径
filepath='./data/2020年第一季度上证指数.xlsx'
# 读取 Excel文件
df = pd.read_excel(filepath,1)
df.date=df['date'].map(lambda x:datetime.strptime(str(x),'%Y%m%d'))
# 使用「面向对象」的方法画图
fig, ax = plt.subplots(figsize=(10, 6))
fig.tight_layout()
# 设置标题
ax.set_title('n郑州市2018年PM2.5变化趋势n', fontsize=26, loc='left', color=colors['深灰色'])
# 开始画图,时间线图(颜色/线条类型/标记)
# 填充区域
ax.fill_between(df['date'], df['amin'], df['amax'], color=colors['浅灰色'],label='最高最低区间')
ax.plot(df['date'], df['mean'], label='日均值', color=colors['蓝色'], ls='-', lw=1,
marker='o',markevery=[-1] )
# 显示最后 n 个数据的标签
n = 1
# 设置第一条折线图的数据标签
for a, b in zip(df['date'][-n:], df['mean'][-n:]):
plt.text(a, b 25, '%.0f' % b, ha='center', va= 'bottom', fontsize=12, color=colors['浅蓝色'])
# 隐藏边框
ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)
ax.spines['bottom'].set_color(colors['灰色'])
ax.spines['left'].set_color(colors['灰色'])
# 隐藏 X 轴的刻度线
ax.tick_params(axis='x', which='major', length=0)
# 设置坐标标签字体大小和颜色
ax.tick_params(labelsize=16, colors=colors['深灰色'])
plt.legend()
fig.autofmt_xdate()
plt.show()