我是Python新手!我正在尝试编写一个程序来读取多个 csv 文件,获取数据列并将它们绘制在散点图上。然后用户将与每个图进行交互并选择一个点。该数据点将改变颜色,并会提示一条消息,询问用户是否对此选择感到满意。如果用户选择“是”,则将返回该点的索引并用于分析,并绘制下一个数据集并重新开始循环。如果用户选择否,则数据点将更改为原始颜色,不返回索引,并提示用户选择另一个点。
这是我尝试过的。
但是有些事情不起作用
import os
import tkinter as tk
from tkinter import filedialog, messagebox
import pandas as pd
from openpyxl import Workbook
import numpy as np
from statistics import mean
import math as M
from scipy import stats
import matplotlib.pyplot as plt
import mplcursors
def on_pick(event,disp_list,load_list,F_vs_D_plot):
ind = event.ind[0]
print(ind)
F_vs_D_plot.set_facecolors(['red' if i == ind else 'blue' for i in range(len(disp_list))])
# F_vs_D_plot.set_color(ind,'red')
# plt.scatter(disp_list[ind],load_list[ind],color = 'red')
plt.draw()
confirmation = messagebox.askyesno("Confirmation", "Are you sure you want to select this point?")
if confirmation:
selected_index = ind
# print(f"Selected point index: {selected_index}")
#ask if user wants to close plot and move onto next file
# if yes, close plot
# if no, select again and overwrite previous selection for that file
plt.close()
return selected_index
def graph_method(disp_list, load_list):
selectedPoint = None
fig, ax = plt.subplots()
mplcursors.cursor(hover=True)
F_vs_D_plot = ax.scatter(disp_list, load_list, picker=True, color = 'blue')
selected_index = fig.canvas.mpl_connect('pick_event',lambda event: on_pick(event,disp_list,load_list,F_vs_D_plot))
print('This is the selected index',selected_index)
ax.set_xlabel('Displacement (mm)')
ax.set_ylabel('Load (g)')
ax.set_title(file_name)
plt.show()
def main()
disp_list = random.randint(100, size=(1000))
load_list = random.randint(100, size=(1000))
graph_method(disp_list, load_list)
好吧,你的代码对我来说仍然不清楚,有点不完全按照SO指南的MRE(如何创建一个最小的、可重现的示例),
最终得到:
import tkinter as tk
from tkinter import messagebox
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import random
file_name = None
def on_pick(event , disp_list,load_list , F_vs_D_plot ):
ind = event.ind
F_vs_D_plot.set_facecolors(['red' if i == ind else 'blue' for i in range(len(disp_list))])
plt.draw()
confirmation = messagebox.askyesno("Confirmation", "Are you sure you want to select this point?")
if confirmation :
print('!!!!!!!!!!!!!!!!!!!!!!!!!!! ', ind , disp_list[ind[0]] , load_list[ind[0]])
print('!!!!!!!!!!!!!!!!!!!!!!!!!!! ', ind , type(ind))
pippo = event.artist
print ('line : ' , pippo , type(pippo))
print(event.artist.get_cursor_data(event))
def main() :
disp_list = random.sample(range(1, 11), 10) # lista
load_list = random.sample(range(1, 11), 10)
print(disp_list)
print(load_list)
root = tk.Tk()
fig, ax = plt.subplots()
F_vs_D_plot = ax.scatter(disp_list, load_list, picker=True, color = 'blue')
ax.set_xlabel('Displacement (mm)')
ax.set_ylabel('Load (g)')
ax.set_title(file_name)
canvas = FigureCanvasTkAgg(fig, master=root)
canvas.draw()
canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1)
canvas.mpl_connect('pick_event',lambda event: on_pick(event,disp_list , load_list , F_vs_D_plot))
tk.mainloop()
main()
运行代码我得到这个图:
选择并单击它,其中一个点/点会变红(参见箭头):
然后在 messagebox.askyesno
消息框中单击
是,我得到关注
输出:
[10, 4, 2, 6, 5, 7, 3, 1, 8, 9]
[6, 7, 1, 3, 2, 10, 9, 8, 4, 5]
!!!!!!!!!!!!!!!!!!!!!!!!!!! [5] 7 10
!!!!!!!!!!!!!!!!!!!!!!!!!!! [5] <class 'numpy.ndarray'>
line : <matplotlib.collections.PathCollection object at 0x7f42fdd16940> <class 'matplotlib.collections.PathCollection'>
None
我想您需要在 Tkinter 中嵌入 ypur 图才能使消息框正常工作,请参阅 在 Tkinter 中嵌入时未调用 Matplotlib 事件处理程序了解更多信息。
其他有趣的链接是:
选取散点图 matplotlib 示例,展示了使用
event.ind
选取散点图(散点图由 PathCollection
支持),但无法找到有关 event.ind id matplotlib 文档的任何参考:
from numpy.random import rand
from matplotlib import pyplot as plt
x, y, c, s = rand(4, 100)
def onpick3(event):
ind = event.ind
print('onpick3 scatter:', ind, x[ind], y[ind])
print('onpick3 scatter:', ind, type(ind))
fig, ax = plt.subplots()
ax.scatter(x, y, 100*s, c, picker=True)
fig.canvas.mpl_connect('pick_event', onpick3)
plt.show()
和 Matplotlib 中的事件处理和选取 以简要了解更多信息 :
Matplotlib 可与许多用户界面工具包(wxpython、tkinter、qt、gtk 和 macosx)配合使用,为了支持交互式平移和缩放图形等功能,拥有一个用于与通过按键和鼠标移动来绘制图形是“GUI中立的”,因此我们不必在不同的用户界面上重复大量代码。尽管事件处理 API 与 GUI 无关,但它基于 GTK 模型,这是 Matplotlib 支持的第一个用户界面。与 Matplotlib 相比,触发的事件也比标准 GUI 事件更丰富,包括事件发生在哪个轴等信息。这些事件还了解 Matplotlib 坐标系,并报告像素和数据坐标中的事件位置.
很抱歉无法更详细/清晰地解释任何内容,只是在“审查队列”中收到您的问题,而不是 matplotlib/tkinter 的专家。
只是想指出,即使 Tkinter 是 Python 附带的 Tk GUI 工具包的 Python 接口,PyQt5 如今可能比 Tkinter 更时尚、更高效