作者:雷蕾
什么是随机漫步?随机漫步是怎样的一个行走路径?随机漫步每次行走都是完全随机的、没有明确的方向,结果是由一系列随机决策决定的。为了更好地理解,我们可以把随机漫步看作是蚂蚁晕头转向的情况下,每次都沿随机的方向前行所经过的路径。
(一)创建RandomWalk类
为模拟随机漫步,将创建一个名为RandomWalk的类,它随机地选择方向前进,这个类需要包含三个属性:一个存储随机漫步次数的变量,其他两个属性是列表,分别存储随机漫步经过的每个点的x坐标和y坐标:
from random import choice
class RandomWalk:
'''一个生成随机漫步数据的类'''
def __init__(self,num_points=5000):
'''初始化随机漫步的属性'''
self.num_points=num_points
#所有随机漫步数都始于0
self.x_values=[0]
self.y_values=[0]
为做出随机决策,将所有可能的选择都存储在一个列表中,并在每次决策时都使用模块random中的choice()来决定使用哪种选择。
类 RandomWalk中定义了方法__init__(),并将随机漫步包含的默认点数设置为5000,当然我们也可改变随机漫步点数。
self.x_values=[0]
self.y_values=[0]
这两行代码是创建两个用于存储x值和y值的列表,并让每次漫步起点从(0,0)开始。
(二)选择方向
在类RandomWalk中定义了方法fill_walk():
#选择方向
def fill_walk(self):
'''计算随机漫步包含的所有点'''
#不断漫步,直到列表达到指定的列表
while len(self.x_values)
该示例中使用方法fill_walk()来生成漫步包含的点并决定每次漫步的方向,在方法fill_walk()中主要是告诉python如何模拟四种漫步决定:向右走还是向左走?沿指定的方向走多远?向上走还是向下走?沿选定的方向走多远?
代码行 while len(self.x_values)
代码行 x_distance=choice([0,1,2,3,4])是choice([0,1,2,3,4])随机地选择一个1~4的整数,告诉python沿指定的方向走多远( x_distance),通过包含0,不仅能够同时沿两个轴移动,还能够只沿一个轴移动;
代码行 x_step=x_direction*x_distance将移动方向乘以移动距离,确定沿x轴和y轴的距离:如果x_step为正将向右移动,x_step为负向左移动,x_step为零将垂直移动,y_step为正向上移动,y_step为负向下移动,y_step为零水平移动;
x_step和y_step都为零的话则原地踏步,为了拒绝这种情况,我们使用 continue语句,让代码接着执行下一次循环;
代码行 x=self.x_values[-1]+x_step是为获取下一个点的x值,将x_step与x_values中的最后一个值相加,对y做同样的处理;
代码行 self.x_values.append(x)是获取下一个点的x值后,将值附加到列表x_values末尾中,y类似。
(三)绘制随机漫步图
#绘制随机漫步图
import matplotlib.pyplot as plt
from random_walk import RandomWalk
#创建一个RandomWalk实例
rw=RandomWalk()
rw.fill_walk()
#将所有的点都绘制出来
plt.style.use('classic')
fig,ax=plt.subplots()
ax.scatter(rw.x_values,rw.y_values,s=15)
plt.show()
示例中首先导入了模块pyplot 和类 RandomWalk,再创建了一个 RandomWalk实例并存储到rw中;
代码行rw.fill_walk()是调用方法fill_walk();
代码行ax.scatter(rw.x_values,rw.y_values,s=15)是将随机漫步包含的x值和y值传递给scatter(),并将点的尺寸大小设置为15。
运行代码结果结果:
运行所得图表展示了包含5000个点的随机漫步图
(四)模拟多次随机漫步图
要在不多次运行程序的情况下使用已有的代码模拟多次随机漫步,可将已有代码放在while循环中:
#模拟多次随机漫步
#绘制随机漫步图
import matplotlib.pyplot as plt
from random_walk import RandomWalk
#只要程序处于活动状态,就不断地模拟随机漫步
while True:
#创建一个RandomWalk实例
rw=RandomWalk()
rw.fill_walk()
#将所有的点都绘制出来
plt.style.use('classic')
fig,ax=plt.subplots()
ax.scatter(rw.x_values,rw.y_values,s=15)
plt.show()
keep_running=input("Make another walk?(y/n):")
if keep_running=='n':
break
每次模拟随机漫步,可在显示器查看结果,通过添加while循环,当我们关闭查看器时,程序会询问是否要再模拟一次随机漫步,当输入y(yes),可继续模拟随机漫步,当输入n(no),结束程序,不继续模拟随机漫步,当点击关闭显示器按钮时,会如下图所示:
(五)设置随机漫步的样式
1.给点着色:
import matplotlib.pyplot as plt
from random_walk import RandomWalk
#只要程序处于活动状态,就不断地模拟随机漫步
while True:
#创建一个RandomWalk实例
rw=RandomWalk()
rw.fill_walk()
#将所有的点都绘制出来
plt.style.use('classic')
fig,ax=plt.subplots()
#给点着色
point_numbers=range(rw.num_points)
ax.scatter(rw.x_values,rw.y_values,c=point_numbers,cmap=plt.cm.Blues,
edgecolors='none',s=15)
plt.show()
keep_running=input("Make another walk?(y/n):")
if keep_running=='n':
break
我们使用颜色映射指出漫步中各点的先后顺序,并删除各点的黑色轮廓,使其颜色明显。
#给点着色
point_numbers=range(rw.num_points)
ax.scatter(rw.x_values,rw.y_values,c=point_numbers,cmap=plt.cm.Blues,
edgecolors='none',s=15)
第一行代码行中,使用range()生成了一个数字列表,它包含的点数和漫步包含的点数一致,并将该列表保存在 point_numbers中;
第二行代码中,将参数c设置为 point_numbers,并指定使用颜色(Bules)映射;
第三行代码中, 使用edgecolors='none’将各点轮廓颜色去掉。
2.重新绘制起点和终点:
import matplotlib.pyplot as plt
from random_walk import RandomWalk
#只要程序处于活动状态,就不断地模拟随机漫步
while True:
#创建一个RandomWalk实例
rw=RandomWalk()
rw.fill_walk()
#将所有的点都绘制出来
plt.style.use('classic')
fig,ax=plt.subplots()
#给点着色
point_numbers=range(rw.num_points)
ax.scatter(rw.x_values,rw.y_values,c=point_numbers,cmap=plt.cm.Blues,
edgecolors='none',s=15)
#突出起点和终点
ax.scatter(0,0,c='green',edgecolor='none',s=100)
ax.scatter(rw.x_values[-1],rw.y_values[-1],c='red',edgecolor='none',s=100)
plt.show()
keep_running=input("Make another walk?(y/n):")
if keep_running=='n':
break
绘制图表的起点和终点可使图表更具可读性。
#突出起点和终点
ax.scatter(0,0,c='green',edgecolor='none',s=100)
ax.scatter(rw.x_values[-1],rw.y_values[-1],c='red',edgecolor='none',s=100)
第一行代码中,使用了绿色来突出起点;
第二行代码中,使用了红色来突出终点。
3.隐藏坐标轴:
当然,为了图表的可读性,还可将图表的坐标轴进行隐藏。
import matplotlib.pyplot as plt
from random_walk import RandomWalk
#只要程序处于活动状态,就不断地模拟随机漫步
while True:
#创建一个RandomWalk实例
rw=RandomWalk()
rw.fill_walk()
#将所有的点都绘制出来
plt.style.use('classic')
fig,ax=plt.subplots()
#给点着色
point_numbers=range(rw.num_points)
ax.scatter(rw.x_values,rw.y_values,c=point_numbers,cmap=plt.cm.Blues,
edgecolors='none',s=15)
#突出起点和终点
ax.scatter(0,0,c='green',edgecolor='none',s=100)
ax.scatter(rw.x_values[-1],rw.y_values[-1],c='red',edgecolor='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
为了将坐标轴隐藏,可使用方法ax.get_xaxis()和 方法ax.get_yaxis()将每条坐标轴的可见性设置为False:
#隐藏坐标轴
ax.get_xaxis().set_visible(False)
ax.get_yaxis().set_visible(False)
最终运行代码结果展示:
4.增加点数:
我们还可增加随机漫步的点数:
import matplotlib.pyplot as plt
from random_walk import RandomWalk
#只要程序处于活动状态,就不断地模拟随机漫步
while True:
#创建一个RandomWalk实例
rw=RandomWalk(50_000)
rw.fill_walk()
#将所有的点都绘制出来
plt.style.use('classic')
#给点着色
point_numbers=range(rw.num_points)
ax.scatter(rw.x_values,rw.y_values,c=point_numbers,cmap=plt.cm.Blues,
edgecolors='none',s=1)
#突出起点和终点
ax.scatter(0,0,c='green',edgecolor='none',s=100)
ax.scatter(rw.x_values[-1],rw.y_values[-1],c='red',edgecolor='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
运行代码结果展示:
5.调整尺寸合适的屏幕
为了图表可读性,图表适合屏幕大小时,也更加能有效地将数据中地规律出现出来,为此可通过以下代码使绘图窗口更加适合屏幕大小(根据需要调整figsize数字):
fig,ax=plt.subplots(figsize=(15,9))