Monkey 修补 pandas 和 matplotlib 以移除 df.plot() 的脊椎
Monkey patching pandas and matplotlib to remove spines for df.plot()
问题:
我正在尝试掌握 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
详情:
我认为 df.plot()
中的默认设置非常简洁,特别是如果您 运行 正在使用深色主题的 Jupyter Notebook,例如来自 dunovank 的 chesterish:
我想尽可能多地将它用于我的数据分析工作流程,但我真的很想像这样删除框架(或所谓的脊柱):
可以说,这是一个完美的时间序列图。但是 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)
输出 1:
但是,就未来修订的灵活性和可读性而言,这是 "best" 的做法吗?如果我们谈论数百个地块,甚至是执行时间最快的?
我知道如何获得 df.plot()
source,但从那里得到的一切让我感到困惑。那么 do 如何将这些设置包含在 df.plot
中?也许包装函数方法和猴子修补一样好?
包含完整代码和示例数据的代码段:
要 100% 重现示例,请将其粘贴到已激活 chesterish theme
的 Jupyter Notebook 单元格中:
# 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)
我会部分回答问题的自定义部分:不是通过单独的命令隐藏每个样条曲线,而是可以将它们放在 for
循环中,如下所示。
def plotPerfect(df, spline):
ax = df.plot()
if not spline:
for i in ['top', 'right', 'bottom', 'left']:
ax.spines[i].set_visible(False)
return(ax)
# Plot the perfect time-series plot
plotPerfect(df = df, spline = False)
如果您想隐藏所有四个书脊并且不想手动指定顶部、右侧等,您可以按如下所示以更自动化的方式进行。第一个允许您选择隐藏哪些。
def plotPerfect(df, spline):
ax = df.plot()
if not spline:
for i in ax.spines.values():
i.set_visible(False)
return(ax)
另一个答案的替代解决方案是使用 plt.box(False)
or ax.set_frame_on(False)
,这两个都隐藏了轴矩形补丁。
def plotPerfect(df, spline):
ax = df.plot()
if not spline:
ax.set_frame_on(False)
# plt.box(False) # another possible option
return ax
请注意,set_frame_on(False)
删除了背景使其透明,这可能不是我们想要的
这似乎是 xyproblem。
猴子修补(Y)
问题要求猴子修补 pandas plot 功能以添加额外的功能。在这种情况下,这可以通过用它的自定义版本替换 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
然后用作
df = pd.DataFrame([[0.1, 0.1], [0.9, 0.9]]).set_index(0)
df.plot() ## Normal Plot
df.plot(spline=False) ## "Despined" Plot
注意,如果在jupyter notebook中,带有猴子补丁的单元格不能运行多次,否则它会以递归结束。
造型(X)
以上对于改变情节的风格来说是相当矫枉过正的。人们应该使用 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,}
然后将其应用于笔记本中的一些图,使用 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
或者,如果您想全局应用此样式,请更新 rcParams
。
plt.rcParams.update(mystyle)
问题:
我正在尝试掌握 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
详情:
我认为 df.plot()
中的默认设置非常简洁,特别是如果您 运行 正在使用深色主题的 Jupyter Notebook,例如来自 dunovank 的 chesterish:
我想尽可能多地将它用于我的数据分析工作流程,但我真的很想像这样删除框架(或所谓的脊柱):
可以说,这是一个完美的时间序列图。但是 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)
输出 1:
但是,就未来修订的灵活性和可读性而言,这是 "best" 的做法吗?如果我们谈论数百个地块,甚至是执行时间最快的?
我知道如何获得 df.plot()
source,但从那里得到的一切让我感到困惑。那么 do 如何将这些设置包含在 df.plot
中?也许包装函数方法和猴子修补一样好?
包含完整代码和示例数据的代码段:
要 100% 重现示例,请将其粘贴到已激活 chesterish theme
的 Jupyter Notebook 单元格中:
# 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)
我会部分回答问题的自定义部分:不是通过单独的命令隐藏每个样条曲线,而是可以将它们放在 for
循环中,如下所示。
def plotPerfect(df, spline):
ax = df.plot()
if not spline:
for i in ['top', 'right', 'bottom', 'left']:
ax.spines[i].set_visible(False)
return(ax)
# Plot the perfect time-series plot
plotPerfect(df = df, spline = False)
如果您想隐藏所有四个书脊并且不想手动指定顶部、右侧等,您可以按如下所示以更自动化的方式进行。第一个允许您选择隐藏哪些。
def plotPerfect(df, spline):
ax = df.plot()
if not spline:
for i in ax.spines.values():
i.set_visible(False)
return(ax)
另一个答案的替代解决方案是使用 plt.box(False)
or ax.set_frame_on(False)
,这两个都隐藏了轴矩形补丁。
def plotPerfect(df, spline):
ax = df.plot()
if not spline:
ax.set_frame_on(False)
# plt.box(False) # another possible option
return ax
请注意,set_frame_on(False)
删除了背景使其透明,这可能不是我们想要的
这似乎是 xyproblem。
猴子修补(Y)
问题要求猴子修补 pandas plot 功能以添加额外的功能。在这种情况下,这可以通过用它的自定义版本替换 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
然后用作
df = pd.DataFrame([[0.1, 0.1], [0.9, 0.9]]).set_index(0)
df.plot() ## Normal Plot
df.plot(spline=False) ## "Despined" Plot
注意,如果在jupyter notebook中,带有猴子补丁的单元格不能运行多次,否则它会以递归结束。
造型(X)
以上对于改变情节的风格来说是相当矫枉过正的。人们应该使用 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,}
然后将其应用于笔记本中的一些图,使用 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
或者,如果您想全局应用此样式,请更新 rcParams
。
plt.rcParams.update(mystyle)