写点什么

Pandas 高级教程之:plot 画图详解

发布于: 2021 年 07 月 07 日

简介

python 中 matplotlib 是非常重要并且方便的图形化工具,使用 matplotlib 可以可视化的进行数据分析,今天本文将会详细讲解 Pandas 中的 matplotlib 应用。

基础画图

要想使用 matplotlib,我们需要引用它:

In [1]: import matplotlib.pyplot as plt
复制代码

假如我们要从 2020 年 1 月 1 日开始,随机生成 365 天的数据,然后作图表示应该这样写:

ts = pd.Series(np.random.randn(365), index=pd.date_range("1/1/2020", periods=365))
ts.plot()
复制代码



使用 DF 可以同时画多个 Series 的图像:

df3 =  pd.DataFrame(np.random.randn(365, 4), index=ts.index, columns=list("ABCD"))
df3= df3.cumsum()
df3.plot()
复制代码



可以指定行和列使用的数据:

df3 = pd.DataFrame(np.random.randn(365, 2), columns=["B", "C"]).cumsum()
df3["A"] = pd.Series(list(range(len(df))))
df3.plot(x="A", y="B");
复制代码



其他图像

plot() 支持很多图像类型,包括 bar, hist, box, density, area, scatter, hexbin, pie 等,下面我们分别举例子来看下怎么使用。

bar

 df.iloc[5].plot(kind="bar");
复制代码



多个列的 bar:

df2 = pd.DataFrame(np.random.rand(10, 4), columns=["a", "b", "c", "d"])
df2.plot.bar();
复制代码



stacked bar

df2.plot.bar(stacked=True);
复制代码



barh

barh 表示横向的 bar 图:

df2.plot.barh(stacked=True);
复制代码



Histograms

df2.plot.hist(alpha=0.5);
复制代码



box

df.plot.box();
复制代码



box 可以自定义颜色:

color = {   ....:     "boxes": "DarkGreen",   ....:     "whiskers": "DarkOrange",   ....:     "medians": "DarkBlue",   ....:     "caps": "Gray",   ....: }
df.plot.box(color=color, sym="r+");
复制代码



可以转成横向的:

df.plot.box(vert=False);
复制代码



除了 box,还可以使用 DataFrame.boxplot 来画 box 图:

In [42]: df = pd.DataFrame(np.random.rand(10, 5))
In [44]: bp = df.boxplot()
复制代码



boxplot 可以使用 by 来进行分组:

df = pd.DataFrame(np.random.rand(10, 2), columns=["Col1", "Col2"])
dfOut[90]: Col1 Col20 0.047633 0.1500471 0.296385 0.2128262 0.562141 0.1362433 0.997786 0.2245604 0.585457 0.1789145 0.551201 0.8671026 0.740142 0.0038727 0.959130 0.5815068 0.114489 0.5342429 0.042882 0.314845
df.boxplot()
复制代码



现在给 df 加一列:

 df["X"] = pd.Series(["A", "A", "A", "A", "A", "B", "B", "B", "B", "B"])
dfOut[92]: Col1 Col2 X0 0.047633 0.150047 A1 0.296385 0.212826 A2 0.562141 0.136243 A3 0.997786 0.224560 A4 0.585457 0.178914 A5 0.551201 0.867102 B6 0.740142 0.003872 B7 0.959130 0.581506 B8 0.114489 0.534242 B9 0.042882 0.314845 B
bp = df.boxplot(by="X")
复制代码



Area

使用 Series.plot.area() 或者 DataFrame.plot.area() 可以画出 area 图。

In [60]: df = pd.DataFrame(np.random.rand(10, 4), columns=["a", "b", "c", "d"])
In [61]: df.plot.area();
复制代码



如果不想叠加,可以指定 stacked=False

In [62]: df.plot.area(stacked=False);
复制代码



Scatter

DataFrame.plot.scatter() 可以创建点图。

