【问题标题】:How can I create a new list every x amount of steps in a loop?如何在循环中每 x 步创建一个新列表?
【发布时间】:2018-10-26 12:17:18
【问题描述】:

我正在 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 处特定步行的位置,但有没有办法自动完成?

【问题讨论】:

  • 您希望输出是什么?
  • 我想要多个列表,每个列表都包含当时随机游走的所有值。然后我希望它在直方图中绘制所有这些列表的概率。
  • 请显示示例输出和您希望看到的图
  • 具体来说,您是要绘制 5 个不同的直方图还是只绘制上面示例中的一个?
  • 5 个直方图,我知道如何手动执行此操作 - 但是如果 n 更改为 10000 而不是 5000,有没有办法让它在这种情况下自动生成 10 个直方图?现在在我的手机上,但稍后会显示一个示例。

标签: python list numpy histogram random-walk


【解决方案1】:

通常,在使用 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 求累积和意味着跨列求和。现在每一行都是一个独立的步行。您可以使用非常基本的切片来获得所需的任何列。 nth 列将包含来自每个 Z 步行的 nth 步骤。您想要制作切片列的原因是这样可以更轻松地进行绘图。

我们来看看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 处的步骤。在此示例中,您似乎希望总共有五个样本。在我看来,有三种合理的方法可以做到这一点:

  1. 从索引开始0:samples = all_walks[:, ::n]
  2. 从索引开始n-1:samples = all_walks[:, n-1::n]
  3. 为您的步行添加一个额外的步骤(列):

    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 的数组,您可以使用一次生成一个 walk 的循环来实现行 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]

如果您从相同的随机种子开始,这两种方法应该会得到相同的结果。主要区别在于第一个需要更多内存,而第二个需要更多时间。

【讨论】:

  • 非常感谢!非常感谢所有的帮助和解释!
【解决方案2】:

也许您可以使用 python 字典并在字典中创建列表。

可能是这样的:

if k%1000 == 0:
    rw_dict[str(k/1000)]=[]

其中 str(k/1000) 只是字典中键的名称:1.0、2.0 等。每当您需要对该特定列表进行操作时,都可以使用 rw_dict[list_name] 访问该列表。

我希望这会有所帮助!

【讨论】:

    猜你喜欢
    • 2020-02-11
    • 2022-07-12
    • 1970-01-01
    • 2015-06-29
    • 2011-10-22
    • 2018-12-24
    • 1970-01-01
    • 1970-01-01
    • 2014-11-17
    相关资源
    最近更新 更多