本帖将《Python编程从入门到实践》中代码实现,并在过程中解决了一些遇到的问题。
一、安装matplotlib
笔者使用pycharm2020,打开pycharm终端输入以下内容进行下载:
pip install matplotlib -i http://mirrors.aliyun.com/pypi/simple/ --trusted-host mirrors.aliyun.com
二、初期问题汇总
1、无法显示汉字标题
UserWarning: Glyph 24179 (\N{CJK UNIFIED IDEOGRAPH-5E73}) missing from current font.
func(*args)
解决办法:输入以下内容设置汉字格式(设置方式多样,可自行搜索)
(1)获取字体格式
from matplotlib.font_manager import FontManager
mpl_fonts = set(f.name for f in FontManager().ttflist)
print('all font list get from matplotlib.font_manager:')
for f in sorted(mpl_fonts):
print('\t' + f)
(2)设置字体格式
plt.rcParams['font.sans-serif'] = ['KaiTi']
结果如图:
2、使用内置格式
(1)获取内置格式
from matplotlib import style as plt
print(plt.available)
输出结果如下
(2)使用内置格式(使用某些格式会出现问题,而另外一些不会)
结果如图:
三、具体绘图实例
1、绘制简单的折线图
import matplotlib.pyplot as plt
# 设置字体为楷体
plt.rcParams['font.sans-serif'] = ['KaiTi']
input_values=[1,2,3,4,5]
squares=[1,4,9,16,25]
plt.style.use('fivethirtyeight')
fig,ax=plt.subplots()
ax.plot(input_values,squares,linewidth=3)
# 设置图表标题并给坐标轴加上标签
ax.set_title("平方数",fontsize=24)
ax.set_xlabel("值",fontsize=14)
ax.set_ylabel("值的平方",fontsize=14)
# 设置刻度标记的大小
ax.tick_params(axis="both",labelsize=14)
plt.show()
结果如图:
2、使用scatter() 绘制散点图
# 导入绘图模块
import matplotlib.pyplot as plt
# 使用内置样式
# 有的内置样式不显示汉字,有的内置样式只显示一半的汉字
plt.style.use('bmh')
# 设置汉字字体
plt.rcParams['font.sans-serif'] = ['KaiTi']
# 绘图
fig,ax=plt.subplots()
# 输入绘图数据
x_values=[1,2,3,4,5]
y_values=[1,4,9,16,25]
# 绘制散点图
ax.scatter(x_values, y_values, s=100)
# 设置图标标题并给坐标轴加上标签
ax.set_title("平方数",fontsize=24)
ax.set_xlabel("值",fontsize=14)
ax.set_ylabel("值的平方",fontsize=14)
# 设置刻度标记的大小
ax.tick_params(axis='both',which='major',labelsize=14)
plt.show()
结果如图:
自动计算、自定义颜色、使用颜色映射
# 导入计算模块
import matplotlib.pyplot as plt
# 设置汉字字体格式
plt.rcParams['font.sans-serif'] = ['KaiTi']
# 使用内置格式
plt.style.use('bmh')
# 绘图所需数据
x_values=range(1,1001)
y_values=[x**2 for x in x_values]
# 绘图
fig,ax=plt.subplots()
# ax.scatter(x_values,y_values,c='red',s=10)
# ax.scatter(x_values,y_values,c=(0,0.8,0),s=10)
# 使用颜色映射突出数据规律
ax.scatter(x_values,y_values,c=y_values,cmap=plt.cm.Blues,s=10)
# 设置坐标轴的取值范围
ax.axis([0,1100,0,1100000])
# 设置图标标题并给坐标轴加上名称
ax.set_title("平方数",fontsize=24)
ax.set_xlabel("值",fontsize=14)
ax.set_ylabel("值的平方",fontsize=14)
# 设置坐标刻度值的大小
ax.tick_params(axis='both',which='major',labelsize=14)
# 输出图片
plt.show()
# 自动保存图表,第一个实参指定要以什么文件名保存图表,这个文件将存储到本程序所在的目录,第二个实参指定将图表多余的空白区域裁减掉。
# 如果想保留空白区域,只需省略该实参
# plt.savefig('graph_calculate_squares.png',bbox_inches='tight')
结果如图:
3、 随机漫步
创建RandomWalk类并选择方向
# 导入choice模块
from random import choice
# 生成一个随机漫步类
class RandomWalk:
def __init__(self,num_points=5000):
# 初始化随机漫步的属性
self.num_points=num_points
# 所有随机漫步都起始于(0,0)
self.x_values=[0]
self.y_values=[0]
def fill_walk(self):
# 计算随机漫步包含的所有点
# 不断漫步,直到列表达到指定的长度
while len(self.x_values) < self.num_points:
# 决定前进方向以及沿这个方向前进的距离
x_direction=choice([1,-1])
x_distance=choice([0,1,2,3,4])
x_step= x_direction*x_distance
y_direction=choice([1,-1])
y_distance=choice([0,1,2,3,4])
y_step=y_direction*y_distance
# 拒绝原地踏步
if x_step == 0 and y_step == 0:
continue
# 计算下一个点的x值和y值
x=self.x_values[-1]+x_step
y=self.y_values[-1]+y_step
self.x_values.append(x)
self.y_values.append(y)
绘制随机漫步图
import matplotlib.pyplot as plt
from random_walk import RandomWalk
# 只要程序处于活动状态,就不断的模拟随机漫步
while True:
# 创建一个RandomWalk实例
rw=RandomWalk(50_000)
rw.fill_walk()
# 将所有点都绘制出来
plt.style.use('fivethirtyeight')
fig,ax=plt.subplots(figsize=(15,9))
fig,ax=plt.subplots()
ax.scatter(rw.x_values,rw.y_values,s=15)
points_numbers= range(rw.num_points)
ax.scatter(rw.x_values,rw.y_values,c=points_numbers,cmap=plt.cm.Blues,edgecolors='none',s=1)
# 突出起点和终点
ax.scatter(0,0,c='green',edgecolors='none',s=100)
ax.scatter(rw.x_values[-1],rw.y_values[-1],c='red',edgecolors='none',s=100)
# 隐藏坐标轴
ax.get_xaxis().set_visible(False)
ax.get_yaxis().set_visible(False)
plt.show()
keep_running=input("Make another walk? (y/n):")
if keep_running=='n':
break
结果如图:
4、使用Plotly模拟掷骰子
安装Plotly
pip install plotly
创建Die类
from random import randint
class Die:
# 表示一个骰子的类
def __init__(self,num_sides=6):
# 骰子默认为6面
self.num_sides=num_sides
def roll(self):
# 返回一个位于1和骰子面数之间的随机值
return randint(1,self.num_sides)
掷骰子、分析结果、绘制直方图
from plotly.graph_objs import Bar,Layout
from plotly import offline
from die import Die
# 创建一个D6
# die=Die()
# 创建两个D6
die_1=Die()
# die_2=Die()
die_2=Die(10)
# 掷几次骰子并将结果存储在一个列表中
results=[]
for roll_num in range(50000):
# result=die.roll()
# 将投掷的两个骰子点数相加
result=die_1.roll()+die_2.roll()
results.append(result)
# 输出结果
# print(results)
# 分析结果
frequencies=[]
max_result=die_1.num_sides+die_2.num_sides
for value in range(2,max_result+1):
# range(a,b)代表什么意思,生成到一系列数字:从a开始,到小于b(或等于b-1)结束。
# for value in range(1,die.num_sides+1):
# count():统计在字符串/列表/元组中某个字符出现的次数。
frequency=results.count(value)
frequencies.append(frequency)
# print(frequencies)
# 对结果进行可视化
# list() 函数用于将元组、区间(range)等转换为列表。列表和元组非常类似,但列表与元组最大的区别在于:元组是不可改变的,列表是可改变的。
# 元组支持的操作,列表基本上都支持;列表支持对元素的修改,而元组则不支持。从这个角度来看,可以认为列表是增强版的元组。
# 虽然大部分时候都可使用列表来代替元组,但如果程序不需要修改列表所包含的元素,那么使用元组代替列表会更安全。
# 可视化结果
# x_values=list(range(1,die.num_sides+1))
x_values=list(range(2,max_result+1))
data=[Bar(x=x_values,y=frequencies)]
x_axis_config={'title':'结果','dtick':1}
y_axis_config={'title':'结果的频率'}
# my_layout=Layout(title='投掷一个D6 1000次的结果',xaxis=x_axis_config,yaxis=y_axis_config)
# my_layout=Layout(title='投掷两个D6 1000次的结果',xaxis=x_axis_config,yaxis=y_axis_config)
my_layout=Layout(title='投掷一个D6和一个D10 50000次的结果',xaxis=x_axis_config,yaxis=y_axis_config)
# offline.plot({'data':data,'layout':my_layout},filename='d6.html')
# offline.plot({'data':data,'layout':my_layout},filename='d6_d6.html')
offline.plot({'data':data,'layout':my_layout},filename='d6_d10.html')
结果如图