matplotlib 在一个图子图中合并由不同散点图组成的多个路径集合

mccptt67  于 2023-05-18  发布在  其他
关注(0)|答案(2)|浏览(140)

我正试图删除基于this example的散点图创建的一些点。当我在一个子图中有多个散点图并因此有多个PathCollections时,问题就会出现。我正在尝试创建一个包含所有散点图中的点的PathCollection。我如何才能做到这一点?
下面是一个最小代码:

import numpy as np

from matplotlib.collections import PathCollection
from matplotlib.lines import Line2D
from matplotlib.path import Path
from matplotlib.widgets import LassoSelector

class RemoveButton:

    def __init__(self, ax, collection, alpha_other=0.3):
        self.canvas = ax.figure.canvas
        self.collection = collection
        self.alpha_other = alpha_other

        self.xys = collection.get_offsets()
        self.Npts = len(self.xys)

        # Ensure that we have separate colors for each object
        self.fc = collection.get_facecolors()
        if len(self.fc) == 0:
            raise ValueError('Collection must have a facecolor')
        elif len(self.fc) == 1:
            self.fc = np.tile(self.fc, (self.Npts, 1))

        self.lasso = LassoSelector(ax, onselect=self.onselect)
        self.ind = []

    def onselect(self, verts):
        path = Path(verts)
        self.ind = np.nonzero(path.contains_points(self.xys))[0]
        self.fc[:, -1] = self.alpha_other
        self.fc[self.ind, -1] = 1
        self.collection.set_facecolors(self.fc)
        self.canvas.draw_idle()

    def disconnect(self):
        self.lasso.disconnect_events()
        self.fc[:, -1] = 1
        self.collection.set_facecolors(self.fc)
        self.canvas.draw_idle()

if __name__ == '__main__':
    import matplotlib.pyplot as plt

    data = np.random.rand(100, 2)
    data2 = np.random.rand(100, 2)

    subplot_kw = dict(xlim=(0, 1), ylim=(0, 1), autoscale_on=False)
    fig, ax = plt.subplots(subplot_kw=subplot_kw)

    pc1 = ax.scatter(data[:, 0], data[:, 1], s=80)
    pc2 = ax.scatter(data2[:, 0], data2[:, 1], s=80)

    pts = pc1

    selector = RemoveButton(ax=ax, collection=pts)

    def accept(event):
        if event.key == "enter":
            for p in selector.xys[selector.ind]:
                offsets: np.ma.MaskedArray = pts.get_offsets()
                if p in offsets:
                    offsets_list = offsets.tolist()
                    offsets_list.remove(p.tolist())
                    pts.set_offsets(np.ma.MaskedArray(offsets_list))

            fig.canvas.draw()

            selector.disconnect()
            ax.set_title("")

    fig.canvas.mpl_connect("key_press_event", accept)
    ax.set_title("Press enter to accept selected points.")

    plt.show()

如您所见,我只向RemoveButton类传递了一个PathCollection,并且它可以工作。但是我需要能够从任何我想要的散点图中删除点。

dgsult0t

dgsult0t1#

实际上,我可以将第二个数据附加/扩展到第一个数据,然后运行scatter()一次。这样你就只有一个路径集合了...

q43xntqr

q43xntqr2#

这种技术可以用于组合不同轴上散点图的PathCollections,即使在提问者的情况下,也可以避免生成多个集合。作为一个完整的演示,这里是如何在matplotlib 3.7.1中创建基于多个子图散点的图例。

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.collections import PathCollection

data1 = np.random.rand(100, 3)
data2 = np.random.rand(100, 3)

# Create scatter plots on separate axes
fig, axs = plt.subplots(1, 2)
s1 = axs[0].scatter(data1[:, 0], data1[:, 1], s=data1[:, 2]*100, alpha=0.6)
s2 = axs[1].scatter(data2[:, 0], data2[:, 1], s=data2[:, 2]*100, alpha=0.6)

# Combine the PathCollections into a single one
# get_paths() returns a list, get_sizes() returns an array. They must be
# concatenated differently
s = PathCollection(s1.get_paths() + s2.get_paths(),
                   np.concatenate((s1.get_sizes(), s2.get_sizes())),
                  )

# Now assemble a legend from the new PathCollection based on sizes.
# Note that I'm copying the color from the first collection
handles, labels = s.legend_elements(prop="sizes", color=s1.get_facecolor())

# Build the legend on the figure
fig.legend(handles, labels, loc='upper right')

相关问题