Matplotlib は、Python および NumPy のためのグラフ描画ライブラリです。Qt for Python (PySide) などと組み合わせて GUI アプリを作成するのに重宝しています。プロットを静的に描画するだけでも十分有用です。しかし、時にはプロット上のデータ集団をマウスでドラッグして抽出するちょっとインタラクティブな用途にも使いたいことがあり、調べてそういう使い方もしていたのですが [1]、使い方についてはいまひとつ理解ができていない部分がありました。
Matplotlib 3.5.0 のリリースでようやく PySide6/PyQt6 でも利用できるようになったので、この機にあらためて試行錯誤を重ね、理解しやすい記述に書き直しました。
本記事では、下記の OS 環境を使用しています。
![]() |
Fedora 35 Workstation | x86_64 |
Python | 3.10.0 | |
PySide6 | 6.2.1 | |
matplotlib | 3.5.0 |
以下にサンプルの実行例を示します。
qt_matplotlib_scatter.py の実行例
(0.39, 0.32) --> (0.81, 0.83)
サンプルコードを下記に示しました。
qt_matplotlib_scatter.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
# coding: utf-8 | |
# Reference | |
# https://matplotlib.org/stable/gallery/widgets/rectangle_selector.html | |
from PySide6.QtCore import Qt | |
from PySide6.QtWidgets import ( | |
QApplication, | |
QMainWindow | |
) | |
import sys | |
import numpy as np | |
import pandas as pd | |
import matplotlib.pyplot as plt | |
from matplotlib.backends.backend_qtagg import FigureCanvasQTAgg as FigureCanvas | |
from matplotlib.backends.backend_qtagg import NavigationToolbar2QT as NavigationToolbar | |
from matplotlib.widgets import EllipseSelector, RectangleSelector | |
import seaborn as sns | |
class Example(QMainWindow): | |
def __init__(self): | |
super().__init__() | |
self.setWindowTitle('Scatter') | |
self.init_ui() | |
def init_ui(self): | |
# sample data | |
df = pd.DataFrame(np.random.random(size=(100, 2)), columns=['X', 'Y']) | |
canvas = self.chart(df) | |
self.setCentralWidget(canvas) | |
navtoolbar = NavigationToolbar(canvas, self) | |
self.addToolBar( | |
Qt.BottomToolBarArea, | |
navtoolbar | |
) | |
def chart(self, df): | |
fig, ax = plt.subplots() | |
ax = sns.scatterplot(data=df, x=df.columns[0], y=df.columns[1]) | |
canvas = FigureCanvas(fig) | |
plt.RS = RectangleSelector( | |
ax, self.select_callback, useblit=True, | |
button=[1], # disable middle & right buttons | |
minspanx=5, minspany=5, spancoords='pixels', interactive=True, | |
props=dict( | |
facecolor='pink', | |
edgecolor='red', | |
alpha=0.2, | |
fill=True | |
) | |
) | |
return canvas | |
def select_callback(self, eclick, erelease): | |
x1, y1 = eclick.xdata, eclick.ydata | |
x2, y2 = erelease.xdata, erelease.ydata | |
print(f"({x1:3.2f}, {y1:3.2f}) --> ({x2:3.2f}, {y2:3.2f})") | |
def main(): | |
app = QApplication(sys.argv) | |
ex = Example() | |
ex.show() | |
sys.exit(app.exec()) | |
if __name__ == '__main__': | |
main() |
ちなみに RectangleSelector を EllipseSelector に変更すると、マウスでドラッグする矩形範囲が楕円に変わります。
plt.RS = EllipseSelector(
ax, self.select_callback, useblit=True,
button=[1], # disable middle & right buttons
...
...
qt_matplotlib_scatter.py の実行例 (2)
(0.45, 0.39) --> (0.92, 0.84)
参考サイト
- Rectangle and ellipse selectors — Matplotlib 3.5.0 documentation
- Matplotlib documentation — Matplotlib 3.5.0 documentation

にほんブログ村
0 件のコメント:
コメントを投稿