Embedding seaborn clustermap into tkinter window - python

I'm attempting to display a seaborn clustermap in a tkinter window.
I can embed seaborn heatmaps; however, clustermaps fail to appear in the tkinter window and an empty seaborn frame appears instead.
#Libraries
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
import tkinter
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
#Returns plot for tkinter to display
def create_plot():
#creates dataset
data = np.random.rand(50,11)
#Defines plot
plot, ax = plt.subplots(figsize=(11, 9))
#Does work - Outputs heatmap
#sns.heatmap(data, cmap='YlGnBu')
#Doesn't work - Should output clustermap
sns.clustermap(data,cmap='YlGnBu',metric = 'correlation',z_score=0)
return plot
#Generating tkinter window
root = tkinter.Tk()
figure = create_plot()
canvas = FigureCanvasTkAgg(figure, master=root)
canvas.draw()
canvas.get_tk_widget().pack()
tkinter.mainloop()
The clustermap can be correctly displayed inline with the following code:
%matplotlib inline
data = np.random.rand(50,11)
sns.clustermap(data,cmap='YlGnBu',metric = 'correlation',z_score=0)
Is there something different about clustermaps, how can they be embedded?

clustermap creates its own figure. So you need to return this figure to use it elsewhere.
#Libraries
import numpy as np
import seaborn as sns
import tkinter
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
#Returns plot for tkinter to display
def create_plot():
data = np.random.rand(50,11)
g = sns.clustermap(data,cmap='YlGnBu',metric = 'correlation',z_score=0)
return g.fig
#Generating tkinter window
root = tkinter.Tk()
figure = create_plot()
canvas = FigureCanvasTkAgg(figure, master=root)
canvas.draw()
canvas.get_tk_widget().pack()
tkinter.mainloop()
But be aware that seaborn creates a pyplot figure. Embedding a pyplot figure in a custom GUI may cause problems (note how none of the examples from the matplotlib page on embedding use pyplot!).

Related

add Seaborn Scatter plot to tkinter gui

I want to add this scatter plot to my tkinter gui. I ran this on my jupyter notebook and it works but I am not sure how to implement it to the tkinter gui.
enter image description here
this is the window the graph should be
enter image description here
this is the code I have on my jupyter notebook:
### Import libraries
import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd
### Import dataset
players_df = pd.read_csv("player_locations.txt")
players_df
### Draw Seaborn Scatter Plot to find location between lat and long
sns.scatterplot(x = players_df["longitude"], y = players_df["latitude"], hue = players_df["Player"])
this is the code on my gui for the analysis window:
from tkinter import *
import matplotlib
import matplotlib.pyplot as plt
import numpy as np
import csv
import pandas as pd
import seaborn as sns
from matplotlib import animation
from matplotlib.animation import FuncAnimation
from matplotlib import style
players_df = pd.read_csv("player_locations.txt")
players_df
class addAnalysis(Toplevel):
def __init__(self):
Toplevel.__init__(self)
self.geometry("650x650+620+200")
self.title("Analysis")
self.resizable(False,False)
#Frames
self.top=Frame(self,height=150,bg='white')
self.top.pack(fill=X)
self.bottomFrame=Frame(self,height=500,bg='#f1dead')
self.bottomFrame.pack(fill=X)
#heading
self.heading = Label(self.top, text='Player Analysis', font='arial 25 bold',
fg='#000000', bg='white')
self.heading.place(x=230, y=60)
#buttons
graph_button = Button(self.bottomFrame,text=' Graph ',
font='arial 14 bold',command = self.plot)
graph_button.place(x=10,y=380)
exit_button = Button(self.bottomFrame,text=' Exit ',
font='arial 14 bold',command = self.destroy)
exit_button.place(x=10,y=440)
# this is the part where I implement the scatter plot
def plot():
# Draw Seaborn Scatter Plot to find location between lat and long
scatter = self.sns.scatterplot(x = players_df["longitude"], y = players_df["latitude"], hue = players_df["Player"])
I recently learned that tk can import PIL images. I needed to convert an numpy array with raw RGB data to tk and the advice was to use PIL.fromarray() to create a PIL image, then use ImageTk.PhotoImage() to import the PIL image into tk. I hope this information is useful to you.

How to display a pandas datafarme in tkinter

