Python 如何在matplotlib中绘制按密度着色的散点图?
我想做一个散点图,其中每个点都由附近点的空间密度着色 我遇到了一个非常类似的问题,它显示了一个使用R的例子:Python 如何在matplotlib中绘制按密度着色的散点图?,python,matplotlib,Python,Matplotlib,我想做一个散点图,其中每个点都由附近点的空间密度着色 我遇到了一个非常类似的问题,它显示了一个使用R的例子: 使用matplotlib在python中实现类似功能的最佳方法是什么?您可以制作一个直方图: import numpy as np import matplotlib.pyplot as plt # fake data: a = np.random.normal(size=1000) b = a*3 + np.random.normal(size=1000) plt.hist2d(
使用matplotlib在python中实现类似功能的最佳方法是什么?您可以制作一个直方图:
import numpy as np
import matplotlib.pyplot as plt
# fake data:
a = np.random.normal(size=1000)
b = a*3 + np.random.normal(size=1000)
plt.hist2d(a, b, (50, 50), cmap=plt.cm.jet)
plt.colorbar()
除了@askewchan建议的
hist2d
或hexbin
之外,您还可以使用链接到的问题中的公认答案所使用的相同方法
如果您想这样做:
import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import gaussian_kde
# Generate fake data
x = np.random.normal(size=1000)
y = x * 3 + np.random.normal(size=1000)
# Calculate the point density
xy = np.vstack([x,y])
z = gaussian_kde(xy)(xy)
fig, ax = plt.subplots()
ax.scatter(x, y, c=z, s=100)
plt.show()
如果希望按密度顺序打印点,以便最密集的点始终位于顶部(类似于链接的示例),只需按z值对其排序即可。我还将在这里使用更小的标记大小,因为它看起来更好一些:
import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import gaussian_kde
# Generate fake data
x = np.random.normal(size=1000)
y = x * 3 + np.random.normal(size=1000)
# Calculate the point density
xy = np.vstack([x,y])
z = gaussian_kde(xy)(xy)
# Sort the points by density, so that the densest points are plotted last
idx = z.argsort()
x, y, z = x[idx], y[idx], z[idx]
fig, ax = plt.subplots()
ax.scatter(x, y, c=z, s=50)
plt.show()
此外,如果点数使KDE计算太慢,可以在np.historogram2d中插值颜色[根据注释更新:如果希望显示颜色栏,请使用plt.scatter()而不是ax.scatter(),后跟plt.colorbar()]: 绘图>100k数据点? 使用,将花费很多时间。在我的机器上,10万行花了大约11分钟。在这里,我将添加两个可选方法(和),并将给定的答案与相同的数据集进行比较 在下面,我使用了一个100k行的测试数据集:
导入matplotlib.pyplot作为plt
将numpy作为np导入
#用于测试的假数据
x=np.随机.正常(尺寸=100000)
y=x*3+np.随机.正常(尺寸=100000)
输出和计算时间比较
下面是不同方法的比较
1:mpl散射密度
安装pip install mpl-scatter-density
示例代码pip install mpl-scatter-density
import mpl_scatter_density#添加投影='scatter_density'
从matplotlib.colors导入LinearSegmentedColormap
#白色背景的“类绿色”彩色地图
white_viridis=LinearSegmentedColormap。从_列表(“white_viridis”)[
(0,#ffffff'),
(1e-20,“440053”),
(0.2, '#404388'),
(0.4,#2a788e'),
(0.6,#21a784'),
(0.8,#78d151'),
(1,“fde624”),
],N=256)
使用散射密度的def(图x、y):
ax=图添加子图(1,1,1,投影=“散射密度”)
密度=最大散射密度(x,y,cmap=白色绿色)
图颜色条(密度,标签='每像素点数')
图=plt.图()
使用散射密度(图,x,y)
plt.show()
绘制此图花费了0.05秒:
放大效果看起来相当不错:
2:datashader
- 这是一个有趣的项目。然而,截至2020年9月,该公司仍将继续运营。我从以下克隆安装了mpl分支:
从functools导入部分
将datashader作为ds导入
从datashader.mpl\u ext导入dsshow
作为pd进口熊猫
dyn=部分(ds.tf.dynspread,max_px=40,阈值=0.5)
使用_数据着色器(ax、x、y)定义:
df=pd.DataFrame(dict(x=x,y=y))
da1=dsshow(df,ds.点('x','y'),排列=dyn,纵横比=auto',ax=ax)
打印颜色条(da1)
图,ax=plt.子批次()
使用_数据着色器(ax、x、y)
plt.show()
- 绘制此图需要0.83秒:
3:使用高斯kde进行散射
def scatter_和_gaussian_kde(ax,x,y):
# https://stackoverflow.com/a/20107592/3015186
#乔尔·金顿的回答
xy=np.vstack([x,y])
z=高斯分布(xy)(xy)
最大散射(x,y,c=z,s=100,边缘颜色=“”)
- 画这个花了11分钟:
4:使用\u hist2d
导入matplotlib.pyplot作为plt
使用_hist2d(ax、x、y、bin=(50、50))定义:
# https://stackoverflow.com/a/20105673/3015186
#阿斯克尚的回答
ax.hist2d(x,y,bin,cmap=plt.cm.jet)
- 绘制此箱子需要0.021 s=(50,50):
- 绘制此箱子需要0.173秒=(10001000):
- 缺点:放大的数据看起来不像mpl散射密度或数据阴影中的数据那样好。此外,您还必须自己确定垃圾箱的数量
5:密度分布
- 代码如by中所示
- 使用bins=(50,50)绘制此图需要0.073 s:
- 使用bins=(10001000)绘制此图需要0.368 s:
gaussian_kde
)。为什么用(xy)调用两次gaussian内核?@ArjanGroen第一次调用创建一个新的gaussian_kde对象,第二次调用对点集上估计的pdf进行求值(调用求值方法的快捷方式)。在较新的matplotlib版本中,使用此代码段可能会导致错误ValueError:Expected 2D array,Get 1
。修复方法是将edgecolor='
更改为edgecolor=None
。这是一个很好的提示,谢谢。我正在绘制100k点,而gaussian_kde的速度非常慢。警告,我注意到在某些情况下his生成NaN,因为“bounds_error=False”是静默的。c设置为NaN的点不会绘制。这不是gaussian_kde的问题。非常感谢您的回答。U
pip install "git+https://github.com/nvictus/datashader.git@mpl"