15.3 随机游走
#random_walk.py
#15.3随机游走.py
from random import choice
class RandomWalk:
"""一个生成随机游走数据的类"""
def __init__(self,num_points=5000):
self.num_points = num_points
self.x_value = [0]
self.y_value = [0]
def fill_walk(self):
#不断游走,直至列表达到指定长度
while len(self.x_value) < 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_value[-1] + x_step
y = self.y_value[-1] + y_step
self.x_value.append(x)
self.y_value.append(y)
#rw_visual.py
#rw_visual.py
import matplotlib.pyplot as plt
import matplotlib
matplotlib.use('TkAgg')
from random_walk import RandomWalk
rw= RandomWalk()
rw.fill_walk()
plt.style.use('classic')
fig, ax = plt.subplots()
ax.scatter(rw.x_value,rw.y_value,s=15)
ax.set_aspect('equal')
plt.show()
这段写了很多错误,回顾bug如下
- class的RandomWalk应该放置在一个单独的.py文件中供调用,我一开始全写到了同一个.py文件中,导致循环引用报错;
- __init__方法,init前后下划线是双下划线,“_ _”,而非单下划线“_”,一开始用的单下划线导致__init__方法定义错误,一直报错;
- 很多拼写错误,前面定义的x_value,然后在#rw_visual.py中调用成了x_values,无语;
15.3.4 模拟多次随机游走
#rw_visual.py
import matplotlib.pyplot as plt
import matplotlib
matplotlib.use('TkAgg')
from random_walk import RandomWalk
#模拟多次随机游走,只要程序处于活动状态就不断的模拟随机游走
#通过while循环实现
while True:
#生成一个RandomWalk实例
rw= RandomWalk()
rw.fill_walk()
plt.style.use('classic')
fig, ax = plt.subplots()
ax.scatter(rw.x_value,rw.y_value,s=15)
ax.set_aspect('equal')
plt.show()
keep_running = input("Make another walk?(y/n):")
if keep_running == 'n':
break
15.3.5 设置随机游走图的样式
根据需要着重突出的部分,利用可视化的手段在图里进行突出和强调(所以本质上自己要对数据的意义有深刻理解,可视化只是辅助理解、让图漂亮的手段而已)
1. 给点着色
#rw_visual.py
import matplotlib.pyplot as plt
import matplotlib
from random_walk import RandomWalk
#模拟多次随机游走,只要程序处于活动状态就不断的模拟随机游走
#通过while循环实现
while True:
#生成一个RandomWalk实例
rw= RandomWalk()
rw.fill_walk()
#绘制出所有的点
plt.style.use('classic')
fig, ax = plt.subplots()
#使用range生成一个数值列表,列表自带顺序
point_numbers = range(rw.num_points)
#将列表传递给c,这样c也有了顺序,根据顺序就能绘制不同颜色从而实现渐变色
#指定使用Blues颜色映射
ax.scatter(rw.x_value,rw.y_value,c=point_numbers,cmap=plt.cm.Blues,
edgecolors='none',s=15)
ax.set_aspect('equal')
plt.show()
keep_running = input("Make another walk?(y/n):")
if keep_running == 'n':
break
2.重新绘制起点和终点
在所有点绘制完毕以后再绘制一次【起点】和【终点】,让二者更加突出
#rw_visual.py
import matplotlib.pyplot as plt
import matplotlib
from random_walk import RandomWalk
#生成一个RandomWalk实例
rw= RandomWalk()
rw.fill_walk()
#绘制出所有的点
plt.style.use('classic')
fig, ax = plt.subplots()
#使用range生成一个数值列表,列表自带顺序
point_numbers = range(rw.num_points)
#将列表传递给c,这样c也有了顺序,根据顺序就能绘制不同颜色从而实现渐变色
ax.scatter(rw.x_value,rw.y_value,c=point_numbers,cmap=plt.cm.Blues,
edgecolors='none',s=15)
ax.set_aspect('equal')
#突出起点和终点
ax.scatter(0,0,c='green',edgecolors='none',s=100)
ax.scatter(rw.x_value[-1],rw.y_value[-1],c='red',edgecolors='none',s=100)
plt.show()
3.隐藏坐标轴
#rw_visual.py
import matplotlib.pyplot as plt
import matplotlib
from random_walk import RandomWalk
#生成一个RandomWalk实例
rw= RandomWalk()
rw.fill_walk()
#绘制出所有的点
plt.style.use('classic')
fig, ax = plt.subplots()
#使用range生成一个数值列表,列表自带顺序
point_numbers = range(rw.num_points)
#将列表传递给c,这样c也有了顺序,根据顺序就能绘制不同颜色从而实现渐变色
ax.scatter(rw.x_value,rw.y_value,c=point_numbers,cmap=plt.cm.Blues,
edgecolors='none',s=15)
ax.set_aspect('equal')
#突出起点和终点
ax.scatter(0,0,c='green',edgecolors='none',s=100)
ax.scatter(rw.x_value[-1],rw.y_value[-1],c='red',edgecolors='none',s=100)
#隐藏坐标轴
ax.get_xaxis().set_visible(False)
ax.get_yaxis().set_visible(False)
plt.show()
4.增加点的个数
#rw_visual.py
import matplotlib.pyplot as plt
import matplotlib
from random_walk import RandomWalk
#生成一个RandomWalk实例
#增大num_numpoints的值
rw= RandomWalk(50_000)
rw.fill_walk()
#绘制出所有的点
plt.style.use('classic')
fig, ax = plt.subplots()
#使用range生成一个数值列表,列表自带顺序
point_numbers = range(rw.num_points)
#num_points变大了,相应地把size调小,不然没法看了
ax.scatter(rw.x_value,rw.y_value,c=point_numbers,cmap=plt.cm.Blues,
edgecolors='none',s=1)
ax.set_aspect('equal')
#突出起点和终点
ax.scatter(0,0,c='green',edgecolors='none',s=100)
ax.scatter(rw.x_value[-1],rw.y_value[-1],c='red',edgecolors='none',s=100)
#隐藏坐标轴
ax.get_xaxis().set_visible(False)
ax.get_yaxis().set_visible(False)
plt.show()
5.调整尺寸以适应屏幕大小
#rw_visual.py
import matplotlib.pyplot as plt
import matplotlib
from random_walk import RandomWalk
#生成一个RandomWalk实例
#增大num_numpoints的值
rw= RandomWalk(50_000)
rw.fill_walk()
#绘制出所有的点
plt.style.use('classic')
#调整生成屏幕尺寸
fig, ax = plt.subplots(figsize=(10,6), dpi=128)
#使用range生成一个数值列表,列表自带顺序
point_numbers = range(rw.num_points)
#num_points变大了,相应地把size调小,不然没法看了
ax.scatter(rw.x_value,rw.y_value,c=point_numbers,cmap=plt.cm.Blues,
edgecolors='none',s=1)
ax.set_aspect('equal')
#突出起点和终点
ax.scatter(0,0,c='green',edgecolors='none',s=100)
ax.scatter(rw.x_value[-1],rw.y_value[-1],c='red',edgecolors='none',s=100)
#隐藏坐标轴
ax.get_xaxis().set_visible(False)
ax.get_yaxis().set_visible(False)
plt.show()
15.4 使用Plotly模拟掷骰子
15.4.2创建Die类
#die.py
from random import randint
class Die:
#默认是一个六面的骰子
def __init__(self,num_sides=6):
self.num_sides = num_sides
#但可以赋值num_sides,即可以八面可以十二面等等
def roll(self):
return randint(1,self.num_sides)
15.4.3投掷骰子
#die_visual.py
from die import Die
die = Die()
results = []
for roll_num in range(100):
result = die.roll()
results.append(result)
print (results)
15.4.4分析结果
#die_visual.py
from die import Die
die = Die()
results = []
for roll_num in range(100):
result = die.roll()
results.append(result)
frequencies = []
poss_results = range(1,die.num_sides+1)
for value in poss_results:
frequency=results.count(value)
frequencies.append(frequency)
print(frequencies)
这里报错了一次,
File "die_visual分析数据.py", line 14, in <module> frequency=result.count(value) ^^^^^^^^^^^^ AttributeError: 'int' object has no attribute 'count'
检查以后发现是
frequency=results.count(value)
被我打成了
result
count是计数,results是列表,能够被计数,result只有一次随机数据不能被计数,因此报错了。实话实说,这些bug太几把难找了,但如果理解深刻、自己定义的东西自己记好,熟练的老师傅是很容易避免的吧!
15.4.5绘制直方图
#die_visual.py
import plotly.express as px
from die import Die
die = Die()
results = []
for roll_num in range(100):
result = die.roll()
results.append(result)
frequencies = []
poss_results = range(1,die.num_sides+1)
for value in poss_results:
frequency=results.count(value)
frequencies.append(frequency)
#对结果进行可视化
fig=px.bar(x=poss_results,y=frequencies)
fig.show()
报错,发现应该
import plotly.express as px
加载成了
import plotly as px
15.4.6定制绘图
#die_visual.py
import plotly.express as px
from die import Die
die = Die()
results = []
for roll_num in range(100):
result = die.roll()
results.append(result)
frequencies = []
poss_results = range(1,die.num_sides+1)
for value in poss_results:
frequency=results.count(value)
frequencies.append(frequency)
#对结果进行可视化
title="Results of Rolling On D6 1000 times"
#大括号创建字典,键值对实现label的一一对应
labels={'x':'Result','y':'Frequency of Result'}
fig=px.bar(x=poss_results,y=frequencies,title=title,labels=labels)
fig.show()
15.4.7同时投掷两个骰子
#dice_visual.py
import plotly.express as px
from die import Die
die_1 = Die()
die_2 = Die()
results = []
for roll_num in range(1000):
result = die_1.roll()+die_2.roll()
results.append(result)
frequencies = []
max_result=die_1.num_sides + die_2.num_sides
poss_results = range(2,max_result+1)
for value in poss_results:
frequency=results.count(value)
frequencies.append(frequency)
#对结果进行可视化
title="Results of Rolling Two D6 Dice 1000 Times"
#大括号创建字典,键值对实现label的一一对应
labels={'x':'Result','y':'Frequency of Result'}
fig=px.bar(x=poss_results,y=frequencies,title=title,labels=labels)
fig.show()
15.4.8 updata_layout方法进一步定制
#dice_visual.py
import plotly.express as px
from die import Die
die_1 = Die()
die_2 = Die()
results = []
for roll_num in range(1000):
result = die_1.roll()+die_2.roll()
results.append(result)
frequencies = []
max_result=die_1.num_sides + die_2.num_sides
poss_results = range(2,max_result+1)
for value in poss_results:
frequency=results.count(value)
frequencies.append(frequency)
#对结果进行可视化
title="Results of Rolling Two D6 Dice 1000 Times"
#大括号创建字典,键值对实现label的一一对应
labels={'x':'Result','y':'Frequency of Result'}
fig=px.bar(x=poss_results,y=frequencies,title=title,labels=labels)
#update_layout method进行进一步定制
fig.update_layout(xaxis_dtick=1)
fig.show()
15.4.9同时投掷两个面数不同的骰子
#dice_visual.py
import plotly.express as px
from die import Die
die_1 = Die()
die_2 = Die(10)
results = []
for roll_num in range(50_000):
result = die_1.roll()+die_2.roll()
results.append(result)
frequencies = []
max_result=die_1.num_sides + die_2.num_sides
poss_results = range(2,max_result+1)
for value in poss_results:
frequency=results.count(value)
frequencies.append(frequency)
#对结果进行可视化
title="Results of Rolling a D6 and a D10 50,000 Times"
#大括号创建字典,键值对实现label的一一对应
labels={'x':'Result','y':'Frequency of Result'}
fig=px.bar(x=poss_results,y=frequencies,title=title,labels=labels)
#update_layout method进行进一步定制
fig.update_layout(xaxis_dtick=1)
fig.show()
15.4.10保存图形
#dice_visual.py
import plotly.express as px
from die import Die
die_1 = Die()
die_2 = Die(10)
results = []
for roll_num in range(50_000):
result = die_1.roll()+die_2.roll()
results.append(result)
frequencies = []
max_result=die_1.num_sides + die_2.num_sides
poss_results = range(2,max_result+1)
for value in poss_results:
frequency=results.count(value)
frequencies.append(frequency)
#对结果进行可视化
title="Results of Rolling a D6 and a D10 50,000 Times"
#大括号创建字典,键值对实现label的一一对应
labels={'x':'Result','y':'Frequency of Result'}
fig=px.bar(x=poss_results,y=frequencies,title=title,labels=labels)
#update_layout method进行进一步定制
fig.update_layout(xaxis_dtick=1)
#保存只需要把fig.show()替换掉就行了
fig.write_html('dice_visual_d6d10.html')
今天到此为止了,发现bug+debug真的挺费神费力的...真的是照着抄都能抄错哈哈