Python 3 中使用 pandas 和 Jupyter Notebook 进行数据分析和可视化

前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站

简介

Python 的 pandas 包用于数据操作和分析,旨在让您以直观的方式处理带标签或关系型数据。

pandas 包提供了电子表格功能,但因为您正在使用 Python,所以它比传统的图形电子表格程序要快得多,效率更高。

在本教程中,我们将介绍如何设置一个大型数据集,pandasgroupby()pivot_table() 函数,以及如何可视化数据。

要熟悉 pandas 包,您可以阅读我们的教程《Python 3 中 pandas 包及其数据结构的介绍》。

先决条件

本指南将介绍如何在本地桌面或远程服务器上使用 pandas 处理数据。处理大型数据集可能会占用大量内存,因此在任何情况下,计算机都需要至少 2GB 内存 来执行本指南中的一些计算。

在本教程中,我们将使用 Jupyter Notebook 来处理数据。如果您还没有安装它,您应该按照我们的教程安装和设置 Python 3 的 Jupyter Notebook。

设置数据

在本教程中,我们将使用美国社会保障网站上提供的有关婴儿姓名的数据,该数据以 8MB 的压缩文件形式提供。

让我们在本地计算机上激活我们的 Python 3 编程环境,或者在服务器上从正确的目录中激活:

cd environments
. my_env/bin/activate

现在让我们为我们的项目创建一个新目录。我们可以称之为 names,然后进入该目录:

mkdir names
cd names

在这个目录中,我们可以使用 curl 命令从社会保障网站获取 zip 文件:

curl -O https://www.ssa.gov/oact/babynames/names.zip

文件下载完成后,让我们验证我们将要使用的所有软件包是否已安装:

  • numpy 用于支持多维数组
  • matplotlib 用于可视化数据
  • pandas 用于数据分析
  • seaborn 用于美化我们的 matplotlib 统计图形

如果您还没有安装这些软件包中的任何一个,可以使用 pip 安装它们,如下所示:

pip install pandas
pip install matplotlib
pip install seaborn

如果您还没有安装 numpy 软件包,它也将被安装。

现在我们可以启动 Jupyter Notebook:

jupyter notebook

一旦您进入 Jupyter Notebook 的 Web 界面,您将在那里看到 names.zip 文件。

要创建一个新的笔记本文件,请从右上角的下拉菜单中选择 New > Python 3

!创建一个新的 Python 3 笔记本

这将打开一个笔记本。

让我们从导入我们将要使用的软件包开始。在我们的笔记本顶部,我们应该写入以下内容:

import numpy as np
import matplotlib.pyplot as pp
import pandas as pd
import seaborn

我们可以运行此代码,并通过键入 ALT + ENTER 进入新的代码块。

让我们还告诉 Python Notebook 在线保留我们的图形:

matplotlib inline

让我们运行代码,并通过键入 ALT + ENTER 继续。

从这里,我们将继续解压缩 zip 存档,将 CSV 数据集加载到 pandas 中,然后连接 pandas DataFrames。

解压缩 Zip 存档

要将 zip 存档解压缩到当前目录中,我们将导入 zipfile 模块,然后使用文件名(在我们的情况下是 names.zip)调用 ZipFile 函数:

import zipfile
zipfile.ZipFile('names.zip').extractall('.')

我们可以运行代码,并通过键入 ALT + ENTER 继续。

现在,如果您回到您的 names 目录,您将在其中看到以 CSV 格式存储的姓名数据的 .txt 文件。这些文件将对应于文件中的年份数据,从 1881 年到 2015 年。这些文件都遵循类似的命名约定。例如,2015 年的文件名为 yob2015.txt,而 1927 年的文件名为 yob1927.txt

为了查看其中一个文件的格式,让我们使用 Python 打开一个文件并显示前 5 行:

open('yob2015.txt','r').readlines()[:5]

运行代码,并通过键入 ALT + ENTER 继续。

['Emma,F,20355\n',
 'Olivia,F,19553\n',
 'Sophia,F,17327\n',
 'Ava,F,16286\n',
 'Isabella,F,15504\n']

