Как создать новый список данных, взятых между двумя выделенными точками на графике матплотлиб

есть код, который считывает excel- файл при помощи пандаса, после чего в нем создается новый столбец, состоящий из сцепки данных из двух столбцов, считанных ранее, также строится точечный график, оси которого и являются этими двумя столбцами, необходимо сделать так чтобы при нажатии на две точки программа проверяла вхождения данных в новый список и оставляла только точки, которые находятся между двумя нажатыми точками до этого , код приложу следом:

    from typing import Optional
       import PySimpleGUI as sg
       import pandas as pd
       import numpy as np
       import matplotlib.pyplot as plt
       from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
       import matplotlib.text
       import matplotlib.backend_bases
       # marker: Optional[matplotlib.text.Text] = None
       def read_table():
           sg.set_options(auto_size_buttons=True) #Эта строка устанавливает опцию auto_size_buttons в библиотеке PySimpleGUI. Она отвечает за автоматическое изменение размеров кнопок в окне программы.
           filename = sg.popup_get_file(
               'SA',
               title='Dataset to read',
               no_window=False,
               file_types=(("CSV Files", "*.csv"), ("Text Files", "*.txt"),('Excel Files','.xlsx'),('Excel Files','.xls'))) # В этой строке кода используется функция popup_get_file из библиотеки PySimpleGUI. Она открывает диалоговое окно, которое позволяет пользователю выбрать файл для чтения. В данном случае, окно имеет заголовок 'Dataset to read' и отображает файлы только с расширениями .csv, .txt, .xlsx и .xls. Выбранный файл будет сохранен в переменной filename.
    # --- populate table with file contents --- ##ак как вызывается проводник не будет названия первого окна
          if filename == '':   #Эта строка кода проверяет, если переменная filename (предполагается, что это строка, содержащая путь к выбранному файлу) пустая, то есть если пользователь не выбрал файл. Если это условие выполняется, то код переходит к следующей строке после блока if
             return         #В этой строке кода используется оператор return, который прекращает выполнение текущей функции и возвращает управление вызывающей части программы. В данном случае, если filename пустая, то функция будет прекращать выполнение и возвращать управление вызывающей части программы
         data = []
         header_list = []
         colnames_prompt = sg.popup_yes_no('Does this file have column names already?')
         nan_prompt = sg.popup_yes_no('Drop NaN entries?')

         if filename is not None:
             fn = filename
             print(fn)
        try:
            if colnames_prompt == 'Yes':
                df = pd.read_excel(filename)
                print(df)
                df['lat_long'] = df[['skv2', 'lg(t)']].apply(tuple, axis=1)
                # Uses the first row (which should be column names) as columns names
                header_list = list(df.columns)
                print(header_list)
                # Drops the first row in the table (otherwise the header names and the first row will be the same)
                data = df[0:].values.tolist()

                print(data)

            else:
                df = pd.read_excel(filename)
                # Creates columns names for each column ('column0', 'column1', etc)
                header_list = ['column' + str(x) for x in range(len(df.iloc[0]))]
                df.columns = header_list
                # read everything else into a list of rows
                data = df.values.tolist()
                print(data)
            # NaN drop?
            if nan_prompt == 'Yes':
                df = df.dropna()

            return(df, data, header_list, fn)
        except:
            sg.popup_error('Error reading file')
            return
      def show_table(data, header_list, fn):
          layout = [
                     [sg.Table(values=data,
                   headings=header_list,
                   font='Helvetica', #Шрифт
                   pad=(0, 0),     #отступы
                   display_row_numbers=False, #Слева создает еще один столбец с номером строки
                   auto_size_columns=True, #Автоматические задает границы колонок
                   num_rows=min(25, len(data)))] #Минимум 25 значений в окне показывает
     ]

    window = sg.Window(fn, layout)
    event, values = window.read()
      def plot_fig(df):
    """
    Plots
    """
        fig = plt.figure() # переменная fig типа Figure из библиотеки Matplotlib,  использовуется для создания и настройки графика.
        x = list(df.columns)[19] # создается переменная x, которая получает значение имени столбца в DataFrame df по индексу 3. Предполагается, что это будет использоваться как ось x на графике.
        y = list(df.columns)[3] # создается переменная y, которая получает значение имени столбца в DataFrame df по индексу 5. Предполагается, что это будет использоваться как ось y на графике.
       fig.add_subplot(111).scatter(df[x], df[y], color='blue', edgecolor='m') #  график добавляется    создается подграфик (subplot) на объекте fig и на нем рисуется точечная диаграмма (scatter plot) с данными из столбцов x и y из DataFrame df. Точки на графике будут красного цвета с черными границами.
       plt.xlabel(x) #ось икс подпись
       plt.ylabel(y) #ось у подпись
           
       def draw_figure(canvas, figure): #отображение фигуры и графика построения   Функция draw_figure принимает два аргумента: объект canvas (холст) и фигуру figure
        figure_canvas_agg = FigureCanvasTkAgg(figure, canvas) #Создает экземпляр класса FigureCanvasTkAgg, который представляет собой комбинацию графики Matplotlib и виджетов Tkinter
        figure_canvas_agg.draw()  #отрисовка графика на холсте.
        figure_canvas_agg.get_tk_widget().pack() # вызов виджета ткинтер
        return figure_canvas_agg #Возвращает созданный экземпляр FigureCanvasTkAgg для дальнейшего использования.

       def onMouseClick(event: matplotlib.backend_bases.MouseEvent) : #Выполняется функция ,которая принимает аргумент событие типа matplotlib.backend_bases.MouseEvent

        axes = event.inaxes #Объект,представляющий оси на которые произошло событие щелчка мыши
        print(axes)

        if axes is None:
            return # Если кликнули вне какого-либо графика, то не будем ничего делать

        global marker #Глобальная переменная маркер может быть использована и изменена внутри функции даже если она объявлена вне функции
        if event.button == 3:
            marker.remove()
            # Если нажимаем правую кнопку мыши, то удалим его, эта строка под вопросом ,Вполне вероятно удалю ее
                # Координаты клика в системе координат осей
        xq = event.xdata  #клик координаты х
        yq = event.ydata  #клик координаты у
        text = f'({xq:.3f}; {yq:.3f})'  #строка с тремя знаками после запятой представление
        print(text)

            # Выведем текст в точку, куда кликнули
        marker = axes.text(xq, yq, text) #создание текстового маркера с координатами щелчков
        if event.button == 3:
            marker.remove()
        axes.figure.canvas.draw() #обновление графика



    # define the window layout

    layout = [[sg.Text('Plot of {} vs. {}'.format(x, y))],  #название графика
              [sg.Canvas(key='-CANVAS-',
                         size=(800, 600),
                         pad=(15, 15))],  #используется для отображения графика
              [sg.Button('Ok')]] # создание кнопки Ок

        # create the form and show it without the plot
    window = sg.Window('Plot',
                       layout,
                       size=(800, 600),
                       finalize=True,
                       element_justification='center',
                       font='Helvetica 18')   #создание окна,в котором будет лежать кнопка и график

    # add the plot to the window
    fig_canvas_agg = draw_figure(window['-CANVAS-'].TKCanvas,fig )
    fig_canvas_agg.mpl_connect('button_press_event', onMouseClick)
            # Обновим график

    event, values = window.read()

    # window.close()
#
#
    def main():  #Функция,в которой будут реализовываться  функции описанные ранее
        df, data, header_list, fn = read_table()

    # Show data?
       show_prompt = sg.popup_yes_no('Show the dataset?')
       if show_prompt == 'Yes':
           show_table(data, header_list, fn)

   

    # Show a plot?
    plot_prompt = sg.popup_yes_no('Show a scatter plot?')
    if plot_prompt == 'Yes':
        plot_fig(df)
#
#
# Executes main
    if __name__ == '__main__':  #проверяет был ли файл запущен напрямую
    main()

Ответы (1 шт):

Автор решения: Petr6446

попробуйте вставить эту функцию в вашу функцию нажатия на кнопку мыши:

if event.dblclick:
    x_clicked=event.xdata
    y_clicked=event.ydata
    selected_points=df[(df[x]== x_clicked) & (df[y] == y_clicked)]
    if selected_points in list(df.columns)[7]:
       x_min = selected_points[x].min()
       x_max = selected_points[x].max()
       y_min = selected_points[y].min()
       y_max = selected_points[y].max()
       points_between = data[(data[x]>=x_min) & (data[x]<=x_max) &(data[y]>=y_min) & (data[y]<=y_max)]
       print(points_between)
→ Ссылка