In [63]: df = pd.DataFrame(np.random.rand(50, 4), columns=["a", "b", "c", "d"])
In [64]: df.plot.scatter(x="a", y="b");
复制代码



scatter 图还可以带第三个轴:

 df.plot.scatter(x="a", y="b", c="c", s=50);
复制代码



可以将第三个参数变为散点的大小:

df.plot.scatter(x="a", y="b", s=df["c"] * 200);
复制代码



Hexagonal bin

使用 DataFrame.plot.hexbin() 可以创建蜂窝图:

In [69]: df = pd.DataFrame(np.random.randn(1000, 2), columns=["a", "b"])
In [70]: df["b"] = df["b"] + np.arange(1000)
In [71]: df.plot.hexbin(x="a", y="b", gridsize=25);
复制代码



默认情况下颜色深度表示的是(x,y)中元素的个数,可以通过 reduce_C_function 来指定不同的聚合方法:比如 meanmaxsumstd.

In [72]: df = pd.DataFrame(np.random.randn(1000, 2), columns=["a", "b"])
In [73]: df["b"] = df["b"] = df["b"] + np.arange(1000)
In [74]: df["z"] = np.random.uniform(0, 3, 1000)
In [75]: df.plot.hexbin(x="a", y="b", C="z", reduce_C_function=np.max, gridsize=25);
复制代码



Pie

使用 DataFrame.plot.pie() 或者 Series.plot.pie()来构建饼图:

In [76]: series = pd.Series(3 * np.random.rand(4), index=["a", "b", "c", "d"], name="series")
In [77]: series.plot.pie(figsize=(6, 6));
复制代码



可以按照列的个数分别作图:

In [78]: df = pd.DataFrame(   ....:     3 * np.random.rand(4, 2), index=["a", "b", "c", "d"], columns=["x", "y"]   ....: )   ....: 
In [79]: df.plot.pie(subplots=True, figsize=(8, 4));
复制代码



更多定制化的内容:

In [80]: series.plot.pie(   ....:     labels=["AA", "BB", "CC", "DD"],   ....:     colors=["r", "g", "b", "c"],   ....:     autopct="%.2f",   ....:     fontsize=20,   ....:     figsize=(6, 6),   ....: );
复制代码



如果传入的 value 值加起来不是 1,那么会画出一个伞形:

In [81]: series = pd.Series([0.1] * 4, index=["a", "b", "c", "d"], name="series2")
In [82]: series.plot.pie(figsize=(6, 6));
复制代码



在画图中处理 NaN 数据

下面是默认画图方式中处理 NaN 数据的方式:

其他作图工具

散点矩阵图 Scatter matrix

可以使用 pandas.plotting 中的 scatter_matrix 来画散点矩阵图:

In [83]: from pandas.plotting import scatter_matrix
In [84]: df = pd.DataFrame(np.random.randn(1000, 4), columns=["a", "b", "c", "d"])
In [85]: scatter_matrix(df, alpha=0.2, figsize=(6, 6), diagonal="kde");
复制代码



密度图 Density plot

使用 Series.plot.kde() 和 DataFrame.plot.kde() 可以画出密度图:

In [86]: ser = pd.Series(np.random.randn(1000))
In [87]: ser.plot.kde();
复制代码



安德鲁斯曲线 Andrews curves

安德鲁斯曲线允许将多元数据绘制为大量曲线,这些曲线是使用样本的属性作为傅里叶级数的系数创建的. 通过为每个类对这些曲线进行不同的着色,可以可视化数据聚类。 属于同一类别的样本的曲线通常会更靠近在一起并形成较大的结构。

In [88]: from pandas.plotting import andrews_curves
In [89]: data = pd.read_csv("data/iris.data")
In [90]: plt.figure();
In [91]: andrews_curves(data, "Name");
复制代码



平行坐标 Parallel coordinates

平行坐标是一种用于绘制多元数据的绘制技术。 平行坐标允许人们查看数据中的聚类,并直观地估计其他统计信息。 使用平行坐标点表示为连接的线段。 每条垂直线代表一个属性。 一组连接的线段代表一个数据点。 趋于聚集的点将显得更靠近。

In [92]: from pandas.plotting import parallel_coordinates
In [93]: data = pd.read_csv("data/iris.data")
In [94]: plt.figure();
In [95]: parallel_coordinates(data, "Name");
复制代码



滞后图 lag plot

滞后图是用时间序列和相应的滞后阶数序列做出的散点图。可以用于观测自相关性。

In [96]: from pandas.plotting import lag_plot
In [97]: plt.figure();
In [98]: spacing = np.linspace(-99 * np.pi, 99 * np.pi, num=1000)
In [99]: data = pd.Series(0.1 * np.random.rand(1000) + 0.9 * np.sin(spacing))
In [100]: lag_plot(data);
复制代码



自相关图 Autocorrelation plot

自相关图通常用于检查时间序列中的随机性。 自相关图是一个平面二维坐标悬垂线图。横坐标表示延迟阶数,纵坐标表示自相关系数。

In [101]: from pandas.plotting import autocorrelation_plot
In [102]: plt.figure();
In [103]: spacing = np.linspace(-9 * np.pi, 9 * np.pi, num=1000)
In [104]: data = pd.Series(0.7 * np.random.rand(1000) + 0.3 * np.sin(spacing))
In [105]: autocorrelation_plot(data);
复制代码



Bootstrap plot

bootstrap plot 用于直观地评估统计数据的不确定性,例如均值,中位数,中间范围等。从数据集中选择指定大小的随机子集,为该子集计算出相关统计信息, 重复指定的次数。 生成的图和直方图构成了引导图。

In [106]: from pandas.plotting import bootstrap_plot
In [107]: data = pd.Series(np.random.rand(1000))
In [108]: bootstrap_plot(data, size=50, samples=500, color="grey");
复制代码



RadViz

他是基于弹簧张力最小化算法。它把数据集的特征映射成二维目标空间单位圆中的一个点,点的位置由系在点上的特征决定。把实例投入圆的中心,特征会朝圆中此实例位置(实例对应的归一化数值)“拉”实例。

In [109]: from pandas.plotting import radviz
In [110]: data = pd.read_csv("data/iris.data")
In [111]: plt.figure();
In [112]: radviz(data, "Name");
复制代码



图像的格式

matplotlib 1.5 版本之后,提供了很多默认的画图设置,可以通过 matplotlib.style.use(my_plot_style)来进行设置。

可以通过使用 matplotlib.style.available 来列出所有可用的 style 类型:

import matplotlib as plt;
plt.style.availableOut[128]: ['seaborn-dark', 'seaborn-darkgrid', 'seaborn-ticks', 'fivethirtyeight', 'seaborn-whitegrid', 'classic', '_classic_test', 'fast', 'seaborn-talk', 'seaborn-dark-palette', 'seaborn-bright', 'seaborn-pastel', 'grayscale', 'seaborn-notebook', 'ggplot', 'seaborn-colorblind', 'seaborn-muted', 'seaborn', 'Solarize_Light2', 'seaborn-paper', 'bmh', 'seaborn-white', 'dark_background', 'seaborn-poster', 'seaborn-deep']
复制代码

去掉小图标

默认情况下画出来的图会有一个表示列类型的图标,可以使用 legend=False 禁用:

In [115]: df = pd.DataFrame(np.random.randn(1000, 4), index=ts.index, columns=list("ABCD"))
In [116]: df = df.cumsum()
In [117]: df.plot(legend=False);
复制代码



设置 label 的名字

In [118]: df.plot();
In [119]: df.plot(xlabel="new x", ylabel="new y");
复制代码



缩放

画图中如果 X 轴或者 Y 轴的数据差异过大,可能会导致图像展示不友好,数值小的部分基本上无法展示,可以传入 logy=True 进行 Y 轴的缩放:

