I have an application set up with an interactive plot window embedded. I would like to put a couple of subplots on top of eachother, with a shared x-axis and an independent y-axis. The whole thing is meant for data analysis.
I got the subplots set up, but for some reason the y-axis of the first subplot is somehow connected to the other subplots, but not the other way around. Additionally, the ticks and labels overlap instead of staying at their respective subplots.
I tried using the pyplot.subplots
function, which takes care of the problem of the independent axes and ticks/labels, but this opens up another window when I call it instead of embedding it.
working example code that showcases the problem (Python 3.7):
# -*- coding: utf-8 -*-
import tkinter as tk
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2Tk
from matplotlib.figure import Figure
from tkinter import ttk
import numpy as np
import pandas as pd
class window(tk.Tk):
def __init__(self,*args,**kwargs):
tk.Tk.__init__(self,*args,**kwargs)
self.generate_data()
self.plotPane = self.plot_pane(self)
def generate_data(self):
self.data = pd.DataFrame()
x = [1,2,3,4,5]
y = np.zeros((len(x)))
for i,yy in enumerate(y):
y[i] = yy + 10.*float(np.random.random())
self.data['x'] = x
self.data['y'] = y
class plot_pane():
def __init__(self,parent):
self.parent = parent
self.labelframe = ttk.Labelframe(self.parent,text="Plot")
replotButton = ttk.Button(self.parent,text="replot",command=self.update_plot)
self.labelframe.grid(row=0, column=0)
replotButton.grid(row=1,column=0)
self.figure = Figure(figsize=(6,3),dpi=100)
self.figure.subplots_adjust(left=0.11,bottom=0.09,right=0.77,top=0.92)# BaMa:. subplot margins, so labels are visible
self.sub = self.figure.add_subplot(111)
# toolbar and canvas for live plot
canvas = FigureCanvasTkAgg(self.figure,self.labelframe)
canvas.get_tk_widget().grid(row=1,column=1,rowspan=2,sticky="NSEW",pady=20)
canvas._tkcanvas.grid(row=1,column=1,rowspan=2, sticky="NSEW")
toolbar_frame = tk.Frame(self.labelframe)
toolbar_frame.grid(row=0,column=1,sticky="SEW")
toolbar = NavigationToolbar2Tk(canvas,toolbar_frame)
toolbar.update()
self.update_plot()
def update_plot(self,*args):
# clear figure
self.figure.clf()
stackAx = []
for i in range(0,2):
# generate new random data
self.parent.generate_data()
testX = self.parent.data['x']
testY = self.parent.data['y']
# add subplots
if i == 0:
stackAx.append(self.figure.add_subplot(i+1,1,1))# y-axis of this subplot is somehow connected to the other
else:
stackAx.append(self.figure.add_subplot(i+1,1,1,sharex=stackAx[0]))
# plot, add labels, ticks and grid
stackAx[i].plot(testX,testY)
stackAx[i].set_ylabel("ax-"+str(i))
stackAx[i].tick_params('y')
stackAx[i].grid()
self.figure.canvas.draw()
window = window()
window.mainloop()
So, when you move the subplot at the top, the bottom y-axis moves as well and the "ax-0" label + tickmarks breach the upper subplot. When you move the lower plot, the y-axis of the upper plot does not move (as it should be)
I figured it out. Apparently add_subplot
and pyplot.subplots
function somewhat differently and I didn't understand it correctly.
The following update function works:
def update_plot(self,*args):
# clear figure
self.figure.clf()
stackAx = []
numberOfPlots = 2
for i in range(0,numberOfPlots):
# generate new random data
self.parent.generate_data()
testX = self.parent.data['x']
testY = self.parent.data['y']
# add subplots
if i == 0:
stackAx.append(self.figure.add_subplot(numberOfPlots,1,i+1))
else:
stackAx.append(self.figure.add_subplot(numberOfPlots,1,i+1,sharex=stackAx[0]))
# plot, add labels, ticks and grid
stackAx[i].plot(testX,testY)
stackAx[i].set_ylabel("ax-"+str(i))
stackAx[i].tick_params('y')
stackAx[i].grid()
self.figure.canvas.draw()
I got it from here: https://pythonprogramming.net/subplot2grid-add_subplot-matplotlib-tutorial/