Matplotlib辅助工具,用于制作密度散点图
项目描述
关于
绘制数百万个点可能很慢。非常慢…… :sleeping
那么为什么不使用密度图呢? :zap
mpl-scatter-density 小型包提供功能,使您轻松制作自己的散点密度图,无论是交互式还是非交互式使用。快速。以下动画展示了与1000万个点的实时交互使用,即使在有足够RAM的情况下,即使有1亿个点(甚至更多),交互性能仍然很好。
在平移时,为了保持响应性,密度图以较低分辨率显示(尽管这可以自定义)。
要安装,只需做
pip install mpl-scatter-density
此包需要Numpy、Matplotlib 和 fast-histogram - 如果缺少这些,pip将安装它们。支持Python 2.7和Python 3.x,并且该包应在Linux、MacOS X和Windows上正确运行。
用法
使用 mpl-scatter-density 有两种主要方式,下面都进行了说明。
scatter_density 方法
使用此包的最简单方法是将 mpl_scatter_density 导入,然后像往常一样创建Matplotlib轴,但添加一个 projection='scatter_density' 选项(如果你的反应是“等等,什么?”,请参阅 此处)。这将返回一个具有 scatter_density 方法的 ScatterDensityAxes 实例,它还具有所有常规方法(scatter、plot 等)。
import numpy as np
import mpl_scatter_density
import matplotlib.pyplot as plt
# Generate fake data
N = 10000000
x = np.random.normal(4, 2, N)
y = np.random.normal(3, 1, N)
# Make the plot - note that for the projection option to work, the
# mpl_scatter_density module has to be imported above.
fig = plt.figure()
ax = fig.add_subplot(1, 1, 1, projection='scatter_density')
ax.scatter_density(x, y)
ax.set_xlim(-5, 10)
ax.set_ylim(-5, 10)
fig.savefig('gaussian.png')
这将给出
散点密度方法与imshow方法具有相同的选项(例如cmap、alpha、norm等),但还包含以下可选参数:
dpi:这是一个整数,用于确定密度图的分辨率。默认值为72,但可以根据需要更改,或者将其设置为None以使用您所使用的Matplotlib后端的默认值。
downres_factor:这是一个整数,用于确定在交互模式中平移时如何下采样密度图。如果不想进行任何下采样,请将其设置为1。
color:可以将其设置为任何有效的matplotlib颜色,并将自动使用此颜色创建单色颜色映射。颜色映射将淡出为透明,这意味着当一起显示多个密度图时,此模式是理想的。
以下是使用color选项的示例
import numpy as np
import matplotlib.pyplot as plt
import mpl_scatter_density # noqa
fig = plt.figure()
ax = fig.add_subplot(1, 1, 1, projection='scatter_density')
n = 10000000
x = np.random.normal(0.5, 0.3, n)
y = np.random.normal(0.5, 0.3, n)
ax.scatter_density(x, y, color='red')
x = np.random.normal(1.0, 0.2, n)
y = np.random.normal(0.6, 0.2, n)
ax.scatter_density(x, y, color='blue')
ax.set_xlim(-0.5, 1.5)
ax.set_ylim(-0.5, 1.5)
fig.savefig('double.png')
这将产生以下输出
ScatterDensityArtist
如果您是经验丰富的Matplotlib用户,您可能希望直接使用ScatterDensityArtist(此示例在幕后使用)。要使用此方法,请使用轴作为第一个参数初始化ScatterDensityArtist,然后传递任何您在上述scatter_density中传递的参数(您还可以查看ScatterDensityArtist的文档字符串)。然后应将艺术家添加到轴上
from mpl_scatter_density import ScatterDensityArtist
a = ScatterDensityArtist(ax, x, y)
ax.add_artist(a)
高级
非线性拉伸用于高动态范围绘图
在某些情况下,您的密度图可能具有高动态范围,因此您可能想显示计数的对数而不是计数本身。您可以通过将matplotlib.colors.Normalize对象传递给norm参数(与imshow相同的方式)来实现此操作。例如,astropy包包含一个优秀的框架,用于为不同的函数创建此类Normalize对象。以下示例展示了如何在对数尺度上显示密度图
import numpy as np
import mpl_scatter_density
import matplotlib.pyplot as plt
# Make the norm object to define the image stretch
from astropy.visualization import LogStretch
from astropy.visualization.mpl_normalize import ImageNormalize
norm = ImageNormalize(vmin=0., vmax=1000, stretch=LogStretch())
N = 10000000
x = np.random.normal(4, 2, N)
y = np.random.normal(3, 1, N)
fig = plt.figure()
ax = fig.add_subplot(1, 1, 1, projection='scatter_density')
ax.scatter_density(x, y, norm=norm)
ax.set_xlim(-5, 10)
ax.set_ylim(-5, 10)
fig.savefig('gaussian_log.png')
这将产生以下输出
添加颜色条
您可以通过与图像相同的方式显示颜色条 - 以下示例展示了如何实现此操作
import numpy as np
import mpl_scatter_density
import matplotlib.pyplot as plt
N = 10000000
x = np.random.normal(4, 2, N)
y = np.random.normal(3, 1, N)
fig = plt.figure()
ax = fig.add_subplot(1, 1, 1, projection='scatter_density')
density = ax.scatter_density(x, y)
ax.set_xlim(-5, 10)
ax.set_ylim(-5, 10)
fig.colorbar(density, label='Number of points per pixel')
fig.savefig('gaussian_colorbar.png')
这将产生以下输出
使用单个值对“标记”进行着色
与可以将值的一维数组传递给Matplotlib的scatter函数/方法一样,可以使用c=参数将值的一维数组传递给scatter_density
import numpy as np
import mpl_scatter_density
import matplotlib.pyplot as plt
N = 10000000
x = np.random.normal(4, 2, N)
y = np.random.normal(3, 1, N)
c = x - y + np.random.normal(0, 5, N)
fig = plt.figure()
ax = fig.add_subplot(1, 1, 1, projection='scatter_density')
ax.scatter_density(x, y, c=c, vmin=-10, vmax=+10, cmap=plt.cm.RdYlBu)
ax.set_xlim(-5, 13)
ax.set_ylim(-5, 11)
fig.savefig('gaussian_color_coded.png')
这将产生以下输出
请注意,为了尽可能保持良好的性能,密度图每个像素中的c属性值将被平均,然后应用颜色映射。这与scatter在许多点的情况下会收敛到的情况略有不同(因为在那种情况下,它会对所有标记应用颜色而不是平均颜色)。
Q&A
这基本上与datashader相同吗?
这遵循了datashader的相同理念,但mpl-scatter-density的目标是专门为Matplotlib用户带来类似datashader的功能。此外,mpl-scatter-density旨在非常容易安装——例如,可以使用pip安装。但是,如果您已经安装了datashader并经常使用bokeh,mpl-scatter-density对您的作用不大。请注意,如果您对datashader和Matplotlib都感兴趣,@tacaswell有一个正在进行的工作(pull request),旨在创建一个类似于此包中的matplotlib artist,但由datashader提供动力。
关于vaex呢?
Vaex是一个强大的包,用于在N维网格上可视化大型数据集,因此它有一些与这里的功能重叠。然而,mpl-scatter-density的目标只是提供一个轻量级的解决方案,使用户能够轻松地将散点密度图添加到他们的图表中,而不是提供一个完整的数据可视化环境。我强烈建议您查看Vaex并确定哪种方法适合您!
为什么要把scatter_density定义为投影?
如果您是Matplotlib的开发者:我为扭曲了projection的预期目的而深感抱歉:blush:.但您必须承认,即使它与实际的投影没有关系,这也是让用户获得自定义Axes子类的一种非常方便的方式!
您认为它会走向何方?
我们可以向这个包添加很多东西,例如,以等高线的形式绘制密度图,或者通过第三种量来为每个点着色,并在密度图中反映出来。如果您有想法,请提出问题,甚至更好的是贡献一个pull request!:smile
我可以贡献吗?
我很高兴您这样问——当然,您非常欢迎贡献!如果您有一些想法,您可以提出问题或直接创建pull request。即使您没有时间贡献实际的代码更改,如果您在使用此包时遇到问题,我也愿意听到您的声音。
[
运行测试
要运行测试,您需要pytest和pytest-mpl插件。然后您可以使用以下命令运行测试:
pytest mpl_scatter_density --mpl