python matplotlib中重叠点散点图的可视化

oymdgrw7  于 2023-11-15  发布在  Python
关注(0)|答案(4)|浏览(227)

我必须在matplotlib的散点图中表示大约30,000个点。这些点属于两个不同的类,所以我想用不同的颜色来描绘它们。
我成功地做到了这一点,但有一个问题。点在许多区域重叠,我最后描绘的类将被可视化在另一个之上,隐藏它。此外,散点图不可能显示每个区域中有多少点。我还尝试使用histogram2d和imshow制作2d直方图,但是很难清楚地显示属于两个类的点。
你能不能建议一种方法来明确班级的分布和分数的集中?
编辑:为了更清楚,这是link到我的数据文件的格式为“x,y,class”

j0pj023g

j0pj023g1#

一种方法是将数据绘制为具有低alpha**的散点图,这样您就可以看到单个点以及粗略的密度测量。(这种方法的缺点是它可以显示的重叠范围有限-即最大密度约为1/alpha。)
下面是一个例子:
x1c 0d1x的数据
正如你所想象的,由于可以表达的重叠范围有限,在各个点的可见性和重叠量的表达(以及标记、绘图等的大小)之间存在权衡。

import numpy as np
import matplotlib.pyplot as plt

N = 10000
mean = [0, 0]
cov = [[2, 2], [0, 2]]
x,y = np.random.multivariate_normal(mean, cov, N).T

plt.scatter(x, y, s=70, alpha=0.03)
plt.ylim((-5, 5))
plt.xlim((-5, 5))
plt.show()

字符串
(我假设你在这里指的是30 e3点,而不是30 e6。对于30 e6,我认为需要某种类型的平均密度图。)

axkjgtzd

axkjgtzd2#

您也可以通过首先计算散点分布的核密度估计值,然后使用密度值为散点的每个点指定颜色来为点着色。要修改前面示例中的代码,请执行以下操作:

import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import gaussian_kde as kde
from matplotlib.colors import Normalize
from matplotlib import cm

N = 10000
mean = [0,0]
cov = [[2,2],[0,2]]

samples = np.random.multivariate_normal(mean,cov,N).T
densObj = kde( samples )

def makeColours( vals ):
    colours = np.zeros( (len(vals),3) )
    norm = Normalize( vmin=vals.min(), vmax=vals.max() )

    #Can put any colormap you like here.
    colours = [cm.ScalarMappable( norm=norm, cmap='jet').to_rgba( val ) for val in vals]

    return colours

 colours = makeColours( densObj.evaluate( samples ) )

 plt.scatter( samples[0], samples[1], color=colours )
 plt.show()

字符串
x1c 0d1x的数据
不久前,当我注意到分散函数的文档时,我学到了这个技巧--

c : color or sequence of color, optional, default : 'b'


c可以是单个颜色格式字符串,或者长度为N的颜色规范序列,或N数字序列,使用kwargs指定的cmapnormMap到颜色(见下文)注意,c不应该是单个数字RGB或RGBA序列,因为这与要进行颜色Map的值数组无法区分。c可以是一个二维数组,其中的行是RGB或RGBA,但是,包括单行的情况,为所有点指定相同的颜色。

lfapxunr

lfapxunr3#

我的答案可能不能完美地回答你的问题,但是,我也试图绘制重叠点,但我的重叠是完美的。因此,我想出了这个函数,以抵消相同的点。

import numpy as np

def dodge_points(points, component_index, offset):
    """Dodge every point by a multiplicative offset (multiplier is based on frequency of appearance)

    Args:
        points (array-like (2D)): Array containing the points
        component_index (int): Index / column on which the offset will be applied 
        offset (float): Offset amount. Effective offset for each point is `index of appearance` * offset

    Returns:
        array-like (2D): Dodged points
    """

    # Extract uniques points so we can map an offset for each
    uniques, inv, counts = np.unique(
        points, return_inverse=True, return_counts=True, axis=0
    )

    for i, num_identical in enumerate(counts):
        # Prepare dodge values
        dodge_values = np.array([offset * i for i in range(num_identical)])
        # Find where the dodge values must be applied, in order
        points_loc = np.where(inv == i)[0]
        #Apply the dodge values
        points[points_loc, component_index] += dodge_values

    return points

字符串
这是一个之前和之后的例子。
之前:


的数据
之后:



此方法仅适用于完全重叠的点(或者如果您愿意以np.unique查找匹配点的方式将点舍入)。

xwbd5t1u

xwbd5t1u4#

使用透明度/alpha,如this answer中所建议的,对于拥挤是一个问题的情况非常有帮助。但是,如果您有多个数据类,您仍然可能会遇到后面绘制的类掩盖前面的类的问题,特别是当某些类比其他类具有更多的数据点时。
This answer使用热图来显示密度,当你想显示单个类的密度时,这是很好的,但不直接适应有多个重叠类并希望所有类都可见的情况。
在这种情况下,我发现一种很有用的方法是随机绘制顺序,而不是按顺序绘制类。
例如,修改tom 10的回答中给出的例子:

import numpy as np
import matplotlib.pyplot as plt

N0 = 2000
x0 = np.random.normal(0,2,N0)
y0 = np.random.normal(0,0.2,N0) + 0.25/(x0**2+0.25)

plt.scatter(x0, y0, s=70, alpha=0.03,c="r")

N1 = 10000
mean = [0, 0]
cov = [[2, 2], [0, 2]]
x1,y1 = np.random.multivariate_normal(mean, cov, N1).T

plt.scatter(x1, y1, s=70, alpha=0.03,c="b")
plt.ylim((-5, 5))
plt.xlim((-5, 5))
plt.show()

字符串
结果是:
x1c 0d1x的数据
看一下这张图,红色的点似乎分布在y = 0线附近。
但是如果我们随机化情节顺序:

x = np.concatenate((x0,x1))
y = np.concatenate((y0,y1))
cols = np.concatenate((np.tile("r",len(x0)),np.tile("b",len(x1))))

rng = np.random.default_rng()
neworder=rng.permutation(len(x))

x_shuffled = x[neworder]
y_shuffled = y[neworder]
cols_shuffled = cols[neworder]

plt.ylim((-5, 5))
plt.xlim((-5, 5))
plt.show()


我们得到这个:



现在更容易看到,在x = 0附近,红点明显偏离了y=0的关系,当我们只能看到该分布的边缘时,我们已经猜测到了。
我们可以通过将点分箱(例如在十六进制或正方形网格上),然后根据每个bin的类分布和数据点的数量为每个bin设置颜色和alpha来实现类似的结果。但我喜欢随机顺序方法,因为它技术含量较低,减少了我需要记住的方法数量。

相关问题