The question:
I'm trying to grasp the concept of monkey patching and at the same time make a function to produce the perfect time-series plot. How can I include the following matplotlib functionality in pandas pandas.DataFrame.plot()?
ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)
ax.spines['bottom'].set_visible(False)
ax.spines['left'].set_visible(False)
complete code at the end of the question
The details:
I think the default settings in df.plot()
is pretty neat, especially if you're running a Jupyter Notebook with a dark theme like chesterish from dunovank:
And I'd like to use it for as much of my data analysis workflow as possible, but I'd really like to remove the frame (or what's called spines) like this:
Arguably, this is a perfect time-series plot. But df.plot()
doesn't have a built-in argument for this. The closest thing seems to be grid = False
, but that takes away the whole grid in the same run:
What I've tried
I know I can wrap the spine
snippet in a function along with df.plot()
so I end up with this:
Snippet 1:
def plotPerfect(df, spline):
ax = df.plot()
if not spline:
ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)
ax.spines['bottom'].set_visible(False)
ax.spines['left'].set_visible(False)
return(ax)
plotPerfect(df = df, spline = False)
Output 1:
But is that the "best" way to do it with regards to flexibilty and readability for future amendments? Or even the fastest with regards to execution time if we're talking hundreds of plots?
I know how I can get the df.plot()
source, but everything from there leaves me baffled. So how do I include those settings in df.plot
? And perhaps the wrapped function approach is just as good as monkey patching?
Snippet with full code and sample data:
To reproduce the example 100%, paste this into a Jupyter Notebook cell with the chesterish theme
activated:
# imports
import pandas as pd
import numpy as np
from jupyterthemes import jtplot
# Sample data
np.random.seed(123)
rows = 50
dfx = pd.DataFrame(np.random.randint(90,110,size=(rows, 1)), columns=['Variable Y'])
dfy = pd.DataFrame(np.random.randint(25,68,size=(rows, 1)), columns=[' Variable X'])
df = pd.concat([dfx,dfy], axis = 1)
jtplot.style()
# Plot with default settings
df.plot()
# Wrap df.plot() and matplotlib spine in a function
def plotPerfect(df, spline):
ax = df.plot()
if not spline:
ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)
ax.spines['bottom'].set_visible(False)
ax.spines['left'].set_visible(False)
return(ax)
# Plot the perfect time-series plot
plotPerfect(df = df, spline = False)
Using plt. gca(). legend_. remove() after the call to parallel_coordinates successfully turned off the legend.
To hide or remove X-axis labels, use set(xlabel=None). To display the figure, use show() method.
Pandas uses the plot() method to create diagrams. We can use Pyplot, a submodule of the Matplotlib library to visualize the diagram on the screen. Read more about Matplotlib in our Matplotlib Tutorial.
This seems like an xyproblem.
The question asks for monkey patching pandas plot function to add additional features. This can in this case be done by replacing the pandas.plotting._core.plot_frame
function with a custom version of it.
import pandas as pd
import pandas.plotting._core
orginal = pandas.plotting._core.plot_frame
def myplot(*args, **kwargs):
spline = kwargs.pop("spline", True)
ax = orginal(*args, **kwargs)
ax.set_frame_on(spline)
ax.grid(not spline)
ax.tick_params(left=spline, bottom=spline)
return ax
pandas.plotting._core.plot_frame = myplot
Then use it as
df = pd.DataFrame([[0.1, 0.1], [0.9, 0.9]]).set_index(0)
df.plot() ## Normal Plot
df.plot(spline=False) ## "Despined" Plot
Note that if in jupyter notebook, the cell with the monkey patching cannot be run more than once, else it would end up in recursion.
The above is pretty overkill for changing the style of a plot. One should rather use the style options of matplotlib.
mystyle = {"axes.spines.left" : False,
"axes.spines.right" : False,
"axes.spines.bottom" : False,
"axes.spines.top" : False,
"axes.grid" : True,
"xtick.bottom" : False,
"ytick.left" : False,}
Then to apply this for some plots in the notebook, use the plt.style.context
manager,
import pandas as pd
import matplotlib.pyplot as plt
df = pd.DataFrame([[0.1, 0.1], [0.9, 0.9]]).set_index(0)
df.plot() ## Normal Plot
with plt.style.context(mystyle):
df.plot() ## "Despined" Plot
Or, if you want to apply this style globally, update the rcParams
.
plt.rcParams.update(mystyle)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With