Python 数据分析(PYDA)第三版(四)(2)

简介: Python 数据分析(PYDA)第三版(四)

Python 数据分析(PYDA)第三版(四)(1)https://developer.aliyun.com/article/1482383


8.3 重塑和旋转

有许多用于重新排列表格数据的基本操作。这些操作被称为重塑旋转操作。

使用分层索引进行重塑

分层索引提供了在 DataFrame 中重新排列数据的一致方法。有两个主要操作:

stack

这将从数据中的列旋转或旋转到行。

unstack

这将从行旋转到列。

我将通过一系列示例来说明这些操作。考虑一个具有字符串数组作为行和列索引的小 DataFrame:

In [126]: data = pd.DataFrame(np.arange(6).reshape((2, 3)),
 .....:                     index=pd.Index(["Ohio", "Colorado"], name="state"),
 .....:                     columns=pd.Index(["one", "two", "three"],
 .....:                     name="number"))
In [127]: data
Out[127]: 
number    one  two  three
state 
Ohio        0    1      2
Colorado    3    4      5

在这些数据上使用stack方法将列旋转为行,生成一个 Series:

In [128]: result = data.stack()
In [129]: result
Out[129]: 
state     number
Ohio      one       0
 two       1
 three     2
Colorado  one       3
 two       4
 three     5
dtype: int64

从具有分层索引的 Series 中,您可以使用unstack将数据重新排列回 DataFrame:

In [130]: result.unstack()
Out[130]: 
number    one  two  three
state 
Ohio        0    1      2
Colorado    3    4      5

默认情况下,最内层级别被取消堆叠(与stack相同)。您可以通过传递级别编号或名称来取消堆叠不同的级别:

In [131]: result.unstack(level=0)
Out[131]: 
state   Ohio  Colorado
number 
one        0         3
two        1         4
three      2         5
In [132]: result.unstack(level="state")
Out[132]: 
state   Ohio  Colorado
number 
one        0         3
two        1         4
three      2         5

如果在每个子组中未找到级别中的所有值,则取消堆叠可能会引入缺失数据:

In [133]: s1 = pd.Series([0, 1, 2, 3], index=["a", "b", "c", "d"], dtype="Int64")
In [134]: s2 = pd.Series([4, 5, 6], index=["c", "d", "e"], dtype="Int64")
In [135]: data2 = pd.concat([s1, s2], keys=["one", "two"])
In [136]: data2
Out[136]: 
one  a    0
 b    1
 c    2
 d    3
two  c    4
 d    5
 e    6
dtype: Int64

堆叠默认会过滤掉缺失数据,因此该操作更容易反转:

In [137]: data2.unstack()
Out[137]: 
 a     b  c  d     e
one     0     1  2  3  <NA>
two  <NA>  <NA>  4  5     6
In [138]: data2.unstack().stack()
Out[138]: 
one  a    0
 b    1
 c    2
 d    3
two  c    4
 d    5
 e    6
dtype: Int64
In [139]: data2.unstack().stack(dropna=False)
Out[139]: 
one  a       0
 b       1
 c       2
 d       3
 e    <NA>
two  a    <NA>
 b    <NA>
 c       4
 d       5
 e       6
dtype: Int64

当您在 DataFrame 中取消堆叠时,取消堆叠的级别将成为结果中的最低级别:

In [140]: df = pd.DataFrame({"left": result, "right": result + 5},
 .....:                   columns=pd.Index(["left", "right"], name="side"))
In [141]: df
Out[141]: 
side             left  right
state    number 
Ohio     one        0      5
 two        1      6
 three      2      7
Colorado one        3      8
 two        4      9
 three      5     10
In [142]: df.unstack(level="state")
Out[142]: 
side   left          right 
state  Ohio Colorado  Ohio Colorado
number 
one       0        3     5        8
two       1        4     6        9
three     2        5     7       10

unstack一样,调用stack时,我们可以指定要堆叠的轴的名称:

