我正在python上绘制一些随机游动函数,并尝试创建它,以便它每隔1000步获取一次随机游动的位置,然后将它们绘制在直方图中。我意识到我可以每次从字面上为n = 1000,2000等创建一个新列表,然后将walk的值附加到该列表中,但是有没有办法让python每1000个步骤创建一个新列表?
import numpy as np
import matplotlib.pyplot as plt
def random_walk(N,d):
walk = d*np.cumsum(2*np.random.binomial(1,.6,N)-1)
return walk
n1=[]
n2=[]
n3=[]
n4=[]
n5=[]
for k in range(5000):
particular_walk = random_walk(5000,2)
n1.append(particular_walk[1000])
n2.append(particular_walk[2000])
n3.append(particular_walk[3000])
n4.append(particular_walk[4000])
n5.append(particular_walk[-1])
plt.hist(n1,bins=20,histtype='step',density=True)
plt.hist(n2,bins=20,histtype='step',density=True)
plt.hist(n3,bins=20,histtype='step',density=True)
plt.hist(n4,bins=20,histtype='step',density=True)
plt.hist(n5,bins=20,histtype='step',density=True)
plt.show()
到目前为止,这是我的代码,但我意识到它不起作用。我知道我可以有一个名为“中点”的列表,并将其设置为特定步行路线的位置2500,但是有没有办法自动做到这一点?
通常,在使用numpy时,您要排除使用列表。就时间和空间而言,阵列效率更高。您还应该尝试避免使用显式的Python循环,因为numpy提供的向量化将会更快。
假设您想针对样本中Z
不同位置的步行进行此操作Z = 5000
,但在一般情况下希望更大。您可以使用大多数numpy函数可以应用于特定轴这一事实来完成此任务:
import numpy as np
from matplotlib import pyplot as plt
Z = 5000
N = 5000
d = 2
all_walks = d * np.cumsum(2 * np.random.binomial(1, 0.6, size=(Z, N)) - 1, axis=1)
将步骤的大小设置为,(Z, N)
将为您提供一个包含Z
行的矩阵,每一行都有N
步骤。取累加总和axis=1
意味着跨列求和。现在每一行都是独立的步行。您可以使用非常基本的切片来获取所需的任何列。第n
th列将包含各n
步的第th步Z
。您希望将“切片”列作为原因的原因在于,这种方式使绘图变得更加容易。
让我们来看看n=1000
:
n1k = all_walks[:, 1000]
plt.hist(n1k, bins=20, histtype='step', density=True)
到现在为止还挺好。要获取每1000个样本,请使用索引中的步长:
n = 1000
samples = all_walks[:, n::n]
samples
现在是Zx(N // n)-1((5000, 4)
)数组,其中包含1000, 3000, 4000
每个数组中索引处的步骤。在此示例中,您似乎希望有五个样本。我认为可以通过三种合理的方式来做到这一点:
0
:samples = all_walks[:, ::n]
n-1
:samples = all_walks[:, n-1::n]
向步行添加额外的步骤(列):
all_walks = ... size=(Z, N+1) ...
samples = all_walks[:, n::n]
我不认为通过不一致地添加索引来弄乱间距-1
不是一个特别好的主意。我将改用选项#2(请记住,索引999包含第1000个步骤)。
好消息是matplotlib允许您一次绘制向量的列:
plt.hist(samples, bins=20, histtype='step', density=True)
因此,整个脚本实际上很短:
import numpy as np
from matplotlib import pyplot as plt
Z = 5000
N = 5000
d = 2
n = 1000
all_walks = d * np.cumsum(2 * np.random.binomial(1, 0.6, size=(Z, N)) - 1, axis=1)
samples = all_walks[:, n-1::n]
plt.hist(samples, bins=20, histtype='step', density=True)
plt.show()
如果由于某种原因不能一次将大小为Z * N
float的数组全部保存在内存中,则可以all_walks
使用一次生成一个遍历的循环来实现该行,这有点像您最初尝试做的那样。请记住,仅当您制作Z
数量惊人地大或由于某些原因而没有RAM时,这才行:
samples = np.empty((Z, N//n))
for row in range(Z):
walk = d * np.cumsum(2 * np.random.binomial(1, 0.6, size=N) - 1)
samples[row] = walk[n-1::n]
如果您从相同的随机种子开始,则这两种方法应会给您相同的结果。主要区别在于,第一个占用更多内存,而第二个占用更多时间。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句