H5W3
当前位置:H5W3 > 其他技术问题 > 正文

Python Numpy数组教程

本文概述

NumPy就像SciPy, Scikit-Learn, Pandas等一样, 是你学习数据科学时不容错过的软件包之一, 主要是因为该库为你提供了一个数组数据结构, 该结构具有一些优点Python列表, 例如:更紧凑, 读写项目的访问速度更快, 更方便, 更高效。

今天的帖子将重点关注这一点。此NumPy教程不仅将向你展示NumPy数组的实际含义以及如何安装Python, 而且还将学习如何制作数组(即使数据来自文件!), 广播的工作方式, 如何请求帮助, 如何操作数组以及如何对其进行可视化。

内容

  • 什么是Python Numpy数组?
  • 如何安装Numpy
  • 如何制作NumPy数组
  • NumPy广播如何工作
  • 数组数学如何工作?
  • 如何子集, 切片和索引数组
  • 如何寻求帮助
  • 如何操作数组
  • 如何可视化NumPy数组
  • 使用NumPy进行数据分析之外

如果你想进一步了解NumPy数组和数据科学过程中所需的其他数据结构, 请考虑阅读srcmini的Python数据科学入门, 其中有NumPy一章。

什么是Python Numpy数组?

你已经在介绍中读到了NumPy数组有点像Python列表, 但同时仍然有很大的不同。对于那些不熟悉该主题的人, 让我们澄清一下它的确切含义和优点。

顾名思义, NumPy数组是numpy库的中央数据结构。该库的名称是”数字Python”或”数字Python”的缩写。

这已经使你了解正在处理的内容, 对吗?

换句话说, NumPy是一个Python库, 它是Python中科学计算的核心库。它包含可用于在计算机上解决科学与工程问题数学模型的工具和技术的集合。这些工具之一是高性能多维数组对象, 它是用于高效计算数组和矩阵的强大数据结构。要使用这些数组, 需要对这些矩阵和数组进行大量的高级数学运算。

那么, 什么是数组?

当你查看几个数组的打印内容时, 可能会看到它是一个包含相同类型值的网格:

你会看到, 在上面的示例中, 数据是整数。该数组以结构化方式保存并表示任何常规数据。

但是, 你应该知道, 从结构上讲, 数组基本上就是指针。它是内存地址, 数据类型, 形状和步幅的组合:

  • 数据指针指示数组中第一个字节的内存地址,
  • 数据类型或dtype指针描述了数组中包含的元素的类型,
  • 形状表示阵列的形状, 并且
  • 跨度是应在内存中跳过以转到下一个元素的字节数。如果你的步幅为(10, 1), 则需要前进一个字节才能到达下一列, 而前进10字节才能找到下一行。

或者换句话说, 数组包含有关原始数据, 如何定位元素以及如何解释元素的信息。

足够的理论。让我们自己检查一下:

你可以通过探索numpy数组属性来轻松地测试它:

你现在会看到更多信息:例如, 打印出的数据类型是” int64″或带符号的32位整数类型;这要详细得多!这也意味着该数组以64个字节的形式存储在内存中(每个整数占用8个字节, 并且你有一个8个整数的数组)。数组的步幅告诉我们, 你必须跳过8个字节(一个值)才能移到下一列, 但是要跳过32个字节(4个值)才能到达下一行的相同位置。这样, 数组的步幅将为(32, 8)。

请注意, 如果将数据类型设置为int32, 则返回的步幅元组将为(16, 4), 因为你仍然需要将一个值移至下一列, 将4个值移至同一位置。唯一会改变的事实是每个整数将占用4个字节而不是8个字节。

numpy数组轴

顾名思义, 你在上面看到的数组是一个二维数组:你有行和列。行表示为”轴0″, 而列表示为”轴1″。轴的数量随尺寸的数量而增加:在3D数组中, 你在上一个代码块中也看到了一个示例, 你将拥有一个附加的”轴2″。请注意, 这些轴仅适用于至少二维的数组, 因为对于一维数组没有意义。

这些轴将在以后处理NumPy数组的形状时派上用场。

如何安装Numpy

在开始自己尝试使用这些NumPy阵列之前, 首先必须确保已在本地安装(假设你正在使用PC)。如果你已经拥有Python库, 请继续并跳过此部分:)

如果仍然需要设置环境, 则必须意识到在PC上安装NumPy的主要方法有两种:借助Python wheel或Anaconda Python发行版。

…使用Python轮子

首先确保你已安装Python。如果你仍然需要这样做, 可以去这里:)

如果你使用的是Windows, 请确保已将Python添加到PATH环境变量中。然后, 别忘了安装软件包管理器, 例如pip, 它将确保你能够使用Python的开源库。

请注意, Python 3的最新版本附带了pip, 因此请在安装NumPy之前仔细检查是否已安装, 如果有, 请对其进行升级:


 pip install pip --upgrade
 pip --version

接下来, 你可以在这里或这里获取NumPy滚轮。下载后, 导航至PC上通过终端存储它的文件夹并安装它:


install "numpy-1.9.2rc1+mkl-cp34-none-win_amd64.whl"
import numpy
numpy.__version__

最后两行允许你验证是否已安装NumPy并检查软件包的版本。

完成这些步骤后, 你就可以开始使用NumPy了!

…通过Anaconda Python发行版

要获取NumPy, 你还可以下载Anaconda Python发行版。这很容易, 可以让你快速入门!如果你还没有下载, 请去这里获取。按照说明进行安装, 就可以开始了!

你想知道为什么这实际上会更容易吗?

获得此Python发行版的好处是, 你无需担心单独安装NumPy或将用于数据分析的任何主要软件包(例如pandas, scikit-learn, 等等

因为, 特别是如果你是Python, 编程或终端的新手, 那么, Anaconda已经包含100个最受欢迎的Python, R和Scala数据科学软件包, 确实可以让你感到轻松。对于经验丰富的数据科学家而言, Anaconda是你要快速开始解决数据科学问题的理想之选。

此外, Anaconda还包括几个开源开发环境, 例如Jupyter和Spyder。如果你想在本教程之后开始使用Jupyter Notebook, 请转至此页面。

简而言之, 请考虑下载Anaconda, 以开始使用numpy和其他与数据科学相关的软件包!

如何制作NumPy数组

因此, 既然你已经设置好环境, 就该进行实际工作了。诚然, 你已经在上面的srcmini Light块中使用数组尝试了一些东西。但是, 你实际上并没有进行任何实际动手实践, 因为你首先需要在自己的PC上安装NumPy。现在, 你已经完成了操作, 现在该看看需要执行什么操作才能自己运行上述代码块。

下面包含一些练习, 因此你可以自己练习如何做!

要创建一个numpy数组, 你只需使用np.array()函数。你需要做的只是向其传递一个列表, 并且你还可以选择指定数据的数据类型。如果你想进一步了解可以选择的数据类型, 请转到此处或考虑简要了解一下srcmini的NumPy速查表。

如果你是新用户, 则无需记住这些NumPy数据类型;但是, 你必须知道并关心要处理的数据。当你需要更好地控制数据在内存和磁盘中的存储方式时, 可以使用数据类型。特别是在你要处理大量数据的情况下, 最好知道存储类型。

别忘了, 为了使用np.array()函数, 你需要确保环境中存在numpy库。 NumPy库遵循导入约定:导入该库时, 必须确保将其导入为np。这样, 你可以确保其他Pythonista使用者更轻松地理解你的代码。

在以下示例中, 你将创建上面已经使用过的my_array数组:

如果你想进一步了解如何制作列表, 请转到此处。

但是, 有时你不知道要在数组中放入哪些数据, 或者想从其他来源将数据导入numpy数组。在这种情况下, 你将利用初始占位符或函数将数据从文本分别加载到数组中。

以下各节将向你展示如何执行此操作。

如何制作一个”空”的NumPy数组

人们说要创建”空”数组时经常表示的意思是, 他们想使用初始占位符, 你可以在以后填充。你可以使用1或0初始化数组, 但也可以创建以均匀间隔的值, 常量或随机值填充的数组。

但是, 你仍然可以制作一个完全空的数组。

幸运的是, 我们有很多功能

尝试所有下面!

提示:尝试以上功能, 以便你了解它们的工作原理!

  • 对于某些对象, 例如np.ones(), np.random.random(), np.empty(), np.full()或np.zeros(), 你要做的唯一事情就是使用数组1或0将传递你要制作的数组的形状。作为np.ones()和np.zeros()的选项, 你还可以指定数据类型。对于np.full(), 还必须指定要插入到数组中的常量值。
  • 使用np.linspace()和np.arange()可以创建均匀间隔的值的数组。这两个函数之间的区别在于, 在上面的代码块中传递的三个函数的最后一个值指定np.linspace()的步进值或np.arange()的多个样本。第一种情况是你想要的, 例如, 一个9个值的数组, 它们位于0到2之间。对于后者, 你指定希望一个数组从10开始并以5的步长生成该值。你正在创建的数组。

请记住, NumPy还允许你使用np.eye()和np.identity()创建一个标识数组或矩阵。单位矩阵是一个方矩阵, 其主对角线上的所有元素均为1, 所有其他元素均为零。当你将矩阵与单位矩阵相乘时, 给定的矩阵将保持不变。

换句话说, 如果将矩阵乘以单位矩阵, 则乘以矩阵乘法的标准惯例, 所得乘积将再次为同一矩阵。

即使本教程的重点不是演示身份矩阵的工作原理, 也可以说身份矩阵在你开始进行矩阵计算时很有用:它们可以简化数学方程式, 从而使你的计算更加高效和健壮。

如何从文本加载NumPy数组

在初始占位符或一些示例数据的帮助下创建数组是使用numpy的绝佳方法。但是, 当你要开始进行数据分析时, 需要从文本文件中加载数据。

到目前为止, 你所看到的一切将使你真正无法做很多事情。利用某些特定功能从文件中加载数据, 例如loadtxt()或genfromtxt()。

假设你有以下带有数据的文本文件:


# This is your data in the text file
# Value1  Value2  Value3
# 0.2536  0.1008  0.3857
# 0.4839  0.4536  0.3561
# 0.1292  0.6875  0.5929
# 0.1781  0.3049  0.8928
# 0.6253  0.3486  0.8791

# Import your data
x, y, z = np.loadtxt('data.txt', skiprows=1, unpack=True)

在上面的代码中, 你使用loadtxt()在你的环境中加载数据。你会看到两个函数都采用的第一个参数是文本文件data.txt。接下来, 每个参数都有一些特定的参数:在第一条语句中, 跳过第一行, 并使用unpack = TRUE将列作为单独的数组返回。这意味着Value1列中的值将放入x, 依此类推。

请注意, 如果你有逗号分隔的数据或要指定数据类型, 则还可以将参数delimiter和dtype添加到loadtxt()参数中。

这很简单明了, 对不对?

让我们看一下第二个包含数据的文件:


# Your data in the text file
# Value1  Value2  Value3
# 0.4839  0.4536  0.3561
# 0.1292  0.6875  MISSING
# 0.1781  0.3049  0.8928
# MISSING 0.5801  0.2038
# 0.5993  0.4357  0.7410

my_array2 = np.genfromtxt('data2.txt', skip_header=1, filling_values=-999)

你会在这里看到, 你诉诸genfromtxt()来加载数据。在这种情况下, 你必须处理” MISSING”字符串指示的某些缺失值。由于genfromtxt()函数将数字列中的字符串转换为nan, 因此你可以通过指定filling_values参数将这些值转换为其他值。在这种情况下, 你选择将这些缺失值的值设置为-999。

如果碰巧你的值无法通过genfromtxt()转换为nan, 则始终会有missing_values参数, 可让你指定数据的确切缺失值。

但这并不是全部。

提示:请查看此页面, 查看可以添加哪些其他参数以成功导入数据。

你现在可能想知道这两个功能之间的真正区别是什么。

这些示例可能暗示了这一点, 但是总的来说, genfromtxt()给你更多的灵活性。比loadtxt()更强大。

让我们使这种区别更加实用:后者, loadtxt()仅在文本文件中的每一行具有相同数量的值时才有效;因此, 当你想轻松处理缺失值时, 通常会发现使用genfromtxt()更容易。

但这绝对不是唯一的原因。

简要了解genfromtxt()所提供的参数数量将使你了解, 实际上你可以在导入中指定更多的东西, 例如要读取的最大行数或自动剥离白色的选项变量中的空格。

如何保存NumPy数组

完成阵列所需的所有操作后, 还可以将它们保存到文件中。如果要将数组保存到文本文件, 可以使用savetxt()函数执行以下操作:


import numpy as np
x = np.arange(0.0, 5.0, 1.0)
np.savetxt('test.out', x, delimiter=', ')

请记住, np.arange()创建了一个NumPy数组, 这些数组由均匀间隔的值组成。你传递给该函数的第三个值是步长值。

当然, 还有其他方法可以将NumPy数组保存到文本文件。如果要将数据保存到二进制文件或档案中, 请查看下表中的功能:

save() 将数组保存为NumPy .npy格式的二进制文件
savez() 将几个数组保存到未压缩的.npz存档中
savez_compressed() 将多个数组保存到压缩的.npz存档中

有关如何使用上述功能保存数据的更多信息或示例, 请转到此处或使用NumPy提供的帮助功能之一, 以立即了解更多信息!

你不确定这些NumPy帮助功能是什么吗?

别担心!你将在下一小节中进一步了解它们!

如何检查你的NumPy阵列

除了上面提到的数组属性(即数据, 形状, dtype和跨度)外, 你还可以使用其他一些属性轻松地了解数组。刚开始使用时可能会觉得有趣的是:

这些几乎是数组可以拥有的所有属性。

此时, 如果你不觉得它们对你有用, 请不要担心;这是很正常的做法, 因为就像你在上一节中所读到的那样, 只有在处理大型数据集时才需要担心内存问题。

还要注意, 除了属性外, 你还可以通过其他方法来获取更多信息, 甚至可以稍微调整数组:

现在, 你已经可以通过使用np.array()或初始占位符功能之一来创建数组, 或者通过loadtxt()或genfromtxt()函数来加载数据, 现在是时候看更多了紧密定义了真正定义NumPy库的第二个关键元素:科学计算。

NumPy广播如何工作

在深入研究科学计算之前, 最好先仔细了解什么是确切的广播:它是一种机制, 可以让NumPy在执行算术运算时处理不同形状的数组。

为了更实际地进行说明, 你通常会使用一个较大的数组, 而另一个数组则稍小。理想情况下, 你希望多次使用较小的数组对较大的数组执行运算(例如求和, 乘法等)。

为此, 你可以使用广播机制。

但是, 如果要使用它, 则有一些规则。而且, 在你叹口气之前, 你会发现这些”规则”非常简单, 也很简单!

  • 首先, 为确保广播成功, 阵列的尺寸必须兼容。两个维度相等时是兼容的。考虑以下示例:
  • 当其中之一为1时, 两个维度也兼容:

请注意, 如果尺寸不兼容, 则会出现ValueError。

提示:完成计算后, 还要测试结果数组的大小!你会看到大小实际上是输入数组每个维度上的最大大小。

换句话说, 你看到x-y的结果给出了形状为(3, 4)的数组:y的形状为(4, ), x的形状为(3, 4)。沿x和y的每个维度的最大大小用于组成新的结果数组的形状。

  • 最后, 如果阵列在所有维度上都兼容, 则只能一起广播。考虑以下示例:

你会看到, 即使x和y似乎有一些不同的尺寸, 也可以将两者加在一起。

这是因为它们在所有维度上都是兼容的:

  • 数组x的尺寸为3 X 4,
  • 数组y的尺寸为5 X 1 X 4

由于你已经在上面看到, 如果其中之一等于1, 那么维度也是兼容的, 因此你会看到这两个数组确实是广播的不错选择!

你会注意到, 在y的大小为1的维中, 另一个数组的大小大于1(即3), 第一个数组的行为就像是沿着该维复制的一样。

请注意, 结果数组的形状将再次为沿x和y的每个维度的最大大小:结果的维度将为(5, 3, 4)

简而言之, 如果你想利用广播, 你将在很大程度上依赖于要处理的阵列的形状和尺寸。

但是, 如果尺寸不兼容怎么办?

如果它们不相等或其中之一不等于1怎么办?

你必须通过操作数组来解决此问题!你将在下一部分中看到如何执行此操作。

数组数学如何工作?

你已经看到, 进行算术运算时, 广播很方便。在本节中, 你将发现一些可用于对数组进行数学运算的函数。

因此, 只要使用+, -, *, /或%来加, 减, 乘, 除或计算两个(或多个)数组的余数, 可能不会让你感到惊讶。但是, 为什么NumPy如此方便的很大一部分是因为它也具有执行此操作的功能。你刚才看到的操作的等效功能分别是np.add(), np.subtract(), np.multiply(), np.divide()和np.remainder()。

你还可以使用np.exp()和np.sqrt()轻松进行求幂并取数组的平方根, 或者使用np.sin()和np.cos()计算数组的正弦或余弦。最后, 提到一个有用的方法也是有用的, 你可以使用np.log()计算自然对数, 或者通过将dot()应用于数组来计算点积。

在下面的srcmini Light块中全部尝试。

提示:确保先检查一下已为此练习加载的阵列!

还记得广播的运作方式吗?在你的IPython Shell中检查x和y的尺寸和形状。是否遵守广播规则?

但是还有更多。

查看以下汇总函数列表:

a.sum() 阵列求和
a.min() 数组最小值
b.max(轴= 0) 数组行的最大值
b.cumsum(轴= 1) 元素的累计和
一个平均值() 意思
b.median() 中位数
a.corrcoef() 相关系数
np.std(b)中 标准偏差

除了所有这些功能之外, 了解某些机制可以比较数组元素也可能会很有用。例如, 如果要检查两个数组的元素是否相同, 则可以使用==运算符。要检查数组元素是较小还是较大, 请使用<或>运算符。

这一切看起来都很简单, 是吗?

但是, 你也可以将整个数组相互比较!在这种情况下, 请使用np.array_equal()函数。只需传入你要相互比较的两个数组, 就可以完成。

请注意, 除了比较之外, 你还可以对阵列执行逻辑操作。你可以从np.logical_or(), np.logical_not()和np.logical_and()开始。这基本上就像你的典型OR, NOT和AND逻辑运算一样;

在最简单的示例中, 你使用OR来查看元素是否相同(例如1), 或者两个数组元素之一是否为1。如果两个元素均为0, 则返回FALSE。你将使用AND来查看第二个元素是否也为1, 而不是查看第二个元素是否不同于1。

在下面的代码块中进行测试:

如何子集, 切片和索引数组

除了数学运算之外, 你还可以考虑仅获取原始数组(或所得数组)的一部分, 或仅获取某些数组元素以用于进一步分析或其他运算。在这种情况下, 你将需要对数组进行子集化, 切片化和/或索引化。

这些操作与在Python列表上执行它们时非常相似。如果你想亲自检查相似之处, 或者想要更详尽的说明, 则可以考虑查看srcmini的Python列表教程。

如果你对这些操作的工作方式一无所知, 那么现在就足以了解以下两个基本知识:

  • 你使用方括号[]作为索引运算符, 然后
  • 通常, 你将整数传递到这些方括号中, 但是你也可以放置冒号:或冒号与整数的组合, 以指定要选择的元素/行/列。

除了这两点, 查看所有内容如何组合的最简单方法是查看一些子集示例:

如果可以的话, 比分集要先进一些。在这里, 你不仅考虑数组的特定值, 还考虑行和列的级别。你基本上是在处理数据的”区域”, 而不是纯粹的”位置”。

你可以在以下代码示例中看到此类比的含义:

你实质上将看到以下内容:


a[start:end] # items start through the end (but the end is not included!)
a[start:]    # items start through the rest of the array
a[:end]      # items from the beginning through the end (but the end is not included!)

最后, 还有索引。对于NumPy, 有布尔索引和高级或”奇特”索引。

(如果你想知道, 这是真正的NumPy行话, 我没有提出最后一个!)

首先是布尔索引。在这里, 你无需从索引号中选择元素, 行或列, 而是从数组中选择满足特定条件的值。

将其放入代码中非常容易:

请注意, 要指定条件, 你还可以使用逻辑运算符|。 (OR)和&(AND)。如果你想以这种方式重写上面的条件(效率低下, 但是我出于教育目的在这里演示了它:)), 你将获得big_than_3 =(my_3d_array> 3)| (my_3d_array == 3)。

装入数组后, 可能性就不会太多, 但是对于包含名称或大写字母的数组, 可能性可能是无限的!

对于花式索引, 基本上要执行以下操作:传递列表或整数数组以指定要从原始数组中选择的行的子集的顺序。

这听起来对你来说有点抽象吗?

不用担心, 只需在下面的代码块中进行尝试:

现在, 乍看之下, 第二条陈述似乎对你没有意义。这很正常。如果将其分解, 可能会更有意义:

如果仅执行my_2d_array [[1, 0, 1, 0]], 则结果如下:


array([[5, 6, 7, 8], [1, 2, 3, 4], [5, 6, 7, 8], [1, 2, 3, 4]])

第二部分, 即[:, [0, 1, 2, 0]], 告诉你要保留此结果的所有行, 但是要稍微更改列的顺序。你希望立即显示第0、1、2列, 但是你希望将第0列作为最后一列而不是显示第3列。这将为你提供以下结果:


array([[5, 6, 7, 5], [1, 2, 3, 1], [5, 6, 7, 5], [1, 2, 3, 1]])

显然, 高级索引不再为你保留任何秘密!

如何寻求帮助

作为一个简短的解释, 你应该知道你总是可以要求获得有关你正在使用的模块, 函数或类的更多信息, 尤其是因为当你初次使用NumPy时, NumPy可能是相当有用的。

寻求帮助非常容易。

你只需利用numpy提供的特定帮助功能来设置你的方式:

  • 使用lookfor()对文档字符串进行关键字搜索。如果你刚刚起步, 这特别方便, 因为其背后的”理论”可能会逐渐淡化你的记忆。不利的一面是, 如果你的查询不那么具体, 则必须仔细检查所有搜索结果, 如下面的代码示例所示。这可能使你无法全面了解它。
  • 使用info()获得功能, 类或模块的快速说明和代码示例。如果你是一个边干边学的人, 这就是方法!使用此函数的唯一弊端可能是你需要了解某些属性或函数所在的模块。如果你不立即知道其含义, 请查看下面的代码示例。

你会看到, 这两个函数都有其优点和缺点, 但是你将亲身看到为什么两个函数都有用:请在下面的srcmini Light代码块中亲自尝试一下!

注意, 你确实需要知道dtype是ndarray的属性。另外, 请确保不要忘记将np放在要询问其信息的模块, 类或术语的前面, 否则你将收到如下错误消息:


Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'ndarray' is not defined

你现在知道了如何寻求帮助, 这是一件好事。本NumPy教程介绍的下一个主题是数组操作。

并不是说你不能自己克服这个问题, 相反!

但是某些功能可能会引起疑问, 因为, 调整大小和重塑之间有什么区别?

水平和垂直堆叠阵列有什么区别?

下一部分将讨论这些问题, 但是, 如果你有疑问, 请随时使用刚刚看到的帮助功能, 以快速上手。

如何操作数组

在数组上执行数学运算是你要做的事情之一, 但可能最重要的是做到这一点, 广播工作是要知道如何操作数组。

以下是你将要执行的一些最常见的操作。

如何转置数组

转置数组的实际作用是置换数组的尺寸。或者, 换句话说, 你在数组的形状之间切换。让我们举一个小例子向你展示移调的效果:

提示:如果数组及其转置版本之间的视觉比较尚不完全清楚, 请检查两个数组的形状, 以确保你了解排列尺寸的原因。

请注意, 有两个转置函数。两者都一样;没有太大的区别。你确实必须考虑到T似乎更多是一个便利函数, 并且使用np.transpose()具有更大的灵活性。因此, 如果你想要更多参数, 建议使用此功能。

当转置比一维大的数组时, 一切都很好, 但是只有一维数组时会发生什么呢?你认为会有效果吗?

在下面的代码块中自己尝试一下。你的一维数组已加载到:

你是绝对正确的!转置一维数组时没有任何效果!

重塑与调整阵列大小

你可能已经在广播部分中读到, 如果希望数组的尺寸适合算术运算, 则它们的尺寸必须兼容。但是, 如果不是这种情况, 你应该怎么做的问题尚未得到回答。

好吧, 这就是你得到答案的地方!

如果阵列的尺寸不同, 该怎么办, 请调整阵列的大小。然后, 你将返回一个具有传递给np.resize()函数的形状的新数组。如果将原始数组与新维度一起传递, 并且该新数组大于原始数组, 则新数组将填充有原始数组的副本, 并根据需要重复多次。

但是, 如果仅将np.resize()应用于数组, 然后将新形状传递给它, 则新数组将被零填充。

让我们用一个例子来尝试一下:

除了调整大小外, 你还可以调整数组的形状。这意味着你可以在不更改数据的情况下为数组赋予新的形状。重塑的关键是确保新阵列的总大小不变。如果以上面使用的数组x为例, 其大小为3 X 4或12, 则必须确保新数组的大小也为12。

Psst…如果要使用代码计算数组的大小, 请确保使用size属性:x.size或x.reshape((2, 6))。size:

如果所有其他方法均失败, 则还可以将数组追加到原始数组中, 或者插入或删除数组元素, 以确保维度与要用于计算的另一个数组相符。

更改数组形状时可能会方便使用的另一种操作是ravel()。此功能使你可以展平阵列。这意味着, 如果你有2D, 3D或n-D阵列, 则可以使用此函数将其全部展平为一维阵列。

很方便, 不是吗?

如何追加数组

当你将数组追加到原始数组时, 它们会”粘合”到该原始数组的末尾。如果要确保添加的内容不在数组的末尾, 则可以考虑将其插入。如果你想了解更多, 请转到下一部分。

借助NumPy库, 添加附件非常容易。你可以只使用np.append()。

在下面的代码块中查看操作方法。不要忘记, 你总是可以通过在IPython shell中键入例如my_array并按Enter来检查要加载的数组。

请注意, 在将额外的列追加到my_2d_array时如何指定轴。请记住, 轴1指示列, 而轴0指示二维数组中的行。

如何插入和删除数组元素

除了追加, 还可以插入和删除数组元素。你可能已经猜到了, 可以执行以下操作的函数是np.insert()和np.delete():

如何连接和拆分数组

你也可以”合并”或加入阵列。为此, 你可以使用很多功能, 下面列出了其中的大多数功能。

试试看, 但还要确保测试IPython Shell中数组的形状。已加载的数组是x, my_array, my_resized_array和my_2d_array。

使用这些功能时, 你会注意到一些注意事项:

  • 如果要使用np.concatenate()连接两个数组, 则维数必须相同。因此, 如果要使用my_array将一维数组连接成1维, 则需要确保第二个数组也是1维。
  • 使用np.vstack(), 你可以轻松地将my_array与my_2d_array组合在一起。你只需确保在逐行堆叠数组时确保两个数组中的列数相同。这样, 你还可以将形状为(2, 4)或(3, 4)的数组添加到my_2d_array中, 只要列数匹配即可。换句话说, 除第一轴外, 所有阵列的形状都必须相同。当你要使用np.r []时, 也是如此。
  • 对于np.hstack(), 必须确保维数相同, 并且两个数组中的行数相同。这意味着你可以将诸如(2, 3)或(2, 4)之类的数组堆叠到my_2d_array中, 其本身的形状为(2, 4)。只要你确保行数匹配, 就可以。 NumPy仍支持此功能, 但你应首选np.concatenate()或np.stack()。
  • 使用np.column_stack(), 必须确保输入的数组具有相同的第一维。在这种情况下, 两个形状都相同, 但是如果my_resized_array为(2, 1)或(2, ), 则该数组仍将被堆叠。
  • np.c_ []是另一种连接方式。同样, 这两个数组的第一个维度需要匹配。

加入阵列后, 你可能还需要在某些时候拆分它们。就像可以将它们水平堆叠一样, 也可以先垂直堆叠。你分别使用np.hsplit()和np.vsplit():

使用这两个拆分函数时, 需要记住的可能是数组的形状。让我们以上述情况为例:my_stacked_array的形状为(2, 8)。如果要选择发生分割的索引, 则必须牢记形状。

如何可视化NumPy数组

最后, 一定会派上用场的是知道如何绘制数组。当你要可视化阵列时, 这在数据探索中特别方便, 但在数据科学工作流的后期也可能非常方便。

使用np.histogram()

与该函数可能提出的建议相反, np.histogram()函数未绘制直方图, 但它确实计算了每个bin中数组的出现次数;这将确定直方图的每个条形占用的面积。

然后, 传递给np.histogram()函数的首先是你正在使用的输入数据或数组。计算直方图时, 该数组将被展平。

你会看到结果将被计算为直方图:第一个数组列出了数组中所有元素的频率, 而第二个数组列出了未指定任何bin时将使用的bin。

如果你确实指定了多个垃圾箱, 则计算结果将有所不同:浮点数将消失, 你将看到垃圾箱的所有整数。

你还可以指定其他一些参数, 这些参数会影响所计算的直方图。你可以在这里找到所有这些。

但是, 如果你无法可视化, 那么计算这样的直方图有什么意义呢?

在Matplotlib的帮助下, 可视化只是小菜一碟, 但是你不需要np.histogram()来计算直方图。当你传递(平化的)数据和垃圾箱时, plt.hist()会自行执行此操作:



# Import numpy and matplotlib
import numpy as np
import matplotlib.pyplot as plt

# Construct the histogram with a flattened 3d array and a range of bins
plt.hist(my_3d_array.ravel(), bins=range(0, 13))

# Add a title to the plot
plt.title('Frequency of My 3D Array Elements')

# Show the plot
plt.show()

上面的代码将为你提供以下(基本)直方图:

numpy数组直方图

使用np.meshgrid()

(间接)可视化数组的另一种方法是使用np.meshgrid()。数组面临的问题是, 你需要x和y坐标值的二维数组。使用上面的函数, 你可以从x值数组和y值数组中创建一个矩形网格:np.meshgrid()函数采用两个1D数组, 并生成与所有(x, y )在两个数组中。然后, 你可以使用这些矩阵进行各种绘图。

如果要评估网格上的函数, np.meshgrid()尤其有用, 如以下代码所示:


# Import NumPy and Matplotlib
import numpy as np
import matplotlib.pyplot as plt

# Create an array
points = np.arange(-5, 5, 0.01)

# Make a meshgrid
xs, ys = np.meshgrid(points, points)
z = np.sqrt(xs ** 2 + ys ** 2)

# Display the image on the axes
plt.imshow(z, cmap=plt.cm.gray)

# Draw a color bar
plt.colorbar()

# Show the plot
plt.show()

上面的代码给出以下结果:

python numpy meshgrid

使用NumPy进行数据分析之外

恭喜, 你已经结束了NumPy教程!

你已经掌握了很多基础知识, 所以现在你必须确保保留所获得的知识。别忘了获得srcmini的NumPy备忘单, 以帮助你实现这一目标!

总结了所有这些理论之后, 你还应该使用本教程中学到的概念和技术进行更多的练习。实现此目的的一种方法是返回scikit-learn教程并开始对用于构建机器学习模型的数据数组进行进一步的试验。

如果这不是你想要的, 请再次检查是否已下载Anaconda。然后, 通过此《 Jupyter Notebook权威指南》开始在Jupyter中使用NumPy数组。还要确保检查出这个Jupyter Notebook, 它还将指导你通过Python和NumPy以及Jupyter Notebook交互式数据科学环境中的其他一些库进行数据分析。

最后, 考虑查看srcmini的数据处理和可视化课程。特别是我们与Continuum Analytics合作提供的最新课程绝对会让你感兴趣!看看使用Pandas操纵DataFrame或Pandas Foundations课程。

本文地址:H5W3 » Python Numpy数组教程

评论 0

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址