In [143]: df.unstack(level="state").stack(level="side")
Out[143]: 
state         Colorado  Ohio
number side 
one    left          3     0
 right         8     5
two    left          4     1
 right         9     6
three  left          5     2
 right        10     7

将“长”格式旋转为“宽”格式

在数据库和 CSV 文件中存储多个时间序列的常见方法有时被称为堆叠格式。在此格式中,单个值由表中的一行表示,而不是每行多个值。

让我们加载一些示例数据,并进行少量时间序列整理和其他数据清理:

In [144]: data = pd.read_csv("examples/macrodata.csv")
In [145]: data = data.loc[:, ["year", "quarter", "realgdp", "infl", "unemp"]]
In [146]: data.head()
Out[146]: 
 year  quarter   realgdp  infl  unemp
0  1959        1  2710.349  0.00    5.8
1  1959        2  2778.801  2.34    5.1
2  1959        3  2775.488  2.74    5.3
3  1959        4  2785.204  0.27    5.6
4  1960        1  2847.699  2.31    5.2

首先,我使用pandas.PeriodIndex(表示时间间隔而不是时间点),在 Ch 11: Time Series 中更详细地讨论,将yearquarter列组合起来,将索引设置为每个季度末的datetime值:

In [147]: periods = pd.PeriodIndex(year=data.pop("year"),
 .....:                          quarter=data.pop("quarter"),
 .....:                          name="date")
In [148]: periods
Out[148]: 
PeriodIndex(['1959Q1', '1959Q2', '1959Q3', '1959Q4', '1960Q1', '1960Q2',
 '1960Q3', '1960Q4', '1961Q1', '1961Q2',
 ...
 '2007Q2', '2007Q3', '2007Q4', '2008Q1', '2008Q2', '2008Q3',
 '2008Q4', '2009Q1', '2009Q2', '2009Q3'],
 dtype='period[Q-DEC]', name='date', length=203)
In [149]: data.index = periods.to_timestamp("D")
In [150]: data.head()
Out[150]: 
 realgdp  infl  unemp
date 
1959-01-01  2710.349  0.00    5.8
1959-04-01  2778.801  2.34    5.1
1959-07-01  2775.488  2.74    5.3
1959-10-01  2785.204  0.27    5.6
1960-01-01  2847.699  2.31    5.2

在这里,我在 DataFrame 上使用了pop方法,该方法返回一个列,同时从 DataFrame 中删除它。

然后,我选择一部分列,并给columns索引命名为"item"

In [151]: data = data.reindex(columns=["realgdp", "infl", "unemp"])
In [152]: data.columns.name = "item"
In [153]: data.head()
Out[153]: 
item         realgdp  infl  unemp
date 
1959-01-01  2710.349  0.00    5.8
1959-04-01  2778.801  2.34    5.1
1959-07-01  2775.488  2.74    5.3
1959-10-01  2785.204  0.27    5.6
1960-01-01  2847.699  2.31    5.2

最后,我使用stack重新塑造,使用reset_index将新的索引级别转换为列,最后给包含数据值的列命名为"value"

In [154]: long_data = (data.stack()
 .....:              .reset_index()
 .....:              .rename(columns={0: "value"}))

现在,ldata看起来像这样:

In [155]: long_data[:10]
Out[155]: 
 date     item     value
0 1959-01-01  realgdp  2710.349
1 1959-01-01     infl     0.000
2 1959-01-01    unemp     5.800
3 1959-04-01  realgdp  2778.801
4 1959-04-01     infl     2.340
5 1959-04-01    unemp     5.100
6 1959-07-01  realgdp  2775.488
7 1959-07-01     infl     2.740
8 1959-07-01    unemp     5.300
9 1959-10-01  realgdp  2785.204

在这种所谓的格式中,每个时间序列的每一行在表中代表一个单独的观察。

数据经常以这种方式存储在关系型 SQL 数据库中,因为固定的模式(列名和数据类型)允许item列中的不同值的数量随着数据添加到表中而改变。在前面的例子中,dateitem通常会成为主键(在关系数据库术语中),提供关系完整性和更容易的连接。在某些情况下,以这种格式处理数据可能更加困难;您可能更喜欢拥有一个 DataFrame,其中包含一个以date列中的时间戳为索引的每个不同item值的列。DataFrame 的pivot方法正好执行这种转换:

In [156]: pivoted = long_data.pivot(index="date", columns="item",
 .....:                           values="value")
In [157]: pivoted.head()
Out[157]: 
item        infl   realgdp  unemp
date 
1959-01-01  0.00  2710.349    5.8
1959-04-01  2.34  2778.801    5.1
1959-07-01  2.74  2775.488    5.3
1959-10-01  0.27  2785.204    5.6
1960-01-01  2.31  2847.699    5.2

传递的前两个值分别是要使用的列,作为行和列索引,最后是一个可选的值列,用于填充 DataFrame。假设您有两个值列,希望同时重塑:

In [159]: long_data["value2"] = np.random.standard_normal(len(long_data))
In [160]: long_data[:10]
Out[160]: 
 date     item     value    value2
0 1959-01-01  realgdp  2710.349  0.802926
1 1959-01-01     infl     0.000  0.575721
2 1959-01-01    unemp     5.800  1.381918
3 1959-04-01  realgdp  2778.801  0.000992
4 1959-04-01     infl     2.340 -0.143492
5 1959-04-01    unemp     5.100 -0.206282
6 1959-07-01  realgdp  2775.488 -0.222392
7 1959-07-01     infl     2.740 -1.682403
8 1959-07-01    unemp     5.300  1.811659
9 1959-10-01  realgdp  2785.204 -0.351305

通过省略最后一个参数,您可以获得一个具有分层列的 DataFrame:

In [161]: pivoted = long_data.pivot(index="date", columns="item")
In [162]: pivoted.head()
Out[162]: 
 value                    value2 
item        infl   realgdp unemp      infl   realgdp     unemp
date 
1959-01-01  0.00  2710.349   5.8  0.575721  0.802926  1.381918
1959-04-01  2.34  2778.801   5.1 -0.143492  0.000992 -0.206282
1959-07-01  2.74  2775.488   5.3 -1.682403 -0.222392  1.811659
1959-10-01  0.27  2785.204   5.6  0.128317 -0.351305 -1.313554
1960-01-01  2.31  2847.699   5.2 -0.615939  0.498327  0.174072
In [163]: pivoted["value"].head()
Out[163]: 
item        infl   realgdp  unemp
date 
1959-01-01  0.00  2710.349    5.8
1959-04-01  2.34  2778.801    5.1
1959-07-01  2.74  2775.488    5.3
1959-10-01  0.27  2785.204    5.6
1960-01-01  2.31  2847.699    5.2

请注意,pivot等同于使用set_index创建一个分层索引,然后调用unstack

In [164]: unstacked = long_data.set_index(["date", "item"]).unstack(level="item")
In [165]: unstacked.head()
Out[165]: 
 value                    value2 
item        infl   realgdp unemp      infl   realgdp     unemp
date 
1959-01-01  0.00  2710.349   5.8  0.575721  0.802926  1.381918
1959-04-01  2.34  2778.801   5.1 -0.143492  0.000992 -0.206282
1959-07-01  2.74  2775.488   5.3 -1.682403 -0.222392  1.811659
1959-10-01  0.27  2785.204   5.6  0.128317 -0.351305 -1.313554
1960-01-01  2.31  2847.699   5.2 -0.615939  0.498327  0.174072

从“宽”格式到“长”格式的旋转

DataFrame 的pivot的逆操作是pandas.melt。与在新的 DataFrame 中将一个列转换为多个不同,它将多个列合并为一个,生成一个比输入更长的 DataFrame。让我们看一个例子:

