I am using a wrapper of PyQt (pyqtgraph) to build a GUI application.
I wish to embed a Seaborn plot within it using the MatplotlibWidget. However, my problem is that the Seaborn wrapper method such as FacetGrid
do not accept an external figure handle. Moreover, when I try to update the MatplotlibWidget object underlying figure (.fig
) with the figure produced by the FacetGrid
it doesn't work (no plot after draw
). Any suggestion for a workaround?
相关问题
- How to plot a draggable polygon
- QGraphicsView / QGraphicsScene size matching
- Tick label text and frequency in matplotlib plot
- Matplotlib: how to set ticks of twinned axis in lo
- Matplotlib differentiate between mean and median w
相关文章
- How to use a framework build of Python with Anacon
- Adding line markers when using LineCollection
- How to add clipboard support to Matplotlib figures
- Adding a legend to a matplotlib boxplot with multi
- Matplotlib pyplot axes formatter
- matplotlib bwr-colormap, always centered on zero
- how do I correctly return values from pyqt to Java
- TypeError: ufunc 'isnan' not supported for
Seaborn's
Facetgrid
provides a convenience function to quickly connect pandas dataframes to the matplotlib pyplot interface.However in GUI applications you rarely want to use pyplot, but rather the matplotlib API.
The problem you are facing here is that
Facetgrid
already creates its ownmatplotlib.figure.Figure
object (Facetgrid.fig
). Also, the MatplotlibWidget creates its own figure, so you end up with two figures.Now, let's step back a bit: In principle it is possible to use a seaborn
Facetgrid
plot in PyQt, by first creating the plot and then providing the resulting figure to the figure canvas (matplotlib.backends.backend_qt4agg.FigureCanvasQTAgg
). The following is an example of how to do that.While this works fine, it is a bit questionable, if it's useful at all. Creating a plot inside a GUI in most cases has the purpose of beeing updated depending on user interactions. In the example case from above, this is pretty inefficient, as it would require to create a new figure instance, create a new canvas with this figure and replace the old canvas instance with the new one, adding it to the layout.
Note that this problematics is specific to those plotting functions in seaborn, which work on a figure level, like
lmplot
,factorplot
,jointplot
,FacetGrid
and possibly others.Other functions like
regplot
,boxplot
,kdeplot
work on an axes level and accept a matplotlibaxes
object as argument (sns.regplot(x, y, ax=ax1)
).A possibile solution is to first create the subplot axes and later plot to those axes, for example using the pandas plotting functionality.
where
ax
should be set to the previously created axes.This allows to update the plot within the GUI. See the example below. Of course normal matplotlib plotting (
ax.plot(x,y)
) or the use of the seaborn axes level function discussed above work equally well.A final word about pyqtgraph: I wouldn't call pyqtgraph a wrapper for PyQt but more an extention. Although pyqtgraph ships with its own Qt (which makes it portable and work out of the box), it is also a package one can use from within PyQt. You can therefore add a
GraphicsLayoutWidget
to a PyQt layout simply byThe same holds for a MatplotlibWidget (
mw = pg.MatplotlibWidget()
). While you can use this kind of widget, it's merely a convenience wrapper, since all it's doing is finding the correct matplotlib imports and creating aFigure
and aFigureCanvas
instance. Unless you are using other pyqtgraph functionality, importing the complete pyqtgraph package just to save 5 lines of code seems a bit overkill to me.There a better way to do this, is to set up a 'Widget Layout setting' file so you have less code to type in your actual Main App code.
See here: https://yapayzekalabs.blogspot.com/2018/11/pyqt5-gui-qt-designer-matplotlib.html
It is helpful just the image and process you should follow.