I created a pandas dataframe from a csv file in python. How do I display this dataframe in a tkinter window.
import pandas as pd
methods = pd.read_csv('metode.csv')
methods = methods.drop(methods.columns[[0]], axis=1)
Here an example of creating a csv file with square roots; reading the the csv and plotting it in tkinter. To capture the matplotlib figure you have to use FigureCanvasTkAgg and link the mpl plot with the tkinter figure with ax=tk_ax as in the below example.
import pandas as pd
import tkinter as tk
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
# create the csv file with square roots
squareroots = [(i, i**0.5) for i in range(0, 100)]
squareroot_df = pd.DataFrame(squareroots, columns=['i', 'i^0.5'])
squareroot_df.to_csv('temp_squareroots.csv', index=False)
# set up the tkinter GUI
root = tk.Tk()
fig, tk_ax = plt.subplots(figsize=(10, 10))
mpl_plot = FigureCanvasTkAgg(fig, root)
mpl_plot.get_tk_widget().pack()
# read the csv file
square_roots_df = pd.read_csv('temp_squareroots.csv')
# plot the values in the data frame and invert the x-axis
mpl_ax = square_roots_df.plot(x='i', y='i^0.5', color='firebrick', ax=tk_ax)
mpl_ax.invert_xaxis()
root.mainloop()
In any case it is just a lot easier to just plot in matplotlib:
import pandas as pd
import matplotlib.pyplot as plt
squareroots = [(i, i**0.5) for i in range(0, 100)]
squareroot_df = pd.DataFrame(squareroots, columns=['i', 'i^0.5'])
squareroot_df.to_csv('temp_squareroots.csv', index=False)
square_roots_df = pd.read_csv('temp_squareroots.csv')
ax = square_roots_df.plot(x='i', y='i^0.5', color='firebrick')
ax.invert_xaxis()
plt.show()
Note I added mpl_ax.invert_xaxis() just to show you can adjust your plot manipulating the mpl_ax object. (see Matplotlib documentation)

Matplotlib shows no reading if the tick labels get modified

I expect to hover my mouse over the plot and get clean data reading on the right side of the navigation bar in the automatically-generated plot window.
In my case (see code at the bottom), however, if I turn the y-axis tick labels into decibel, the y-reading in the navigation bar (bottom right corner) will disappear, like this:
Workaround: If you comment out the #PROBLEM code block in the code below, then the y-reading in the bottom right corner will be visible, like this:
The code I used to pack the widgets:
from os.path import abspath, dirname, join
import tkinter as tk
import numpy as np
import matplotlib
matplotlib.use("TkAgg")
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2Tk as NavigationToolbar
from scipy.io import wavfile
root = tk.Tk()
mainframe = tk.Frame(root)
mainframe.pack()
frame = tk.Frame(mainframe)
frame.pack()
figFrame = tk.Frame(frame)
toolFrame = tk.Frame(frame)
figFrame.pack(side='top', fill='both', expand=True)
toolFrame.pack(side='top', fill='both', expand=True)
# Place the figure
fig = plt.Figure()
figWidget = FigureCanvasTkAgg(fig, master=figFrame)
track = figWidget.get_tk_widget()
track.pack(side='top', fill='both', expand=True)
# Place the toolbar
toolbar = NavigationToolbar(figWidget, toolFrame)
toolbar.pack(side='top', fill='both', expand=True)
# Get data
SR, signal = wavfile.read(join(abspath(dirname(__file__)), 'y.wav'))
# Plot the signal read from wav file
ax = fig.add_subplot(111)
ax.set_title('Waveform and Spectrogram of a wav file')
ax.plot(signal)
ax.set_xlabel('Sample')
ax.set_ylabel('Amplitude')
# PROBLEM: Truncated y-readings in Toolbar
ax.set_ylabel('Amplitude (dB)')
ticks = ax.get_yticks()
t1 = 20*np.log10(-ticks[(ticks < 0)])
t2 = 20*np.log10(ticks[(ticks > 0)])
t1 = [float('{:.1f}'.format(i)) for i in t1]
t2 = [float('{:.1f}'.format(i)) for i in t2]
ticks = np.concatenate((t1, [-np.inf], t2))
ax.set_yticklabels(ticks)
# PROBLEM: END
plt.show()
root.mainloop()
I wonder where I did wrong. My guess is that when the ticks are hacked (my way), then there will be no reading at all.... If so, then that's a pity, because I only modified the ticks not the data.
It's clear that no useful y coordinate can be shown when you set the ticklabels manually; maybe that becomes clearer if you consider that you could have labelled the plot with "Apple", "Banana", "Cherry" - in that case what would the coordinate be when the mouse is halfway between "Banana" and "Cherry"?
You may however use a FuncFormatter to set the format of the tickslabels.
import matplotlib.pyplot as plt
from matplotlib.ticker import FuncFormatter
import numpy as np
signal = np.sin(np.linspace(0,12,300))*.7
fig, ax = plt.subplots()
ax.set_title('Waveform and Spectrogram of a wav file')
ax.plot(signal)
ax.set_xlabel('Sample')
ax.set_ylabel('Amplitude (dB)')
def fmt(x,pos=None):
if x==0:
return "-inf"
else:
return '{:.1f}'.format(20*np.log10(np.sign(x)*x))
ax.yaxis.set_major_formatter(FuncFormatter(fmt))
plt.show()

Embedding matplotlib into tkinter canvas opens two windows