In [167]: df = pd.DataFrame({"key": ["foo", "bar", "baz"],
 .....:                    "A": [1, 2, 3],
 .....:                    "B": [4, 5, 6],
 .....:                    "C": [7, 8, 9]})
In [168]: df
Out[168]: 
 key  A  B  C
0  foo  1  4  7
1  bar  2  5  8
2  baz  3  6  9

"key"列可以是一个组指示器,其他列是数据值。在使用pandas.melt时,我们必须指示哪些列(如果有的话)是组指示器。让我们在这里只使用"key"作为唯一的组指示器:

In [169]: melted = pd.melt(df, id_vars="key")
In [170]: melted
Out[170]: 
 key variable  value
0  foo        A      1
1  bar        A      2
2  baz        A      3
3  foo        B      4
4  bar        B      5
5  baz        B      6
6  foo        C      7
7  bar        C      8
8  baz        C      9

使用pivot,我们可以重新塑造回原始布局:

In [171]: reshaped = melted.pivot(index="key", columns="variable",
 .....:                         values="value")
In [172]: reshaped
Out[172]: 
variable  A  B  C
key 
bar       2  5  8
baz       3  6  9
foo       1  4  7

由于pivot的结果从用作行标签的列创建索引,我们可能希望使用reset_index将数据移回到列中:

In [173]: reshaped.reset_index()
Out[173]: 
variable  key  A  B  C
0         bar  2  5  8
1         baz  3  6  9
2         foo  1  4  7

您还可以指定要用作“值”列的列的子集:

In [174]: pd.melt(df, id_vars="key", value_vars=["A", "B"])
Out[174]: 
 key variable  value
0  foo        A      1
1  bar        A      2
2  baz        A      3
3  foo        B      4
4  bar        B      5
5  baz        B      6

pandas.melt也可以在没有任何组标识符的情况下使用:

In [175]: pd.melt(df, value_vars=["A", "B", "C"])
Out[175]: 
 variable  value
0        A      1
1        A      2
2        A      3
3        B      4
4        B      5
5        B      6
6        C      7
7        C      8
8        C      9
In [176]: pd.melt(df, value_vars=["key", "A", "B"])
Out[176]: 
 variable value
0      key   foo
1      key   bar
2      key   baz
3        A     1
4        A     2
5        A     3
6        B     4
7        B     5
8        B     6

8.4 结论

现在您已经掌握了一些关于 pandas 的基础知识,用于数据导入、清理和重新组织,我们准备继续使用 matplotlib 进行数据可视化。当我们讨论更高级的分析时,我们将回到书中的其他领域来探索 pandas 的更多功能。

九、绘图和可视化

原文:wesmckinney.com/book/plotting-and-visualization

译者:飞龙

协议:CC BY-NC-SA 4.0

此开放访问网络版本的《Python 数据分析第三版》现已作为印刷版和数字版的伴侣提供。如果您发现任何勘误,请在此处报告。请注意,由 Quarto 生成的本站点的某些方面与 O’Reilly 的印刷版和电子书版本的格式不同。

如果您发现本书的在线版本有用,请考虑订购纸质版无 DRM 的电子书以支持作者。本网站的内容不得复制或再生产。代码示例采用 MIT 许可,可在 GitHub 或 Gitee 上找到。

制作信息丰富的可视化(有时称为*图)是数据分析中最重要的任务之一。它可能是探索过程的一部分,例如,帮助识别异常值或所需的数据转换,或者作为生成模型想法的一种方式。对于其他人,构建用于网络的交互式可视化可能是最终目标。Python 有许多附加库用于制作静态或动态可视化,但我主要关注matplotlib和构建在其之上的库。

matplotlib 是一个桌面绘图包,旨在创建适合出版的图形和图表。该项目由 John Hunter 于 2002 年发起,旨在在 Python 中实现类似 MATLAB 的绘图界面。matplotlib 和 IPython 社区合作简化了从 IPython shell(现在是 Jupyter 笔记本)进行交互式绘图。matplotlib 支持所有操作系统上的各种 GUI 后端,并且可以将可视化导出为所有常见的矢量和光栅图形格式(PDF、SVG、JPG、PNG、BMP、GIF 等)。除了一些图表外,本书中几乎所有的图形都是使用 matplotlib 生成的。

随着时间的推移,matplotlib 衍生出了许多用于数据可视化的附加工具包,这些工具包使用 matplotlib 进行底层绘图。其中之一是seaborn,我们将在本章后面探讨。

在本章中跟随代码示例的最简单方法是在 Jupyter 笔记本中输出图形。要设置这个,可以在 Jupyter 笔记本中执行以下语句:

%matplotlib inline

注意

自 2012 年第一版以来,已经创建了许多新的数据可视化库,其中一些(如 Bokeh 和 Altair)利用现代网络技术创建交互式可视化,与 Jupyter 笔记本很好地集成。与在本书中使用多个可视化工具不同,我决定坚持使用 matplotlib 来教授基础知识,特别是因为 pandas 与 matplotlib 有很好的集成。您可以根据本章的原则学习如何使用其他可视化库。

9.1 简要的 matplotlib API 入门

使用 matplotlib 时,我们使用以下导入约定:

In [13]: import matplotlib.pyplot as plt

在 Jupyter 中运行%matplotlib notebook(或在 IPython 中运行%matplotlib),我们可以尝试创建一个简单的图。如果一切设置正确,应该会出现一个类似 Simple line plot 的线图:

In [14]: data = np.arange(10)
In [15]: data
Out[15]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
In [16]: plt.plot(data)

图 9.1:简单线图

虽然像 seaborn 和 pandas 内置绘图函数将处理许多制作图形的琐碎细节,但如果您希望自定义超出提供的函数选项之外的内容,您需要了解一些关于 matplotlib API 的知识。

注意

本书中没有足够的空间来全面介绍 matplotlib 的功能广度和深度。它应该足以教会您如何上手。matplotlib 图库和文档是学习高级功能的最佳资源。

图和子图

matplotlib 中的绘图位于 Figure 对象中。您可以使用 plt.figure 创建一个新的图:

In [17]: fig = plt.figure()

在 IPython 中,如果您首先运行 %matplotlib 来设置 matplotlib 集成,将会出现一个空白绘图窗口,但在 Jupyter 中,直到我们使用更多命令之前,什么都不会显示。

plt.figure 有许多选项;特别是,如果保存到磁盘,figsize 将保证图的特定大小和纵横比。

您不能在空白图中制作绘图。您必须使用 add_subplot 创建一个或多个 subplots

In [18]: ax1 = fig.add_subplot(2, 2, 1)

这意味着图应该是 2 × 2(因此总共最多四个绘图),我们选择了四个子图中的第一个(从 1 编号)。如果您创建下两个子图,您将得到一个看起来像 一个空的 matplotlib 图,带有三个子图 的可视化:

In [19]: ax2 = fig.add_subplot(2, 2, 2)
In [20]: ax3 = fig.add_subplot(2, 2, 3)

图 9.2:一个空的 matplotlib 图,带有三个子图

提示:

使用 Jupyter 笔记本的一个细微之处是,每次评估单元格后绘图都会重置,因此您必须将所有绘图命令放在一个单独的笔记本单元格中。

在这里,我们在同一个单元格中运行所有这些命令:

fig = plt.figure()
ax1 = fig.add_subplot(2, 2, 1)
ax2 = fig.add_subplot(2, 2, 2)
ax3 = fig.add_subplot(2, 2, 3)

这些绘图轴对象有各种方法,可以创建不同类型的绘图,最好使用轴方法而不是像 plt.plot 这样的顶级绘图函数。例如,我们可以使用 plot 方法制作一条线图(参见单个绘图后的数据可视化):

