前言
在前文中,我们介绍了使用pyecharts绘制南丁格尔玫瑰图,本章我们再学习一下使用matplotlib绘制南丁格尔玫瑰图,了解在极坐标系中绘制柱状图。并对比一下两种不同的绘制方法,如何实现?
介绍
玫瑰图是弗罗伦斯·南丁格尔所发明的。又名为极坐标面积图,是一种圆形的直方图。 南丁格尔自己常昵称这类图为鸡冠花图(coxcomb),适用于绘制比较、随时间变化的循环现象。和传统的饼图展示形式单一相比,南丁格尔玫瑰图更加绚丽,给人的感觉更直观、深刻,因此,南丁格尔玫瑰图在数据可视化领域的应用十分广泛。
Matplotlib
Matplotlib 是 Python 的绘图库,它能让使用者很轻松地将数据图形化,并且提供多样化的输出格式。是一个非常强大的 Python 画图工具,我们可以使用该工具将很多数据通过图表的形式更直观的呈现出来。可以用来绘制各种静态,动态,交互式的图表,线图、散点图、等高线图、条形图、柱状图、3D 图形、甚至是图形动画等等。
安装matplotlib库:
pip install matplotlib
准备数据
以水果为例,生成一组数据。
# coding=utf-8
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
fruits = {'香蕉': 115, '梨': 79, '椰子': 241, '柿子': 74, '鲜枣': 125,
'榴莲': 147, '石榴': 72, '菠萝蜜': 105, '牛油果': 143, '山楂': 102}
s_fruits = pd.Series(fruits)
print(s_fruits)
香蕉 115
梨 79
椰子 241
柿子 74
鲜枣 125
榴莲 147
石榴 72
菠萝蜜 105
牛油果 143
山楂 102
dtype: int64
源码实现
将上面的数据拆分成为一维数组。
labels = []
nums = []
for x,y in [list(z) for z in zip([fruit for fruit in s_fruits.index], s_fruits)]:
labels.append(x)
nums.append(y)
labels
['香蕉', '梨', '椰子', '柿子', '鲜枣', '榴莲', '石榴', '菠萝蜜', '牛油果', '山楂']
绘制玫瑰图所需要的参数,柱子数量、每个柱子的宽度和角度。
size= len(nums) # 柱子的数量
width = 2 * np.pi / size # 每个柱子的宽度
rad = np.cumsum([width] * size) # 每个柱子的角度
配置每一个柱子的颜色。
# 转化为小数的rgb色列表
colors = [
(0.68359375, 0.02734375, 0.3203125),
(0.78125, 0.05078125, 0.2578125),
(0.875, 0.0390625, 0.1796875),
(0.81640625, 0.06640625, 0.0625),
(0.8515625, 0.1484375, 0.08203125),
(0.90625, 0.203125, 0.13671875),
(0.89453125, 0.2890625, 0.0703125),
(0.84375, 0.2421875, 0.03125),
(0.9140625, 0.26953125, 0.05078125),
(0.85546875, 0.31640625, 0.125)
]
绘制玫瑰图
text使用参数,请参考:matplotlib.axes.Axes.text()
plt.rcParams['font.sans-serif'] = ['SimHei'] # 中文显示
plt.figure(figsize=(12, 12),dpi=300,) # 创建画布
ax = plt.subplot(projection='polar')
ax.set_ylim(-8, np.ceil(max(nums) + 1)) # 中间空白,-8为空白半径大小,可自行调整
ax.set_theta_zero_location('N',-5.0) # 设置极坐标的起点方向 W,N,E,S, -5.0为偏离数值,可自行调整
ax.set_theta_direction(1) # 1为逆时针,-1为顺时针
ax.grid(False) # 不显示极轴
ax.spines['polar'].set_visible(False) # 不显示极坐标最外的圆形
ax.set_yticks([]) # 不显示坐标间隔
ax.set_thetagrids([]) # 不显示极轴坐标
ax.bar(rad, nums, width=width, color=colors, alpha=1) # 画图
# 设置text
for i in np.arange(len(nums)):
ax.text(rad[i], # 角度
nums[i]-20, # 长度
labels[i]+'\n'+str(nums[i]), # 文本
rotation=rad[i] * 180 / np.pi -5, # 文字角度
rotation_mode='anchor', # 对齐文本,可选参数['default','anchor']
alpha=0.8,#透明度
fontstyle='normal',# 设置字体类型,可选参数[ ‘normal’ | ‘italic’ | ‘oblique’ ],italic斜体,oblique倾斜
fontweight='medium', # 设置字体粗细,可选参数 [‘light’, ‘normal’, ‘medium’, ‘semibold’, ‘bold’, ‘heavy’, ‘black’]
color='white', # 设置字体颜色
size=nums[i]/8, # 设置字体大小
ha="center", # 'left','right','center'
va="top", # 'top', 'bottom', 'center', 'baseline', 'center_baseline'
)
plt.show()
效果图
优化玫瑰图
通过对nums数组进行排序,可美化玫瑰图,如下:
# 对数组进行排序操作
nums.sort()
plt.rcParams['font.sans-serif'] = ['SimHei'] # 中文显示
plt.figure(figsize=(12, 12),dpi=300,) # 创建画布
ax = plt.subplot(projection='polar')
ax.set_ylim(-2, np.ceil(max(nums) + 1)) # 中间空白,-2为空白半径大小,可自行调整
ax.set_theta_zero_location('N',-5.0) # 设置极坐标的起点方向 W,N,E,S, -5.0为偏离数值,可自行调整
ax.set_theta_direction(1) # 1为逆时针,-1为顺时针
ax.grid(False) # 不显示极轴
ax.spines['polar'].set_visible(False) # 不显示极坐标最外的圆形
ax.set_yticks([]) # 不显示坐标间隔
ax.set_thetagrids([]) # 不显示极轴坐标
ax.bar(rad, nums, width=width, color=colors, alpha=1) # 画图
# 设置text
for i in np.arange(len(nums)):
ax.text(rad[i], # 角度
nums[i]-2, # 长度,-2为文字偏离顶部距离
labels[i]+'\n'+str(nums[i]), # 文本
rotation=rad[i] * 180 / np.pi -5, # 文字角度
rotation_mode='anchor', # 对齐文本,可选参数['default','anchor']
alpha=0.8,#透明度
fontstyle='normal',# 设置字体类型,可选参数[ ‘normal’ | ‘italic’ | ‘oblique’ ],italic斜体,oblique倾斜
fontweight='medium', # 设置字体粗细,可选参数 [‘light’, ‘normal’, ‘medium’, ‘semibold’, ‘bold’, ‘heavy’, ‘black’]
color='white', # 设置字体颜色
size=nums[i]/0.8, # 设置字体大小
ha="center", # 'left','right','center'
va="top", # 'top', 'bottom', 'center', 'baseline', 'center_baseline'
)
plt.show()
效果图