I have functions or methods in a class that produce plots with matplotlib. I would like to use that functions in various contexts. I never can be sure about what the function is supposed to return. I will be use that function essentially in jupyter notebooks but also in widgets or qt app for example.
Here is a minimal example:
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
# some interesting data
df = pd.DataFrame({c: np.random.randn(10) for c in "ABC"})
Here is the function. I used to use as optional argument the matplotlib axes and I return it. But sometimes (like in the example) I have a twin axes or other things and thus returning only one axes is strange and I return the whole figure object.
def make_fake_plot(
df: pd.DataFrame,
col_x: str,
col_y: str,
show_mean: bool = True,
ax: plt.Axes = None
):
""" make a plot
Args:
df (pd.DataFrame): The data
col_x (str): name of col for x
col_y (str): name of col for y
show_mean (bool): an option
ax (plt.Axes): axes on which make the plot
"""
if ax is None:
fig, ax = plt.subplots()
# What is best here ?
# ax = plt.subplot(1, 1, 1)
ax = df.plot.scatter(x=col_x, y=col_y, marker="d", s=20, ax=ax)
if show_mean:
ax2 = ax.twiny()
ax2.set_xlim(ax.get_xlim())
mu = df[col_x].mean()
ax2.axvline(mu, color="C3")
ax2.set_xticks([mu])
ax2.set_xticklabels(["mean"])
# is something is supposed to be returned ??
# return ax
# return fig
# return fig, ax
# nothing ??
This function work quite well in a jupyter notebook. I can even put the plots in subplots while the function does not return anything (that is a point also I do not undersdant).
And here is an example using that function in widgets. But here it dos not work, the plot is not updated. The problem is that if I return something from the function, in the notebook, sometimes figures appear two times, and in the widget, instead of update the figure, the plots stack again and again one below the previous one.
import ipywidgets as ipw
from IPython.display import display
def show_nice_app(dataset):
output = ipw.Output()
dropdown_xcol = ipw.Dropdown(
options=dataset.columns,
value=dataset.columns[0],
description='X col:')
dropdown_ycol = ipw.Dropdown(
options=dataset.columns,
value=dataset.columns[1],
description='Y col:')
def dropdown_xcol_eventhandler(change):
with output:
output.clear_output(wait=True)
make_fake_plot(dataset, col_x=change.new, col_y=dropdown_ycol.value)
# display(fig)
def dropdown_ycol_eventhandler(change):
with output:
output.clear_output(wait=True)
make_fake_plot(dataset, col_x=dropdown_xcol.value, col_y=change.new)
# display(fig)
dropdown_xcol.observe(dropdown_xcol_eventhandler, names='value')
dropdown_ycol.observe(dropdown_ycol_eventhandler, names='value')
input_widgets = ipw.HBox([dropdown_xcol, dropdown_ycol])
all_widgets = ipw.VBox([input_widgets, output])
display(all_widgets)
with output:
output.clear_output(wait=True)
make_fake_plot(dataset, col_x=dropdown_xcol.value, col_y=dropdown_ycol.value)
At the end, these functions (widget and plots functions) are not supposed to be in the notebook. They are supposed to be in a library (in classes or simply in module) which will be imported in the notebook.