环境
开发工具
python
VSCode
库的版本
python
numpy==1.26.4
matplotlib==3.10.1
ipympl==0.9.7
教材
本书为《Python数据可视化》一书的配套内容,本章为第4章 图表样式的美化
本章主要介绍了图表样式的美化,包括图表样式概述、使用颜色、选择线型、添加数据标记、设置字体、切换主题风格和填充区域。通过学习本章的内容,希望读者可以明确图表美化的意义,并能够采用适当的方式进行图表美化。
参考
第4章-图表样式的美化
4.1 图表样式概述
4.1.1 默认图表样式
matplotlib在绘图的过程中会读取存储在本地的
配置文件matplotlibrc
,通过matplotlibrc文件中的缺省配置信息指定图表元素的默认样式
,完成图表元素样式的初始设置。通过
rc_params()函数
可以查看matplotlibrc文件中全部的配置项。
rc_params()函数
返回一个RcParams对象
。RcParams对象是一个字典对象,其中字典的键为由配置要素(如axes)及其属性(如edgecolor)组成的配置项,值为配置项的默认值(如black)。
python
import matplotlib
matplotlib.rc_params()
输出如下
RcParams({'_internal.classic_mode': False,
'agg.path.chunksize': 0,
'animation.bitrate': -1,
'animation.codec': 'h264',
'animation.convert_args': ['-layers', 'OptimizePlus'],
'animation.convert_path': 'convert',
'animation.embed_limit': 20.0,
'animation.ffmpeg_args': [],
'animation.ffmpeg_path': 'ffmpeg',
'animation.frame_format': 'png',
'animation.html': 'none',
'animation.writer': 'ffmpeg',
'axes.autolimit_mode': 'data',
'axes.axisbelow': 'line',
'axes.edgecolor': 'black',
'axes.facecolor': 'white',
'axes.formatter.limits': [-5, 6],
'axes.formatter.min_exponent': 0,
'axes.formatter.offset_threshold': 4,
'axes.formatter.use_locale': False,
'axes.formatter.use_mathtext': False,
'axes.formatter.useoffset': True,
'axes.grid': False,
'axes.grid.axis': 'both',
'axes.grid.which': 'major',
...
'ytick.minor.right': True,
'ytick.minor.size': 2.0,
'ytick.minor.visible': False,
'ytick.minor.width': 0.6,
'ytick.right': False})
配置项按照作用对象的不同主要分为10种配置要素:
常用配置项
matplotlib库载入时会主动调用rc_params()函数获取包含全部配置项的字典,并将该字典赋值给变量rcParams,以便
用户采用访问字典rcParams的方式设置或获取配置项
。
4.1.2 图表样式修改
matplotlib通过灵活地修改配置项以改变图表的样式,而不必拘泥于系统默认的配置。图表的样式可以通过两种方式进行修改:
局部修改
和全局修改
。
局部修改
局部修改的方式是指
通过代码动态地修改matplotlib配置项
,此方式用于程序局部定制的需求。若希望局部修改图表的样式,可以通过以下任一种方式实现。
第1种
---通过给绘图函数或设置图表元素函数的关键字参数传值来修改图表的样式。
第2种
---通过"rcParams[配置项]"重新为配置项赋值来修改图表的样式。
第3种
---通过给rc()函数的关键字参数传值来修改图表的样式。
第1种方式
只能对某一指定元素的样式进行修改,
第2种和第3种方式
可以对整个py文件中全部指定元素的样式进行修改。
python
rc(group, **kwargs)
group:表示配置要素。
**kwargs:表示配置要素的属性。
设置线条的宽度
全局修改
全局修改的方式是指
直接修改matplotlibrc文件的配置项
,此方式适用于程序全局定制的需求,可以将指定的图表样式进行统一修改,无需每次在具体的程序中进行单独修改。 matplotlib使用matplotlibrc文件的路径搜索顺序:
当前工作路径
:程序运行的目录。
用户配置路径
:通常位于HOME/.matplotlib/目录中,可以通过环境变量MATPLOTLIBRC进行修改。
系统配置路径
:位于matplotlib安装路径的mpl-data目录中。matplotlib可以使用
matplotlib_fname()函数
查看当前使用的matplotlibrc文件所在的路径。
python
import matplotlib
matplotlib.matplotlib_fname()
'd:\ProgramData\Anaconda3\envs\py312\Lib\site-packages\matplotlib\mpl-data\matplotlibrc'
4.2 使用颜色
4.2.1 使用基础颜色
图表在使用颜色时应遵循一定的基本规则
,既要避免使用过多的颜色,又要避免随意使用颜色,否则会直接影响可视化的效果且不易让人理解。
matplotlib的基础颜色主要有3种表示方式:单词缩写或单词
、十六进制或HTML模式
、RGB模式
。
单词缩写或单词表示的颜色
matplotlib中支持使用单词缩写或单词表示的8种颜色:青色、洋红色、黄色、黑色、红色、绿色、蓝色、白色。
十六进制/HTML模式表示的颜色
matplotlib支持使用十六进制或HTML模式表示更多的颜色,它将这些颜色存储在colors.cnames字典中,可通过访问
colors.cnames
字典查看全部的颜色。
python
import matplotlib
import matplotlib.colors
print(len(matplotlib.colors.cnames.items()))
for name, hex in matplotlib.colors.cnames.items():
print(name, hex)
148
aliceblue #F0F8FF
antiquewhite #FAEBD7
aqua #00FFFF
aquamarine #7FFFD4
azure #F0FFFF
beige #F5F5DC
bisque #FFE4C4
black #000000
blanchedalmond #FFEBCD
blue #0000FF
blueviolet #8A2BE2
brown #A52A2A
burlywood #DEB887
cadetblue #5F9EA0
chartreuse #7FFF00
chocolate #D2691E
coral #FF7F50
cornflowerblue #6495ED
cornsilk #FFF8DC
crimson #DC143C
cyan #00FFFF
darkblue #00008B
darkcyan #008B8B
...
white #FFFFFF
whitesmoke #F5F5F5
yellow #FFFF00
yellowgreen #9ACD32
RGB模式表示的颜色
matplotlib支持使用
RGB模式的三元组
表示颜色,其中元组的第1个元素代表红色值,第2个元素代表绿色值,第3个元素代表蓝色值,且每个元素的取值范围均是[0,1]。
以上3种方式表示的颜色都可以传入matplotlib中带有表示颜色的color或c参数的函数或方法中,从而为图表的相应元素设置颜色。
python
import matplotlib.pyplot as plt
plt.plot([1, 2, 3], [3, 4, 5], color='g') # 第1种
plt.plot([1, 2, 3], [4, 5, 6], color='#2E8B57') # 第2种
plt.plot([1, 2, 3], [5, 6, 7], color=(0.0, 0.5, 0.0)) # 第3种