In [120]: ts = pd.Series(np.random.randn(1000), index=pd.date_range("1/1/2000", periods=1000))
In [121]: ts = np.exp(ts.cumsum())
In [122]: ts.plot(logy=True);
复制代码



多个 Y 轴

使用 secondary_y=True 可以绘制多个 Y 轴数据:

In [125]: plt.figure();
In [126]: ax = df.plot(secondary_y=["A", "B"])
In [127]: ax.set_ylabel("CD scale");
In [128]: ax.right_ax.set_ylabel("AB scale");
复制代码



小图标上面默认会添加 right 字样,想要去掉的话可以设置 mark_right=False:

In [129]: plt.figure();
In [130]: df.plot(secondary_y=["A", "B"], mark_right=False);
复制代码

坐标文字调整

使用时间做坐标的时候,因为时间太长,导致 x 轴的坐标值显示不完整,可以使用 x_compat=True 来进行调整:

In [133]: plt.figure();
In [134]: df["A"].plot(x_compat=True);
复制代码



如果有多个图像需要调整,可以使用 with:

In [135]: plt.figure();
In [136]: with pd.plotting.plot_params.use("x_compat", True): .....: df["A"].plot(color="r") .....: df["B"].plot(color="g") .....: df["C"].plot(color="b") .....:
复制代码



子图

绘制 DF 的时候,可以将多个 Series 分开作为子图显示:

In [137]: df.plot(subplots=True, figsize=(6, 6));
复制代码



可以修改子图的 layout:

df.plot(subplots=True, layout=(2, 3), figsize=(6, 6), sharex=False);
复制代码



上面等价于:

In [139]: df.plot(subplots=True, layout=(2, -1), figsize=(6, 6), sharex=False);
复制代码

一个更复杂的例子:

In [140]: fig, axes = plt.subplots(4, 4, figsize=(9, 9))
In [141]: plt.subplots_adjust(wspace=0.5, hspace=0.5)
In [142]: target1 = [axes[0][0], axes[1][1], axes[2][2], axes[3][3]]
In [143]: target2 = [axes[3][0], axes[2][1], axes[1][2], axes[0][3]]
In [144]: df.plot(subplots=True, ax=target1, legend=False, sharex=False, sharey=False);
In [145]: (-df).plot(subplots=True, ax=target2, legend=False, sharex=False, sharey=False);
复制代码



画表格

如果设置 table=True , 可以直接将表格数据一并显示在图中:

In [165]: fig, ax = plt.subplots(1, 1, figsize=(7, 6.5))
In [166]: df = pd.DataFrame(np.random.rand(5, 3), columns=["a", "b", "c"])
In [167]: ax.xaxis.tick_top() # Display x-axis ticks on top.
In [168]: df.plot(table=True, ax=ax)
fig
复制代码



table 还可以显示在图片上面:

In [172]: from pandas.plotting import table
In [173]: fig, ax = plt.subplots(1, 1)
In [174]: table(ax, np.round(df.describe(), 2), loc="upper right", colWidths=[0.2, 0.2, 0.2]);
In [175]: df.plot(ax=ax, ylim=(0, 2), legend=None);
复制代码



使用 Colormaps

如果 Y 轴的数据太多的话,使用默认的线的颜色可能不好分辨。这种情况下可以传入 colormap 。

In [176]: df = pd.DataFrame(np.random.randn(1000, 10), index=ts.index)
In [177]: df = df.cumsum()
In [178]: plt.figure();
In [179]: df.plot(colormap="cubehelix");
复制代码



本文已收录于 http://www.flydean.com/09-python-pandas-plot/

最通俗的解读,最深刻的干货,最简洁的教程,众多你不知道的小技巧等你来发现!

发布于: 2021 年 07 月 07 日阅读数: 4
用户头像

关注公众号:程序那些事,更多精彩等着你! 2020.06.07 加入

最通俗的解读,最深刻的干货,最简洁的教程,众多你不知道的小技巧,尽在公众号:程序那些事!

评论

发布
暂无评论
Pandas高级教程之:plot画图详解