如何在循环中每隔 x 步创建一个新列表?
How can I create a new list every x amount of steps in a loop?
我正在 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()
这是我目前的代码,但我意识到它不起作用。我知道我可以有一个名为 say "midpoint" 的列表,并将其设置为 2500 处特定步行的位置,但是有没有办法自动执行此操作?
也许您可以使用 python 字典并在字典中创建列表。
可能是这样的:
if k%1000 == 0:
rw_dict[str(k/1000)]=[]
其中 str(k/1000) 只是字典中键的名称:1.0、2.0 等。每当您需要对该特定列表进行操作时,您可以使用 [= 访问该列表20=][list_name]。
希望对您有所帮助!
通常,您希望在使用 numpy 时排除使用列表的可能性。就时间和 space 而言,数组的效率要高得多。您还应该尽量避免使用显式 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
列将包含每个 Z
步行的第 n
步。您想要制作切片列的原因是这样绘图变得容易得多。
我们来看看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
的数组,你可以使用一次生成一次行走的循环来实现行 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]
如果您从相同的随机种子开始,这两种方法应该会得到相同的结果。主要区别在于第一个占用更多内存,而第二个占用更多时间。
我正在 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()
这是我目前的代码,但我意识到它不起作用。我知道我可以有一个名为 say "midpoint" 的列表,并将其设置为 2500 处特定步行的位置,但是有没有办法自动执行此操作?
也许您可以使用 python 字典并在字典中创建列表。
可能是这样的:
if k%1000 == 0:
rw_dict[str(k/1000)]=[]
其中 str(k/1000) 只是字典中键的名称:1.0、2.0 等。每当您需要对该特定列表进行操作时,您可以使用 [= 访问该列表20=][list_name]。
希望对您有所帮助!
通常,您希望在使用 numpy 时排除使用列表的可能性。就时间和 space 而言,数组的效率要高得多。您还应该尽量避免使用显式 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
列将包含每个 Z
步行的第 n
步。您想要制作切片列的原因是这样绘图变得容易得多。
我们来看看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
的数组,你可以使用一次生成一次行走的循环来实现行 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]
如果您从相同的随机种子开始,这两种方法应该会得到相同的结果。主要区别在于第一个占用更多内存,而第二个占用更多时间。