In [21]: ax3.plot(np.random.standard_normal(50).cumsum(), color="black",
 ....:          linestyle="dashed")

图 9.3:单个绘图后的数据可视化

当您运行此命令时,您可能会注意到类似 的输出。matplotlib 返回引用刚刚添加的绘图子组件的对象。大多数情况下,您可以安全地忽略此输出,或者您可以在行末加上分号以抑制输出。

附加选项指示 matplotlib 绘制一条黑色虚线。这里由 fig.add_subplot 返回的对象是 AxesSubplot 对象,您可以通过调用每个实例方法直接在其他空子图上绘制(参见添加额外绘图后的数据可视化):

In [22]: ax1.hist(np.random.standard_normal(100), bins=20, color="black", alpha=0
.3);
In [23]: ax2.scatter(np.arange(30), np.arange(30) + 3 * np.random.standard_normal
(30));

图 9.4:添加额外绘图后的数据可视化

alpha=0.3 样式选项设置了叠加绘图的透明度。

您可以在 matplotlib 文档 中找到绘图类型的全面目录。

为了更方便地创建子图网格,matplotlib 包括一个 plt.subplots 方法,它创建一个新图并返回一个包含创建的子图对象的 NumPy 数组:

In [25]: fig, axes = plt.subplots(2, 3)
In [26]: axes
Out[26]: 
array([[<Axes: >, <Axes: >, <Axes: >],
 [<Axes: >, <Axes: >, <Axes: >]], dtype=object)

然后,axes 数组可以像二维数组一样索引;例如,axes[0, 1] 指的是顶部行中心的子图。您还可以使用 sharexsharey 指示子图应具有相同的 x 或 y 轴。当您在相同比例上比较数据时,这可能很有用;否则,matplotlib 会独立自动缩放绘图限制。有关此方法的更多信息,请参见 表 9.1。

表 9.1:matplotlib.pyplot.subplots 选项

参数 描述
nrows 子图的行数
ncols 子图的列数
sharex 所有子图应使用相同的 x 轴刻度(调整 xlim 将影响所有子图)
sharey 所有子图应使用相同的 y 轴刻度(调整 ylim 将影响所有子图)
subplot_kw 传递给 add_subplot 调用的关键字字典,用于创建每个子图
**fig_kw 创建图时使用subplots的附加关键字,例如plt.subplots(2, 2, figsize=(8, 6))
调整子图周围的间距

默认情况下,matplotlib 在子图周围留有一定量的填充和子图之间的间距。这些间距都是相对于绘图的高度和宽度指定的,因此如果您通过编程或使用 GUI 窗口手动调整绘图大小,绘图将动态调整自身。您可以使用Figure对象上的subplots_adjust方法更改间距:

subplots_adjust(left=None, bottom=None, right=None, top=None,
                wspace=None, hspace=None)

wspacehspace控制子图之间使用的百分比图宽度和图高度的间距。这里是一个您可以在 Jupyter 中执行的小例子,我将间距缩小到零(参见没有子图间距的数据可视化):

fig, axes = plt.subplots(2, 2, sharex=True, sharey=True)
for i in range(2):
 for j in range(2):
 axes[i, j].hist(np.random.standard_normal(500), bins=50,
 color="black", alpha=0.5)
fig.subplots_adjust(wspace=0, hspace=0)

图 9.5:没有子图间距的数据可视化

您可能会注意到轴标签重叠。matplotlib 不会检查标签是否重叠,因此在这种情况下,您需要通过指定显式刻度位置和刻度标签自行修复标签(我们将在后面的部分刻度、标签和图例中看到如何做到这一点)。

颜色、标记和线型

matplotlib 的线plot函数接受 x 和 y 坐标数组以及可选的颜色样式选项。例如,要用绿色虚线绘制xy,您可以执行:

ax.plot(x, y, linestyle="--", color="green")

提供了许多常用颜色的颜色名称,但您可以通过指定其十六进制代码(例如,"#CECECE")来使用光谱上的任何颜色。您可以查看plt.plot的文档字符串以查看一些支持的线型。在线文档中提供了更全面的参考资料。

线图还可以具有标记来突出实际数据点。由于 matplotlib 的plot函数创建连续线图,插值点之间的插值,有时可能不清楚点位于何处。标记可以作为附加样式选项提供(参见带有标记的线图):

In [31]: ax = fig.add_subplot()
In [32]: ax.plot(np.random.standard_normal(30).cumsum(), color="black",
 ....:         linestyle="dashed", marker="o");

图 9.6:带有标记的线图

对于线图,您会注意到默认情况下后续点是线性插值的。这可以通过drawstyle选项进行更改(参见带有不同 drawstyle 选项的线图):

In [34]: fig = plt.figure()
In [35]: ax = fig.add_subplot()
In [36]: data = np.random.standard_normal(30).cumsum()
In [37]: ax.plot(data, color="black", linestyle="dashed", label="Default");
In [38]: ax.plot(data, color="black", linestyle="dashed",
 ....:         drawstyle="steps-post", label="steps-post");
In [39]: ax.legend()

图 9.7:带有不同 drawstyle 选项的线图

在这里,由于我们将label参数传递给plot,我们能够使用ax.legend创建一个图例,以标识每条线。我在刻度、标签和图例中更多地讨论图例。

注意

无论您在绘制数据时是否传递了label选项,都必须调用ax.legend来创建图例。

刻度、标签和图例

大多数类型的绘图装饰都可以通过 matplotlib 轴对象上的方法访问。这包括xlimxticksxticklabels等方法。它们分别控制绘图范围、刻度位置和刻度标签。它们可以以两种方式使用:

  • 不带参数调用返回当前参数值(例如,ax.xlim()返回当前 x 轴绘图范围)
  • 带参数调用设置参数值(例如,ax.xlim([0, 10])将 x 轴范围设置为 0 到 10)

所有这些方法都作用于活动或最近创建的AxesSubplot。每个对应于 subplot 对象本身的两种方法;在xlim的情况下,这些方法是ax.get_xlimax.set_xlim

设置标题、轴标签、刻度和刻度标签

为了说明如何自定义坐标轴,我将创建一个简单的图和一个随机漫步的绘图(参见用于说明 xticks 的简单绘图(带有默认标签)):

In [40]: fig, ax = plt.subplots()
In [41]: ax.plot(np.random.standard_normal(1000).cumsum());

图 9.8:用于说明 xticks 的简单图表(带有默认标签)

要更改 x 轴刻度,最简单的方法是使用set_xticksset_xticklabels。前者指示 matplotlib 在数据范围内放置刻度的位置;默认情况下,这些位置也将是标签。但是我们可以使用set_xticklabels设置任何其他值作为标签:

In [42]: ticks = ax.set_xticks([0, 250, 500, 750, 1000])
In [43]: labels = ax.set_xticklabels(["one", "two", "three", "four", "five"],
 ....:                             rotation=30, fontsize=8)

rotation选项将 x 轴刻度标签设置为 30 度旋转。最后,set_xlabel为 x 轴命名,set_title为子图标题(请参见用于说明自定义 xticks 的简单图表以查看生成的图):

In [44]: ax.set_xlabel("Stages")
Out[44]: Text(0.5, 6.666666666666652, 'Stages')
In [45]: ax.set_title("My first matplotlib plot")

图 9.9:用于说明自定义 xticks 的简单图表

修改 y 轴的过程与此示例中的x替换为y相同。axes 类有一个set方法,允许批量设置绘图属性。从前面的示例中,我们也可以这样写:

ax.set(title="My first matplotlib plot", xlabel="Stages")
添加图例

图例是识别图表元素的另一个关键元素。有几种方法可以添加图例。最简单的方法是在添加每个图表元素时传递label参数:

In [46]: fig, ax = plt.subplots()
In [47]: ax.plot(np.random.randn(1000).cumsum(), color="black", label="one");
In [48]: ax.plot(np.random.randn(1000).cumsum(), color="black", linestyle="dashed
",
 ....:         label="two");
In [49]: ax.plot(np.random.randn(1000).cumsum(), color="black", linestyle="dotted
",
 ....:         label="three");

一旦您完成了这一步,您可以调用ax.legend()来自动创建图例。生成的图表在带有三条线和图例的简单图表中:

In [50]: ax.legend()

图 9.10:带有三条线和图例的简单图表

legend方法有几个其他选项可用于位置loc参数。有关更多信息,请参阅文档字符串(使用ax.legend?)。

loc图例选项告诉 matplotlib 在哪里放置图例。默认值是"best",它会尝试选择一个最不起眼的位置。要从图例中排除一个或多个元素,请不传递标签或传递label="_nolegend_"


Python 数据分析(PYDA)第三版(四)(3)https://developer.aliyun.com/article/1482385

相关文章
|
1天前
|
SQL 数据可视化 数据挖掘
2024年8个Python高效数据分析的技巧。,2024年最新Python基础面试题2024
2024年8个Python高效数据分析的技巧。,2024年最新Python基础面试题2024
2024年8个Python高效数据分析的技巧。,2024年最新Python基础面试题2024
|
1天前
|
数据采集 SQL 数据挖掘
2024年8个Python高效数据分析的技巧_python 数据分析 效率,2024年最新阿里社招p7面试几轮
2024年8个Python高效数据分析的技巧_python 数据分析 效率,2024年最新阿里社招p7面试几轮
|
4天前
|
机器学习/深度学习 数据挖掘 Python
Python数据分析 | 泰坦尼克逻辑回归(下)
Python数据分析 | 泰坦尼克逻辑回归
8 1
|
4天前
|
机器学习/深度学习 数据挖掘 BI
Python数据分析 | 泰坦尼克逻辑回归(上)
Python数据分析 | 泰坦尼克逻辑回归
18 0
|
4天前
|
数据采集 数据挖掘 Python
Python数据分析 | 线性回归
Python数据分析 | 线性回归
15 1
|
4天前
|
机器学习/深度学习 数据采集 自然语言处理
10个 Python 小技巧,覆盖了90%的数据分析需求!_countries_lat_lon
10个 Python 小技巧,覆盖了90%的数据分析需求!_countries_lat_lon
|
4天前
|
数据采集 人工智能 数据挖掘
「一行分析」利用12000条招聘数据分析Python学习方向和就业方向
「一行分析」利用12000条招聘数据分析Python学习方向和就业方向
|
6天前
|
数据采集 数据可视化 数据挖掘
利用Python和Pandas库优化数据分析流程
在当今数据驱动的时代,数据分析已成为企业和个人决策的重要依据。Python作为一种强大且易于上手的编程语言,配合Pandas这一功能丰富的数据处理库,极大地简化了数据分析的流程。本文将探讨如何利用Python和Pandas库进行高效的数据清洗、转换、聚合以及可视化,从而优化数据分析的流程,提高数据分析的效率和准确性。
|
6天前
|
SQL 数据采集 数据挖掘
构建高效的Python数据处理流水线:使用Pandas和NumPy优化数据分析任务
在数据科学和分析领域,Python一直是最受欢迎的编程语言之一。本文将介绍如何通过使用Pandas和NumPy库构建高效的数据处理流水线,从而加速数据分析任务的执行。我们将讨论如何优化数据加载、清洗、转换和分析的过程,以及如何利用这些库中的强大功能来提高代码的性能和可维护性。
|
6天前
|
数据可视化 数据挖掘 BI
【Python】—— pandas 数据分析
【Python】—— pandas 数据分析
21 1