SW개발/python

[python] PyQt5 그래프 그리기(feat. plotly, matplotlib)

코대장 2021. 9. 10. 22:37
반응형

PyQt5 환경에서 plotly 그래프 그리기

PyQt5는 python 으로 빠르게 GUI 프로그램을 만들 수 있게 도와줍니다. 특히 QtDesigner 를 사용해 직관적으로 콤보박스, 텍스트박스 등을 배치시킬 수도 있고, 코드로 직접 화면 구성을 할 수도 있죠. 최근에는 버전업이 되어 PyQt6가 나왔다고 하네요.
개발언어가 python이고 GUI 환경으로 프로토타입을 빠르게 만들어보고 싶다면 추천드립니다.

오늘은 PyQt5 환경에서 plotly 라이브러리로 그래프를 그리는 방법을 알아 볼게요.

1. 라이브러리 설치

PyQt5와 plotly 라이브러리는 당연히 설치되어 있어야 하고, 추가적으로 Plotly 그래프를 그리기 위해서 PyQtWebEngine 을 설치해줍니다.

pip install PyQtWebEngine

2. 베이스코드

기본 베이스 코드는 아래와 같고 실행해 보면 윈도우 창이 하나 뜨겠죠.

from PyQt5 import QtCore, QtWidgets, QtWebEngineWidgets
import plotly.express as px


class Widget(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.resize(1000,800)


if __name__ == "__main__":
    app = QtWidgets.QApplication([])
    widget = Widget()
    widget.show()
    app.exec()
빈 윈도우 화면

2.1 plotly

아래와 같이 베이스 코드에 plotly 그래프를 그리기 위한 코드를 추가해줍니다.

from PyQt5 import QtCore, QtWidgets, QtWebEngineWidgets
import plotly.express as px


class Widget(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.button = QtWidgets.QPushButton('Plot', self)
        self.browser = QtWebEngineWidgets.QWebEngineView(self)
        vlayout = QtWidgets.QVBoxLayout(self)
        vlayout.addWidget(self.button, alignment=QtCore.Qt.AlignHCenter)
        vlayout.addWidget(self.browser)
        self.button.clicked.connect(self.show_graph)
        self.resize(1000,800)

    def show_graph(self):
        df = px.data.tips()
        fig = px.box(df, x="day", y="total_bill", color="smoker")
        fig.update_traces(quartilemethod="inclusive") # or "inclusive", or "linear" by default
        self.browser.setHtml(fig.to_html(include_plotlyjs='cdn'))


if __name__ == "__main__":
    app = QtWidgets.QApplication([])
    widget = Widget()
    widget.show()
    app.exec()
실행화면

2021. 11.21. plotly 추가예제

from PyQt5 import QtCore, QtWidgets, QtWebEngineWidgets
import plotly.express as px
import plotly.graph_objects as go

# Create random data with numpy
import numpy as np
np.random.seed(1)
N = 100
random_x = np.linspace(0, 1, N)
random_y0 = np.random.randn(N) + 5
random_y1 = np.random.randn(N)
random_y2 = np.random.randn(N) - 5

class Widget(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.button = QtWidgets.QPushButton('Plot', self)
        self.browser = QtWebEngineWidgets.QWebEngineView(self)
        vlayout = QtWidgets.QVBoxLayout(self)
        vlayout.addWidget(self.button, alignment=QtCore.Qt.AlignHCenter)
        vlayout.addWidget(self.browser)
        self.button.clicked.connect(self.show_graph)
        self.resize(1000,800)

    def show_graph(self):
        fig = go.Figure()

        # Add traces
        fig.add_trace(go.Scatter(x=random_x, y=random_y0,
                                 mode='markers',
                                 name='markers'))
        fig.add_trace(go.Scatter(x=random_x, y=random_y1,
                                 mode='lines+markers',
                                 name='lines+markers'))
        fig.add_trace(go.Scatter(x=random_x, y=random_y2,
                                 mode='lines',
                                 name='lines'))
        self.browser.setHtml(fig.to_html(include_plotlyjs='cdn'))


if __name__ == "__main__":
    app = QtWidgets.QApplication([])
    widget = Widget()
    widget.show()
    app.exec()
실행화면

2.2 matplotlib

이번에는 matplib 라이브러리를 사용해 볼까요?

from PyQt5 import QtCore, QtWidgets, QtWebEngineWidgets
import plotly.express as px
import matplotlib.pyplot as plt
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas


class Widget(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.button = QtWidgets.QPushButton('Plot', self)
        self.fig = plt.Figure( figsize=(4, 3) )
        self.canvas = FigureCanvas( self.fig )
        self.canvas.setVisible( True )
        vlayout = QtWidgets.QVBoxLayout(self)
        vlayout.addWidget(self.button, alignment=QtCore.Qt.AlignHCenter)
        vlayout.addWidget(self.canvas)
        self.button.clicked.connect(self.show_graph)
        self.resize(1000,800)

    def show_graph(self):
        ax = self.fig.add_subplot( 1, 1, 1 )
        df = px.data.tips()
        df.boxplot(column=['total_bill'],by="day", ax=ax)
        self.canvas.draw()


if __name__ == "__main__":
    app = QtWidgets.QApplication([])
    widget = Widget()
    widget.show()
    app.exec()
실행화면

감사합니다.