Pandas 2.2 中文官方教程和指南(十八)(3)https://developer.aliyun.com/article/1509793
绘图工具
这些函数可以从 pandas.plotting
中导入,并以 Series
或 DataFrame
作为参数。
散点矩阵图
您可以使用 pandas.plotting
中的 scatter_matrix
方法创建散点图矩阵:
In [92]: from pandas.plotting import scatter_matrix In [93]: df = pd.DataFrame(np.random.randn(1000, 4), columns=["a", "b", "c", "d"]) In [94]: scatter_matrix(df, alpha=0.2, figsize=(6, 6), diagonal="kde");
### 密度图
您可以使用 Series.plot.kde()
和 DataFrame.plot.kde()
方法创建密度图。
In [95]: ser = pd.Series(np.random.randn(1000)) In [96]: ser.plot.kde();
### 安德鲁斯曲线
Andrews 曲线允许将多变量数据绘制为大量曲线,这些曲线是使用样本属性作为傅立叶级数系数创建的,有关更多信息,请参阅Wikipedia 条目。通过为每个类别的曲线着不同颜色,可以可视化数据聚类。同一类别样本的曲线通常会更接近并形成更大的结构。
注意: “鸢尾花”数据集可在此处获取。
In [97]: from pandas.plotting import andrews_curves In [98]: data = pd.read_csv("data/iris.data") In [99]: plt.figure(); In [100]: andrews_curves(data, "Name");
### 平行坐标
平行坐标是一种用于绘制多变量数据的绘图技术,有关简介,请参阅Wikipedia 条目。平行坐标允许查看数据中的聚类并通过视觉估计其他统计量。使用平行坐标,点被表示为连接的线段。每条垂直线代表一个属性。一组连接的线段代表一个数据点。倾向于聚类的点将更接近。
In [101]: from pandas.plotting import parallel_coordinates In [102]: data = pd.read_csv("data/iris.data") In [103]: plt.figure(); In [104]: parallel_coordinates(data, "Name");
### 滞后图
滞后图用于检查数据集或时间序列是否随机。随机数据在滞后图中不应展现任何结构。非随机结构意味着底层数据不是随机的。可以传递lag
参数,当lag=1
时,图基本上是data[:-1]
vs. data[1:]
。
In [105]: from pandas.plotting import lag_plot In [106]: plt.figure(); In [107]: spacing = np.linspace(-99 * np.pi, 99 * np.pi, num=1000) In [108]: data = pd.Series(0.1 * np.random.rand(1000) + 0.9 * np.sin(spacing)) In [109]: lag_plot(data);
### 自相关图
自相关图通常用于检查时间序列中的随机性。这是通过计算不同时间滞后的数据值的自相关来实现的。如果时间序列是随机的,这些自相关应该在任何时间滞后分离上接近零。如果时间序列是非随机的,那么一个或多个自相关将显着非零。图中显示的水平线对应于 95%和 99%的置信区间。虚线是 99%的置信区间。有关自相关图的更多信息,请参阅Wikipedia 条目。
In [110]: from pandas.plotting import autocorrelation_plot In [111]: plt.figure(); In [112]: spacing = np.linspace(-9 * np.pi, 9 * np.pi, num=1000) In [113]: data = pd.Series(0.7 * np.random.rand(1000) + 0.3 * np.sin(spacing)) In [114]: autocorrelation_plot(data);
### 自举图
自举图用于直观评估统计量(如均值、中位数、中程等)的不确定性。从数据集中选择指定大小的随机子集,为该子集计算所需的统计量,并重复指定次数。生成的图和直方图构成了自举图。
In [115]: from pandas.plotting import bootstrap_plot In [116]: data = pd.Series(np.random.rand(1000)) In [117]: bootstrap_plot(data, size=50, samples=500, color="grey");
### RadViz
RadViz 是一种可视化多变量数据的方式。 它基于一种简单的弹簧张力最小化算法。 基本上,您在平面上设置一堆点。 在我们的案例中,它们在一个单位圆上等间距。 每个点表示一个单一属性。 然后,您假装数据集中的每个样本都通过弹簧连接到这些点,其中弹簧的刚度与该属性的数值成比例(它们被归一化为单位间隔)。 平面上我们的样本沉降到的点(作用于我们的样本的力处于平衡状态的地方)是我们的样本将被绘制的点。 根据该样本属于哪个类别,它将以不同的颜色着色。 有关更多信息,请参见 R 包Radviz。
注意: “鸢尾花”数据集可在此处找到。
In [118]: from pandas.plotting import radviz In [119]: data = pd.read_csv("data/iris.data") In [120]: plt.figure(); In [121]: radviz(data, "Name");
### 散点矩阵图
您可以使用pandas.plotting
中的scatter_matrix
方法创建散点图矩阵:
In [92]: from pandas.plotting import scatter_matrix In [93]: df = pd.DataFrame(np.random.randn(1000, 4), columns=["a", "b", "c", "d"]) In [94]: scatter_matrix(df, alpha=0.2, figsize=(6, 6), diagonal="kde");
### 密度图
您可以使用Series.plot.kde()
和DataFrame.plot.kde()
方法创建密度图。
In [95]: ser = pd.Series(np.random.randn(1000)) In [96]: ser.plot.kde();
### 安德鲁曲线
安德鲁曲线允许将多变量数据绘制为大量曲线,这些曲线是使用样本属性作为傅里叶级数的系数创建的,请参阅Wikipedia 词条获取更多信息。 通过为每个类别的曲线着色,可以可视化数据聚类。 属于相同类别样本的曲线通常会更接近并形成较大的结构。
注意: “鸢尾花”数据集可在此处找到。
In [97]: from pandas.plotting import andrews_curves In [98]: data = pd.read_csv("data/iris.data") In [99]: plt.figure(); In [100]: andrews_curves(data, "Name");
### 平行坐标
平行坐标是一种绘制多变量数据的绘图技术,请参阅Wikipedia 词条进行介绍。 平行坐标允许人们看到数据中的聚类并通过视觉估计其他统计数据。 使用平行坐标,点被表示为连接的线段。 每条垂直线代表一个属性。 一组连接的线段代表一个数据点。 倾向于聚类的点将出现在更接近的位置。
In [101]: from pandas.plotting import parallel_coordinates In [102]: data = pd.read_csv("data/iris.data") In [103]: plt.figure(); In [104]: parallel_coordinates(data, "Name");
### 滞后图
Lag plots 用于检查数据集或时间序列是否是随机的。随机数据不应在滞后图中展现任何结构。非随机结构意味着底层数据不是随机的。可以传递 lag
参数,当 lag=1
时,图基本上是 data[:-1]
对 data[1:]
。
In [105]: from pandas.plotting import lag_plot In [106]: plt.figure(); In [107]: spacing = np.linspace(-99 * np.pi, 99 * np.pi, num=1000) In [108]: data = pd.Series(0.1 * np.random.rand(1000) + 0.9 * np.sin(spacing)) In [109]: lag_plot(data);
### Autocorrelation plot
Autocorrelation plots 经常用于检查时间序列的随机性。这是通过计算不同时间滞后的数据值的自相关来完成的。如果时间序列是随机的,这样的自相关应该在任何时间滞后分隔上都接近零。如果时间序列是非随机的,则一个或多个自相关将显着非零。图中显示的水平线对应于 95% 和 99% 的置信区间。虚线是 99% 置信区间。参见 Wikipedia 条目 获取有关自相关图的更多信息。
In [110]: from pandas.plotting import autocorrelation_plot In [111]: plt.figure(); In [112]: spacing = np.linspace(-9 * np.pi, 9 * np.pi, num=1000) In [113]: data = pd.Series(0.7 * np.random.rand(1000) + 0.3 * np.sin(spacing)) In [114]: autocorrelation_plot(data);
### Bootstrap plot
Bootstrap plots 用于直观评估统计量(如均值、中位数、中间范围等)的不确定性。从数据集中选择指定大小的随机子集,计算这个子集的统计量,然后重复这个过程指定次数。生成的图和直方图构成了 Bootstrap plot。
In [115]: from pandas.plotting import bootstrap_plot In [116]: data = pd.Series(np.random.rand(1000)) In [117]: bootstrap_plot(data, size=50, samples=500, color="grey");
### RadViz
RadViz 是一种可视化多变量数据的方式。它基于简单的弹簧张力最小化算法。基本上,你在平面上设置了一堆点。在我们的案例中,它们在单位圆上等距分布。每个点代表一个单一的属性。然后,你假装数据集中的每个样本都通过弹簧与这些点之一相连,弹簧的刚度与该属性的数值成比例(它们被归一化为单位间隔)。平面上我们的样本停留的点(作用于我们的样本的力处于平衡状态的点)就是我们的样本将被绘制的点。取决于该样本属于哪个类,它将以不同的颜色着色。查看 R 包 Radviz 以获取更多信息。
注意: “鸢尾花”数据集可在此处获取。
In [118]: from pandas.plotting import radviz In [119]: data = pd.read_csv("data/iris.data") In [120]: plt.figure(); In [121]: radviz(data, "Name");
## Plot formatting
设置图样式
从 1.5 版本开始,matplotlib 提供了一系列预配置的绘图样式。设置样式可用于轻松地给出所需的一般外观。设置样式就像在创建绘图之前调用matplotlib.style.use(my_plot_style)
一样简单。例如,您可以写matplotlib.style.use('ggplot')
以获得 ggplot 风格的绘图。
你可以在matplotlib.style.available
中看到各种可用的样式名称,很容易尝试它们。
一般绘图样式参数
大多数绘图方法都有一组关键字参数,用于控制返回图的布局和格式:
In [122]: plt.figure(); In [123]: ts.plot(style="k--", label="Series");
对于每种类型的绘图(例如line
,bar
,scatter
),任何额外的参数关键字都会传递给相应的 matplotlib 函数(ax.plot()
, ax.bar()
, ax.scatter()
). 这些可以用于控制额外的样式,超出 pandas 提供的范围。
控制图例
您可以将legend
参数设置为False
以隐藏默认显示的图例。
In [124]: df = pd.DataFrame(np.random.randn(1000, 4), index=ts.index, columns=list("ABCD")) In [125]: df = df.cumsum() In [126]: df.plot(legend=False);
控制标签
您可以设置xlabel
和ylabel
参数,为 x 和 y 轴提供自定义标签。默认情况下,pandas 将选择索引名称作为 xlabel,同时将其留空作为 ylabel。
In [127]: df.plot(); In [128]: df.plot(xlabel="new x", ylabel="new y");
刻度
您可以传递logy
以获得对数刻度 Y 轴。
In [129]: ts = pd.Series(np.random.randn(1000), index=pd.date_range("1/1/2000", periods=1000)) In [130]: ts = np.exp(ts.cumsum()) In [131]: ts.plot(logy=True);
另请参阅logx
和loglog
关键字参数。
在第二个 y 轴上绘图
要在第二个 y 轴上绘制数据,请使用secondary_y
关键字:
In [132]: df["A"].plot(); In [133]: df["B"].plot(secondary_y=True, style="g");
要在DataFrame
中绘制一些列,请将列名提供给secondary_y
关键字:
In [134]: plt.figure(); In [135]: ax = df.plot(secondary_y=["A", "B"]) In [136]: ax.set_ylabel("CD scale"); In [137]: ax.right_ax.set_ylabel("AB scale");
请注意,在第二个 y 轴上绘制的列会自动在图例中标记为“(right)”。要关闭自动标记,请使用mark_right=False
关键字:
In [138]: plt.figure(); In [139]: df.plot(secondary_y=["A", "B"], mark_right=False);
### 时间序列绘图的自定义格式化程序
pandas 为时间序列图提供自定义格式化程序。这些更改日期和时间的轴标签格式。默认情况下,自定义格式化程序仅应用于由 pandas 使用DataFrame.plot()
或Series.plot()
创建的图。要使它们应用于所有图,包括由 matplotlib 创建的图,请设置选项pd.options.plotting.matplotlib.register_converters = True
或使用pandas.plotting.register_matplotlib_converters()
。
抑制刻度分辨率调整
pandas 包括对常规频率时间序列数据的自动刻度分辨率调整。对于 pandas 无法推断频率信息的有限情况(例如,在外部创建的twinx
中),您可以选择抑制此行为以进行对齐。
这是默认行为,请注意 x 轴刻度标签的处理方式:
In [140]: plt.figure(); In [141]: df["A"].plot();
使用x_compat
参数,可以抑制这种行为:
In [142]: plt.figure(); In [143]: df["A"].plot(x_compat=True);
如果有多个需要抑制的图,可以在pandas.plotting.plot_params
中使用use
方法,并在with
语句中使用:
In [144]: plt.figure(); In [145]: with pd.plotting.plot_params.use("x_compat", True): .....: df["A"].plot(color="r") .....: df["B"].plot(color="g") .....: df["C"].plot(color="b") .....:
自动日期刻度调整
TimedeltaIndex
现在使用本机 matplotlib 刻度定位器方法,对于刻度标签重叠的图形,调用 matplotlib 的自动日期刻度调整非常有用。
查看autofmt_xdate
方法和matplotlib 文档以获取更多信息。
子图
DataFrame
中的每个Series
可以使用subplots
关键字在不同的轴上绘制:
In [146]: df.plot(subplots=True, figsize=(6, 6));
使用布局和定位多个轴
子图的布局可以由layout
关键字指定。它可以接受(行数, 列数)
。layout
关键字也可以在hist
和boxplot
中使用。如果输入无效,将引发ValueError
。
由layout
指定的行 x 列中可以包含的轴的数量必须大于所需子图的数量。如果layout
可以包含比所需更多的轴,那么空白轴将不会被绘制。类似于 NumPy 数组的reshape
方法,您可以在一个维度上使用-1
来自动计算所需的行数或列数,给定另一个维度。
In [147]: df.plot(subplots=True, layout=(2, 3), figsize=(6, 6), sharex=False);
上面的示例与使用以下内容相同:
In [148]: df.plot(subplots=True, layout=(2, -1), figsize=(6, 6), sharex=False);
所需的列数(3)是从要绘制的系列数和给定的行数(2)推断出来的。
您可以通过ax
关键字以类似列表的方式传递预先创建的多个轴。这允许更复杂的布局。传递的轴数量必须与正在绘制的子图数量相同。
当通过ax
关键字传递多个轴时,layout
、sharex
和sharey
关键字不会影响输出。您应该明确传递sharex=False
和sharey=False
,否则会看到警告。
In [149]: fig, axes = plt.subplots(4, 4, figsize=(9, 9)) In [150]: plt.subplots_adjust(wspace=0.5, hspace=0.5) In [151]: target1 = [axes[0][0], axes[1][1], axes[2][2], axes[3][3]] In [152]: target2 = [axes[3][0], axes[2][1], axes[1][2], axes[0][3]] In [153]: df.plot(subplots=True, ax=target1, legend=False, sharex=False, sharey=False); In [154]: (-df).plot(subplots=True, ax=target2, legend=False, sharex=False, sharey=False);
另一个选项是将ax
参数传递给Series.plot()
以在特定轴上绘制:
In [155]: np.random.seed(123456) In [156]: ts = pd.Series(np.random.randn(1000), index=pd.date_range("1/1/2000", periods=1000)) In [157]: ts = ts.cumsum() In [158]: df = pd.DataFrame(np.random.randn(1000, 4), index=ts.index, columns=list("ABCD")) In [159]: df = df.cumsum()
In [160]: fig, axes = plt.subplots(nrows=2, ncols=2) In [161]: plt.subplots_adjust(wspace=0.2, hspace=0.5) In [162]: df["A"].plot(ax=axes[0, 0]); In [163]: axes[0, 0].set_title("A"); In [164]: df["B"].plot(ax=axes[0, 1]); In [165]: axes[0, 1].set_title("B"); In [166]: df["C"].plot(ax=axes[1, 0]); In [167]: axes[1, 0].set_title("C"); In [168]: df["D"].plot(ax=axes[1, 1]); In [169]: axes[1, 1].set_title("D");
### 带有误差条的绘图
支持在DataFrame.plot()
和Series.plot()
中绘制带有误差条的图。
水平和垂直误差条可以通过xerr
和yerr
关键字参数提供给plot()
。误差值可以使用各种格式指定:
- 作为一个
DataFrame
或与绘图DataFrame
的columns
属性匹配或与Series
的name
属性匹配的错误dict
。 - 作为一个
str
,指示绘图DataFrame
的哪些列包含错误值。 - 作为原始值(
list
、tuple
或np.ndarray
)。必须与绘图DataFrame
/Series
的长度相同。
这是一个从原始数据轻松绘制组均值和标准差的示例。
# Generate the data In [170]: ix3 = pd.MultiIndex.from_arrays( .....: [ .....: ["a", "a", "a", "a", "a", "b", "b", "b", "b", "b"], .....: ["foo", "foo", "foo", "bar", "bar", "foo", "foo", "bar", "bar", "bar"], .....: ], .....: names=["letter", "word"], .....: ) .....: In [171]: df3 = pd.DataFrame( .....: { .....: "data1": [9, 3, 2, 4, 3, 2, 4, 6, 3, 2], .....: "data2": [9, 6, 5, 7, 5, 4, 5, 6, 5, 1], .....: }, .....: index=ix3, .....: ) .....: # Group by index labels and take the means and standard deviations # for each group In [172]: gp3 = df3.groupby(level=("letter", "word")) In [173]: means = gp3.mean() In [174]: errors = gp3.std() In [175]: means Out[175]: data1 data2 letter word a bar 3.500000 6.000000 foo 4.666667 6.666667 b bar 3.666667 4.000000 foo 3.000000 4.500000 In [176]: errors Out[176]: data1 data2 letter word a bar 0.707107 1.414214 foo 3.785939 2.081666 b bar 2.081666 2.645751 foo 1.414214 0.707107 # Plot In [177]: fig, ax = plt.subplots() In [178]: means.plot.bar(yerr=errors, ax=ax, capsize=4, rot=0);
也支持不对称误差条,但在这种情况下必须提供原始误差值。对于长度为N
的Series
,应提供一个2xN
数组,指示较低和较高(或左侧和右侧)的错误。对于MxN``DataFrame
,不对称误差应该在一个Mx2xN
数组中。
这是一个使用不对称误差条绘制最小/最大范围的示例。
In [179]: mins = gp3.min() In [180]: maxs = gp3.max() # errors should be positive, and defined in the order of lower, upper In [181]: errors = [[means[c] - mins[c], maxs[c] - means[c]] for c in df3.columns] # Plot In [182]: fig, ax = plt.subplots() In [183]: means.plot.bar(yerr=errors, ax=ax, capsize=4, rot=0);
### 绘制表格
现在在DataFrame.plot()
和Series.plot()
中支持使用table
关键字绘制 matplotlib 表格。table
关键字可以接受bool
、DataFrame
或Series
。绘制表格的简单方法是指定table=True
。数据将被转置以符合 matplotlib 的默认布局。
In [184]: np.random.seed(123456) In [185]: fig, ax = plt.subplots(1, 1, figsize=(7, 6.5)) In [186]: df = pd.DataFrame(np.random.rand(5, 3), columns=["a", "b", "c"]) In [187]: ax.xaxis.tick_top() # Display x-axis ticks on top. In [188]: df.plot(table=True, ax=ax);
此外,您可以将不同的DataFrame
或Series
传递给table
关键字。数据将按照打印方法中显示的方式绘制(不会自动转置)。如果需要,可以像下面的示例中所示手动转置。
In [189]: fig, ax = plt.subplots(1, 1, figsize=(7, 6.75)) In [190]: ax.xaxis.tick_top() # Display x-axis ticks on top. In [191]: df.plot(table=np.round(df.T, 2), ax=ax);
还存在一个辅助函数pandas.plotting.table
,它可以从DataFrame
或Series
创建表格,并将其添加到matplotlib.Axes
实例中。此函数可以接受 matplotlib table的关键字。
In [192]: from pandas.plotting import table In [193]: fig, ax = plt.subplots(1, 1) In [194]: table(ax, np.round(df.describe(), 2), loc="upper right", colWidths=[0.2, 0.2, 0.2]); In [195]: df.plot(ax=ax, ylim=(0, 2), legend=None);
注意:您可以使用axes.tables
属性在坐标轴上获取表实例以进行进一步装饰。更多信息请参阅matplotlib 表格文档。### 颜色映射
在绘制大量列时可能会遇到一个潜在问题,即由于默认颜色中的重复,有些系列很难区分。为了解决这个问题,DataFrame
绘图支持使用colormap
参数,该参数接受 Matplotlib 的颜色映射或 Matplotlib 注册的颜色映射名称的字符串。可以在这里查看默认 matplotlib 颜色映射的可视化。
由于 matplotlib 不直接支持基于线条的绘图的颜色映射,颜色是根据DataFrame
中的列数确定的均匀间距选择的。不考虑背景颜色,因此某些颜色映射会产生不易看清的线条。
要使用 cubehelix 颜色映射,我们可以传递colormap='cubehelix'
。
In [196]: np.random.seed(123456) In [197]: df = pd.DataFrame(np.random.randn(1000, 10), index=ts.index) In [198]: df = df.cumsum() In [199]: plt.figure(); In [200]: df.plot(colormap="cubehelix");
或者,我们可以直接传递颜色映射本身:
In [201]: from matplotlib import cm In [202]: plt.figure(); In [203]: df.plot(colormap=cm.cubehelix);
颜色映射也可以用于其他绘图类型,比如条形图:
In [204]: np.random.seed(123456) In [205]: dd = pd.DataFrame(np.random.randn(10, 10)).map(abs) In [206]: dd = dd.cumsum() In [207]: plt.figure(); In [208]: dd.plot.bar(colormap="Greens");
平行坐标图:
In [209]: plt.figure(); In [210]: parallel_coordinates(data, "Name", colormap="gist_rainbow");
Andrews 曲线图:
In [211]: plt.figure(); In [212]: andrews_curves(data, "Name", colormap="winter");
设置绘图样式
从版本 1.5 开始,matplotlib 提供了一系列预配置的绘图样式。设置样式可以轻松地使绘图具有您想要的一般外观。在创建绘图之前调用matplotlib.style.use(my_plot_style)
就可以设置样式。例如,您可以写matplotlib.style.use('ggplot')
来获得 ggplot 风格的绘图。
您可以查看matplotlib.style.available
中提供的各种样式名称,并且非常容易尝试它们。
一般绘图样式参数
大多数绘图方法都有一组关键字参数��用于控制返回绘图的布局和格式:
In [122]: plt.figure(); In [123]: ts.plot(style="k--", label="Series");
对于每种类型的绘图(例如line
,bar
,scatter
),任何额外的参数关键字都会传递给相应的 matplotlib 函数(ax.plot()
, ax.bar()
, ax.scatter()
). 这些参数可以用于控制额外的样式,超出 pandas 提供的范围。
控制图例
您可以将legend
参数设置为False
以隐藏图例,默认情况下会显示图例。
In [124]: df = pd.DataFrame(np.random.randn(1000, 4), index=ts.index, columns=list("ABCD")) In [125]: df = df.cumsum() In [126]: df.plot(legend=False);
控制标签
您可以设置xlabel
和ylabel
参数,为 x 轴和 y 轴提供自定义标签。默认情况下,pandas 会选择索引名称作为 xlabel,而将其留空作为 ylabel。
In [127]: df.plot(); In [128]: df.plot(xlabel="new x", ylabel="new y");
刻度
您可以传递logy
以获得对数刻度 Y 轴。
In [129]: ts = pd.Series(np.random.randn(1000), index=pd.date_range("1/1/2000", periods=1000)) In [130]: ts = np.exp(ts.cumsum()) In [131]: ts.plot(logy=True);
还可以查看logx
和loglog
关键字参数。
在次要 y 轴上绘图
要在次要 y 轴上绘制数据,请使用secondary_y
关键字:
In [132]: df["A"].plot(); In [133]: df["B"].plot(secondary_y=True, style="g");
要在DataFrame
中绘制一些列,请将列名传递给secondary_y
关键字:
In [134]: plt.figure(); In [135]: ax = df.plot(secondary_y=["A", "B"]) In [136]: ax.set_ylabel("CD scale"); In [137]: ax.right_ax.set_ylabel("AB scale");
请注意,在次要 y 轴上绘制的列会在图例中自动标记为“(right)”。要关闭自动标记,使用mark_right=False
关键字:
In [138]: plt.figure(); In [139]: df.plot(secondary_y=["A", "B"], mark_right=False);
### 时间序列图的自定义格式化程序
pandas 为时间序列图提供了自定义格式化程序。这些更改日期和时间的轴标签格式。默认情况下,自定义格式化程序仅应用于由 pandas 使用DataFrame.plot()
或Series.plot()
创建的图。要使其应用于所有图,包括由 matplotlib 创建的图,请设置选项pd.options.plotting.matplotlib.register_converters = True
或使用pandas.plotting.register_matplotlib_converters()
。
抑制刻度分辨率调整
pandas 为常规频率时间序列数据提供自动刻度分辨率调整。对于 pandas 无法推断频率信息的有限情况(例如,在外部创建的twinx
中),您可以选择抑制此行为以进行对齐。
这是默认行为,请注意 x 轴刻度标签的处理方式:
In [140]: plt.figure(); In [141]: df["A"].plot();
使用x_compat
参数,您可以抑制此行为:
In [142]: plt.figure(); In [143]: df["A"].plot(x_compat=True);
如果有多个需要抑制的图,可以在pandas.plotting.plot_params
中使用use
方法,并在with
语句中使用:
In [144]: plt.figure(); In [145]: with pd.plotting.plot_params.use("x_compat", True): .....: df["A"].plot(color="r") .....: df["B"].plot(color="g") .....: df["C"].plot(color="b") .....:
自动日期刻度调整
TimedeltaIndex
现在使用本机 matplotlib 刻度定位器方法,对于刻度标签重叠的图形,调用 matplotlib 的自动日期刻度调整非常有用。
有关更多信息,请参阅autofmt_xdate
方法和matplotlib 文档。
子图
DataFrame
中的每个Series
都可以使用subplots
关键字绘制在不同的轴上:
In [146]: df.plot(subplots=True, figsize=(6, 6));
使用布局和定位多个轴
子图的布局可以通过layout
关键字指定。它可以接受(行数, 列数)
。layout
关键字也可以在hist
和boxplot
中使用。如果输入无效,将引发ValueError
。
通过layout
指定的行 x 列所包含的轴的数量必须大于所需子图的数量。如果布局可以包含比所需更多的轴,则不会绘制空白轴。类似于 NumPy 数组的reshape
方法,您可以在一个维度上使用-1
来自动计算所需的行数或列数,给定另一个维度。
In [147]: df.plot(subplots=True, layout=(2, 3), figsize=(6, 6), sharex=False);
上述示例与使用以下内容相同:
In [148]: df.plot(subplots=True, layout=(2, -1), figsize=(6, 6), sharex=False);
所需的列数(3)是从要绘制的系列数和给定的行数(2)推断出来的。
您可以通过ax
关键字以类似列表的方式传递预先创建的多个轴。这允许更复杂的布局。传递的轴数量必须与正在绘制的子图数量相同。
通过ax
关键字传递多个轴时,layout
、sharex
和sharey
关键字不会影响输出。您应该明确传递sharex=False
和sharey=False
,否则会看到警告。
In [149]: fig, axes = plt.subplots(4, 4, figsize=(9, 9)) In [150]: plt.subplots_adjust(wspace=0.5, hspace=0.5) In [151]: target1 = [axes[0][0], axes[1][1], axes[2][2], axes[3][3]] In [152]: target2 = [axes[3][0], axes[2][1], axes[1][2], axes[0][3]] In [153]: df.plot(subplots=True, ax=target1, legend=False, sharex=False, sharey=False); In [154]: (-df).plot(subplots=True, ax=target2, legend=False, sharex=False, sharey=False);
另一个选项是通过在Series.plot()
中传递一个ax
参数来在特定轴上绘图:
In [155]: np.random.seed(123456) In [156]: ts = pd.Series(np.random.randn(1000), index=pd.date_range("1/1/2000", periods=1000)) In [157]: ts = ts.cumsum() In [158]: df = pd.DataFrame(np.random.randn(1000, 4), index=ts.index, columns=list("ABCD")) In [159]: df = df.cumsum()
In [160]: fig, axes = plt.subplots(nrows=2, ncols=2) In [161]: plt.subplots_adjust(wspace=0.2, hspace=0.5) In [162]: df["A"].plot(ax=axes[0, 0]); In [163]: axes[0, 0].set_title("A"); In [164]: df["B"].plot(ax=axes[0, 1]); In [165]: axes[0, 1].set_title("B"); In [166]: df["C"].plot(ax=axes[1, 0]); In [167]: axes[1, 0].set_title("C"); In [168]: df["D"].plot(ax=axes[1, 1]); In [169]: axes[1, 1].set_title("D");
### 带有误差条的绘图
在DataFrame.plot()
和Series.plot()
中支持带有误差条的绘图。
水平和垂直误差条可以通过xerr
和yerr
关键字参数传递给plot()
。误差值可以使用各种格式指定:
- 作为
DataFrame
或与绘图DataFrame
的columns
属性匹配或与Series
的name
属性匹配的错误的dict
。 - 作为一个
str
,指示绘图DataFrame
中包含误差值的列。 - 作为原始值(
list
、tuple
或np.ndarray
)。必须与绘图DataFrame
/Series
的长度相同。
这是一个从原始数据轻松绘制组均值和标准差的示例方法。
# Generate the data In [170]: ix3 = pd.MultiIndex.from_arrays( .....: [ .....: ["a", "a", "a", "a", "a", "b", "b", "b", "b", "b"], .....: ["foo", "foo", "foo", "bar", "bar", "foo", "foo", "bar", "bar", "bar"], .....: ], .....: names=["letter", "word"], .....: ) .....: In [171]: df3 = pd.DataFrame( .....: { .....: "data1": [9, 3, 2, 4, 3, 2, 4, 6, 3, 2], .....: "data2": [9, 6, 5, 7, 5, 4, 5, 6, 5, 1], .....: }, .....: index=ix3, .....: ) .....: # Group by index labels and take the means and standard deviations # for each group In [172]: gp3 = df3.groupby(level=("letter", "word")) In [173]: means = gp3.mean() In [174]: errors = gp3.std() In [175]: means Out[175]: data1 data2 letter word a bar 3.500000 6.000000 foo 4.666667 6.666667 b bar 3.666667 4.000000 foo 3.000000 4.500000 In [176]: errors Out[176]: data1 data2 letter word a bar 0.707107 1.414214 foo 3.785939 2.081666 b bar 2.081666 2.645751 foo 1.414214 0.707107 # Plot In [177]: fig, ax = plt.subplots() In [178]: means.plot.bar(yerr=errors, ax=ax, capsize=4, rot=0);
不对称误差条也受支持,但在这种情况下必须提供原始误差值。对于长度为N
的Series
,应提供一个2xN
数组,指示下限和上限(或左侧和右侧)误差。对于MxN
的DataFrame
,不对称误差应该是一个Mx2xN
数组。
这是使用不对称误差线绘制最小/最大范围的一种方法示例。
In [179]: mins = gp3.min() In [180]: maxs = gp3.max() # errors should be positive, and defined in the order of lower, upper In [181]: errors = [[means[c] - mins[c], maxs[c] - means[c]] for c in df3.columns] # Plot In [182]: fig, ax = plt.subplots() In [183]: means.plot.bar(yerr=errors, ax=ax, capsize=4, rot=0);
### 绘制表格
使用 matplotlib 表格绘图现在在DataFrame.plot()
和Series.plot()
中支持table
关键字。table
关键字可以接受bool
、DataFrame
或Series
。绘制表格的简单方法是指定table=True
。数据将被转置以符合 matplotlib 的默认布局。
In [184]: np.random.seed(123456) In [185]: fig, ax = plt.subplots(1, 1, figsize=(7, 6.5)) In [186]: df = pd.DataFrame(np.random.rand(5, 3), columns=["a", "b", "c"]) In [187]: ax.xaxis.tick_top() # Display x-axis ticks on top. In [188]: df.plot(table=True, ax=ax);
此外,您可以将不同的DataFrame
或Series
传递给table
关键字。数据将按照打印方法中显示的方式绘制(不会自动转置)。如果需要,可以像下面的示例中所示手动转置。
In [189]: fig, ax = plt.subplots(1, 1, figsize=(7, 6.75)) In [190]: ax.xaxis.tick_top() # Display x-axis ticks on top. In [191]: df.plot(table=np.round(df.T, 2), ax=ax);
还有一个辅助函数pandas.plotting.table
,它可以从DataFrame
或Series
创建表格,并将其添加到matplotlib.Axes
实例中。此函数可以接受 matplotlib table具有的关键字。
In [192]: from pandas.plotting import table In [193]: fig, ax = plt.subplots(1, 1) In [194]: table(ax, np.round(df.describe(), 2), loc="upper right", colWidths=[0.2, 0.2, 0.2]); In [195]: df.plot(ax=ax, ylim=(0, 2), legend=None);
注意:您可以使用axes.tables
属性在轴上获取表格实例以进行进一步装饰。更多信息请参阅matplotlib 表格文档。
色图
在绘制大量列时可能存在的一个问题是,由于默认颜色的重复,有些系列很难区分。为了解决这个问题,DataFrame
绘图支持使用colormap
参数,该参数接受 Matplotlib colormap或注册到 Matplotlib 的调色板名称的字符串。默认 matplotlib 调色板的可视化在这里。
由于 matplotlib 不直接支持基于线条的图形的调色板,颜色是根据DataFrame
中的列数确定的均匀间距选择的。没有考虑背景颜色,因此某些调色板会产生不易看清的线条。
要使用 cubehelix 调色板,我们可以传递colormap='cubehelix'
。
In [196]: np.random.seed(123456) In [197]: df = pd.DataFrame(np.random.randn(1000, 10), index=ts.index) In [198]: df = df.cumsum() In [199]: plt.figure(); In [200]: df.plot(colormap="cubehelix");
或者,我们可以直接传递调色板本身:
In [201]: from matplotlib import cm In [202]: plt.figure(); In [203]: df.plot(colormap=cm.cubehelix);
调色板也可以用于其他绘图类型,比如条形图:
In [204]: np.random.seed(123456) In [205]: dd = pd.DataFrame(np.random.randn(10, 10)).map(abs) In [206]: dd = dd.cumsum() In [207]: plt.figure(); In [208]: dd.plot.bar(colormap="Greens");
平行坐标图表:
In [209]: plt.figure(); In [210]: parallel_coordinates(data, "Name", colormap="gist_rainbow");
安德鲁斯曲线图表:
In [211]: plt.figure(); In [212]: andrews_curves(data, "Name", colormap="winter");
直接使用 Matplotlib 绘图
在某些情况下,直接使用 matplotlib 准备图形可能仍然更可取或必要,例如当某种类型的图形或自定义尚未得到 pandas 的支持时。Series
和 DataFrame
对象的行为类似于数组,因此可以直接传递给 matplotlib 函数,无需显式转换。
pandas 还会自动注册识别日期索引的格式化程序和定位器,从而将日期和时间支持扩展到 matplotlib 中几乎所有可用的绘图类型。虽然这种格式化不提供通过 pandas 绘图时所获得的相同精细程度,但在绘制大量点时可能更快。
In [213]: np.random.seed(123456) In [214]: price = pd.Series( .....: np.random.randn(150).cumsum(), .....: index=pd.date_range("2000-1-1", periods=150, freq="B"), .....: ) .....: In [215]: ma = price.rolling(20).mean() In [216]: mstd = price.rolling(20).std() In [217]: plt.figure(); In [218]: plt.plot(price.index, price, "k"); In [219]: plt.plot(ma.index, ma, "b"); In [220]: plt.fill_between(mstd.index, ma - 2 * mstd, ma + 2 * mstd, color="b", alpha=0.2);
绘图后端
pandas 可以通过第三方绘图后端进行扩展。主要思想是让用户选择一个不同于基于 Matplotlib 提供的后端的绘图后端。
这可以通过在plot
函数中将‘backend.module’作为参数backend
传递来实现。例如:
>>> Series([1, 2, 3]).plot(backend="backend.module")
或者,您也可以全局设置此选项,这样您就不需要在每个plot
调用中指定关键字。例如:
>>> pd.set_option("plotting.backend", "backend.module") >>> pd.Series([1, 2, 3]).plot()
或者:
>>> pd.options.plotting.backend = "backend.module" >>> pd.Series([1, 2, 3]).plot()
这将更或多少等同于:
>>> import backend.module >>> backend.module.plot(pd.Series([1, 2, 3]))
然后,后端模块可以使用其他可视化工具(Bokeh、Altair、hvplot 等)生成图形。一些为 pandas 实现后端的库列在生态系统页面上。
开发者指南可在 pandas.pydata.org/docs/dev/development/extending.html#plotting-backends
找到。