Pandas 中文参考指南
Chart visualization
以下示例假设你在使用 Jupyter。 |
本部分演示通过图表进行可视化。有关表格数据的可视化的信息,请参阅 Table Visualization 部分。
我们使用标准惯例来引用 matplotlib API:
In [1]: import matplotlib.pyplot as plt
In [2]: plt.close("all")
我们在 pandas 中提供了基础知识,可以轻松地创建出色的绘图。有关超出此处记录的基础知识的可视库,请参阅 the ecosystem page。
对 np.random 的所有调用都以 123456 为种子。 |
Basic plotting: plot
我们将演示基础知识,有关一些高级策略,请参阅 cookbook。
序列和数据框上的 plot 方法只是一个简单的包装器,用于链接:https://matplotlib.org/stable/api/as_gen/matplotlib.axes.Axes.plot.html#matplotlib.axes.Axes.plot[_plt.plot()]:
In [3]: np.random.seed(123456)
In [4]: ts = pd.Series(np.random.randn(1000), index=pd.date_range("1/1/2000", periods=1000))
In [5]: ts = ts.cumsum()
In [6]: ts.plot();
如果索引包含日期,它会调用 gcf().autofmt_xdate() 以尝试根据上述内容很好地设置 x 轴的格式。
在数据框上, plot() 是绘制所有带有标签的列的便捷方式:
In [7]: df = pd.DataFrame(np.random.randn(1000, 4), index=ts.index, columns=list("ABCD"))
In [8]: df = df.cumsum()
In [9]: plt.figure();
In [10]: df.plot();
你可以使用 plot() 中的 x 和 y 关键词,根据另一列绘制一列:
In [11]: df3 = pd.DataFrame(np.random.randn(1000, 2), columns=["B", "C"]).cumsum()
In [12]: df3["A"] = pd.Series(list(range(len(df))))
In [13]: df3.plot(x="A", y="B");
有关更多格式化和样式选项,请在下面参阅 formatting。 |
Other plots
除了默认的线图以外,绘图方法允许使用少数几种绘图样式。这些方法可以作为 plot() 的 kind 关键词参数提供,包括:
例如,可以如下方式创建一个条形图:
In [14]: plt.figure();
In [15]: df.iloc[5].plot(kind="bar");
你还可以使用 DataFrame.plot.<kind> 方法来创建这些其他绘图,而不必提供 kind 关键词参数。这可以让你更轻松地发现绘图方法及其使用的特定参数:
In [16]: df = pd.DataFrame()
In [17]: df.plot.<TAB> # noqa: E225, E999
df.plot.area df.plot.barh df.plot.density df.plot.hist df.plot.line df.plot.scatter
df.plot.bar df.plot.box df.plot.hexbin df.plot.kde df.plot.pie
除了这些 kind 之外,还有使用单独界面的 DataFrame.hist()和 DataFrame.boxplot()方法。
最后,pandas.plotting_中还有几个 plotting functions,它们将 _Series或 DataFrame作为参数。这些包括:
Bar plots
对于带标签的非时间序列数据,您可能希望绘制条形图:
In [18]: plt.figure();
In [19]: df.iloc[5].plot.bar();
In [20]: plt.axhline(0, color="k");
调用 DataFrame 的 plot.bar()方法会生成一个多条形图:
In [21]: df2 = pd.DataFrame(np.random.rand(10, 4), columns=["a", "b", "c", "d"])
In [22]: df2.plot.bar();
若要生成堆积条形图,传递 stacked=True:
In [23]: df2.plot.bar(stacked=True);
要获得水平条形图,请使用 _barh_方法:
In [24]: df2.plot.barh(stacked=True);
Histograms
可以使用 DataFrame.plot.hist()和 Series.plot.hist()方法绘制直方图。
In [25]: df4 = pd.DataFrame(
....: {
....: "a": np.random.randn(1000) + 1,
....: "b": np.random.randn(1000),
....: "c": np.random.randn(1000) - 1,
....: },
....: columns=["a", "b", "c"],
....: )
....:
In [26]: plt.figure();
In [27]: df4.plot.hist(alpha=0.5);
可以使用 _stacked=True_对直方图进行堆叠。可以使用 _bins_关键字更改直方图的分组大小。
In [28]: plt.figure();
In [29]: df4.plot.hist(stacked=True, bins=20);
您可以传递 matplotlib _hist_支持的其他关键字。例如,可以通过 _orientation='horizontal'_和 _cumulative=True_绘制水平和累积直方图。
In [30]: plt.figure();
In [31]: df4["a"].plot.hist(orientation="horizontal", cumulative=True);
有关详细信息,请参阅链接:https://matplotlib.org/stable/api/as_gen/matplotlib.axes.Axes.hist.html#matplotlib.axes.Axes.hist[_hist] 方法和 matplotlib hist documentation。
仍然可以使用现有的接口 _DataFrame.hist_来绘制直方图。
In [32]: plt.figure();
In [33]: df["A"].diff().hist();
DataFrame.hist()在多个子图上绘制列的直方图:
In [34]: plt.figure();
In [35]: df.diff().hist(color="k", alpha=0.5, bins=50);
可以指定 _by_关键字来绘制分组直方图:
In [36]: data = pd.Series(np.random.randn(1000))
In [37]: data.hist(by=np.random.randint(0, 4, 1000), figsize=(6, 4));
此外,还可以在 DataFrame.plot.hist()中指定 _by_关键字。
在 1.4.0 版中已更改。
In [38]: data = pd.DataFrame(
....: {
....: "a": np.random.choice(["x", "y", "z"], 1000),
....: "b": np.random.choice(["e", "f", "g"], 1000),
....: "c": np.random.randn(1000),
....: "d": np.random.randn(1000) - 1,
....: },
....: )
....:
In [39]: data.plot.hist(by=["a", "b"], figsize=(10, 5));
Box plots
可以通过调用 Series.plot.box()和 DataFrame.plot.box()或 DataFrame.boxplot()绘制箱线图,以可视化每列中的值的分布。
例如,这里是一个箱线图,表示在 [0,1) 上的均匀随机变量的 10 次观测的五次试验。
In [40]: df = pd.DataFrame(np.random.rand(10, 5), columns=["A", "B", "C", "D", "E"])
In [41]: df.plot.box();
可以通过传递 color_关键字来对箱线图进行着色。您可以传递一个 _dict,其键是 boxes、whiskers、medians_和 _caps。如果 _dict_中缺少某些键,则会为相应的艺术家使用默认颜色。此外,箱线图还有 _sym_关键字来指定离群点样式。
当你通过 color 关键字传递其他类型的参数时,它将直接将其传递给 matplotlib 以供 boxes、whiskers、medians 和 caps 着色。
颜色应用于要绘制的每一个方框。如果你想进行更复杂的着色,你可以通过传递 return_type 来获取每个绘制的图形。
In [42]: color = {
....: "boxes": "DarkGreen",
....: "whiskers": "DarkOrange",
....: "medians": "DarkBlue",
....: "caps": "Gray",
....: }
....:
In [43]: df.plot.box(color=color, sym="r+");
此外,你还可以传递 matplotlib 支持的其他关键字 boxplot。例如,可以通过 vert=False 和 positions 关键字绘制水平和自定义位置的箱形图。
In [44]: df.plot.box(vert=False, positions=[1, 4, 5, 6, 8]);
请参阅链接:https://matplotlib.org/stable/api/as_gen/matplotlib.axes.Axes.boxplot.html#matplotlib.axes.Axes.boxplot[_boxplot] 方法和更多 matplotlib boxplot documentation。
现有的 DataFrame.boxplot 接口仍可用于绘制箱形图。
In [45]: df = pd.DataFrame(np.random.rand(10, 5))
In [46]: plt.figure();
In [47]: bp = df.boxplot()
你可以使用 by 关键字参数创建分层箱形图来创建分组。例如:
In [48]: df = pd.DataFrame(np.random.rand(10, 2), columns=["Col1", "Col2"])
In [49]: df["X"] = pd.Series(["A", "A", "A", "A", "A", "B", "B", "B", "B", "B"])
In [50]: plt.figure();
In [51]: bp = df.boxplot(by="X")
你还可以传递一组待绘制的列,以及按多列分组:
In [52]: df = pd.DataFrame(np.random.rand(10, 3), columns=["Col1", "Col2", "Col3"])
In [53]: df["X"] = pd.Series(["A", "A", "A", "A", "A", "B", "B", "B", "B", "B"])
In [54]: df["Y"] = pd.Series(["A", "B", "A", "B", "A", "B", "A", "B", "A", "B"])
In [55]: plt.figure();
In [56]: bp = df.boxplot(column=["Col1", "Col2"], by=["X", "Y"])
你还可以使用 DataFrame.plot.box() 创建分组,例如:
在 1.4.0 版中已更改。
In [57]: df = pd.DataFrame(np.random.rand(10, 3), columns=["Col1", "Col2", "Col3"])
In [58]: df["X"] = pd.Series(["A", "A", "A", "A", "A", "B", "B", "B", "B", "B"])
In [59]: plt.figure();
In [60]: bp = df.plot.box(column=["Col1", "Col2"], by="X")
在 boxplot 中,可以通过 return_type 关键字控制返回类型。有效的选择是 {"axes", "dict", "both", None}。通过 DataFrame.boxplot 使用 by 关键字创建的分面也会影响输出类型:
return_type
分面
输出类型
None
否
轴
None
是
维度为 2 的轴 ndarray
'axes'
否
轴
'axes'
是
轴序列
'dict'
否
艺术家字典
'dict'
是
艺术家字典系列
'both'
否
命名元组
'both'
是
命名元组系列
Groupby.boxplot 总会返回 Series 的 return_type。
In [61]: np.random.seed(1234)
In [62]: df_box = pd.DataFrame(np.random.randn(50, 2))
In [63]: df_box["g"] = np.random.choice(["A", "B"], size=50)
In [64]: df_box.loc[df_box["g"] == "B", 1] += 3
In [65]: bp = df_box.boxplot(by="g")
上面按数字列拆分子图,然后按 g 列的值拆分。下面的子图按 g 的值拆分,然后再按数字列拆分。
In [66]: bp = df_box.groupby("g").boxplot()
Area plot
可以通过 Series.plot.area() 和 DataFrame.plot.area() 创建面积图。面积图默认堆叠。为了生成堆叠面积图,每列都必须是全正值或全负值。
当输入数据包含 NaN 时,它将自动填充为 0。如果你想删除或用不同值填充,在调用 plot 之前使用 dataframe.dropna() 或 dataframe.fillna()。
In [67]: df = pd.DataFrame(np.random.rand(10, 4), columns=["a", "b", "c", "d"])
In [68]: df.plot.area();
要生成非堆叠图,传递 stacked=False。除非另有指定,否则 Alpha 值设置为 0.5:
In [69]: df.plot.area(stacked=False);
Scatter plot
可以使用 DataFrame.plot.scatter() 方法绘制散点图。散点图需要 x 轴和 y 轴的数字列。可以通过 x 和 y 关键字来指定这些列。
In [70]: df = pd.DataFrame(np.random.rand(50, 4), columns=["a", "b", "c", "d"])
In [71]: df["species"] = pd.Categorical(
....: ["setosa"] * 20 + ["versicolor"] * 20 + ["virginica"] * 10
....: )
....:
In [72]: df.plot.scatter(x="a", y="b");
要在单个轴内绘制多列组,重复 plot 方法指定目标 ax。建议指定 color 和 label 关键字以区分每个组。
In [73]: ax = df.plot.scatter(x="a", y="b", color="DarkBlue", label="Group 1")
In [74]: df.plot.scatter(x="c", y="d", color="DarkGreen", label="Group 2", ax=ax);
关键字 c 可以作为列的名称,为每个点提供颜色:
In [75]: df.plot.scatter(x="a", y="b", c="c", s=50);
如果向 c 传递分类列,那么将生成离散颜色条:
1.3.0 版中的新增功能。
In [76]: df.plot.scatter(x="a", y="b", c="species", cmap="viridis", s=50);
你可以传递 matplotlib 链接:https://matplotlib.org/stable/api/as_gen/matplotlib.axes.Axes.scatter.html#matplotlib.axes.Axes.scatter[_scatter] 支持的其他关键字。下面的示例展示了使用 DataFrame 列作为气泡大小的带气泡的图表。
In [77]: df.plot.scatter(x="a", y="b", s=df["c"] * 200);
请参见链接:https://matplotlib.org/stable/api/as_gen/matplotlib.axes.Axes.scatter.html#matplotlib.axes.Axes.scatter[_scatter] 方法和 matplotlib scatter documentation 以获取更多信息。
Hexagonal bin plot
可以通过 DataFrame.plot.hexbin() 创建六边形箱形图。如果数据太密集而无法逐个绘制每个点,六边形箱形图可以成为散点图的有用替代。
In [78]: df = pd.DataFrame(np.random.randn(1000, 2), columns=["a", "b"])
In [79]: df["b"] = df["b"] + np.arange(1000)
In [80]: df.plot.hexbin(x="a", y="b", gridsize=25);
一个有用的关键字参数是 gridsize;它控制 x 方向上的六边形数量,默认为 100。更大的 gridsize 意味着更多、更小的箱。
默认情况下,计算每个 (x, y) 点周围计数的直方图。你可以通过向 C 和 reduce_C_function 参数传递值来指定备选聚合。C 指定每个 (x, y) 点的值,而 reduce_C_function 是一个自变量函数,它将箱子中的所有值简化为一个数字(例如 mean、max、sum、std)。在这个示例中,位置由列 a 和 b 给出,而值由列 z 给出。这些箱使用 NumPy 的 max 函数聚合。
In [81]: df = pd.DataFrame(np.random.randn(1000, 2), columns=["a", "b"])
In [82]: df["b"] = df["b"] + np.arange(1000)
In [83]: df["z"] = np.random.uniform(0, 3, 1000)
In [84]: df.plot.hexbin(x="a", y="b", C="z", reduce_C_function=np.max, gridsize=25);
请参阅此链接:https://matplotlib.org/stable/api/as_gen/matplotlib.axes.Axes.hexbin.html#matplotlib.axes.Axes.hexbin[_hexbin] 方法和 matplotlib hexbin documentation 以了解更多信息。
Pie plot
您可以使用 DataFrame.plot.pie() 或 Series.plot.pie() 创建饼形图。如果您的数据包含任何 NaN,它们将自动填充为 0。如果您的数据中存在任何负值,则会引发 ValueError。
In [85]: series = pd.Series(3 * np.random.rand(4), index=["a", "b", "c", "d"], name="series")
In [86]: series.plot.pie(figsize=(6, 6));
对于饼形图,最好使用正方形图形,即图形宽高比为 1。您可以创建宽度和高度相等的图形,或通过在返回的 axes 对象上调用 ax.set_aspect('equal') 在绘制后强制宽高比相等。
请注意,带有 DataFrame 的饼形图要求您通过 y 自变量或 subplots=True 指定目标列。当指定 y 时,将绘制所选列的饼图。如果指定 subplots=True,则将绘制每个列的饼图作为子图。默认情况下,每个饼图中都将绘制一个图例;指定 legend=False 以隐藏它。
In [87]: df = pd.DataFrame(
....: 3 * np.random.rand(4, 2), index=["a", "b", "c", "d"], columns=["x", "y"]
....: )
....:
In [88]: df.plot.pie(subplots=True, figsize=(8, 4));
您可以使用 labels 和 colors 关键字指定每个楔形的标签和颜色。
警告
大多数熊猫图使用 label 和 color 自变量(请注意这两个自变量上缺少“s”)。为了与 _matplotlib.pyplot.pie() 保持一致,您必须使用 labels 和 colors。
如果您想隐藏楔形标签,请指定 labels=None。如果指定 fontsize,则该值将应用于楔形标签。此外, _matplotlib.pyplot.pie() 支持的其他关键字也可以使用。
In [89]: series.plot.pie(
....: labels=["AA", "BB", "CC", "DD"],
....: colors=["r", "g", "b", "c"],
....: autopct="%.2f",
....: fontsize=20,
....: figsize=(6, 6),
....: );
....:
如果您传递的总和小于 1.0 的值,则将对它们进行重新缩放,使其相加为 1。
In [90]: series = pd.Series([0.1] * 4, index=["a", "b", "c", "d"], name="series2")
In [91]: series.plot.pie(figsize=(6, 6));
请参阅 matplotlib pie documentation 以了解更多信息。
Plotting with missing data
熊猫尝试实际地绘制包含缺失数据的 DataFrames 或 Series。根据绘图类型,舍弃、留出或填充缺失值。
绘图类型
NaN 处理
行
在 NaN 处留出间隙
行(堆叠)
填充 0
条形
填充 0
散点
舍弃 NaN
直方图
(按行丢弃)NaN
盒形图
(按行丢弃)NaN
面积图
填充 0
核密度估计(KDE)
(按行丢弃)NaN
六边形网格图
舍弃 NaN
饼图
填充 0
Plotting tools
Scatter matrix plot
您可以使用 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");
Density plot
您可以使用 Series.plot.kde() 和 DataFrame.plot.kde() 方法创建密度图。
In [95]: ser = pd.Series(np.random.randn(1000))
In [96]: ser.plot.kde();
Andrews curves
安德鲁斯曲线允许将多变量数据绘制为大量的曲线,这些曲线是使用样本的属性作为傅立叶级数的系数创建的,请参阅 Wikipedia entry 以获取更多信息。通过对每个类的曲线着不同的颜色,可以可视化数据聚类。属于同一类样本的曲线通常会靠得更近并形成更大的结构。
注:“鸢尾”数据集可用 here 获取。
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");
Parallel coordinates
并行坐标是一种绘制多变量数据的绘图技术,请参阅 Wikipedia entry 了解介绍。并行坐标允许人们查看数据中的聚类,并直观地估计其他统计数据。使用并行坐标,点表示为连接的线段。每条垂直线代表一个属性。一组连接的线段代表一个数据点。倾向于聚类的点将靠得更近。
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 plot
滞后图用于检查数据集或时间序列是否是随机的。随机数据在滞后图中不应显示任何结构。非随机结构意味着底层数据不是随机的。可以传递 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);
Autocorrelation plot
自相关图通常用于检查时间序列中的随机性。这是通过针对不同时间滞后处的数据值计算自相关来完成的。如果时间序列是随机的,则对于任何和所有时间滞后分离,此类自相关都应该接近零。如果时间序列不是随机的,那么一个或多个自相关将显著不为零。绘图中显示的水平线对应于 95% 和 99% 置信带。虚线为 99% 置信带。有关自相关图的更多信息,请参阅 Wikipedia entry。
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
自举图用于直观地评估统计的不确定性,例如均值、中位数、中值范围等。从数据集中选择特定大小的随机子集,针对此子集计算相关统计数据,并重复该过程指定次数。生成的绘图和直方图构成了自举图。
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。
注:“鸢尾”数据集可用 here 获取。
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
Setting the plot style
从 1.5 版开始,matplotlib 提供了一系列预配置的绘图样式。设置样式可用于轻松地为绘图赋予您想要的总体外观。只需在创建绘图之前调用 matplotlib.style.use(my_plot_style) 即可设置样式。例如,您可以编写 matplotlib.style.use('ggplot') 以获得 ggplot 风格的绘图。
您可以在 matplotlib.style.available 查看可用的各种样式名称,试用也非常简单。
General plot style arguments
大多数绘制方法都有一组关键词参数,用于控制返回的绘制图的布局和格式:
In [122]: plt.figure();
In [123]: ts.plot(style="k--", label="Series");
对于每种类型的绘制图(例如 line、bar、scatter),任何其他实参关键词都会传给相对应的 matplotlib 函数(链接:https://matplotlib.org/stable/api/as_gen/matplotlib.axes.Axes.plot.html#matplotlib.axes.Axes.plot[_ax.plot()]、链接:https://matplotlib.org/stable/api/as_gen/matplotlib.axes.Axes.bar.html#matplotlib.axes.Axes.bar[_ax.bar()]、链接:https://matplotlib.org/stable/api/as_gen/matplotlib.axes.Axes.scatter.html#matplotlib.axes.Axes.scatter[_ax.scatter()])。除了 pandas 提供的内容外,这些内容还可以用于控制其他样式。
Controlling the legend
您可以将 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);
Controlling the labels
您可以设置 xlabel 和 ylabel 实参,以便为 x 和 y 轴提供自定义标签。默认情况下,pandas 会选取索引名称作为 xlabel,而将其保留为空值以用作 ylabel。
In [127]: df.plot();
In [128]: df.plot(xlabel="new x", ylabel="new y");
Scales
您可以传递 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 关键词实参。
Plotting on a secondary y-axis
若要在辅助 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);
Custom formatters for timeseries plots
pandas 为时间序列图提供了自定义格式化程序。这些程序会更改日期和时间的轴标签格式。默认情况下,自定义格式化程序仅应用于 pandas 使用 DataFrame.plot() 或 Series.plot() 创建的绘制图。若让它们应用于所有绘制图,包括 matplotlib 创建的绘制图,请设置选项 pd.options.plotting.matplotlib.register_converters = True 或使用 pandas.plotting.register_matplotlib_converters()。
Suppressing tick resolution adjustment
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")
.....:
Automatic date tick adjustment
TimedeltaIndex 现在使用基本的 matplotlib 刻度定位器方法,这有助于调用 matplotlib 中适用于刻度标签重叠的数字自动刻度调整。
请参阅 autofmt_xdate 方法和 matplotlib documentation 以了解详情。
Subplots
DataFrame 中的每个 Series 都可以使用 subplots 关键词在不同的轴上绘制:
In [146]: df.plot(subplots=True, figsize=(6, 6));
Using layout and targeting multiple axes
子图的布局可以通过 layout 关键词指定。它可以接受 (rows, columns)。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);
另一个选项是将 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");
Plotting with error bars
使用误差线进行绘图在 DataFrame.plot() 和 Series.plot() 中支持。
可以将水平和垂直误差线提供给 plot() 的 xerr 和 yerr 关键字参数。可以使用各种格式指定误差值:
以下是一个轻松绘制原始数据的组均值加上标准差的示例。
# 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);
Plotting tables
使用 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);
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 table documentation 了解更多信息。
Colormaps
绘制大量列时的一个潜在问题是,由于默认颜色的重复,很难区分某些序列。为了解决这个问题,DataFrame 绘图支持使用 colormap 参数,它接受 matplotlib colormap 或作为在 matplotlib 中注册的配色表名称的字符串。matplotlib 默认配色表的可视化可在 here 处获得。
由于 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");
Plotting directly with 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);
Plotting backends
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 等)生成绘图。 the ecosystem page 上列出了实现 pandas 后端的一些库。