The following code I am working on in not behaving the way I wish it to. I have embedded a matplotlib graph into a tkinter canvas. The program opens up two windows, one of which functions properly, and one of which is not necessary.I am not sure how to fix this. Here is the code, please ignore the unnecessary imports :)
import numpy as np
import sys
import matplotlib.pyplot as plt
import matplotlib.animation as animation
import matplotlib as mpl
from matplotlib import cm
from numpy.random import random
from matplotlib.widgets import Button
import matplotlib.colors
import tkinter as tk
import matplotlib.backends.tkagg as tkagg
from matplotlib.backends.backend_agg import FigureCanvasAgg
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
DEBUG_MODE = False #Debug mode - True = ON
MATRIX_WIDTH = 50
MATRIX_HEIGHT = 50
WINDOW_WIDTH = 800
WINDOW_HEIGHT = 600
LED_COUNT = MATRIX_WIDTH * MATRIX_HEIGHT
REFRESH_RATE = 30 #REFRESH_RATE used to control FuncAnimation interval
MATRIX = random((50,50)) #Fills MATRIX as not to be null for first print
plt.rcParams['toolbar'] = 'None' #Disables matplotlib toolbar
fig = plt.figure(figsize=(3,3)) #'figsize' measured in inches
im = plt.imshow(MATRIX, interpolation='nearest', cmap=cm.Spectral)
plt.axis('off') #Turns off x, y axis
def data_gen(): #Generates amd populates MATRIX with pattern data
while True:
MATRIX = random((MATRIX_WIDTH, MATRIX_HEIGHT))
yield MATRIX
if (DEBUG_MODE): print("MATRIX yeilded")
def update(data): #Updates/prints new MATRIX from data_gen()
im.set_array(data)
if (DEBUG_MODE): print("Updated data")
root = tk.Tk()
label = tk.Label(root,text="Matrix Program").grid(column=0, row=0)
canvas = FigureCanvasTkAgg(fig, master=root)
canvas.get_tk_widget().grid(column=0,row=1)
ani = animation.FuncAnimation(fig, update, data_gen, interval=REFRESH_RATE)
plt.show()
What needs to be done to this code so that it opens only one canvas from tkinter with the live matplotlib graph embedded?
How can I set the size of the canvas?
Do not call plt.show() if you want to show your figure inside a tk GUI. Best do not use pyplot at all when embedding.
On the other hand, you probably want to start the mainloop, tk.mainloop(), at some point.
Refer to the matplotlib example on how to embedd a matplotlib figure into tk.

Python: Embed pandas plot in Tkinter GUI

I'm writing an application using pandas DataFrames in Python 2.7. I need to plot columns of my DataFrames to a Tkinter window. I know that I can plot pandas DataFrames columns using the built-in plot method on the DataFrame or Series (that is just a wrapper of the matplotlib plot function), like so:
import pandas as pd
df = pd.DataFrame({'one':[2,4,6,8], 'two':[3,5,7,9]})
df.plot('one')
Also, I figured out how to plot to a Tkinter GUI window using matplotlib:
import matplotlib
matplotlib.use('TkAgg')
from numpy import arange, sin, pi
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure
import pandas as pd
import Tkinter as tk
import ttk
root = tk.Tk()
#-------------------------------------------------------------------------------
lf = ttk.Labelframe(root, text='Plot Area')
lf.grid(row=0, column=0, sticky='nwes', padx=3, pady=3)
f = Figure(figsize=(5,4), dpi=100)
a = f.add_subplot(111)
t = arange(0.0,3.0,0.01)
s = sin(2*pi*t)
a.plot(t,s)
dataPlot = FigureCanvasTkAgg(f, master=lf)
dataPlot.show()
dataPlot.get_tk_widget().grid(row=0, column=0)
#-------------------------------------------------------------------------------
root.mainloop()
This all works as expected. What I want to do is have the pandas.DataFrame.plot() output on a Tkinter window, e.g. in the Labelframe as above. I can't get this to work. If possible, I do not want to use matplotlibs plot tools, as the pandas plot tools suit my needs much better. Is there a way to combine pandas plot() with Tkinter? Basically instead of this line:
dataPlot = FigureCanvasTkAgg(f, master=lf)
dataPlot.show()
I need this:
dataPlot = FigureCanvasTkAgg(df.plot('one'), master=lf)
dataPlot.show()
pandas uses matplotlib for plotting. Most pandas plotting functionality takes an ax kwarg that specifies the axes object that will be used. There are a few pandas functions that can't be used this way, and will always create their own figure/axes using pyplot. (e.g. scatter_matrix)
For a simple case based on your example, however:
import matplotlib
import numpy as np
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure
import pandas as pd
import Tkinter as tk
import ttk
root = tk.Tk()
lf = ttk.Labelframe(root, text='Plot Area')
lf.grid(row=0, column=0, sticky='nwes', padx=3, pady=3)
t = np.arange(0.0,3.0,0.01)
df = pd.DataFrame({'t':t, 's':np.sin(2*np.pi*t)})
fig = Figure(figsize=(5,4), dpi=100)
ax = fig.add_subplot(111)
df.plot(x='t', y='s', ax=ax)
canvas = FigureCanvasTkAgg(fig, master=lf)
canvas.show()
canvas.get_tk_widget().grid(row=0, column=0)
root.mainloop()

Categories

Resources