2021-12-03

【備忘録】Matplotlib の RectangleSelector

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
#!/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)

参考サイト

  1. Rectangle and ellipse selectors — Matplotlib 3.5.0 documentation
  2. Matplotlib documentation — Matplotlib 3.5.0 documentation

 

 

ブログランキング・にほんブログ村へ bitWalk's - にほんブログ村 にほんブログ村 IT技術ブログ Linuxへ
にほんブログ村

0 件のコメント: