具有 alpha 的散点图在斑点密集的区域仍然不透明
Scatter plot with alpha still opaque on areas where spots are dense
我有一个散点图,它绘制了来自两个不同数据集的大量点。在某些区域,有大量的点,因此即使具有非常低的 alpha(例如 alpha=0.1),您也无法看透这些点。但是在那个 alpha 下,你几乎看不到稀疏区域中的点。有没有办法限制堆叠点的 alpha,或者以某种方式使背景在密集区域下可见,同时不冲掉稀疏区域?
代码片段如下所示:
# Code to populate the datasets not included.
fig, ax = plt.subplots()
ax.scatter(x1, y1, s=12, color='red')
ax.scatter(x2, y2, s=12, color='blue', alpha=0.1)
# Plus code to do xlabels and such not included.
制作这个:
如你所见,很难看到底部红色腿的界限,仍然使顶部蓝色腿冲出。
有什么方法可以实现这种效果吗?
提前致谢。
编辑
一个好的建议似乎是使用 hexbin 而不是 scatter。这看起来很有希望,但颜色仍然不能很好地融合。例如,
ax.hexbin(x1, y1, cmap='Reds', mincnt=1, vmax=100)
ax.hexbin(x2, y2, cmap='Blues', mincnt=1, vmax=50, alpha=0.8, linewidths=0)
产量:
如果能把那些蓝调和红调融合起来,那就太好了。也许每个像素都可以有一个来自一个数据集的 R 值,和一个来自另一个数据集的 B 值之类的?但是在hexbin中好像没有这个选项。
编辑
应用 Thomasillo 的答案后:
谢谢,我觉得比原版好看。
1) 为了改进 hexbin 图,您可以使用选项 bins='log'。这会以对数方式计算六边形合并的颜色,有效地使较低的数字比较高的数字更好地突出。
2) 自己计算每个数据集的密度。并且从两种密度产生颜色,例如让一个密度影响红色,另一个影响蓝色通道。使用 imshow 绘制结果。
类似于
import matplotlib.pyplot as plt
import numpy as np
import itertools
x1 = np.random.binomial(5100,0.5,51100)
y1 = np.random.binomial(5000,0.7,51100)
x2 = np.random.binomial(5000,0.5,51100)
y2 = np.random.binomial(5000,0.7,51100)
xmin,xmax,xnum = 2350,2700,50
ymin,ymax,ynum = 3350,3700,50
xx,yy=np.mgrid[xmin:xmax:xnum*1j,ymin:ymax:ynum*1j]
def closest_idx(x,y):
idcs = np.argmin((xx-x)**2 + (yy-y)**2)
i_x,i_y = np.unravel_index(idcs, (xnum,ynum) )
return i_x,i_y
def calc_count( xdat,ydat ):
ct = np.zeros_like(xx)
for x,y in itertools.izip(xdat,ydat):
ix,iy = closest_idx(x,y)
ct [ix,iy] += 1
return ct
ct1 = calc_count( x1,y1 )
ct2 = calc_count( x2,y2 )
def color_mix( c1 , c2 ):
cm=np.empty_like(c1)
for i in [0,1,2]:
cm[i] = (c1[i]+c2[i])/2.
return cm
dens1 = ct1 / np.max(ct1)
dens2 = ct2 / np.max(ct2)
ct1_color = np.array([1+0*dens1 , 1-dens1 , 1-dens1 ])
ct2_color = np.array([1-dens2 , 1-dens2 , 1+0*dens2])
col = color_mix( ct1_color , ct2_color )
col = np.transpose( col, axes=(2,1,0))
plt.imshow( col , interpolation='nearest' ,extent=(xmin,xmax,ymin,ymax),origin='lower')
plt.show()
我有一个散点图,它绘制了来自两个不同数据集的大量点。在某些区域,有大量的点,因此即使具有非常低的 alpha(例如 alpha=0.1),您也无法看透这些点。但是在那个 alpha 下,你几乎看不到稀疏区域中的点。有没有办法限制堆叠点的 alpha,或者以某种方式使背景在密集区域下可见,同时不冲掉稀疏区域?
代码片段如下所示:
# Code to populate the datasets not included.
fig, ax = plt.subplots()
ax.scatter(x1, y1, s=12, color='red')
ax.scatter(x2, y2, s=12, color='blue', alpha=0.1)
# Plus code to do xlabels and such not included.
制作这个:
如你所见,很难看到底部红色腿的界限,仍然使顶部蓝色腿冲出。
有什么方法可以实现这种效果吗?
提前致谢。
编辑
一个好的建议似乎是使用 hexbin 而不是 scatter。这看起来很有希望,但颜色仍然不能很好地融合。例如,
ax.hexbin(x1, y1, cmap='Reds', mincnt=1, vmax=100)
ax.hexbin(x2, y2, cmap='Blues', mincnt=1, vmax=50, alpha=0.8, linewidths=0)
产量:
如果能把那些蓝调和红调融合起来,那就太好了。也许每个像素都可以有一个来自一个数据集的 R 值,和一个来自另一个数据集的 B 值之类的?但是在hexbin中好像没有这个选项。
编辑
应用 Thomasillo 的答案后:
谢谢,我觉得比原版好看。
1) 为了改进 hexbin 图,您可以使用选项 bins='log'。这会以对数方式计算六边形合并的颜色,有效地使较低的数字比较高的数字更好地突出。
2) 自己计算每个数据集的密度。并且从两种密度产生颜色,例如让一个密度影响红色,另一个影响蓝色通道。使用 imshow 绘制结果。
类似于
import matplotlib.pyplot as plt
import numpy as np
import itertools
x1 = np.random.binomial(5100,0.5,51100)
y1 = np.random.binomial(5000,0.7,51100)
x2 = np.random.binomial(5000,0.5,51100)
y2 = np.random.binomial(5000,0.7,51100)
xmin,xmax,xnum = 2350,2700,50
ymin,ymax,ynum = 3350,3700,50
xx,yy=np.mgrid[xmin:xmax:xnum*1j,ymin:ymax:ynum*1j]
def closest_idx(x,y):
idcs = np.argmin((xx-x)**2 + (yy-y)**2)
i_x,i_y = np.unravel_index(idcs, (xnum,ynum) )
return i_x,i_y
def calc_count( xdat,ydat ):
ct = np.zeros_like(xx)
for x,y in itertools.izip(xdat,ydat):
ix,iy = closest_idx(x,y)
ct [ix,iy] += 1
return ct
ct1 = calc_count( x1,y1 )
ct2 = calc_count( x2,y2 )
def color_mix( c1 , c2 ):
cm=np.empty_like(c1)
for i in [0,1,2]:
cm[i] = (c1[i]+c2[i])/2.
return cm
dens1 = ct1 / np.max(ct1)
dens2 = ct2 / np.max(ct2)
ct1_color = np.array([1+0*dens1 , 1-dens1 , 1-dens1 ])
ct2_color = np.array([1-dens2 , 1-dens2 , 1+0*dens2])
col = color_mix( ct1_color , ct2_color )
col = np.transpose( col, axes=(2,1,0))
plt.imshow( col , interpolation='nearest' ,extent=(xmin,xmax,ymin,ymax),origin='lower')
plt.show()