# 如何在 Python 中为机器学习索引，切片和重塑 NumPy 数组

> 原文： [https://machinelearningmastery.com/index-slice-reshape-numpy-arrays-machine-learning-python/](https://machinelearningmastery.com/index-slice-reshape-numpy-arrays-machine-learning-python/)

机器学习数据表示为数组。

在 Python 中，数据几乎普遍表示为 NumPy 数组。

如果您是 Python 的新手，您可能会对某些 [pythonic](https://stackoverflow.com/questions/25011078/what-does-pythonic-mean) 访问数据的方式感到困惑，例如负索引和数组切片。

在本教程中，您将了解如何在 NumPy 数组中正确操作和访问数据。

完成本教程后，您将了解：

*   如何将列表数据转换为 NumPy 数组。
*   如何使用 Pythonic 索引和切片访问数据。
*   如何调整数据大小以满足某些机器学习 API 的期望。

让我们开始吧。

![How to Index, Slice and Reshape NumPy Arrays for Machine Learning in Python](img/9c384b0ca667a815e91824f434e4dcac.jpg)

如何在 Python 中为机器学习索引，切片和重塑 NumPy 数组
[BjörnSöderqvist](https://www.flickr.com/photos/kapten/433809071/)的照片，保留一些权利。

## 教程概述

本教程分为 4 个部分;他们是：

1.  从列表到数组
2.  数组索引
3.  数组切片
4.  数组重塑

## 1.从列表到数组

通常，我建议使用 Pandas 甚至 NumPy 函数从文件加载数据。

例如，请看帖子：

*   [如何在 Python 中加载机器学习数据](http://machinelearningmastery.com/load-machine-learning-data-python/)

本节假定您已通过其他方式加载或生成数据，现在使用 Python 列表表示它。

我们来看看将列表中的数据转换为 NumPy 数组。

### 一维列表到数组

您可以加载数据或生成数据，并以列表形式访问它。

您可以通过调用 array（）NumPy 函数将一维数据列表转换为数组。

```
# one dimensional example
from numpy import array
# list of data
data = [11, 22, 33, 44, 55]
# array of data
data = array(data)
print(data)
print(type(data))
```

运行该示例将一维列表转换为 NumPy 数组。

```
[11 22 33 44 55]
<class 'numpy.ndarray'>
```

### 数组列表的二维列表

在机器学习中，你更有可能拥有二维数据。

这是一个数据表，其中每一行代表一个新观察，每一列代表一个新特征。

也许您使用自定义代码生成数据或加载数据，现在您有一个列表列表。每个列表代表一个新观察。

您可以通过调用 array（）函数将列表列表转换为 NumPy 数组，方法与上面相同。

```
# two dimensional example
from numpy import array
# list of data
data = [[11, 22],
		[33, 44],
		[55, 66]]
# array of data
data = array(data)
print(data)
print(type(data))
```

运行该示例显示已成功转换的数据。

```
[[11 22]
 [33 44]
 [55 66]]
<class 'numpy.ndarray'>
```

## 2.数组索引

使用 NumPy 数组表示数据后，可以使用索引访问它。

我们来看一些通过索引访问数据的例子。

### 一维索引

通常，索引的工作方式与您对其他编程语言（如 Java，C＃和 C ++）的体验一样。

例如，您可以使用括号运算符[]访问元素，为要检索的值指定零偏移索引。

```
# simple indexing
from numpy import array
# define array
data = array([11, 22, 33, 44, 55])
# index data
print(data[0])
print(data[4])
```

运行该示例将打印数组中的第一个和最后一个值。

```
11
55
```

指定对于数组边界而言太大的整数将导致错误。

```
# simple indexing
from numpy import array
# define array
data = array([11, 22, 33, 44, 55])
# index data
print(data[5])
```

运行该示例将显示以下错误：

```
IndexError: index 5 is out of bounds for axis 0 with size 5
```

一个关键的区别是您可以使用负索引来检索从数组末尾偏移的值。

例如，索引-1 指的是数组中的最后一项。对于当前示例中的第一个项，索引-2 将第二个最后一项返回到-5。

```
# simple indexing
from numpy import array
# define array
data = array([11, 22, 33, 44, 55])
# index data
print(data[-1])
print(data[-5])
```

运行该示例将打印数组中的最后一项和第一项。

```
55
11
```

### 二维索引

索引二维数据类似于索引一维数据，除了使用逗号分隔每个维度的索引。

```
data[0,0]
```

这与基于 C 的语言不同，其中每个维度使用单独的括号运算符。

```
data[0][0]
```

例如，我们可以访问第一行和第一列，如下所示：

```
# 2d indexing
from numpy import array
# define array
data = array([[11, 22], [33, 44], [55, 66]])
# index data
print(data[0,0])
```

运行该示例将打印数据集中的第一个项目。

```
11
```

如果我们对第一行中的所有项目感兴趣，我们可以将第二个维度索引留空，例如：

```
# 2d indexing
from numpy import array
# define array
data = array([[11, 22], [33, 44], [55, 66]])
# index data
print(data[0,])
```

这将打印第一行数据。

```
[11 22]
```

## 3.数组切片

到现在为止还挺好;创建和索引数组看起来很熟悉。

现在我们来到数组切片，这是一个导致 Python 和 NumPy 数组初学者出现问题的功能。

像列表和 NumPy 数组这样的结构可以被切片。这意味着可以索引和检索结构的子序列。

在指定输入变量和输出变量或从测试行中分割训练行时，这在机器学习中最有用。

使用冒号运算符'：'指定切片，分别在列之前和之后使用来自'的'_ 和'_ 到 _'索引。切片从'from'索引延伸，并在'to'索引之前结束一个项目。_

```
data[from:to]
```

让我们通过一些例子来解决。

### 一维切片

您可以通过指定没有索引的切片'：'来访问数组维度中的所有数据。

```
# simple slicing
from numpy import array
# define array
data = array([11, 22, 33, 44, 55])
print(data[:])
```

运行该示例将打印数组中的所有元素。

```
[11 22 33 44 55]
```

可以通过指定从索引 0 开始并在索引 1 结束的切片（“to”索引之前的一个项目）来切片数组的第一项。

```
# simple slicing
from numpy import array
# define array
data = array([11, 22, 33, 44, 55])
print(data[0:1])
```

运行该示例将返回带有第一个元素的子数组。

```
[11]
```

我们也可以在切片中使用负索引。例如，我们可以通过在-2 处开始切片（第二个最后一项）并且不指定'to'索引来切片列表中的最后两个项目;将切片带到维度的末尾。

```
# simple slicing
from numpy import array
# define array
data = array([11, 22, 33, 44, 55])
print(data[-2:])
```

运行该示例仅返回包含最后两个项的子数组。

```
[44 55]
```

### 二维切片

让我们看看你最有可能在机器学习中使用的二维切片的两个例子。

#### 分割输入和输出功能

通常将加载的数据拆分为输入变量（X）和输出变量（y）。

我们可以通过将所有行和所有列切片到最后一列，然后分别索引最后一列来完成此操作。

对于输入要素，我们可以通过在行索引中指定'：'来选择除最后一行之外的所有行和所有列，并且在列 index 中指定-1。

```
X = [:, :-1]
```

对于输出列，我们可以使用'：'再次选择所有行，并通过指定-1 索引仅索引最后一列。

```
y = [:, -1]
```

将所有这些放在一起，我们可以将 3 列 2D 数据集分成输入和输出数据，如下所示：

```
# split input and output
from numpy import array
# define array
data = array([[11, 22, 33],
		[44, 55, 66],
		[77, 88, 99]])
# separate data
X, y = data[:, :-1], data[:, -1]
print(X)
print(y)
```

运行该示例将打印分隔的 X 和 y 元素。注意，X 是 2D 数组，y 是 1D 数组。

```
[[11 22]
 [44 55]
 [77 88]]
[33 66 99]
```

#### 拆分训练和测试行

将加载的数据集拆分为单独的训练和测试集是很常见的。

这是行的分割，其中一些部分将用于训练模型，剩余部分将用于估计训练模型的技能。

这将涉及通过在第二个维度索引中指定“：”来切片所有列。训练数据集将是从开始到分割点的所有行。

```
dataset
train = data[:split, :]
```

测试数据集将是从拆分点到维度末尾的所有行。

```
test = data[split:, :]
```

将所有这些放在一起，我们可以将数据集拆分为 2 的设计分割点。

```
# split train and test
from numpy import array
# define array
data = array([[11, 22, 33],
		[44, 55, 66],
		[77, 88, 99]])
# separate data
split = 2
train,test = data[:split,:],data[split:,:]
print(train)
print(test)
```

运行该示例选择前两行进行训练，选择最后一行进行测试。

```
[[11 22 33]
[44 55 66]]
[[77 88 99]]
```

## 4.数组重塑

切片数据后，您可能需要重新整形。

例如，某些库（例如 scikit-learn）可能要求将输出变量（y）的一维数组形成为具有一列的二维数组，并且每列的结果。

一些算法，如 Keras 中的长短期记忆递归神经网络，需要将输入指定为由样本，时间步长和特征组成的三维数组。

了解如何重塑 NumPy 数组以使您的数据满足特定 Python 库的期望非常重要。我们将看看这两个例子。

### 数据形状

NumPy 数组具有 shape 属性，该属性返回数组每个维度长度的元组。

例如：

```
# array shape
from numpy import array
# define array
data = array([11, 22, 33, 44, 55])
print(data.shape)
```

运行该示例会打印一维的元组。

```
(5,)
```

对于二维数组，返回具有两个长度的元组。

```
# array shape
from numpy import array
# list of data
data = [[11, 22],
		[33, 44],
		[55, 66]]
# array of data
data = array(data)
print(data.shape)
```

运行该示例将返回一个包含行数和列数的元组。

```
(3, 2)
```

您可以在形状维度中使用数组维度的大小，例如指定参数。

可以像数组一样访问元组的元素，行数为第 0 个索引，列数为第 1 个索引。例如：

```
# array shape
from numpy import array
# list of data
data = [[11, 22],
		[33, 44],
		[55, 66]]
# array of data
data = array(data)
print('Rows: %d' % data.shape[0])
print('Cols: %d' % data.shape[1])
```

运行该示例可访问每个维度的特定大小。

```
Rows: 3
Cols: 2
```

### 重塑 1D 到 2D 数组

通常需要将一维数组重塑为具有一列和多个数组的二维数组。

NumPy 在 NumPy 数组对象上提供 reshape（）函数，可用于重塑数据。

reshape（）函数采用一个参数来指定数组的新形状。在将一维数组重新整形为具有一列的二维数组的情况下，元组将是第一维（data.shape [0]）的数组形状和第二维的 1。

```
data = data.reshape((data.shape[0], 1))
```

综上所述，我们得到以下工作示例。

```
# reshape 1D array
from numpy import array
from numpy import reshape
# define array
data = array([11, 22, 33, 44, 55])
print(data.shape)
# reshape
data = data.reshape((data.shape[0], 1))
print(data.shape)
```

运行该示例将打印一维数组的形状，将数组重新整形为包含 1 列的 5 行，然后打印此新形状。

```
(5,)
(5, 1)
```

### 重塑 2D 到 3D 数组

通常需要重新形成二维数据，其中每行表示序列为三维数组，用于期望一个或多个时间步长和一个或多个特征的多个样本的算法。

一个很好的例子是 Keras 深度学习库中的 [LSTM 递归神经网络](https://keras.io/layers/recurrent/#lstm)模型。

可以直接使用重塑功能，指定新的维度。这是清楚的，其中每个序列具有多个时间步长，每个时间步长具有一个观察（特征）。

我们可以使用数组上 shape 属性的大小来指定样本（行）和列的数量（时间步长），并将要素数量固定为 1。

```
data.reshape((data.shape[0], data.shape[1], 1))
```

Putting this all together, we get the following worked example.

```
# reshape 2D array
from numpy import array
# list of data
data = [[11, 22],
		[33, 44],
		[55, 66]]
# array of data
data = array(data)
print(data.shape)
# reshape
data = data.reshape((data.shape[0], data.shape[1], 1))
print(data.shape)
```

首先运行示例打印 2D 数组中每个维度的大小，重新整形数组，然后总结新 3D 数组的形状。

```
(3, 2)
(3, 2, 1)
```

## 进一步阅读

如果您要深入了解，本节将提供有关该主题的更多资源。

*   [Python 非正式介绍](https://docs.python.org/3/tutorial/introduction.html)
*   [在 NumPy API 中创建数组](https://docs.scipy.org/doc/numpy/user/basics.creation.html)
*   [NumPy API 中的索引和切片](https://docs.scipy.org/doc/numpy/reference/arrays.indexing.html)
*   [NumPy API 中的基本索引](https://docs.scipy.org/doc/numpy/user/basics.indexing.html)
*   [NumPy 形状属性](https://docs.scipy.org/doc/numpy/reference/generated/numpy.ndarray.shape.html)
*   [NumPy reshape（）函数](https://docs.scipy.org/doc/numpy/reference/generated/numpy.reshape.html)

## 摘要

在本教程中，您了解了如何使用 Python 访问和重塑 NumPy 数组中的数据。

具体来说，你学到了：

*   如何将列表数据转换为 NumPy 数组。
*   如何使用 Pythonic 索引和切片访问数据。
*   如何调整数据大小以满足某些机器学习 API 的期望。

你有任何问题吗？
在下面的评论中提出您的问题，我会尽力回答。