数据的格式是先是姓名(如 EmmaOlivia),然后是性别(女性姓名为 F,男性姓名为 M),然后是当年使用该姓名的婴儿数量(2015 年出生的名为 Emma 的婴儿有 20,355 个)。

有了这些信息,我们就可以将数据加载到 pandas 中。

将 CSV 数据加载到 pandas

要将逗号分隔值数据加载到 pandas 中,我们将使用 pd.read_csv() 函数,传递文本文件的名称以及我们决定的列名。我们将把这个赋值给一个变量,这里我们使用 names2015,因为我们使用的是 2015 年出生文件的数据。

names2015 = pd.read_csv('yob2015.txt', names = ['Name', 'Sex', 'Babies'])

键入 ALT + ENTER 来运行代码并继续。

为了确保这个操作成功,让我们显示表的顶部:

names2015.head()

当我们运行代码并继续使用 ALT + ENTER 时,我们将看到如下输出:

!names2015.head 输出

我们的表现在包含了按列组织的名称、性别和每个名称出生的婴儿数量的信息。

连接 pandas 对象

连接 pandas 对象将允许我们处理 names 目录中的所有单独的文本文件。

为了连接这些文件,我们首先需要通过将变量赋值给一个未填充的列表数据类型来初始化一个列表:

all_years = []

一旦我们这样做了,我们将使用 for 循环来遍历所有年份的文件,这些文件的范围是从 1880 年到 2015 年。我们将在 2015 年的末尾添加 +1,以便在循环中包括 2015 年。

all_years = []

for year in range(1880, 2015+1):

在循环内部,我们将使用字符串格式化程序将每个文本文件的值附加到列表中,使用字符串格式化程序来处理每个文件的不同名称。我们将这些值传递给 year 变量。同样,我们将为 NameSexBabies 指定列:

all_years = []

for year in range(1880, 2015+1):
    all_years.append(pd.read_csv('yob{}.txt'.format(year),
                                 names = ['Name', 'Sex', 'Babies']))

此外,我们将为每一年创建一个列,以保持这些列的顺序。我们可以在每次迭代后使用索引 -1 来指向它们,以便随着循环的进行而进行操作。

all_years = []

for year in range(1880, 2015+1):
    all_years.append(pd.read_csv('yob{}.txt'.format(year),
                                 names = ['Name', 'Sex', 'Babies']))
    all_years[-1]['Year'] = year

最后,我们将使用 pd.concat() 函数将其添加到 pandas 对象中进行连接,并使用变量 all_names 存储这些信息。

all_years = []

for year in range(1880, 2015+1):
    all_years.append(pd.read_csv('yob{}.txt'.format(year),
                                 names = ['Name', 'Sex', 'Babies']))
    all_years[-1]['Year'] = year

all_names = pd.concat(all_years)

我们现在可以使用 ALT + ENTER 运行循环,然后通过调用结果表的尾部(最底部的行)来检查输出:

all_names.tail()

!all_names.tail 输出

我们的数据集现在已经完整,准备在 pandas 中进行进一步的处理。

数据分组

使用 pandas,您可以使用 .groupby() 函数按列对数据进行分组。使用我们的 all_names 变量作为完整数据集,我们可以使用 groupby() 将数据分割成不同的桶。

让我们按性别和年份对数据集进行分组。我们可以这样设置:

group_name = all_names.groupby(['Sex', 'Year'])

我们可以运行代码并继续使用 ALT + ENTER

此时,如果我们只调用 group_name 变量,我们将得到这样的输出:


<pandas.core.groupby.DataFrameGroupBy object at 0x1187b82e8>

这向我们显示它是一个 DataFrameGroupBy 对象。这个对象包含了如何对数据进行分组的指令,但它没有给出如何显示值的指令。

要显示值,我们需要给出指令。我们可以计算 .size().mean().sum(),例如,来返回一个表。

让我们从 .size() 开始:

group_name.size()

当我们运行代码并继续使用 ALT + ENTER 时,我们的输出将如下所示:


Sex  Year
F    1880      942
     1881      938
     1882     1028
     1883     1054
     1884     1172
...

这些数据看起来不错,但它可能更易读。我们可以通过附加 .unstack 函数来使其更易读:

group_name.size().unstack()

现在当我们运行代码并继续输入 ALT + ENTER 时,输出将如下所示:

!group_name.size().unstack() 输出

这些数据告诉我们每年有多少个女性和男性的名字。例如,在 1889 年,有 1,479 个女性名字和 1,111 个男性名字。在 2015 年,有 18,993 个女性名字和 13,959 个男性名字。这显示了随着时间的推移,名字的多样性增加。

如果我们想要得到出生的总婴儿数,我们可以使用 .sum() 函数。让我们将其应用于一个较小的数据集,即我们之前创建的单个 yob2015.txt 文件的 names2015 集:

names2015.groupby(['Sex']).sum()

让我们键入 ALT + ENTER 来运行代码并继续:

names2015.groupby(['Sex']).sum() 输出

这显示了 2015 年出生的男性和女性婴儿的总数,尽管数据集中只计算了那一年至少使用 5 次的名字的婴儿。

pandas.groupby() 函数允许我们将数据分割成有意义的组。

透视表

透视表对于总结数据非常有用。它们可以自动对存储在一个表中的数据进行排序、计数、求和或求平均值。然后,它们可以在一个新的表中显示这些操作的结果。

pandas 中,使用 pivot_table() 函数来创建透视表。

要构建一个透视表,我们首先会调用我们想要处理的 DataFrame,然后是我们想要显示的数据以及它们如何分组。

在这个例子中,我们将使用 all_names 数据,并按照一个维度中的名称和另一个维度中的年份来显示婴儿数据:

pd.pivot_table(all_names, 'Babies', 'Name', 'Year')

当我们键入 ALT + ENTER 来运行代码并继续时,我们将看到以下输出:

!pd.pivot_table(all_names, ‘Babies’, ‘Name’, ‘Year’) 输出

因为这显示了很多空值,我们可能希望将名称和年份保留为列,而不是在一个情况下作为行,在另一个情况下作为列。我们可以通过在方括号中对数据进行分组来实现:

pd.pivot_table(all_names, 'Babies', ['Name', 'Year'])

一旦我们键入 ALT + ENTER 来运行代码并继续,这个表现在只会显示每个名称记录的年份的数据:

Name       Year
Aaban      2007     5.0
           2009     6.0
           2010     9.0
           2011    11.0
           2012    11.0
           2013    14.0
           2014    16.0
           2015    15.0
Aabha      2011     7.0
           2012     5.0
           2014     9.0
           2015     7.0
Aabid      2003     5.0
Aabriella  2008     5.0
           2014     5.0
           2015     5.0

此外,我们可以将数据分组为一个维度中的名称和性别,另一个维度中的年份,如下所示:

pd.pivot_table(all_names, 'Babies', ['Name', 'Sex'], 'Year')

当我们运行代码并继续使用 ALT + ENTER 时,我们将看到以下表格:

pd.pivot_table(all_names, 'Babies', ['Name', 'Sex'], 'Year') 输出

透视表让我们可以从现有表格中创建新表格,从而可以决定如何对数据进行分组。

可视化数据

通过使用 pandas 与其他包如 matplotlib,我们可以在笔记本中可视化数据。

我们将要可视化有关特定名称多年来的受欢迎程度的数据。为了做到这一点,我们需要设置和排序索引以重新处理数据,这将允许我们看到特定名称受欢迎程度的变化。

pandas 包让我们可以进行分层或多级索引,这使我们能够存储和操作具有任意数量维度的数据。

我们将使用性别、名称和年份的信息来索引我们的数据。我们还希望对索引进行排序:

all_names_index = all_names.set_index(['Sex','Name','Year']).sort_index()

键入 ALT + ENTER 来运行并继续到我们的下一行,我们将让笔记本显示新的索引 DataFrame:

all_names_index

运行代码并继续使用 ALT + ENTER,输出将如下所示:

!all_names_index 输出

接下来,我们将编写一个函数来绘制名称随时间的受欢迎程度。我们将命名该函数为 name_plot,并将 sexname 作为参数传递,这样我们在运行函数时就可以调用它们。

def name_plot(sex, name):

现在,我们将设置一个名为 data 的变量来保存我们创建的表。我们还将使用 pandas DataFrame 的 loc 来根据索引的值选择我们的行。在我们的情况下,我们希望 loc 基于 MultiIndex 中的字段组合,涉及到 sexname 数据。

让我们将这个构造写入我们的函数中:

def name_plot(sex, name):
    data = all_names_index.loc[sex, name]

最后,我们将使用 matplotlib.pyplot 来绘制值,我们将其导入为 pp。然后,我们将性别和名称数据的值绘制到我们的索引上,对于我们的目的来说,这个索引是年份。

def name_plot(sex, name):
    data = all_names_index.loc[sex, name]
    
    pp.plot(data.index, data.values)

键入 ALT + ENTER 来运行代码并移动到下一个单元格。现在我们可以使用我们选择的性别和名称来调用函数,比如使用给定名称 Danica 的女性名称 F

name_plot('F', 'Danica')

当你现在键入 ALT + ENTER,你将收到以下输出:

!Danica 名称绘图 输出

请注意,根据您使用的系统,您可能会收到有关字体替换的警告,但数据仍将正确绘制。

通过查看可视化,我们可以看到女性名称 Danica 在 1990 年左右有一小波动,并在 2010 年之前达到了高峰。

我们创建的函数可以用于绘制多个名称的数据,这样我们就可以看到不同名称随时间的趋势。

让我们首先将我们的绘图稍微放大一点:

pp.figure(figsize = (18, 8))

接下来,让我们创建一个包含我们想要绘制的所有名称的列表:

pp.figure(figsize = (18, 8))

names = ['Sammy', 'Jesse', 'Drew', 'Jamie']

现在,我们可以通过 for 循环迭代列表,并为每个名称绘制数据。首先,我们将尝试将这些性别中性的名称作为女性名称:

pp.figure(figsize = (18, 8))

names = ['Sammy', 'Jesse', 'Drew', 'Jamie']

for name in names:
    name_plot('F', name)

为了使这些数据更容易理解,让我们包括一个图例:

pp.figure(figsize = (18, 8))

names = ['Sammy', 'Jesse', 'Drew', 'Jamie']

for name in names:
    name_plot('F', name)
    
pp.legend(names)

我们将键入 ALT + ENTER 来运行代码并继续,然后我们将收到以下输出:

!名称绘图,女性名称 输出

尽管每个名称作为女性名称的受欢迎程度都在缓慢增长,但在 1980 年左右,名称 Jamie 作为女性名称的受欢迎程度是压倒性的。

让我们以相同的名称绘制相同的名称,但这次作为男性名称:

pp.figure(figsize = (18, 8))

names = ['Sammy', 'Jesse', 'Drew', 'Jamie']

for name in names:
    name_plot('M', name)
    
pp.legend(names)

再次键入 ALT + ENTER 来运行代码并继续。图表将如下所示:

!名称绘图,男性名称 输出

这些数据显示了更多名称的受欢迎程度,Jesse 通常是最受欢迎的选择,并且在 1980 年代和 1990 年代特别受欢迎。

从这里开始,您可以继续处理名称数据,创建关于不同名称及其受欢迎程度的可视化,并创建其他脚本来查看不同的数据以进行可视化。

结论

本教程介绍了处理大型数据集的方法,从设置数据开始,到使用 groupby()pivot_table() 对数据进行分组,使用 MultiIndex 对数据进行索引,并使用 matplotlib 包可视化 pandas 数据。

许多组织和机构提供数据集,您可以继续学习 pandas 和数据可视化。例如,美国政府通过 data.gov 提供数据。

您可以通过阅读我们的指南《如何使用 matplotlib 在 Python 3 中绘制数据》和《如何使用 Python 3 中的 matplotlib 绘制词频图表》来了解更多关于使用 matplotlib 可视化数据的内容。

  • 29
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

白如意i

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值