geekdoc-python-zh/docs/realpython/pandas-plot-python.md

27 KiB
Raw Blame History

熊猫绘图:Python 数据可视化初学者

原文:https://realpython.com/pandas-plot-python/

*立即观看**本教程有真实 Python 团队创建的相关视频课程。配合文字教程一起看,加深理解: 与熊猫的剧情:Python 数据可视化基础知识

无论你只是开始了解一个数据集还是准备发表你的发现,可视化是一个必不可少的工具。Python 流行的数据分析库,熊猫,提供了几个不同的选项来用.plot()可视化你的数据。即使你刚刚开始你的熊猫之旅,你也将很快创建基本的情节,这些情节将对你的数据产生有价值的见解。

在本教程中,您将学习:

  • 什么是不同类型的熊猫地块以及何时使用它们
  • 如何使用直方图获得数据集的概览
  • 如何发现与散点图的相关性
  • 如何分析不同的类别及其比率

免费奖励: 点击此处获取 Conda 备忘单,其中包含管理您的 Python 环境和包的便捷使用示例。

设置您的环境

您可以在 Jupyter 笔记本中最好地跟随本教程中的代码。这样,你将立即看到你的情节,并能够发挥他们左右。

您还需要一个包含熊猫的 Python 工作环境。如果你还没有,那么你有几个选择:

  • 如果你有更大的计划,那么下载 Anaconda 发行版。它很大(大约 500 MB),但您将为大多数数据科学工作做好准备。

  • 如果你喜欢极简的设置,那么看看在 Windows 上为机器学习设置 Python 中关于安装 Miniconda 的部分。

  • 如果你想坚持使用 pip ,那么用pip install pandas matplotlib安装本教程讨论的库。你也可以用pip install jupyterlab抢 Jupyter 笔记本。

  • 如果你不想做任何设置,那么就跟随在线 Jupyter 笔记本试用

设置好环境后,您就可以下载数据集了。在本教程中,您将分析来自美国社区调查 20102012 公共使用微数据样本的大学专业数据。它是在fivethirtyeeight网站上发布的选择大学专业的经济指南的基础。

首先,通过将下载 URL 传递给pandas.read_csv()来下载数据:

In [1]: import pandas as pd

In [2]: download_url = (
 ...:    "https://raw.githubusercontent.com/fivethirtyeight/"
 ...:    "data/master/college-majors/recent-grads.csv"
 ...: )

In [3]: df = pd.read_csv(download_url)

In [4]: type(df)
Out[4]: pandas.core.frame.DataFrame

通过调用read_csv(),您创建了一个数据帧,这是 pandas 中使用的主要数据结构。

**注意:**即使您不熟悉数据帧,也可以跟随本教程。但是如果你有兴趣学习更多关于使用熊猫和数据框架的知识,那么你可以查看使用熊猫和 Python 来探索你的数据集熊猫数据框架:让使用数据变得愉快

现在你有了一个数据框架,你可以看看数据。首先,您应该配置display.max.columns选项以确保 pandas 不隐藏任何列。然后可以用 .head() 查看前几行数据:

In [5]: pd.set_option("display.max.columns", None)

In [6]: df.head()

您已经使用.head()显示了数据帧df的前五行。您的输出应该如下所示:

The output of df.head()

.head()显示的默认行数是 5但是您可以指定任意行数作为参数。例如要显示前十行您可以使用df.head(10)

Remove ads

创建你的第一个熊猫地块

您的数据集包含一些与每个专业的毕业生收入相关的列:

  • "Median" 是全职、全年工作者的收入中值。
  • "P25th" 是收益的第 25 个百分位数。
  • "P75th" 是收入的第 75 百分位。
  • "Rank" 是按收入中位数排列的少校军衔。

让我们从显示这些列的图开始。首先,你需要用%matplotlib 魔法命令设置你的 Jupyter 笔记本来显示剧情:

In [7]: %matplotlib
Using matplotlib backend: MacOSX

%matplotlib magic 命令用 Matplotlib 设置你的 Jupyter 笔记本显示图形。默认情况下使用标准的 Matplotlib 图形后端,您的绘图将显示在一个单独的窗口中。

**注意:**您可以通过向%matplotlib magic 命令传递一个参数来更改 Matplotlib 后端。

例如,inline后端很受 Jupyter 笔记本的欢迎,因为它在笔记本本身中显示绘图,就在创建绘图的单元格下面:

In [7]: %matplotlib inline

还有许多其他后端可用。有关更多信息,请查看 IPython 文档中的丰富输出教程

现在你已经准备好制作你的第一个情节了!你可以用 .plot() 这样做:

In [8]: df.plot(x="Rank", y=["P25th", "Median", "P75th"])
Out[8]: <AxesSubplot:xlabel='Rank'>

.plot()返回一个折线图其中包含数据帧中每一行的数据。x 轴值代表每个机构的排名,"P25th""Median""P75th"值绘制在 y 轴上。

**注意:**如果您没有使用 Jupyter 笔记本或 IPython shell那么您需要使用来自matplotlibpyplot接口来显示图表。

下面是如何在标准 Python shell 中显示图形:

>>> import matplotlib.pyplot as plt
>>> df.plot(x="Rank", y=["P25th", "Median", "P75th"])
>>> plt.show()

注意,在调用plt.show()显示绘图之前,必须首先从 Matplotlib 导入pyplot模块。

默认情况下,.plot()生成的图形显示在一个单独的窗口中,如下所示:

line plot with P25, median, P75 earnings

查看该图,您可以做出以下观察:

  • 收入中位数随着排名的下降而下降。这是意料之中的,因为排名是由收入中位数决定的。

  • 一些专业在第 25 和第 75 个百分点之间有很大的差距。拥有这些学位的人的收入可能远低于或高于中值收入。

  • 其他专业在第 25 和第 75 个百分点之间的差距非常小。拥有这些学位的人的工资非常接近收入的中位数。

你的第一个图已经暗示了在数据中还有更多要发现的!有些专业的收益范围很广,有些专业的收益范围相当窄。为了发现这些差异,您将使用几种其他类型的图。

**注意:**关于中位数、百分位数和其他统计数据的介绍,请查看 Python 统计基础:如何描述您的数据

.plot()有几个可选参数。最值得注意的是,kind参数接受 11 个不同的字符串值,并决定您将创建哪种绘图:

  1. "area" 是针对小区地块的。
  2. "bar" 是针对垂直条形图的。
  3. "barh" 是针对水平条形图的。
  4. "box" 是为方框图。
  5. "hexbin" 是为赫克宾出谋划策。
  6. "hist" 为直方图。
  7. "kde" 是对内核密度的估计图表。
  8. "density""kde"的别名。
  9. "line" 是为折线图。
  10. "pie" 是为饼状图。
  11. "scatter" 是为散点图。

默认值为"line"。像上面创建的折线图一样,可以很好地概述您的数据。您可以使用它们来检测总体趋势。它们很少提供复杂的洞察力,但它们可以给你一些线索,告诉你应该往哪里放大。

如果您没有为.plot()提供参数那么它会创建一个线图x 轴上是索引y 轴上是所有的数字列。虽然对于只有几列的数据集来说,这是一个有用的默认设置,但是对于 college majors 数据集及其几个数值列来说,它看起来相当混乱。

**注意:**作为将字符串传递给.plot()kind参数的替代方法,DataFrame对象有几种方法可以用来创建上述各种类型的图:

  1. T2.area()
  2. T2.bar()
  3. T2.barh()
  4. T2.box()
  5. T2.hexbin()
  6. T2.hist()
  7. T2.kde()
  8. T2.density()
  9. T2.line()
  10. T2.pie()
  11. T2.scatter()

在本教程中,您将使用.plot()接口并将字符串传递给kind参数。我们鼓励你也尝试一下上面提到的方法。

现在你已经创建了你的第一个熊猫图,让我们仔细看看.plot()是如何工作的。

Remove ads

看看引擎盖下面:Matplotlib

当您在一个DataFrame对象上调用.plot()Matplotlib 会在幕后创建绘图。

要验证这一点,请尝试两个代码片段。首先,使用 Matplotlib 创建一个使用两列数据帧的绘图:

In [9]: import matplotlib.pyplot as plt

In [10]: plt.plot(df["Rank"], df["P75th"])
Out[10]: [<matplotlib.lines.Line2D at 0x7f859928fbb0>]

首先,导入matplotlib.pyplot模块,并将其重命名为plt。然后调用plot(),将DataFrame对象的"Rank"列作为第一个参数传递,将"P75th"列作为第二个参数传递。

结果是一个线形图,它在 y 轴上绘制了第 75 个百分位数,在 x 轴上绘制了排名:

line plot with P75

您可以使用DataFrame对象的.plot()方法创建完全相同的图形:

In [11]: df.plot(x="Rank", y="P75th")
Out[11]: <AxesSubplot:xlabel='Rank'>

.plot()pyplot.plot()包装器,结果是一个与您用 Matplotlib 生成的图形相同的图形:

line plot with P75

您可以使用pyplot.plot()df.plot()DataFrame对象的列中生成相同的图形。然而,如果你已经有了一个DataFrame实例,那么df.plot()会提供比pyplot.plot()更清晰的语法。

**注意:**如果你已经熟悉 Matplotlib那么你可能会对.plot()kwargs参数感兴趣。您可以向它传递一个包含关键字参数的字典,然后这些关键字参数将被传递到 Matplotlib 绘图后端。

有关 Matplotlib 的更多信息,请查看使用 Matplotlib 的 Python 绘图。

现在你知道了DataFrame对象的.plot()方法是 Matplotlib 的pyplot.plot()的包装器,让我们深入了解你可以创建的不同类型的图以及如何创建它们。

调查您的数据

接下来的图将为您提供数据集特定列的概述。首先,您将看到一个直方图属性的分布。然后,您将了解一些检查异常值的工具。

分布和直方图

DataFrame并不是熊猫中唯一一个使用.plot()方法的职业。正如在熊猫身上经常发生的那样, Series 对象提供了类似的功能。

您可以将数据帧的每一列作为一个Series对象。下面是一个使用从大学专业数据创建的数据框的"Median"列的示例:

In [12]: median_column = df["Median"]

In [13]: type(median_column)
Out[13]: pandas.core.series.Series

现在您有了一个Series对象,您可以为它创建一个图。一个直方图是一个很好的方法来可视化数据集中的值是如何分布的。直方图将值分组到中,并显示其值在特定箱中的数据点的计数。

让我们为"Median"列创建一个直方图:

In [14]: median_column.plot(kind="hist")
Out[14]: <AxesSubplot:ylabel='Frequency'>

您在median_column系列上调用.plot(),并将字符串"hist"传递给kind参数。这就是全部了!

当你调用.plot()时,你会看到下图:

median hist plot

直方图显示数据被分成 10 个区间,范围从$20000 到$120000每个区间的宽度为$10000。直方图的形状与正态分布不同,后者呈对称的钟形,中间有一个峰值。

**注:**关于直方图的更多信息,请查看 Python 直方图绘制:NumPyMatplotlibPandas & Seaborn

然而,中间数据的直方图在低于 40000 美元时在左边达到峰值。尾巴向右延伸很远,表明确实有专业可以期望更高收入的领域。

Remove ads

离群值

你发现分布右边那个孤独的小箱子了吗?好像一个数据点都有自己的类别。这个领域的专业不仅与平均水平相比,而且与亚军相比,他们的工资都很高。虽然这不是它的主要目的,但直方图可以帮助您检测这样的异常值。让我们更深入地研究一下异常值:

  • 这个离群值代表了哪些专业?
  • 它的边缘有多大?

与第一个概述相反,您只想比较几个数据点,但是您想看到关于它们的更多细节。对于这一点,条形图是一个很好的工具。首先,选择收入中位数最高的五个专业。您需要两步:

  1. 要按"Median"列排序,使用 .sort_values() ,并提供您要排序的列的名称以及方向ascending=False
  2. 要获得列表中的前五项,请使用.head()

让我们创建一个名为top_5的新数据帧:

In [15]: top_5 = df.sort_values(by="Median", ascending=False).head()

现在你有一个更小的数据框架,只包含前五名最赚钱的专业。下一步,您可以创建一个条形图,仅显示工资中位数最高的五个专业:

In [16]: top_5.plot(x="Major", y="Median", kind="bar", rot=5, fontsize=4)
Out[16]: <AxesSubplot:xlabel='Major'>

请注意,您使用了rotfontsize参数来旋转和调整 x 轴标签的大小,以便它们可见。您将看到一个包含 5 个条形的图:

bar plot with top 5 median

这张图显示,石油工程专业学生的工资中位数比其他专业高出 2 万多美元。第二名到第四名专业的收入彼此相对接近。

如果您有一个数据点的值比其他数据点的值高得多或低得多,那么您可能需要进一步调查。例如,您可以查看包含相关数据的列。

我们来调查一下所有薪资中位数在 6 万美元以上的专业。首先你需要用口罩df[df["Median"] > 60000]过滤这些专业。然后,您可以创建另一个条形图,显示所有三个收入栏:

In [17]: top_medians = df[df["Median"] > 60000].sort_values("Median")

In [18]: top_medians.plot(x="Major", y=["P25th", "Median", "P75th"], kind="bar")
Out[18]: <AxesSubplot:xlabel='Major'>

您应该会看到每个专业有三个小节的图,如下所示:

bar plot with multiple columns

第 25 和第 75 百分位证实了你在上面看到的:石油工程专业是目前收入最高的应届毕业生。

为什么您会对这个数据集中的异常值如此感兴趣?如果你是一个正在考虑选择哪个专业的大学生,你至少有一个非常明显的理由。但是从分析的角度来看,离群值也非常有趣。它们不仅可以显示资金充裕的行业,也可以显示无效数据。

任何数量的错误或疏忽都可能导致无效数据,包括传感器故障、手动数据输入过程中的错误,或者五岁儿童参加了针对十岁及以上儿童的焦点小组。调查异常值是数据清理的重要步骤。

即使数据是正确的,你可能会认为它与其他数据有很大的不同,它产生的噪音大于益处。让我们假设你分析一个小出版商的销售数据。您按地区对收入进行分组,并将它们与上一年的同一个月进行比较。然后出乎意料地,出版商拿到了一本全国畅销书。

这个愉快的事件让你的报告变得毫无意义。包括畅销书的数据在内,各地的销售额都在上升。在没有异常值的情况下执行相同的分析会提供更多有价值的信息,让你看到在纽约你的销售数字有了显著的提高,但是在迈阿密却变得更糟。

Remove ads

检查相关性

通常,您希望查看数据集的两列是否连接。如果你选择一个收入中位数较高的专业,你失业的几率是否也较低?首先,用这两列创建一个散点图:

In [19]: df.plot(x="Median", y="Unemployment_rate", kind="scatter")
Out[19]: <AxesSubplot:xlabel='Median', ylabel='Unemployment_rate'>

您应该会看到一个看起来很随意的图,就像这样:

scatter plot median unemployment

快速浏览一下这个数字可以发现,收入和失业率之间没有明显的相关性。

虽然散点图是获得可能的相关性的第一印象的极好工具,但它肯定不是联系的决定性证据。对于不同列之间的相关性的概述,可以使用 .corr() 。如果你怀疑两个值之间的相关性,那么你有几个工具来验证你的直觉和测量相关性有多强。

但是请记住,即使两个值之间存在相关性,也并不意味着一个值的变化会导致另一个值的变化。换句话说,关联并不意味着因果关系

分析分类数据

为了处理更大块的信息,人类大脑有意识和无意识地将数据分类。这种技术通常是有用的,但它远非完美无缺。

有时候,我们会把一些东西归入一个范畴,但经过进一步的检验,它们并不完全相似。在本节中,您将了解一些用于检查类别和验证给定分类是否有意义的工具。

许多数据集已经包含一些显式或隐式的分类。在当前示例中173 个专业分为 16 个类别。

分组

类别的一个基本用法是分组和聚合。您可以使用.groupby()来确定大学专业数据集中每个类别的受欢迎程度:

In [20]: cat_totals = df.groupby("Major_category")["Total"].sum().sort_values()

In [21]: cat_totals
Out[21]:
Major_category
Interdisciplinary                        12296.0
Agriculture & Natural Resources          75620.0
Law & Public Policy                     179107.0
Physical Sciences                       185479.0
Industrial Arts & Consumer Services     229792.0
Computers & Mathematics                 299008.0
Arts                                    357130.0
Communications & Journalism             392601.0
Biology & Life Science                  453862.0
Health                                  463230.0
Psychology & Social Work                481007.0
Social Science                          529966.0
Engineering                             537583.0
Education                               559129.0
Humanities & Liberal Arts               713468.0
Business                               1302376.0
Name: Total, dtype: float64

.groupby() ,你创建一个DataFrameGroupBy对象。用 .sum() ,你创建一个系列。

让我们画一个水平条形图,显示cat_totals中的所有类别总数:

In [22]: cat_totals.plot(kind="barh", fontsize=4)
Out[22]: <AxesSubplot:ylabel='Major_category'>

您应该会看到每个类别都有一个水平条的图:

barh plot categories

正如你的图所示,商业是迄今为止最受欢迎的主要类别。虽然人文学科和文科是明显的第二名,但其他领域的受欢迎程度更相似。

**注意:**包含分类数据的列不仅能为分析和可视化提供有价值的见解,它还提供了一个提高代码性能的机会

Remove ads

确定比率

如果你想看到你的类别之间的区别,垂直和水平条形图通常是一个不错的选择。如果你对比率感兴趣,那么饼图是一个很好的工具。然而,由于cat_totals包含一些更小的类别,用cat_totals.plot(kind="pie")创建一个饼图将产生几个带有重叠标签的小切片。

为了解决这个问题,您可以将较小的类别合并到一个组中。将总数低于 100000 的所有类别合并到一个名为"Other"的类别中,然后创建一个饼图:

In [23]: small_cat_totals = cat_totals[cat_totals < 100_000]

In [24]: big_cat_totals = cat_totals[cat_totals > 100_000]

In [25]: # Adding a new item "Other" with the sum of the small categories

In [26]: small_sums = pd.Series([small_cat_totals.sum()], index=["Other"])

In [27]: big_cat_totals = big_cat_totals.append(small_sums)

In [28]: big_cat_totals.plot(kind="pie", label="")
Out[28]: <AxesSubplot:>

请注意,您包含了参数label=""。默认情况下pandas 会添加一个带有列名的标签。这通常是有道理的,但在这种情况下,它只会增加噪音。

现在,您应该会看到这样的饼图:

pie plot category

这个类别仍然只占很小一部分。这是一个好迹象,表明合并这些小类别是正确的选择。

放大类别

有时您还想验证某个分类是否有意义。一个类别的成员是否比数据集中的其他成员更相似?同样,发行版是获得第一手概述的好工具。通常,我们期望一个类别的分布类似于正态分布,但是范围更小。

创建一个直方图,显示工程专业学生收入中位数的分布:

In [29]: df[df["Major_category"] == "Engineering"]["Median"].plot(kind="hist")
Out[29]: <AxesSubplot:ylabel='Frequency'>

你会得到一个直方图,你可以从一开始就与所有专业的直方图进行比较:

hist plot engineering median earnings

主要收入中位数的范围稍微小一些,从 40000 美元开始。该分布更接近正常,尽管其峰值仍在左侧。所以,即使你已经决定在工程类中选择一个专业,深入研究并更彻底地分析你的选择也是明智的。

结论

在本教程中,您已经学习了如何使用 Python 和 pandas 库开始可视化数据集。您已经看到了一些基本图如何让您深入了解数据并指导您的分析。

在本教程中,您学习了如何:

  • 通过直方图了解数据集的分布概况
  • 发现与散点图的相关性
  • 条形图分析类别,用饼图分析它们的比率
  • 确定哪个图最适合你当前的任务

使用.plot()和一个小的数据框架,您发现了提供数据图片的多种可能性。现在,您已经准备好在这些知识的基础上探索更复杂的可视化。

如果你有任何问题或意见,请写在下面的评论区。

Remove ads

延伸阅读

虽然 pandas 和 Matplotlib 使您的数据可视化变得非常简单,但创建更复杂、更美丽或更吸引人的图还有无限的可能性。

一个很好的起点是 pandas DataFrame 文档的绘图部分。它包含了一个很好的概述和一些详细的描述,描述了您可以在数据框中使用的许多参数。

如果你想更好地理解熊猫绘图的基础,那么就多了解一下 Matplotlib。虽然文档有时会让人不知所措但 Matplotlib 的剖析在介绍一些高级特性方面做得非常出色。

如果你想用交互式可视化给你的观众留下深刻印象,并鼓励他们自己探索数据,那么让散景成为你的下一站。你可以在使用散景的 Python 交互式数据可视化中找到散景特性的概述。你也可以用 pandas-bokeh配置熊猫使用散景而不是 Matplotlib

如果您想为统计分析或科学论文创建可视化效果,请查看 Seaborn 。你可以在 Python 直方图绘制中找到关于 Seaborn 的小课。

立即观看本教程有真实 Python 团队创建的相关视频课程。配合文字教程一起看,加深理解: 与熊猫的剧情:Python 数据可视化基础知识*****