Python:如何创建2D装箱的“颜色图”的平滑版本?

问题描述

我想用平滑的颜色创建此二维装箱的“颜色图”的版本。

我什至不确定这将是该图的正确命名法,但从本质上讲,我希望通过第三个变量的中值对我的图形进行颜色编码,该变量位于我的每个定义的bin中( ,Y)空间。

即使我能够在一定程度上做到这一点(请参见示例),我仍想找到一种方法来创建具有平滑颜色渐变的相同图的版本。这样一来,我就可以形象地看到分发的整体行为。

我尝试了以下描述的想法:Smoothing 2D map in python

此处:Python: binned_statistic_2d mean calculation ignoring NaNs in data

以及其中的链接,但找不到解决该问题的明确方法

这是我到目前为止所拥有的:

import numpy as np
import matplotlib.pyplot as plt
from matplotlib import cm
from scipy.stats import binned_statistic_2d
import random
random.seed(999)

x = np.random.normal (0,10,5000)
y = np.random.normal (0,5000)
z = np.random.uniform(0,5000)

fig = plt.figure(figsize=(20,20))
plt.rcParams.update({'font.size': 10})

ax = fig.add_subplot(3,3,1)

ax.set_axisbelow(True)
plt.grid(b=True,lw=0.5,zorder=-1)

x_bins = np.arange(-50.,50.5,1.)
y_bins = np.arange(-50.,1.)

cmap = plt.cm.get_cmap('jet_r',1000) #just a colormap

ret = binned_statistic_2d(x,y,z,statistic=np.median,bins=[x_bins,y_bins]) # Bin (X,Y) and create a map of the medians of "Colors"

plt.imshow(ret.statistic.T,origin='bottom',extent=(-50,50,-50,50),cmap=cmap) 

plt.xlim(-40,40)
plt.ylim(-40,40)
plt.xlabel("X",fontsize=15)
plt.ylabel("Y",fontsize=15)
ax.set_yticks([-40,-30,-20,-10,20,30,40])

bounds = np.arange(2.0,20.0,1.0)
plt.colorbar(ticks=bounds,label="Color",fraction=0.046,pad=0.04)

# save plots
plt.savefig("Whatever_name.png",bBox_inches='tight')

随机数据中产生以下图像:

enter image description here

因此,简单的问题将是:如何使这些颜色平滑?

谢谢!

PS:对于过多的编码感到抱歉,但是我认为清晰的可视化对于这个特殊问题至关重要。

解决方法

感谢所有查看此问题并尝试提供帮助的人!

我最终能够解决自己的问题。最后,这全都涉及使用高斯核进行图像平滑。

此链接:Gaussian filtering a image with Nan in Python为我提供了解决方案的见识。

我基本上实现了完全相同的代码,但是最后,将先前已知的NaN像素从原始2D数组映射到生成的平滑版本。与链接中的解决方案不同,我的版本不会用来自周围像素的某些值填充NaN像素。或者,但是,然后我再次擦除了这些内容。

这是我提供的示例的最终数字:

enter image description here

最终代码,供将来可能需要的人参考:

import numpy as np
import matplotlib.pyplot as plt
from matplotlib import cm
from scipy.stats import binned_statistic_2d
import scipy.stats as st
import scipy.ndimage
import scipy as sp
import random
random.seed(999)

x = np.random.normal (0,10,5000)
y = np.random.normal (0,5000)
z = np.random.uniform(0,5000)

fig = plt.figure(figsize=(20,20))
plt.rcParams.update({'font.size': 10})

ax = fig.add_subplot(3,3,1)

ax.set_axisbelow(True)
plt.grid(b=True,lw=0.5,zorder=-1)

x_bins = np.arange(-50.,50.5,1.)
y_bins = np.arange(-50.,1.)

cmap = plt.cm.get_cmap('jet_r',1000) #just a colormap

ret = binned_statistic_2d(x,y,z,statistic=np.median,bins=[x_bins,y_bins]) # Bin (X,Y) and create a map of the medians of "Colors"

sigma=1                    # standard deviation for Gaussian kernel
truncate=5.0               # truncate filter at this many sigmas

U = ret.statistic.T.copy()

V=U.copy()
V[np.isnan(U)]=0
VV=sp.ndimage.gaussian_filter(V,sigma=sigma)

W=0*U.copy()+1
W[np.isnan(U)]=0
WW=sp.ndimage.gaussian_filter(W,sigma=sigma)

np.seterr(divide='ignore',invalid='ignore')

Z=VV/WW

for i in range(len(Z)):
    for j in range(len(Z[0])):
        if np.isnan(U[i][j]):
             Z[i][j] = np.nan

plt.imshow(Z,origin='bottom',extent=(-50,50,-50,50),cmap=cmap) 

plt.xlim(-40,40)
plt.ylim(-40,40)
plt.xlabel("X",fontsize=15)
plt.ylabel("Y",fontsize=15)
ax.set_yticks([-40,-30,-20,-10,20,30,40])

bounds = np.arange(2.0,20.0,1.0)
plt.colorbar(ticks=bounds,label="Color",fraction=0.046,pad=0.04)

# save plots
plt.savefig("Whatever_name.png",bbox_inches='tight')