Nickpick
Nickpick

Reputation: 6597

Plotting onto QT5 FigureCanvas with multiple axes

I want to plot a stacked grouped bar char (as described here), to a Canvas in QT5. I managed to get it to work with a single axes, but in the below example ax=plt.subplot2grid somehow creates multiple axes, and I'm not sure how this can be projected onto a QT figureCanvas. Currently there is no error message, but the plot is empty. Any suggestions are greatly apprecaited.

class BarPlotter2(FigureCanvas):
    def __init__(self, ui_analyser, lst):
        self.fig = Figure(dpi=70)
        self.axes = self.fig.add_subplot(111)  # This is most probably wrong?
        super(BarPlotter2, self).__init__(self.fig)
        self.drawfigure()

    def drawfigure(self):
        self.fig.clf()

        df = get_data()
        clusters = df.index.levels[0]
        gridspec.GridSpec(1, total_width)
        axes = []

        ax_position = 0
        for cluster in clusters:
            subset = df.loc[cluster]
            self.axes = subset.plot(kind="bar", stacked=True, width=0.8,
                                    ax=plt.subplot2grid((1, total_width), (0, ax_position), colspan=len(subset.index)))
            axes.append(self.axes)
            self.axes.set_title(cluster)
            ax_position += len(subset.index) + inter_graph

        for i in range(1, len(clusters)):
            axes[i].set_yticklabels("")
            axes[i - 1].legend().set_visible(False)
        axes[0].set_ylabel("y_label")


        self.draw()

Upvotes: 0

Views: 601

Answers (1)

eyllanesc
eyllanesc

Reputation: 243993

You have to pass fig as a parameter to the Figure on the canvas to the plt.subplot2grid method:

import sys

from PyQt5.QtWidgets import QApplication

from matplotlib.backends.backend_qt5agg import FigureCanvas
from matplotlib.figure import Figure
from matplotlib.ticker import MaxNLocator
import matplotlib.gridspec as gridspec
import matplotlib.pyplot as plt

import numpy as np
import pandas as pd


class BarPlotter(FigureCanvas):
    def __init__(self, parent=None):
        super(BarPlotter, self).__init__(Figure(dpi=70))
        self.setParent(parent)
        self.draw_figure()

    def draw_figure(self):
        np.random.seed(0)
        df = pd.DataFrame(
            np.asarray(1 + 5 * np.random.random((10, 4)), dtype=int),
            columns=["Cluster", "Bar", "Bar_part", "Count"],
        )
        df = (
            df.groupby(["Cluster", "Bar", "Bar_part"])["Count"]
            .sum()
            .unstack(fill_value=0)
        )

        clusters = df.index.levels[0]
        inter_graph = 0
        maxi = np.max(np.sum(df, axis=1))
        total_width = len(df) + inter_graph * (len(clusters) - 1)

        gridspec.GridSpec(1, total_width)
        axes = []

        ax_position = 0
        for cluster in clusters:
            subset = df.loc[cluster]
            ax = subset.plot(
                kind="bar",
                stacked=True,
                width=0.8,
                ax=plt.subplot2grid(
                    (1, total_width),
                    (0, ax_position),
                    colspan=len(subset.index),
                    fig=self.figure,
                ),
            )
            axes.append(ax)
            ax.set_title(cluster)
            ax.set_xlabel("")
            ax.set_ylim(0, maxi + 1)
            ax.yaxis.set_major_locator(MaxNLocator(integer=True))
            ax_position += len(subset.index) + inter_graph

        for i in range(1, len(clusters)):
            axes[i].set_yticklabels("")
            axes[i - 1].legend().set_visible(False)
        axes[0].set_ylabel("y_label")


if __name__ == "__main__":
    qapp = QApplication.instance()
    if qapp is None:
        qapp = QApplication(sys.argv)

    app = BarPlotter()
    app.show()
    app.activateWindow()
    app.raise_()
    qapp.exec_()

Upvotes: 3

Related Questions