4.2.2 使用颜色映射表
matplotlib中内置了众多预定义的
颜色映射表
,使用这些颜色表可以为用户提供更多的颜色建议,节省大量的开发时间。通过
colormaps()函数
可以查看所有可用的颜色映射表。
python
import matplotlib.pyplot as plt
print(len(plt.colormaps()))
plt.colormaps()
180
'magma', 'inferno', 'plasma', 'viridis', 'cividis', 'twilight', 'twilight_shifted', 'turbo', 'berlin', 'managua', 'vanimo', 'Blues', 'BrBG', 'BuGn', 'BuPu', 'CMRmap', 'GnBu', 'Greens', 'Greys', 'OrRd', 'Oranges', 'PRGn', 'PiYG', 'PuBu', 'PuBuGn', ... 'tab20c_r', 'grey_r', 'gist_grey_r', 'gist_yerg_r', 'Grays_r'
Output is truncated. View as a scrollable element or open in a text editor. Adjust cell output settings...
颜色映射表一般可以划分为以下3类:
Sequential
:表示同一颜色从低饱和度到高饱和度的单色颜色映射表。
Diverging
:表示颜色从中间的明亮色过渡到两个不同颜色范围方向的颜色映射表。
Qualitative
:表示可以轻易区分不同种类数据的颜色映射表。
开发人员可以自定义新的颜色映射表,再通过matplotlib.cm.register_cmap()函数
将自定义的颜色映射表添加到matplotlib中。
matplotlib主要有两种使用颜色映射表的方式,
第一种方式是在调用函数或方法绘制图表或添加辅助元素时将颜色映射表传递给
关键字参数cmap
,第二种方式是直接调用
set_cmap()函数
进行设置。
python
import matplotlib
import matplotlib.cm
import matplotlib.pyplot as plt
import numpy as np
x=[1,2,3,4,5,6,7,8,9,10]
y=[2,2,3,3,4,4,5,5,6,6]
np.random.seed(3)
# plt.scatter(x,y,c=np.random.rand(10),cmap=matplotlib.cm.jet)
plt.scatter(x,y,c=np.random.rand(10))
plt.set_cmap(matplotlib.cm.jet)
输出如下:
4.2.3 实例1:两个地区对不同种类图书的采购情况
高尔基说:"书籍是人类进步的阶梯"。据统计韩国人的年均阅读量为
7本
,日本人的年均阅读量为40本
,相比较而言,中国人的年均阅读量为0.7本
,还有很大的进步空间。
本实例要求根据下表的数据,绘制反映地区1和地区2对各类图书采购情况的堆积柱形图,并使用#FFCC00
和#B0C4DE
这两种颜色区分地区1和地区2对应的两组柱形。
python
# 01_book_purchase
import numpy as np
import matplotlib.pyplot as plt
plt.rcParams["font.sans-serif"] = ["SimHei"]
plt.rcParams["axes.unicode_minus"] = False
x = np.arange(5)
y1 = [1200, 2400, 1800, 2200, 1600]
y2 = [1050, 2100, 1300, 1600, 1340]
bar_width = 0.6
tick_label = ["家庭", "小说", "心理", "科技", "儿童"]
fig = plt.figure()
ax = fig.add_subplot(111)
# 绘制柱形图 , 并使用颜色
ax.bar(x, y1, bar_width, color="#FFCC00", align="center", label ="地区1")
ax.bar(x, y2, bar_width, bottom=y1, color="#B0C4DE", align="center", label="地区2")
ax.set_ylabel("采购数量(本)")
ax.set_xlabel("图书种类")
ax.set_title(" 地区1和地区2对各类图书的采购情况")
ax.grid(True, axis='y', color="gray", alpha=0.2)
ax.set_xticks(x)
ax.set_xticklabels(tick_label)
ax.legend()
plt.show()

