代码之家  ›  专栏  ›  技术社区  ›  FriskyGrub

散点图中密度最大区域的等高线图

  •  6
  • FriskyGrub  · 技术社区  · 11 年前

    我正在生成一个约300k个数据点的散点图,但遇到的问题是,有些地方过于拥挤,以至于看不到任何结构——所以我想了想!

    我想让绘图为最密集的部分生成等高线图,并将密度较低的区域保留为 scatter() 数据点。

    所以我试图单独计算每个数据点的最近邻距离,然后当这个距离达到特定值时,画一个轮廓并填充它,然后当它达到更大的值(密度较小)时,只进行散射。。。

    几天来,我一直在尝试,但都失败了,我不确定传统的等高线图在这种情况下是否有效。

    我会提供代码,但它太混乱了,可能会混淆问题。而且它的计算量太大了,如果它真的工作的话,我的电脑可能会崩溃!

    提前感谢大家!

    附言:我一直在寻找答案!我确信这甚至不可能得到所有的结果!

    编辑:所以这样做的目的是看看300k样本结构中的一些特定点在哪里。这是一个示例图,我的点分散在三种不同的颜色中。 My scatter version of the data

    我将尝试从我的数据中随机抽取1000个数据点,并将其作为文本文件上传。 干杯堆叠器。:)

    编辑:嘿, 以下是一些1000行的示例数据,只有两列 [X,Y] (或 [g-i,i] 来自上面的绘图)以空格分隔。谢谢大家! the data

    3 回复  |  直到 11 年前
        1
  •  3
  •   FriskyGrub    7 年前

    4年后,我终于可以回答这个问题了! 这可以使用 contains_points 从…起 matplotlib.path .

    我使用了来自 astropy 其可以根据需要省略或替换。

    import matplotlib.colors as colors
    from matplotlib import path
    import numpy as np
    from matplotlib import pyplot as plt
    try:
        from astropy.convolution import Gaussian2DKernel, convolve
        astro_smooth = True
    except ImportError as IE:
        astro_smooth = False
    
    np.random.seed(123)
    t = np.linspace(-1,1.2,2000)
    x = (t**2)+(0.3*np.random.randn(2000))
    y = (t**5)+(0.5*np.random.randn(2000))
    
    H, xedges, yedges = np.histogram2d(x,y, bins=(50,40))
    xmesh, ymesh = np.meshgrid(xedges[:-1], yedges[:-1])
    
    # Smooth the contours (if astropy is installed)
    if astro_smooth:
        kernel = Gaussian2DKernel(stddev=1.)
        H=convolve(H,kernel)
    
    fig,ax = plt.subplots(1, figsize=(7,6)) 
    clevels = ax.contour(xmesh,ymesh,H.T,lw=.9,cmap='winter')#,zorder=90)
    
    # Identify points within contours
    p = clevels.collections[0].get_paths()
    inside = np.full_like(x,False,dtype=bool)
    for level in p:
        inside |= level.contains_points(zip(*(x,y)))
    
    ax.plot(x[~inside],y[~inside],'kx')
    plt.show(block=False)
    

    enter image description here

        2
  •  1
  •   Hooked    11 年前

    您可以使用各种numpy/scpy/matplotlib工具来实现这一点:

    1. 创建 scipy.spatial.KDTree 用于快速查找的原始点的。
    2. 使用 np.meshgrid 以所需轮廓的分辨率创建点网格
    3. 使用 KDTree.query 创建目标密度内所有位置的遮罩
    4. 使用矩形仓或 plt.hexbin .
    5. 根据装仓数据绘制轮廓,但使用步骤3中的遮罩。以过滤掉较低密度区域。
    6. 使用遮罩的反转来 plt.scatter 剩下的几点。
        3
  •  1
  •   scichris    5 年前

    也许有人(像我一样)会在互联网上偶然找到答案@FriskyGrub,我喜欢你的平滑方法。AstroML库中有一个解决方案,例如 https://www.astroml.org/book_figures/chapter1/fig_S82_scatter_contour.html#book-fig-chapter1-fig-s82-scatter-contour 。我不确定您是如何在代码中设置阈值的(超过该阈值时,将点包括在轮廓中,而不是分散),但我设法用以下方法复制了与您的结果类似的结果:

    import matplotlib.pyplot as plt
    from astroML.plotting import scatter_contour
    np.random.seed(123)
    t = np.linspace(-1,1.2,2000)
    x = (t**2)+(0.3*np.random.randn(2000))
    y = (t**5)+(0.5*np.random.randn(2000))
    fig,ax = plt.subplots(1,1,figsize=(6,6))
    scatter_contour(x,y, threshold=15, log_counts=True, ax=ax,
                histogram2d_args=dict(bins=15),
                plot_args=dict(marker='+', linestyle='none', color='black',
                              markersize=5),
                contour_args=dict(cmap='winter',),
               filled_contour=False)
    

    enter image description here

    ( scatter_contour?? 带来了很多医生的帮助,但基本上就像夸尔格所建议的那样, histogram2d_args 这些隐语是由 numpy.histogram2d plot_args args是通过散点获取的吗 plt.plot contour_args 那些由 plt.contour (或 plt.contourf )

    最美好的祝福

    克里斯