【问题标题】:verify distribution of uniformly distributed 3D coordinates验证均匀分布的 3D 坐标的分布
【发布时间】:2019-01-28 20:37:54
【问题描述】:

我想编写一个 python 脚本来生成一个均匀分布的 3D 坐标(例如,x、y、z),其中 x、y 和 z 是 0 到 1 之间的浮点数。目前,z 可以固定,因此我需要的是二维(xy)平面中的均匀分布点。我编写了一个脚本来完成这项工作,并检查了 x 和 y 是统一的数字。但是,我不确定这些点是否均匀分布在(x-y)平面上。

我的代码是

1 import matplotlib.pyplot as plt
2 import random
3 import numpy as np
4 import csv
5 nk1=300
6 nk2=300
7 nk3=10
8 kx=[]
9 ky=[]
10 kz=[]
11 for i in range(nk1):
12     for j in range(nk2):
13         for k in range(nk3):
14             xkg1=random.random()
15             xkg2=random.random()
16             xkg3 = float(k)/nk3
17             kx.append(xkg1)
18             ky.append(xkg2)
19             kz.append(xkg3)
20 kx=np.array(kx)
21 count, bins, ignored = plt.hist(kx, normed=True)
22 plt.plot(bins, np.ones_like(bins), linewidth=2, color='r')
23 plt.show()

该图显示“kx”和“ky”都是均匀分布的数字,但是,如何确保 x-y 在二维平面中均匀分布?

【问题讨论】:

  • 可以直接使用numpy的rand函数来代替循环:np.random.rand(nbr_points, nbre_dim)
  • 抱歉,我的回答经常更新。我在手机上,我不得不继续检查其他东西。现在完成了。
  • 能否请您从代码中删除行号?它们使复制和粘贴到编辑器或控制台变得非常困难。

标签: python numpy random


【解决方案1】:

就像您在 1D 中使用 np.histogram1 来检查均匀性一样,您可以在 2D 中使用 np.histogram2d 来做同样的事情,在 3D+ 中使用 np.histogramdd

为了看一个例子,让我们首先通过让它们消失来修复你的循环:

kx = np.random.random(nk1 * nk2 * nk3)
ky = np.random.random(nk1 * nk2 * nk3)
kz = np.tile(np.arange(nk3) / nk3, n1 * n2)

hist2d, *_ = np.histogram2d(kx, ky, range=[[0, 1], [0, 1]])

range 参数可确保您在每个方向上对 [0, 1) 进行分箱,而不是在数据的实际最小值和最大值之上,无论它可能有多接近。

现在,如何可视化hist2d 中的 100 个数据点完全取决于您。一种简单的方法是解开它并像一维案例一样制作条形图:

plt.bar(np.arange(hist2d.size), hist2d.ravel())
plt.plot([0, hist2d.size], [nk1 * nk2 * nk3 / hist2d.size] * 2)

另一种简单的方法是heat map

plt.imshow(hist2d, interpolation='nearest', cmap='hot')

这实际上不如条形图有用,也不能推广到更高的维度。

您最好的选择可能只是检查原始数据的标准差。


1 或者更确切地说,plt.hist 在幕后为你做了。

【讨论】:

  • @Sky。我可能会。这整件事是在没有在移动设备上测试的情况下编写的。我很想听听它是什么并修复它:)
  • 非常感谢!关于“histogram2d”的概念对我来说有点复杂。我认为你在 "hist2d, *_ = np.histogram2d(kx, ky, range=[[0, 1], [0, 1]])" 中有一些错字,因为这个函数应该返回 3 个值。 “plt.bar(hist2d.ravel())”中还有另一个错误,因为这个函数需要两个输入。我现在正在尝试消化您的建议。
  • @Sky。如果您使用的是 python 3,*_ 将吃掉并丢弃所有额外的输出。实际上,它只会将它们放入一个名为 _ 的两元素列表中。
  • @Sky。您完全正确 bar 需要 x 输入。我现在已经修好了
  • 我终于明白你的建议的逻辑了。但是我修改了你的脚本,以实现二维均匀分布的确认。
【解决方案2】:

在@Mad Physicist 的帮助下,我终于找到了验证二维随机数均匀分布的方法。在这里我发布我的脚本,并解释细节:

 1 import numpy as np
 2 import random
 3 import matplotlib.pyplot as plt
 4 import matplotlib
 5 fig = plt.figure()
 6 ax1 = fig.add_subplot(211)
 7 ax2 = fig.add_subplot(212)
 8 nk=100
 9 nk=100
10 nk=1
11 kx1=[]
12 ky1=[]
13 kz1=[]
14 for i in range(nk1):
15     for j in range(nk2):
16         for k in range(nk3):
17             xkg =r andom.random()
18             ykg = random.random()
19             zkg = float(k)/nk3
20             kx.append(xkg)
21             ky.append(ykg)
22             kz.append(zkg)
23 kx=np.array(kx)
24 ky=np.array(ky)
25 kz=np.array(kz)
26 xedges, yedges = np.linspace(0, 1, 6), np.linspace(0, 1, 6)
27 ## count the number of poins in the region definded by (xedges[i], 
    xedges[i+1])
28 ## and (yedges[i], xedges[y+1]). There are in total 10*10 2D 
    squares. 
29 hist, xedges, yedges = np.histogram2d(kx, ky, (xedges, yedges))
30 xidx = np.clip(np.digitize(kx, xedges) - 1, 0, hist.shape[0] - 1)
31 yidx = np.clip(np.digitize(ky, yedges) - 1, 0, hist.shape[1] - 1)
32 ax1.bar(np.arange(hist.size),hist.ravel())
33 ax1.plot([0,hist.size], [nk1 * nk2 * nk3 / hist.size] * 2)
34 c = hist[xidx, yidx]
35 new = ax2.scatter(kx, ky, c=c, cmap='jet') 
36 cax, _ = matplotlib.colorbar.make_axes(ax2)
37 cbar = matplotlib.colorbar.ColorbarBase(cax, cmap='jet')
38 ax2.grid(True)
39 plt.show()

【讨论】:

    猜你喜欢
    • 2011-04-04
    • 2016-08-07
    • 1970-01-01
    • 1970-01-01
    • 2011-09-16
    • 1970-01-01
    • 1970-01-01
    • 2011-08-07
    • 1970-01-01
    相关资源
    最近更新 更多