4.3 选择线型
4.3.1 选择线条的类型
图表中每个线条均具有不同的含义,一般可以通过颜色、宽度、类型来区分线条,其中类型是区分线条的常见方式之一。
matplotlib中内置了4种线条的类型:
短虚线
、点划线
、长虚线
和实线
。
在使用pyplot绘制折线图、显示网格或添加参考线时,可以将线型取值传递给linestyle或ls参数
,以选择其它的线条类型。
python
import matplotlib.pyplot as plt
import matplotlib
plt.plot([1, 2, 3], [3, 4, 5], linestyle='--')
plt.plot([1, 2, 3], [4, 5, 6], ls='--')
输出如下:
4.3.2 实例2:2017年7月与2019年7月国际外汇市场美元/人民币汇率走势
汇率
又称外汇利率,指两种货币之间兑换的比率,亦可视为一个国家的货币对另一种货币的价值
。汇率会因诸多外界因素(如国际收支状况、通货膨胀)的影响而出现上下波动,从而产生货币贬值和货币升值的现象。
本实例要求根据下表的数据,绘制反映2017年7月与2019年7月美元/人民币汇率走势的折线图,并使用实线
和长虚线
区分代表2017年和2019年汇率走势的两条折线。
python
# 02_dollar_RMB_exchange_rate
import numpy as np
import matplotlib.pyplot as plt
plt.rcParams["font.sans-serif"] = ["SimHei"]
plt.rcParams["axes.unicode_minus"] = False
# 汇率
eurcny_2017 = np.array([6.8007, 6.8007, 6.8015, 6.8015, 6.8060, 6.8060, 6.8060, 6.8036,
6.8025, 6.7877, 6.7835, 6.7758, 6.7700, 6.7463, 6.7519,6.7511,
6.7511, 6.7539, 6.7265])
eurcny_2019 = np.array([6.8640, 6.8705, 6.8697, 6.8697, 6.8697,6.8881, 6.8853, 6.8856,
6.8677, 6.8662, 6.8662, 6.8662, 6.8827, 6.8761, 6.8635,6.8860,
6.8737, 6.8796, 6.8841])
date_x = np.array([3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 17, 18, 19, 24, 25, 26, 31])
fig = plt.figure()
ax = fig.add_subplot(111)
# 第1 条折线 : 湖绿色 , 实线 , 线宽为 2
ax.plot(date_x, eurcny_2017, color='#006374', linewidth=2, label='2017年7月美元/人民币汇率')
# 第2 条折线 : 紫色 , 长虚线 , 线宽为 2
ax.plot(date_x, eurcny_2019, color='#8a2e76', linestyle='--', linewidth=2, label='2019年7月美元/人民币汇率')
ax.set_title('2017年7月与2019年7月美元/人民币汇率走势')
ax.set_xlabel('日期')
ax.set_ylabel('汇率')
ax.legend()
plt.show()
输出为:
4.4 添加数据标记
4.4.1 添加折线图或散点图的数据标记
数据标记一般指代表
单个数据的圆点或其它符号
等,用于强数据点的位置,常见于折线图和散点图中。
matplotlib中内置了许多数据标记,使用这些数据标记可以便捷地为折线图或散点图标注数据点。数据标记可以分为填充型数据标记
和非填充型数据标记
。
在使用pyplot的plot()
或scatter()
函数绘制折线图或散点图时,可以将标记取值传递给marker参数
,从而为折线图或散点图添加数据标记。
python
import matplotlib.pyplot as plt
plt.plot([1, 2, 3], [3, 4, 5], marker='*')
还可以给plot()或scatter()函数的以下参数传值来设置数据标记的属性
。
markeredgecolor或mec:表示数据标记的边框颜色。
markeredgewidth或mew:表示数据标记的边框宽度。
markerfacecolor或mfc:表示数据标记的填充颜色。
markerfacecoloralt或mfcalt:表示数据标记备用的填充颜色。
markersize或ms:表示数据标记的大小。
python
import matplotlib.pyplot as plt
plt.plot([1, 2, 3], [3, 4, 5], marker='*', markersize=20, markerfacecolor='y')
在使用matplotlib绘制折线图时,可以使用字符串分别为线条指定颜色、线型和数据标记这三种样式,但每次都需要分别给参数color、linestyle(ls)、marker传值进行一一设置,使得编写的代码过于繁琐。为此,matplotlib提供了由颜色、标记、线型构成的格式字符串。
多学一招: matplotlib格式字符串
在使用matplotlib绘制折线图时,可以使用字符串分别为线条指定颜色、线型和数据标记这三种样式,但每次都需要分别给参数color、linestyle(ls)、marker传值进行一一设置,使得编写的代码过于繁琐。为此,matplotlib提供了由
颜色
、标记
、线型
构成的格式字符串。格式字符串是快速设置线条基本样式的缩写形式的字符串。
'[颜色][标记][线型]'
以上格式的每个选项都是
可选
的,选项之间组合的顺序也是可变的。若格式字符串中只有颜色一个选项,可以使用十六进制、单词拼写等其它形式表示的颜色。
颜色只能是通过单词缩写方式表示的颜色。
python
import matplotlib.pyplot as plt
plt.plot([1, 2, 3], [3, 4, 5], 'mo--')

4.4.2 实例3:标记不同产品各季度的销售额
本实例要求根据下表的数据,将季度列的数据作为x轴的刻度标签,将产品A、产品B、产品C这三列的数据作为y轴的数据,使用plot()函数绘制反映产品A、产品B和产品C各季度销售额的折线图,并
使用不同的线型、颜色、标记区分3个线条
。
python
# 03_sales_of_different_products
import numpy as np
import matplotlib.pyplot as plt
plt.rcParams["font.sans-serif"] = ["SimHei"]
plt.rcParams["axes.unicode_minus"] = False
sale_a = [2144, 4617, 7674, 6666]
sale_b = [853, 1214, 2414, 4409]
sale_c = [153, 155, 292, 680]
fig = plt.figure()
ax = fig.add_subplot(111)
# 绘制具有不同线条样式的折线图
ax.plot(sale_a, 'D-', sale_b, '^:', sale_c, 's--')
ax.grid(alpha=0.3)
ax.set_ylabel('销售额(万元)')
ax.set_xticks(np.arange(len(sale_c)))
ax.set_xticklabels(['第1季度','第2季度', '第3季度', '第4季度'])
ax.legend(['产品A','产品B','产品C'])
plt.show()
输出为:
4.5 设置字体
4.5.1 设置字体样式
不同的字体给人的直观感受不同,比如宋体给人雅观、大气的感觉;黑体给人厚重、抢眼的感觉。由于每种字体的特点是不一样的,所以每种字体能够适用的场合也是不一样的。
合适的字体可以对图表起到很好的修饰作用
。
matplotlib中文本是text模块的Text类对象
,可以通过之前介绍的text()、annotate()、title()等函数进行创建。Text类中提供了一系列设置文本字体样式的属性,包括字体类别、字体大小、字体风格等。
表中的属性也可以作为
text()、annotate()、title()函数的同名关键字参数
,以便用户在创建文本的同时设置字体的样式。

python
import matplotlib.pyplot as plt
plt.plot([1, 2, 3], [3, 4, 5])
# 参数说明
# x: 横坐标 y: 纵坐标
# color: 线条颜色
# linestyle: 线条样式
# linewidth: 线条宽度
# marker: 标记点样式
# markersize: 标记点大小
# markerfacecolor: 标记点颜色
# markeredgecolor: 标记点边缘颜色
plt.text(1.9, 3.75, 'y=x+2', bbox=dict(facecolor='y'), family='serif', fontsize=18, fontstyle='normal', rotation=-60)

4.5.2 实例4:未来15天最高气温和最低气温(设置字体样式)
2.1.2节实例1的折线图既
没有使用数据标记标注数据的位置
,也没有使用注释文本标注具体的数值
,影响用户的阅读体验。
本实例要求对前面的折线图进行调整,为该图中的折线
添加数据标记和注释文本
,并设置注释文本的字体样式
。
python
# 04_maximum_minimum_temperatures
import matplotlib.pyplot as plt
import numpy as np
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
x = np.arange(4, 19)
y_max =[32, 33, 34, 34, 33, 31, 30, 29, 30, 29, 26, 23, 21, 25, 31]
y_min = [19, 19, 20, 22, 22, 21, 22, 16, 18, 18, 17, 14, 15, 16 , 16]
# 可以调用多次plot() 函数
plt.plot(x, y_max, marker='o', label='最高温度')
plt.plot(x, y_min, marker='o', label='最低温度')
# 为图表添加注释并设置字体的样式
x_temp = 4
for y_h, y_l in zip(y_max, y_min):
plt.text(x_temp-0.3, y_h + 0.7, y_h, family='SimHei', fontsize=8, fontstyle='normal')
plt.text(x_temp-0.3, y_l + 0.7, y_l, family='SimHei', fontsize=8, fontstyle='normal')
x_temp += 1
plt.title('未来15天最高气温和最低气温的走势')
plt.xlabel('日期')
plt.ylabel(r'温度($^\circ$C)')
plt.ylim(0, 40)
plt.legend()
plt.show()
输出如下:
4.6 切换主题风格
matplotlib.style模块
中内置了一些图表的主题风格,通过切换不同的主题风格以满足用户的不同需求。所有的主题风格都存储于matplotlib配置文件夹的stylelib目录中,可以通过访问available变量
查看所有可用的主题风格。
python
import matplotlib.style as ms
print(ms.available)
输出如下
'Solarize_Light2', '_classic_test_patch', '_mpl-gallery', '_mpl-gallery-nogrid', 'bmh', 'classic', 'dark_background', 'fast', 'fivethirtyeight', 'ggplot', 'grayscale', 'petroff10', 'seaborn-v0_8', 'seaborn-v0_8-bright', 'seaborn-v0_8-colorblind', 'seaborn-v0_8-dark', 'seaborn-v0_8-dark-palette', 'seaborn-v0_8-darkgrid', 'seaborn-v0_8-deep', 'seaborn-v0_8-muted', 'seaborn-v0_8-notebook', 'seaborn-v0_8-paper', 'seaborn-v0_8-pastel', 'seaborn-v0_8-poster', 'seaborn-v0_8-talk', 'seaborn-v0_8-ticks', 'seaborn-v0_8-white', 'seaborn-v0_8-whitegrid', 'tableau-colorblind10'
使用matplotlib.style中的
use()函数
可以切换图表的主题风格。以上函数的
参数style表示图表的主题风格
,它可以接收matplotlib中所有可用的主题风格的字符串,也可以接收"default"来恢复默认的主题风格
。
python
plt.plot([1, 2, 3], [3, 4, 5], marker='*', markersize=20, markerfacecolor='y')
ms.use('seaborn-v0_8-deep')
# ms.use('seaborn-v0_8-talk')
输出如下:
4.7 填充区域
matplotlib中提供了多个函数用于填充多边形或区域,分别为
fill()、fill_between()和fill_betweenx()
,其中
fill()函数用于填充多边形
,
fill_between()函数用于填充两条水平曲线之间的区域
fill_betweenx()函数用于填充垂直曲线之间的区域
。
4.7.1 填充多边形或曲线之间的区域-fill() fill_between()和fill_betweenx()函数
fill()函数
的语法格式如下所示:
python
fill(*args, data=None, facecolor, edgecolor, linewidth, **kwargs)
*args:表示x坐标、y坐标或颜色的序列。
facecolor:表示多边形的
填充颜色
。edgecolor:表示多边形的
边框颜色
。linewidth:表示多边形的边框宽度。
python
import matplotlib.pyplot as plt
# 保证 x 和 y 长度一致
x = [1, 2, 3, 4, 2]
y = [1, 3, 2, 3, 6]
# plt.fill(x, y)
plt.fill(x, y,'b', edgecolor='black', label='Blue Polygon') # 使用默认颜色填充多边形
plt.show()
输出如下:
python
import matplotlib.pyplot as plt
x = [1, 2, 3, 4, 1]
y = [1, 4, 3, 4, 5]
x2 = [5, 6, 7, 8, 5]
y2 = [5, 8, 7, 8, 9]
# 填充多边形并设置边框
plt.fill(x, y, 'b', x2, y2, 'r',edgecolor='black', label='Blue Polygon')
# 设置坐标轴范围
plt.xlim(0, 9)
plt.ylim(0, 9)
# 添加标题和图例
plt.title('Polygon Filling with plt.fill')
plt.legend()
plt.show()
输出为:
fill_between()函数
的语法格式如下所示:
python
fill_between(x, y1, y2=0, where=None, interpolate=False, step=None, data=None, **kwargs)
x:表示x轴坐标的序列。
y1:表示
第一条曲线的y轴坐标
。y2:表示
第二条曲线的y轴坐标
。where:布尔值,表示
要填充区域的条件
。y1>y2说明第一条曲线位于第二条曲线上方时填充;y1<y2说明第二条曲线位于第一条曲线上方时填充。
fill_betweenx()函数
的语法格式如下:
python
fill_betweenx(y, x1, x2=0, where=None, step=None, interpolate=False, data=None, **kwargs)
y:表示y轴坐标的序列。
x1:表示
第一条曲线的x轴坐标
。x2:表示
第二条曲线的x轴坐标
。where:布尔值,表示
要填充区域的条件
。x1>x2说明第一条曲线位于第二条曲线右方时填充;x1<x2说明第二条曲线位于第一条曲线右方时填充。
python
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(0, 8 * np.pi, 1000)
sin_y = np.sin(x)
cos_y = np.cos(1.5 * x / np.pi) / 2
plt.plot(x, sin_y)
plt.plot(x, cos_y)
# 填充 fill_between参数
# 1. x轴数据
# 2. 第一条曲线y轴数据
# 3. 第二条曲线y轴数据
# 4. 填充区域的条件
# 5. 填充区域的颜色
plt.fill_between(x, cos_y, sin_y, cos_y < sin_y, color='dodgerblue', alpha=0.5)
plt.fill_between(x, cos_y, sin_y, cos_y > sin_y, color='orangered', alpha=0.5)
输出如下:
python
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(0, 8 * np.pi, 1000)
sin_y = np.sin(x)
cos_y = np.cos(1.5 * x / np.pi) / 2
plt.plot(x, sin_y)
plt.plot(x, cos_y)
# 填充 fill_between参数
# 1. x轴数据
# 2. 第一条曲线y轴数据
# 3. 第二条曲线y轴数据
# 4. 填充区域的条件
# 5. 填充区域的颜色
plt.fill_betweenx(x, cos_y, sin_y, cos_y < sin_y, color='dodgerblue', alpha=0.5)
plt.fill_betweenx(x, cos_y, sin_y, cos_y > sin_y, color='orangered', alpha=0.5)
输出如下:
4.7.2 实例5:彩色的"雪花"
科赫雪花
又叫科赫曲线,科赫曲线是一种典型的分形曲线,形态似雪花,它是瑞典数学家科赫于1904年构造出来的。
一个边长为1的等边三角形,取每边中间的三分之一,接上去一个形状完全相似的但边长为其三分之一的三角形,结果是一个六角形。取六角形的每个边做同样的变换,即在中间三分之一接上更小的三角形,以此重复,直至无穷。外界的变得原来越细微曲折,形状接近理想化的雪花。
本实例要求读者绘制一个形状类似雪花的多边形,并给该多边形填充颜色。
python
# 05_colorful_snowflakes
import numpy as np
import matplotlib.pyplot as plt
def koch_snowflake(order, scale=10):
def _koch_snowflake_complex(order):
if order == 0:
# 初始三角形
angles = np.array([0, 120, 240]) + 90
return scale / np.sqrt(3) * np.exp(np.deg2rad(angles) * 1j)
else:
ZR = 0.5 - 0.5j * np.sqrt(3) / 3
p1 = _koch_snowflake_complex(order - 1) # 起点
p2 = np.roll(p1, shift=-1) # 终点
dp = p2 - p1 # 连接向量
new_points = np.empty(len(p1) * 4, dtype=np.complex128)
new_points[::4] = p1
new_points[1::4] = p1 + dp / 3
new_points[2::4] = p1 + dp * ZR
new_points[3::4] = p1 + dp / 3 * 2
return new_points
points = _koch_snowflake_complex(order)
x, y = points.real, points.imag
return x, y
x, y = koch_snowflake(order=2)
fig = plt.figure()
ax = fig.add_subplot(111)
ax.fill(x, y, facecolor='lightsalmon', edgecolor='orangered', linewidth=3)
plt.show()
输出为: