Как создать новый список данных, взятых между двумя выделенными точками на графике матплотлиб
есть код, который считывает 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)