猴子修补pandas和matplotlib去除df.plot()的刺

ves*_*and 7 python monkeypatching matplotlib pandas

问题:

我正在尝试掌握猴子修补的概念,同时创建一个函数来生成完美的时间序列图.如何在pandas pandas.DataFrame.plot()中包含以下matplotlib功能?

ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)
ax.spines['bottom'].set_visible(False)
ax.spines['left'].set_visible(False)
Run Code Online (Sandbox Code Playgroud)

complete code at the end of the question


细节:


我认为默认设置df.plot()非常简洁,特别是如果你正在运行一个黑暗主题的Jupyter笔记本,比如来自dunovank的chesterish:

df.plot默认

我想尽可能多地使用它来处理我的数据分析工作流程,但我真的想要删除框架(或者所谓的刺)这样:

df.plot没有帧

可以说,这是一个完美的时间序列图.但是df.plot()没有内置的论据.最接近的似乎是grid = False,但这会在同一次运行中夺走整个网格:

在此输入图像描述


我试过的


我知道我可以将spine片段包装在一个函数中,df.plot()所以我最终得到了这个:

小片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)
Run Code Online (Sandbox Code Playgroud)

输出1:

在此输入图像描述

但就未来修正的灵活性和可读性而言,这是"最好的"方式吗?如果我们谈论数百个情节,甚至是关于执行时间最快的?

我知道如何获得df.plot() 消息来源,但是那里的一切让我感到困惑.那么,如何我包括这些设置df.plot?也许包裹的函数方法和猴子修补一样好?


包含完整代码和示例数据的代码段:


要重现100%的示例,请将其粘贴到Jupyter Notebook单元格中并chesterish theme激活:

# 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)
Run Code Online (Sandbox Code Playgroud)

Imp*_*est 2

这似乎是一个xy问题

猴子修补(Y)

该问题要求猴子修补 pandas 绘图功能以添加附加功能。pandas.plotting._core.plot_frame在这种情况下,可以通过用其自定义版本替换该函数来完成。

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
Run Code Online (Sandbox Code Playgroud)

然后将其用作

df = pd.DataFrame([[0.1, 0.1], [0.9, 0.9]]).set_index(0)
df.plot()             ## Normal Plot
df.plot(spline=False) ## "Despined" Plot 
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

请注意,如果在 Jupyter Notebook 中,带有猴子补丁的单元不能运行多次,否则最终会导致递归。

造型(X)

上面的内容对于改变情节风格来说是相当过分的。人们应该使用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,}
Run Code Online (Sandbox Code Playgroud)

然后要将其应用于笔记本中的某些绘图,请使用plt.style.context管理器,

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 
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

或者,如果您想全局应用此样式,请更新rcParams.

plt.rcParams.update(mystyle)
Run Code Online (Sandbox Code Playgroud)