RAs*_*RAs 7 python artifacts matplotlib rounding discretization
在Python中,假设我有连续变量x
和y
,其值在0和1之间是有界的(更容易).我的假设一直是,如果我想将这些变量转换为序数值,其中二进制数为0,0.01,0.02,...,0.98,0.99,1,可以简单地将原始值舍入到第二个数字.出于某种原因,当我这样做时,它留下了文物.
让我来说明问题(但是请注意,我的问题不是如何获得正确的情节,而是实际上如何进行正确的分组).首先,这些是重现问题所需的唯一模块:
import numpy as np
import matplotlib.pyplot as plt
Run Code Online (Sandbox Code Playgroud)
现在,假设我们连续生成如下所示的数据(其他数据生成过程也会产生同样的问题):
# number of points drawn from Gaussian dists.:
n = 100000
x = np.random.normal(0, 2, n)
y = np.random.normal(4, 5, n)
# normalizing x and y to bound them between 0 and 1
# (it's way easier to illustrate the problem this way)
x = (x - min(x))/(max(x) - min(x))
y = (y - min(y))/(max(y) - min(y))
Run Code Online (Sandbox Code Playgroud)
然后,让我们仅仅通过应用一些舍入来转换x
并y
在上述间隔中进行序数.然后,我们将结果存入一个x
由y
以绘制它的热图矩阵用于说明目的:
# matrix that will represent the bins. Notice that the
# desired bins are every 0.01, from 0 to 1, so 100 bins:
mtx = np.zeros([100,100])
for i in range(n):
# my idea was that I could roughly get the bins by
# simply rounding to the 2nd decimal point:
posX = round(x[i], 2)
posY = round(y[i], 2)
mtx[int(posX*100)-1, int(posY*100)-1] += 1
Run Code Online (Sandbox Code Playgroud)
我希望上面的工作能够实现,但是当我绘制矩阵的内容时mtx
,我实际上得到了奇怪的工件.代码:
# notice, however, the weird close-to-empty lines at
# 0.30 and 0.59 of both x and y. This happens regardless
# of how I generate x and y. Regardless of distributions
# or of number of points (even if it obviously becomes
# impossible to see if there are too few points):
plt.matshow(mtx, cmap=plt.cm.jet)
plt.show(block=False)
Run Code Online (Sandbox Code Playgroud)
给我:
最奇怪的是,无论我使用哪种分布来生成x
和使用y
哪种种子用于RNG,我总是得到相同的水平和垂直近空行,分别为0.30和0.59两种,x
并且y
通常情况下,这些线直接平行那些显示积分浓度的人(就像你在图中看到的那样).
当我将值从该矩阵打印到控制台时,我实际上可以确认对应于那些近空行的那些确实是零或非常接近于零 - 与它们的邻居点不同.
我的问题可以更恰当地分为两部分:
为什么上述情况会发生?我真的很想知道在这个简单的代码中究竟出现了什么问题.
什么是更好的方法来生成x
按y
矩阵,根据切割点0,0.01,0.02,...,0.98,0.99,1分离值而不留下上面的工件?
如果想要轻松地直接将上面使用的整个示例代码集中在一个片段中,可以使用以下链接:https: //www.codepile.net/pile/VLAq4kLp
注意:我不想找到正确的绘图方式.我想找到自己生成" binned values matrix"的正确方法,表示的是上图.我知道还有其他方法可以在没有工件的情况下完成热图绘制,例如使用plt.matshow(mtx, cmap=plt.cm.jet); plt.show(block=False)
或plt.hist2d(x, y, bins=100)
.我要问的是我的矩阵生成本身的问题在哪里,它创造了那些接近零的元素.
使用 可以轻松解决该问题np.histogram2d(x,y, bins=100)
。
这个答案的其余部分是为了显示手动算法失败的地方:
从数字上考虑
0.56*100 == 56.00000000000001 -> int(0.56*100) == 56
0.57*100 == 56.99999999999999 -> int(0.57*100) == 56
0.58*100 == 57.99999999999999 -> int(0.58*100) == 57
0.59*100 == 59.00000000000000 -> int(0.59*100) == 59
Run Code Online (Sandbox Code Playgroud)
这样数字 58 就不会出现在索引中,而数字 56 出现的频率会是其两倍(为了均匀分布)。
您可以先相乘,然后截断为整数。另请注意,最后一个 bin 需要关闭,以便将值 1 添加到索引 99 的 bin 中。
mtx = np.zeros([100,100])
for i in range(n):
posX = int(x[i]*100)
posY = int(y[i]*100)
if posX == 100:
posX = 99
if posY == 100:
posY = 99
mtx[posX, posY] += 1
Run Code Online (Sandbox Code Playgroud)
这将通过边缘定义 bin,即第一个 bin 的范围从 0 到 1 等。在调用 imshow/matshow 时,您需要通过设置范围来考虑这一点。
plt.matshow(mtx, cmap=plt.cm.jet, extent=(0,100,0,100))
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
261 次 |
最近记录: |