简体   繁体   English

使用Python绘制2D随机游走的问题

[英]Problems plotting a 2D random walk with Python

I'm trying to create a 2D random walk with Python. 我正在尝试使用Python创建2D随机游动。 The random walk is to occur within a square, and if the particle crosses any side of the square the particle is to appear on the other side -- in effect, the random walk is occurring on a torus. 随机游走将发生在正方形内,并且如果粒子穿过正方形的任一侧,则粒子将出现在另一侧-实际上,随机游走发生在圆环上。

Here's a copy of my code: 这是我的代码的副本:

from random import randrange as rand
from math import cos, sin, radians
import matplotlib.pyplot as plt

N = 100   # Size of square as a multiple of the step size.
NSteps = 5000   # Number of steps in simulation.
xStart = 0   # x coordinate of starting location. Origin is at centre of square
yStart = 0   # y coordinate of starting location. Origin is at centre of square

s = 1   # Step number.
x = xStart   # x coordinate of point.
y = yStart   # y coordinate of point.
xList = []   # List of the x coordinates of all points visited.
yList = []   # List of the y coordinates of all points visited.

while s <= NSteps:
    angle = radians(rand(361))
    x += cos(angle)    
    if x > N/2:
        x -= N
    elif x < -N/2:
        x += N    
    xList += [x]
    y += sin(angle)
    if y > N/2:
        y -= N
    elif y < -N/2:
        y += N
    yList += [y]    
    s += 1

plt.figure(figsize=(13,8))
frame = plt.gca()
plt.plot(xList,yList,c="b")
plt.xlim(-N/2,N/2)
plt.ylim(-N/2,N/2)
frame.axes.get_xaxis().set_visible(False)
frame.axes.get_yaxis().set_visible(False)
plt.savefig("randomWalk.png", bbox_inches="tight")

This code produces a plot like this: 此代码生成如下图: 在此处输入图片说明

As you can see, whenever the particle crosses one of the sides I get these 'streaks' on the plot because plot() will connect two points no matter how far apart they are. 如您所见,每当粒子穿过边的一侧时,我都会在图上看到这些“条纹”,因为plot()会连接两个点,无论它们相距多远。 Is there a way to prevent this from happening? 有办法防止这种情况发生吗?

I also re-wrote your steping code a bit to make it easier (in my opinion) to read: 我还重新编写了您的步进代码,以使其更易于阅读(我认为):

from random import randrange as rand
from numpy import cos, sin, radians
import numpy as np
import matplotlib.pyplot as plt

N = 100   # Size of square as a multiple of the step size.
NSteps = 5000   # Number of steps in simulation.
xStart = 0   # x coordinate of starting location. Origin is at centre of square
yStart = 0   # y coordinate of starting location. Origin is at centre of square

s = 1   # Step number.
x = xStart   # x coordinate of point.
y = yStart   # y coordinate of point.
xList = []   # List of the x coordinates of all points visited.
yList = []   # List of the y coordinates of all points visited.

def wrap(v, N):

    if v > N/2:
        return v - N, True
    elif v < -N/2:
        return v + N, True
    return v, False


for j in range(NSteps):
    angle = radians(rand(361))
    x, wrap_flag_x = wrap(x + cos(angle), N)
    y, wrap_flag_y = wrap(y + sin(angle), N)
    if wrap_flag_x or wrap_flag_y:
        xList.append(np.nan)
        yList.append(np.nan)
    xList.append(x)
    yList.append(y)    

fig, ax = plt.subplots()
ax.plot(xList,yList,c="b")
ax.set_xlim(-N/2,N/2)
ax.set_ylim(-N/2,N/2)
ax.get_xaxis().set_visible(False)
ax.get_yaxis().set_visible(False)

They are putting np.nan (Not A Number, which is part of the float spec) into your list. 他们正在将np.nan (不是数字,这是float规范的一部分)放入您的列表。 When mpl is drawing lines it (with the default line style) connects all of the points. 当mpl绘制线时,它(使用默认线型)连接所有点。 The points that are np.nan can't be drawn to the screen so the line from the last point to the np.nan point is not drawn and the line from the np.nan to the next point is not drawn, hence the break in your line. 无法将np.nan的点绘制到屏幕上,因此不会绘制从最后一个点到np.nan点的线,也不会绘制从np.nan到下一个点的线,因此会中断在你的行。 输出

As a side note, most of this simulation can be vectorized: 附带说明一下,大多数这种模拟可以向量化:

from numpy.random import randint
from numpy import cos, sin, radians, cumsum
import numpy as np
import matplotlib.pyplot as plt

N = 100   # Size of square as a multiple of the step size.
NSteps = 5000   # Number of steps in simulation.
x_start = 0   # x coordinate of starting location. Origin is at centre of square
y_start = 0   # y coordinate of starting location. Origin is at centre of square



# get all of the angles
angles = radians(randint(low=0, high=361, size=NSteps))

# get (unwrapped) positions
x = cumsum(cos(angles)) + x_start
y = cumsum(sin(angles)) + y_start

# find where the position crosses the boundary
x_wraps = np.where(np.diff((x + N/2) // N))[0]
y_wraps = np.where(np.diff((y + N/2) // N))[0]

# do the wrapping
x = x - N * ((x + N/2)//N)
y = y - N * ((y + N/2)//N)

I leave using the wrap locations to insert nans as an exercise for the reader ;) 我离开使用换行位置来插入nans作为读者的练习;)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM