问题描述
我想用平滑的颜色创建此二维装箱的“颜色图”的版本。
我什至不确定这将是该图的正确命名法,但从本质上讲,我希望通过第三个变量的中值对我的图形进行颜色编码,该变量位于我的每个定义的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')
从随机数据中产生以下图像:
因此,简单的问题将是:如何使这些颜色平滑?
谢谢!
PS:对于过多的编码感到抱歉,但是我认为清晰的可视化对于这个特殊问题至关重要。
解决方法
感谢所有查看此问题并尝试提供帮助的人!
我最终能够解决自己的问题。最后,这全都涉及使用高斯核进行图像平滑。
此链接:Gaussian filtering a image with Nan in Python为我提供了解决方案的见识。
我基本上实现了完全相同的代码,但是最后,将先前已知的NaN像素从原始2D数组映射到生成的平滑版本。与链接中的解决方案不同,我的版本不会用来自周围像素的某些值填充NaN像素。或者,但是,然后我再次擦除了这些内容。
这是我提供的示例的最终数字:
最终代码,供将来可能需要的人参考:
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')