首页 > 其他分享 >使用 Matplotlib 进行交互式散点图突出显示和删除

使用 Matplotlib 进行交互式散点图突出显示和删除

时间:2024-09-12 15:24:05浏览次数:3  
标签:canvas self mask 散点图 Matplotlib xy 交互式 ax def

使用 Matplotlib 进行交互式散点图突出显示和删除_散点图

Matplotlib和散点图

Matplotlib是一个用于绘制数据可视化图形的Python库。学习Matplotlib是探索数据可视化领域的重要一步。

散点图是指在回归分析中,数据点在直角坐标系平面上的分布图,散点图表示因变量随 自变量而变化的大致趋势,据此可以选择合适的函数对数据点进行拟合。

交互式散点图,指用户可以通过多种方式与之交互。这包括能够批量选择和突出显示组中的单个散点,以及对高亮显示的点执行操作(例如删除、复制、移动)等功能。

Highlighter Class

首先,在单独的文件中创建 Highlighter 类。将逐一讨论每种方法的创建。

import pandas as pd
import numpy as np
from matplotlib.widgets import RectangleSelector
import keyboard

class Highlighter(object):
    def __init__(self, canvas, ax, x, y):
        self.canvas = canvas
        self.ax = ax
        self.x, self.y = x, y
        self.mask = np.zeros(x.shape, dtype=bool)

        self._highlight = self.ax.scatter([], [], s=50, color='yellow', zorder=10)
        self.selector = RectangleSelector(self.ax, self.select, useblit=True, state_modifier_keys={"center": "alt"})

Highlighter 类的核心部分是 Rectangle Selector,它是一个 matplotlib 功能,用于创建拖动工具。这仅在为拖动工具创建 UI 时有用,但是,实际的选择、突出显示和其他功能将来自我们。

使用 Matplotlib 进行交互式散点图突出显示和删除_应用程序GUI界面_02

此函数的另一个重要部分是self.mask属性,它将是一个 0 和 1 值的列表,其长度与散点图中的点数相同。这将跟踪我们的积分当前是否被选中。此列表的 index-2 处的值为 1 表示我们图中的第三个散点当前突出显示。可以同时选择多个点。

def update(self, x, y):
        self.x, self.y = x, y
        self.mask = np.zeros(x.shape, dtype=bool)

接下来是update函数,每当我们想用新值更新散点图(或删除一些值)时,都会调用该函数。我们更新 highlighter 类中的 x 和 y 值,并将蒙版的大小调整为散点图中的新点数。请注意,这不会影响实际的散点图,其代码将位于主应用程序中的其他位置。

def select(self, event1, event2):
        prevOffsets = []
        prevMask = None

        if keyboard.is_pressed('ctrl'):
            prevOffsets = self._highlight.get_offsets()
            prevMask = self.mask

        self.clear_highlights()
        self.mask |= self.inside(event1, event2)
        xy = np.column_stack([self.x[self.mask], self.y[self.mask]])

        if len(prevOffsets) > 0:
            xy = np.concatenate((xy, prevOffsets))
            self.mask |= prevMask

        if len(xy):
            self._highlight.set_offsets(xy)
            self.canvas.draw_idle()

最重要的功能是select方法,每次使用矩形选择器创建的拖动工具时,矩形选择器都会调用该方法。之所以调用它,是因为我们将Highlighter类的select函数作为第二个参数传递给了矩形选择器的构造函数。

此函数执行以下操作:

1.跟踪以前突出显示的值,以便在按下CTRL键时可以进行多阶段拖动选择。

2.调用inside方法,该方法返回一个布尔值列表,表示哪些点在所选区域内,哪些点不在。掩码属性被分配了这些值。inside方法使用两个事件计算此列表,第一个事件是拖动的开始位置(按住鼠标的位置)和结束位置(释放鼠标的地方)。

def inside(self, event1, event2):
        """Returns a boolean mask of the points inside the rectangle defined by
        event1 and event2."""
        x0, x1 = sorted([event1.xdata, event2.xdata])
        y0, y1 = sorted([event1.ydata, event2.ydata])
        mask = ((self.x > x0) & (self.x < x1) &
                (self.y > y0) & (self.y < y1))
        return mask

3.使用掩码过滤x和y值,并将其存储在xy变量中,该变量将成为需要突出显示的点的坐标。最后,调用set_offsets方法,该方法将处理实际的突出显示。

def set_offsets(self, xy):
        self._highlight.remove()
        self._highlight = self.ax.scatter([], [], s=50, color='yellow', zorder=10)

        if len(xy):
            self._highlight.set_offsets(xy)
        self.canvas.draw_idle()

这是通过在要选择的点的位置上绘制黄色散点来实现的。或者,您可以修改代码,单独更新选定的散点,并将其颜色更改为黄色。

def clear_highlights(self):
        self._highlight.remove()
        self._highlight = self.ax.scatter([], [], s=50, color='yellow', zorder=10)
        self.mask = np.zeros(self.x.shape, dtype=bool)
        self.canvas.draw_idle()

此类中还使用了clear_highlights方法来清除现有的高光。

highlights类-完整代码

import pandas as pd
import numpy as np
from matplotlib.widgets import RectangleSelector
import keyboard

class Highlighter(object):
    def __init__(self, canvas, ax, x, y, ):
        self.canvas = canvas
        self.ax = ax
        self.x, self.y = x, y
        self.mask = np.zeros(x.shape, dtype=bool)

        self._highlight = self.ax.scatter([], [], s=50, color='yellow', zorder=10)
        self.selector = RectangleSelector(self.ax, self.select, useblit=True, state_modifier_keys={"center": "alt"})

    def update(self, x, y):
        self.x, self.y = x, y
        self.mask = np.zeros(x.shape, dtype=bool)

    def select(self, event1, event2):
        prevOffsets = []
        prevMask = None

        if keyboard.is_pressed('ctrl'):
            prevOffsets = self._highlight.get_offsets()
            prevMask = self.mask

        self.clear_highlights()
        self.mask |= self.inside(event1, event2)
        xy = np.column_stack([self.x[self.mask], self.y[self.mask]])

        if len(prevOffsets) > 0:
            xy = np.concatenate((xy, prevOffsets))
            self.mask |= prevMask

        if len(xy):
            self._highlight.set_offsets(xy)
            self.canvas.draw_idle()
    
    def clear_highlights(self):
        self._highlight.remove()
        self._highlight = self.ax.scatter([], [], s=50, color='yellow', zorder=10)
        self.mask = np.zeros(self.x.shape, dtype=bool)
        self.canvas.draw_idle()

    def set_offsets(self, xy):
        self._highlight.remove()
        self._highlight = self.ax.scatter([], [], s=50, color='yellow', zorder=10)

        if len(xy):
            self._highlight.set_offsets(xy)
        self.canvas.draw_idle()

    def check_inside(self, point1, point2):
        """Returns a boolean mask of the points inside the rectangle defined by
        event1 and event2."""
        x0, x1 = sorted([point1[0], point2[0]])
        y0, y1 = sorted([point1[1], point2[1]])
        mask = ((self.x > x0) & (self.x < x1) &
                (self.y > y0) & (self.y < y1))
        return mask

    def inside(self, event1, event2):
        """Returns a boolean mask of the points inside the rectangle defined by
        event1 and event2."""
        x0, x1 = sorted([event1.xdata, event2.xdata])
        y0, y1 = sorted([event1.ydata, event2.ydata])
        mask = ((self.x > x0) & (self.x < x1) &
                (self.y > y0) & (self.y < y1))
        return mask

GUI 应用程序

这是我们的驱动程序应用程序的代码。我们使用 Tkinter GUI 开发了一个应用程序来包装我们的 Matplotlib 图形。您不需要执行此操作,并且可以相应地修改代码(不会进行一些小的更改)。但是,预计任何需要此类高级功能的图形应用程序也将有一个 GUI 库(因为 matplotlib GUI 是有限的)。

这里唯一需要注意的方法是 delete 方法,它处理所选点的删除。您可以使用 delete 方法作为执行其他操作(如复制、粘贴、移动等)的模板。

import tkinter as tk
from tkinter import ttk
from matplotlib.figure import Figure
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from Highlighter import Highlighter
import pandas as pd
import random 

class MatplotlibApp:
    def __init__(self, master):
        self.master = master
        self.master.title("Matplotlib App")
        self.data = pd.DataFrame(columns=["x", "y"])
        self.points = []
        self.create_widgets()

    def create_widgets(self):
        self.fig = Figure(figsize=(5, 4), dpi=100)
        self.ax = self.fig.add_subplot(111)
        self.ax.set_xlim(-1, 11)
        self.ax.set_ylim(-1, 11)    

        self.canvas = FigureCanvasTkAgg(self.fig, master=self.master)
        self.canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1)
        self.canvas.get_tk_widget().bind("<Delete>", self.delete)
        self.canvas.draw()

        tk.Button(self.master, text="Add Random Point", command=self.add).pack(padx=20, pady=20)
        self.highlighter = Highlighter(self.canvas, self.ax, self.data["x"], self.data["y"])

    def add(self):
        x, y = [random.randint(0, 10), random.randint(0, 10)]
        df = pd.DataFrame([[x, y]], columns=["x", "y"])

        self.data = pd.concat([self.data, df], ignore_index=True)
        self.points.append(self.ax.scatter(x, y, color="blue"))
        self.highlighter.update(self.data["x"], self.data["y"])
        self.canvas.draw()

    def delete(self, event):
        self.selected_regions = self.highlighter.mask
        self.data = self.data[~self.selected_regions].reset_index(drop=True)

        for i, artist in enumerate(self.points):
            if self.selected_regions[i]:
                artist.remove()
        self.points = [artist for artist, m in zip(self.points, self.selected_regions) if m != 1]

        self.highlighter.update(self.data["x"], self.data["y"])
        self.highlighter.clear_highlights()
        self.canvas.draw()

def main():
    root = tk.Tk()
    app = MatplotlibApp(root)
    root.mainloop()

if __name__ == "__main__":
    main()

标签:canvas,self,mask,散点图,Matplotlib,xy,交互式,ax,def
From: https://blog.51cto.com/u_14249042/11991719

相关文章

  • 从基础到进阶:用 Plotly 实现交互式数据可视化
    在数据科学和数据分析领域,数据可视化是一种非常重要的技术。Plotly是一个功能强大的Python可视化库,它可以帮助我们创建交互式的数据可视化图表。本文将介绍如何使用Plotly实现交互式数据可视化,包括数据准备、图表创建和交互功能的添加。步骤1.安装Plotly首先,确保已经安装了......
  • [1061] Plotting a GeoDataFrame by matplotlib
    importgeopandasasgpdimportmatplotlib.pyplotaspltfromshapely.geometryimportPoint,LineString,Polygon#Createsamplegeometriespoints=[Point(.5,.5),Point(1.5,1.5),Point(2.5,2.5),Point(3.5,3.5),Point(5,5)]lines=[LineString([(5,0......
  • R:分组散点图
    rm(list=ls())setwd("C:\\Users\\Administrator\\Desktop\\machinelearning\\分组散点图")data("mpg")library(ggplot2)data<-read.table("data.txt",sep="\t",header=TRUE,row.names=1)#自定义刻度和标签cu......
  • 【Python篇】matplotlib超详细教程-由入门到精通(下篇)
    文章目录前言第六部分:保存与导出图表6.1保存为图片文件示例:保存图表为PNG文件解释:关键点:6.2保存为高分辨率图片示例:保存为高分辨率图片解释:6.3保存为不同文件格式示例:保存为不同文件格式解释:6.4调整图表的保存尺寸示例:设置图片尺寸并保存解释:6.5解决中文乱码......
  • OpenCV 与 Matplotlib 的结合使用:轮毂检测与目标跟踪
    目录绘制轮廓图像实现思路1.读取图像并转换为灰度图像2.二值化处理3.查找轮廓4.绘制轮廓5.显示结果代码实现效果展示动态逐步显示轮廓结果实现思路1.读取图像并缩放2.转换为灰度图像3.二值化处理4.查找轮廓5.动态显示轮廓6.显示最终结果并关闭窗口......
  • Matplotlib 完全指南:从基础图表到高级可视化
    Matplotlib是一个功能强大的Python库,用于创建各种类型的图表和可视化。无论您是数据科学家、工程师还是研究人员,Matplotlib都可以帮助您以直观的方式探索数据并传达结果。在本文中,我们将提供一个完整的指南,介绍如何使用Matplotlib创建基本的图表,包括折线图、散点图、柱状图和......
  • python画图|极坐标中画散点图
    python极坐标画图时,不仅可以画实线图,也可以画散点图。实线图画法如下述链接。python画图|极坐标画图基础教程-CSDN博客今天我们一起学习一下散点图画法。【1】官网教程首先依然是导航到官网,乖乖学习官网教程:Scatterplotonpolaraxis—Matplotlib3.9.2documentatio......
  • Python Matplotlib绘制柏拉图以及在ax.table上绘制矩形、直线、椭圆
    快速入门指南官网官方网址:Matplotlib—VisualizationwithPython官方教程:Tutorials—Matplotlib3.9.2documentation官方指南:UsingMatplotlib—Matplotlib3.9.2documentation官方示例:Examples—Matplotlib3.9.2documentation官方API说明:APIReference—Mat......
  • 【C#生态园】构建交互式界面利器:C#命令行解析库全方位评测
    C#命令行利器:选择最适合你的命令行解析器前言在现代软件开发中,命令行解析器库是不可或缺的工具,它们为开发人员提供了简单、高效地处理命令行参数和构建交互式命令行界面的方法。本文将介绍几个用于C#的优秀命令行解析器库,分别探讨它们的核心功能、使用场景、安装配置以及A......
  • 掌握动态图表:使用Python的Matplotlib库实现动态数据可视化
    在数据可视化领域,Matplotlib库是Python中最流行和功能强大的工具之一。它能够生成各种静态图表,如散点图、折线图和柱状图等。然而,Matplotlib也提供了创建动态图表的功能,使得我们能够以动画的方式展示数据的变化趋势,从而更直观地理解数据。本文将介绍如何使用Matplotlib库创建动态图......