快速上手Python三剑客--NumPy篇

NumPy学习

什么是NumPy?

  • NumPy是一个用于处理数组的Python库。
  • 它也有在线性代数、傅里叶变换和矩阵领域工作的功能。
  • NumPy是Numerical Python的缩写。

为什么使用NumPy?

  • 在Python中,我们有列表,可以达到数组的目的,但它们的处理速度很慢
  • NumPy旨在提供一个数组对象,它比传统的Python列表快50倍
  • NumPy中的数组对象被称为ndarray,它提供了很多支持性的函数,使得使用ndarray非常容易
  • 数组在数据科学中使用得非常频繁,速度和资源都非常重要

为什么NumPy比列表快?

  • 与列表不同,NumPy的数组被存储在内存中的一个连续位置,所以进程可以非常有效地访问和操作它们
  • 这种行为在计算机科学中被称为引用的位置性
  • 这就是NumPy比列表快的主要原因。此外,它还被优化以适用于最新的CPU架构

NumPy是用哪种语言编写的?

NumPy是一个Python库,部分是用Python编写的,但大部分需要快速计算的部分是用C或C++编写的

NumPy的代码库地址

NumPy的源代码位于这个github仓库
https://github.com/numpy/numpy

基础知识

数组

创建NumPy ndarray对象

NumPy用于处理数组,NumPy中的数组对象称为ndarray
我们可以使用array()函数创建一个NumPy ndarray对象

# 引入NumPy
import numpy as np

arr = np.array([1, 2, 3, 4, 5])
print(arr)
print(type(arr))
[1 2 3 4 5]

  • type():这个内置的Python函数告诉我们传递给它的对象的类型,像上面的代码一样,它表明arr是numpy.ndarray类型。
  • 要创建ndarray,我们可以将列表、元组或任何类似数组的对象传递给array()方法,然后它将被转换为ndarray
# 使用列表创建NumPy数组
# 列表(list)
a = [5, 5, 5, 5, 5, 5]
b = [5] * 6
# ndarray对象
arr = np.array([5] * 6)

print(a)
print(b)
print(arr)
print(type(a))
print(type(b))
print(type(arr))
[5, 5, 5, 5, 5, 5]
[5, 5, 5, 5, 5, 5]
[5 5 5 5 5 5]



# 使用元组创建NumPy数组
# 元组(tuple)
a = (1, 2, 3, 4, 5)
# ndarray对象
arr = np.array((1, 2, 3, 4, 5))

print(a)
print(arr)
print(type(a))
print(type(arr))
(1, 2, 3, 4, 5)
[1 2 3 4 5]


数组中的维

数组中的维是数组深度(嵌套数组)的一个级别
嵌套数组:指的是将数组作为元组的数组

0-D数组

0-D数组,或标量(Scalars),是数组中的元素,数组中的每个值都是一个0-D数组

1-D数组

其元素为0-D数组的数组,称为一维或1-D数组
这是常见和基础的数组

# 用值61创建0-D数组
arr = np.array(61)
print(arr)
61
# 创建包含值1,2,3,4,5,6,的1-D数组
arr = np.array([1, 2, 3, 4, 5, 6])
print(arr)
[1 2 3 4 5 6]
2-D数组

其元素为1-D数组的数组,称为2-D数组
它们通常用于表示矩阵或二阶张量
NumPy有一个专门用于矩阵运算的完整子模块numpy.mat

# 创建包含值1,2,3和4,5,6两个数组的2-D数组
arr = np.array([[1, 2, 3], [4, 5, 6]])
print(arr)
[[1 2 3]
 [4 5 6]]
3-D数组

其元素为2-D数组的数组,称为3-D数组

# 用两个2-D数组创建一个3-D,这两个数组均包含值1,2,3和4,5,6的两个数组
arr = np.array([[[1, 2, 3], [4, 5, 6]], [[1, 2, 3], [4, 5, 6]]])
print(arr)
[[[1 2 3]
  [4 5 6]]

 [[1 2 3]
  [4 5 6]]]
检查维数

NumPy数组提供了ndim属性,该属性返回一个整数,该整数会告诉我们数组有多少维

# 检查数组有多少维
a = np.array(42)
b = np.array([1, 2, 3, 4, 5])
c = np.array([[1, 2, 3], [4, 5, 6]])
d = np.array([[[1, 2, 3], [4, 5, 6]], [[1, 2, 3], [4, 5, 6]]])
print(a.ndim)
print(b.ndim)
print(c.ndim)
print(d.ndim)
0
1
2
3
更高维的数组

数组可以拥有任意数量的维
在创建数组时,可以使用ndmin参数定义维数
可以简单理解为有多少维就有多少[]

# 创建一个有5个维度的数组,并验证它拥有5个维度
arr = np.array([1, 2, 3, 4], ndmin=5)
print(arr)
print('number of dimensions:', arr.ndim)
[[[[[1 2 3 4]]]]]
number of dimensions: 5

数组索引

访问数组元素

数组索引等同于访问数组元素
您可以通过引用其索引号来访问数组元素
NumPy数组中的索引以0开头,这意味着第一个元素的索引为0,第二个元素的索引为1,依此类推

arr = np.array([1, 2, 3, 4])
# 获取第一个元素
print(arr[0])
# 获取第二个元素
print(arr[1])
# 获取第三个和第四个元素并将其加和
print(arr[2] + arr[3])
1
2
7
arr = np.array([[1], [2], [3], [4]])
# 获取第一个元素
print(arr[0])
# 获取第二个元素
print(arr[1])
# 获取第三个和第四个元素并将其加和
print(arr[2] + arr[3])
[1]
[2]
[7]
访问2-D数组

要访问二维数组中的元素,我们可以使用逗号分隔的整数表示元素的维数和的索引

访问3-D数组

要访问3-D数组中的元素,我们可以使用逗号分隔的整数来表示元素的维数和索引

arr = np.array([[1, 2, 3, 4, 5], [6, 7, 8, 9, 10]])
print(arr)
# 访问第一个数组中的第二个元素
print('2nd element on 1st dim:', arr[0, 1])
# 访问第二个数组中的第五个元素
print('5nd element on 2nd dim:', arr[1, 4])
[[ 1  2  3  4  5]
 [ 6  7  8  9 10]]
2nd element on 1st dim: 2
5nd element on 2nd dim: 10
# 访问第一个数组的第二个数组的第三个元素
arr = np.array([[[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]]])
print(arr)
print(arr[0, 1, 2])
[[[ 1  2  3]
  [ 4  5  6]
  [ 7  8  9]
  [10 11 12]]]
6
负索引

使用负索引从尾开始访问数组

arr = np.array([[1, 2, 3, 4, 5], [6, 7, 8, 9, 10]])
print(arr)
# 打印第二个数组中的最后一个元素
print('Last element from 2nd dim:', arr[-1, -1])
[[ 1  2  3  4  5]
 [ 6  7  8  9 10]]
Last element from 2nd dim: 10

数组裁切

裁切数组

Python中裁切的意思是将元素从一个给定的索引带到另一个给定的索引
我们像这样传递切片而不是索引:[start:end]
我们还可以这样定义步长,如下所示:[startstep]
如果我们不传递start,则将其视为0
如果我们不传递end,则视为该维度内数组的长度
如果我们不传递step,则视为1

arr = np.array([1, 2, 3, 4, 5, 6, 7])

# 裁切索引1到索引5(不包括)的元素
print(arr[1:5])

# 裁切数组中索引为4到结尾的元素
print(arr[4:])

# 裁切从开头到索引4(不包括)的元素
print(arr[:4])
[2 3 4 5 6]
[5 6 7]
[1 2 3 4]
负裁切

使用减号运算符从末尾开始的索引

arr = np.array([1, 2, 3, 4, 5, 6, 7])
# 从末尾开始的索引3到末尾开始的索引1(包括索引1),对数组进行裁切
print(arr[-3:])
[5 6 7]
STEP

使用step值确定裁切的步长

arr = np.array([1, 2, 3, 4, 5, 6, 7])
# 从索引1到索引5(不包括),返回相隔的元素
print(arr[1:5:2])
# 返回数组中相隔的元素
print(arr[::2])
[2 4]
[1 3 5 7]
裁切2-D数组
arr = np.array([[1, 2, 3, 4, 5], [6, 7, 8, 9, 10]])
# 从第二个元素开始,对从索引1到索引4(不包括)的元素进行切片
print(arr[1, 1:4])
# 从两个元素中返回索引2  !!!!注意与下面的2-D数组区分
print(arr[0:2, 2])
# 从两个元素裁切索引1到索引4(不包括),这将返回一个2-D数组
print(arr[0:2, 1:4])
[7 8 9]
[3 8]
[[2 3 4]
 [7 8 9]]

数据类型

Python中的数据类型

默认情况下,Python拥有以下数据类型:

  • strings - 用于表示文本数据,文本用引号引起来,例如:“ABCD”
  • integer - 用于表示整数,例如;-1,-2,-3
  • float - 用于表示实数,例如:1.2,42.1
  • boolean - 用于表示True或False
  • complex - 用于表示复平面中的数字,例如:1.0+2.0j,1.5+2.5j

NumPy中的数据类型

NumPy中有一些额外的数据类型,并通过一个字符引用数据类型,例如i代表整数,u代表无符号整数等
以下是NumPy中所有数据类型的列表以及用于表示它们的字符

字符 数据类型 字符 数据类型 字符 数据类型
i 整数 c 复合浮点数 S (byte-)字符串
b 布尔 m timedelta U unicode字符串
u 无符号整数 M datatime V 固定的其他类型的内存块(void)
f 浮点 O 对象 - -

检查数组的数据类型

Numpy数组对象有一个名为dtype的属性,该属性返回数组的数据类型

arr = np.array([1,2,3,4])
print(arr.dtype)

arr1 = np.array(['apple','banana','cherry'])
print(arr1)
print(arr1.dtype)
int32
['apple' 'banana' 'cherry']

用已定义的数据类型创建数组

我们使用array()函数来创建数组,该函数可以使用可选参数:dtype,它允许我们定义数组元素的预期数据类型

# 创建数据类型为(byte)字符串类型的数组
arr = np.array([1,2,3,4],dtype='S')
print(arr)
print(arr.dtype)

# 创建数据类型为4字节的整数的数组
arr1=np.array([1,2,3,4],dtype='i4')
print(arr1)
print(arr1.dtype)
[b'1' b'2' b'3' b'4']
|S1
[1 2 3 4]
int32

假如值无法转换会怎么样?

如果给出了不能强制转换元素的类型,则Numpy将引发ValueError
ValueError:在Python中,如果传递给函数的参数的类型是非预期或错误的,则会引发ValueError

arr = np.array(['a','2','3'],dtype='i')
---------------------------------------------------------------------------

ValueError                                Traceback (most recent call last)

Cell In[29], line 1
----> 1 arr = np.array(['a','2','3'],dtype='i')


ValueError: invalid literal for int() with base 10: 'a'

转换已有数组的数据类型

更改现有数组的数据类型的最佳方法,是使用astype()方法复制该数组
astype()函数创建数组的副本,并允许您将数据类型指定为参数
数据类型可以使用字符串指定,例如 ‘f’ 表示浮点数,‘i’ 表示整数等。或者您也可以直接使用数据类型,例如float表示浮点数,int表示整数

# 通过使用‘i’作为参数值,将数据类型从浮点数更改为整数
arr=np.array([1.1,2.1,3.1])
newarr=arr.astype('i')
print(newarr)
print(newarr.dtype)

# 通过使用int作为参数值,将数据类型从浮点数更改为整数
arr1=np.array([1.1,2.1,3.1])
newarr1=arr1.astype(int)
print(newarr1)
print(newarr1.dtype)
[1 2 3]
int32
[1 2 3]
int32

NumPy数组副本 VS 视图

副本和视图之间的区别
  • 副本和数据视图之间的主要区别在于副本是一个新数组,而这个视图只是原始数组的视图
  • 副本拥有数据,对副本所做的任何更改都不会影响原始数组,对原始数组所做的任何更改也不会影响副本
  • 视图不拥有数据,对视图所做的任何更改都会影响原始数据,而对原始数组所做的任何更改都会影响视图
副本
视图
arr=np.array([1,2,3,4,5])
x=arr.copy()
arr[0] =61
print(arr)
print(x)

x[0]=31
print(arr)
print(x)
[61  2  3  4  5]
[1 2 3 4 5]
[61  2  3  4  5]
[31  2  3  4  5]
arr=np.array([1,2,3,4,5])
x=arr.view()
arr[0] =61
print(arr)
print(x)

x[0]=31
print(arr)
print(x)
[61  2  3  4  5]
[61  2  3  4  5]
[31  2  3  4  5]
[31  2  3  4  5]
检查数组是否拥有数据

如上所述,副本拥有数据,而视图不拥有数据,但是我们如何检查呢?
每个NumPy数组都有一个属性base,如果该数组拥有数据,则这个base属性返回None
否则,base属性将引用原始对象

arr=np.array([1,2,3,4,5])
x=arr.copy()
y=arr.view()
print(x.base)
print(y.base)
print(arr.base)
None
[1 2 3 4 5]
None

形状

Numpy数组形状

数组的形状

数组的形状是每个维中元素的数量

获取数组的形状

NumPy数组有一个名为shape的属性,该属性返回一个元组,这个元组的长度就是维度的数目,即 ndim 属性(秩)。比如,一个二维数组,其维度表示"行数"和"列数"。

arr = np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]])
# 返回(3,4),这意味着该数组有2个维,第一维度有3个元素,第二维度有4个元素
print(arr.shape)

# 利用ndmin使用值1,2,3,4的向量创建有5个维度的数组,并验证最后一个维度有4个元素
arr1 = np.array([1, 2, 3, 4], ndmin=5)
print(arr1)
print(arr1.shape)
(3, 4)
[[[[[1 2 3 4]]]]]
(1, 1, 1, 1, 4)

NumPy数组重塑

数组重塑

重塑意味着更改数组的形状
数组的形状是每个维中元素的数量
通过重塑,我们可以添加或删除维度或更改每个维度中元素的数量

从1-D重塑为2-D
从1-D重塑为3-D
# 将以下具有12个元素的1-D数组装换为2-D数组
arr = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12])
newarr = arr.reshape(4, 3)
print(arr.shape)
print(newarr)
print(newarr.shape)
(12,)
[[ 1  2  3]
 [ 4  5  6]
 [ 7  8  9]
 [10 11 12]]
(4, 3)
# 将以下具有12个元素的1-D数组装换为3-D数组
arr = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12])
newarr = arr.reshape(2, 2, 3)
print(arr.shape)
print(newarr)
print(newarr.shape)
(12,)
[[[ 1  2  3]
  [ 4  5  6]]

 [[ 7  8  9]
  [10 11 12]]]
(2, 2, 3)
我们可以重塑成任何形状吗?

是的,只要重塑所需的元素数量在两种形状中均相等
我们可以将8个元素1-D数组重塑为2行4个元素的2-D数组,但是我们不能将其重塑为3行3个元素2-D数组

arr = np.array([1, 2, 3, 4, 5, 6, 7, 8])
newarr = arr.reshape(3, 3)
---------------------------------------------------------------------------

ValueError                                Traceback (most recent call last)

Cell In[48], line 2
      1 arr=np.array([1,2,3,4,5,6,7,8])
----> 2 newarr=arr.reshape(3,3)


ValueError: cannot reshape array of size 8 into shape (3,3)
返回副本还是视图?

重塑后的数组是原始数组的一个视图

arr = np.array([1, 2, 3, 4, 5, 6, 7, 8])
newarr = arr.reshape(2, 4)
print(arr)
print(newarr)
print(newarr.base)
# 返回的是原始数组,因此重塑后的数组是一个视图
[1 2 3 4 5 6 7 8]
[[1 2 3 4]
 [5 6 7 8]]
[1 2 3 4 5 6 7 8]
未知的维

您可以使用一个"未知"维度
这意味着您不必在reshape方法中为维度之一指定确切的数字
传递-1作为值,NumPy将为您计算该数字

arr = np.array([1, 2, 3, 4, 5, 6, 7, 8])
newarr = arr.reshape(2, 2, -1)
print(newarr)
print(newarr.shape)
[[[1 2]
  [3 4]]

 [[5 6]
  [7 8]]]
(2, 2, 2)
展平数组

展平数组(Flattening the arrays)是指将多维数组装换为1-D数组
我们可以使用reshape(-1)来做到这一点

arr = np.array([[1, 2, 3, 4], [5, 6, 7, 8]])
newarr = arr.reshape(-1)
print(newarr)
[1 2 3 4 5 6 7 8]

操作(迭代、连接、拆分、搜索、排序、过滤)

NumPy数组迭代

数组迭代

迭代意味着逐一遍历元素
当我们在NumPy中处理多维数组时,可以使用Python的基本for循环来完成此操作
如果我们对1-D数组进行迭代,他将逐一遍历每个元素

arr=np.array([1,2,3])
for x in arr:
    print(x)
1
2
3
迭代2-D数组

在2-D数组中,他将遍历所有行

# 如果我们迭代一个n-D数组,它将逐一遍历第n-1维
arr=np.array([[1,2,3],[4,5,6]])
for x in arr:
    print(x)
    
# 如需返回实际值,标量,我们必须迭代每个维中的数组
arr1=np.array([[1,2,3],[4,5,6]])
for x in arr1:
    for y in x:
        print(y)
[1 2 3]
[4 5 6]
1
2
3
4
5
6
迭代3-D数组

在3-D数组中,它将遍历所有2-D数组

#要返回实际值,标量,我们必须迭代每个维中的数组
arr= np.array([[[1,2,3],[4,5,6]],[[7,8,9],[10,11,12]]])
for x in arr:
    for y in x:
        for z in y:
            print(z)
1
2
3
4
5
6
7
8
9
10
11
12
使用nditer()迭代数组

函数nditer()是一个辅助函数,从非常基本的迭代到非常高级的迭代都可以使用。它解决了我们在迭代中面临的一些基本问题,让我们通过例子进行介绍。

迭代每个标量元素

在基本的for循环中,迭代遍历数组的每个标量,我们需要使用n个for循环,对于具有高维数的数组可能很难编写

arr=np.array([[[1,2],[3,4]],[[5,6],[7,8]]])
for x in np.nditer(arr):
    print(x)
1
2
3
4
5
6
7
8
迭代不同数据类型的数组

我们可以使用op_dtypes参数,并传递期望的数据类型,以在迭代时更改数据元素的数据类型
NumPy不会就地更改元素的数据类型(元素位于数组中),因此它需要一些其它空间来执行此操作,该额外空间称为buffer,为了在nditer()中启用它,我们传参flags=[‘buffered’]

arr=np.array([1,2,3])
for x in np.nditer(arr,flags=['buffered'],op_dtypes=['S']):
    print(x)
b'1'
b'2'
b'3'
以不同的步长迭代

我们可以使用过滤,然后进行迭代

# 每遍历2-D数组的一个标量元素,跳过1个元素
arr=np.array([[1,2,3,4],[5,6,7,8]])
for x in np.nditer(arr[:,::2]):
    print(x)
1
3
5
7
使用ndenumerate()进行枚举迭代

枚举是指逐一提及事物的序号
有时,我们在迭代时需要元素的相应索引,对于这些用例,可以使用ndenumerate()方法

arr=np.array([1,2,3])
for idx,x in np.ndenumerate(arr):
    print(idx,x)
    
arr1=np.array([[1,2,3,4],[5,6,7,8]])
for idx,x in np.ndenumerate(arr1):
    print(idx,x)
(0,) 1
(1,) 2
(2,) 3
(0, 0) 1
(0, 1) 2
(0, 2) 3
(0, 3) 4
(1, 0) 5
(1, 1) 6
(1, 2) 7
(1, 3) 8

NumPy数组连接

连接NumPy数组

连接意味着将两个或多个数组的内容放在单个数组中
在SQL中,我们基于键来连接表,而在NumPy中,我们按轴连接数组
numpy.concatenate 函数用于沿指定轴连接相同形状的两个或多个数组
我们传递了一系列要与轴一起连接到concatenate()函数的数组。如果未显示传递轴,则将其视为0

# 沿着列(axis=0)连接两个2-D数组
arr1=np.array([[1,2],[3,4]])
arr2=np.array([[5,6],[7,8]])

arr=np.concatenate((arr1,arr2))
print(arr,arr.shape)

# 沿着行(axis=1)连接两个2-D数组
arr3=np.array([[1,2],[3,4]])
arr4=np.array([[5,6],[7,8]])

arr=np.concatenate((arr3,arr4),1)
print(arr,arr.shape)
[[1 2]
 [3 4]
 [5 6]
 [7 8]] (4, 2)
[[1 2 5 6]
 [3 4 7 8]] (2, 4)
使用堆栈函数连接数组

堆栈与级联相同,唯一的不同是堆栈是沿着新轴完成的
我们可以沿着第二个轴连接两个一维数组,这将导致它们彼此重叠,即堆叠(stacking)

# 沿轴0堆叠两个数组
arr = np.stack((arr1, arr2), axis=0)
print(arr, arr.shape)
# 沿轴1堆叠两个数组
newarr = np.stack((arr1, arr2), axis=1)
print(newarr, newarr.shape)
[[[1 2]
  [3 4]]

 [[5 6]
  [7 8]]] (2, 2, 2)
[[[1 2]
  [5 6]]

 [[3 4]
  [7 8]]] (2, 2, 2)
沿行堆叠

NumPy提供了一个辅助函数:hstack()沿行堆叠,等同于按轴1(行)连接两数组

arr=np.hstack((arr1,arr2))
print(arr,arr.shape)
[[1 2 5 6]
 [3 4 7 8]]
沿列堆叠

NumPy提供了一个辅助函数:vstack()沿列堆叠,等同于按轴0(列)连接两数组

arr=np.vstack((arr1,arr2))
print(arr,arr.shape)
[[1 2]
 [3 4]
 [5 6]
 [7 8]] (4, 2)
沿高度(深度)堆叠

NumPy提供了一个辅助函数:dstack()沿高度(深度)堆叠,该高度与深度相同

arr=np.dstack((arr1,arr2))
print(arr,arr.shape)
[[[1 5]
  [2 6]]

 [[3 7]
  [4 8]]] (2, 2, 2)

NumPy数组拆分

拆分NumPy数组

拆分是连接的反操作
连接(joining)是将多个数组合并为一个,拆分(Spliting)将一个数组拆分为多个
我们使用array_split()或split()分割数组,将要分割的数组和要分割的数目传递给它
array_split()与split()的区别在于数组不能平均划分时,array_split()会将平均分后的最后一个数组再划分,而split()会报错

arr=np.array([1,2,3,4,5,6])
newarr=np.array_split(arr,3)
print(newarr)
# 返回值是一个包含三个数组的数组

print(newarr[0])
print(newarr[1])
print(newarr[2])

newarr1=np.array_split(arr,4)
print(newarr1) 
[array([1, 2]), array([3, 4]), array([5, 6])]
[1 2]
[3 4]
[5 6]
[array([1, 2]), array([3, 4]), array([5]), array([6])]
newarr=np.split(arr,3)
print(newarr)

newarr1=np.split(arr,4)
print(newarr1) 
[array([1, 2]), array([3, 4]), array([5, 6])]



---------------------------------------------------------------------------

ValueError                                Traceback (most recent call last)

Cell In[99], line 4
      1 newarr=np.split(arr,3)
      2 print(newarr)
----> 4 newarr1=np.split(arr,4)
      5 print(newarr1) 


File D:\Python\Miniconda3\miniconda3\envs\p2s\lib\site-packages\numpy\lib\shape_base.py:864, in split(ary, indices_or_sections, axis)
    862     N = ary.shape[axis]
    863     if N % sections:
--> 864         raise ValueError(
    865             'array split does not result in an equal division') from None
    866 return array_split(ary, indices_or_sections, axis)


ValueError: array split does not result in an equal division
分割二维数组

拆分二维数组时,请使用相同的语法
使用array_split()或split()分割数组,将要分割的数组和要分割的数目传递给它

arr = np.array([[1,2],[3,4],[5,6],[7,8],[9,10],[11,12]])
print(arr.shape)

newarr=np.array_split(arr,3)
print(newarr)
(6, 2)
[array([[1, 2],
       [3, 4]]), array([[5, 6],
       [7, 8]]), array([[ 9, 10],
       [11, 12]])]
arr = np.array([[1,2,3],[4,5,6],[7,8,9],[10,11,12],[13,14,15],[16,17,18]])
print(arr.shape)

newarr=np.array_split(arr,3)
print(newarr)
#另一种解决方案是使用与vstack()相反的vsplit()
newarr1=np.vsplit(arr,3)
print(newarr1)
(6, 3)
[array([[1, 2, 3],
       [4, 5, 6]]), array([[ 7,  8,  9],
       [10, 11, 12]]), array([[13, 14, 15],
       [16, 17, 18]])]
[array([[1, 2, 3],
       [4, 5, 6]]), array([[ 7,  8,  9],
       [10, 11, 12]]), array([[13, 14, 15],
       [16, 17, 18]])]
newarr=np.array_split(arr,3,axis=1)
print(newarr)

#另一种解决方案是使用与hstack()相反的hsplit()
newarr1=np.hsplit(arr,3)
print(newarr1)
[array([[ 1],
       [ 4],
       [ 7],
       [10],
       [13],
       [16]]), array([[ 2],
       [ 5],
       [ 8],
       [11],
       [14],
       [17]]), array([[ 3],
       [ 6],
       [ 9],
       [12],
       [15],
       [18]])]
[array([[ 1],
       [ 4],
       [ 7],
       [10],
       [13],
       [16]]), array([[ 2],
       [ 5],
       [ 8],
       [11],
       [14],
       [17]]), array([[ 3],
       [ 6],
       [ 9],
       [12],
       [15],
       [18]])]

NumPy数组搜索

搜索数组

您可以在数组中搜索(检索)某个值,然后返回获得匹配的索引
要搜索数组,请使用where()方法
numpy.where() 函数返回输入数组中满足给定条件的元素的索引

arr=np.array([1,2,3,4,5,4,7])
x=np.where(arr==4)
print(x)
# 值4出现在索引3,5

#查找值为偶数的索引
y=np.where(arr%2==0)
print(y)
#查找值为奇数的索引
z=np.where(arr%2!=0)
print(z)
(array([3, 5], dtype=int64),)
(array([1, 3, 5], dtype=int64),)
(array([0, 2, 4, 6], dtype=int64),)
搜索排序

有一个名为searchsorted()的方法,该方法在数组中执行二进制搜索,并返回将在其中指定值以维持搜索顺序的索引
假定searchsorted()方法用于排序数组

哪侧开始 满足条件 何时停止 返回序号
left a[i-1] 最后一个满足条件处 i
right a[i-1]<=v 第一个满足条件处 i
# 该方法从左侧开始搜索,并返回第一个索引,其中9不再大于10,故在8-10间停止
arr=np.array([6,8,10,15])
# arr[i-1=1]=8  <  9  <=  arr[i=2]=10,返回i即2
x=np.searchsorted(arr,9)
print(x)

# 从右侧开始搜索,并返回第一个索引,其中9大于8,故在8-10间停止
# arr[i-1=1]=8  <=  9  <  arr[i=2]=10, 返回i即2
y=np.searchsorted(arr,9,side='right')
print(y)
2
2
多个值

要搜索多个值,请使用拥有指定值的数组

arr=np.array([1,3,5,7])
x = np.searchsorted(arr,[2,4,6])
print(x)
[1 2 3]

NumPy数组排序

数组排序

排序是指将元素按有序顺序排列
有序序列是拥有与元素相对应的顺序的任何序列,例如数字或字母,升序或降序
NumPy有一个名为sort()的函数,该函数将对指定的数组进行排序

arr=np.array([3,2,0,1])
print(np.sort(arr))

newarr = np.array(['banana','cherry','apple'])
print(np.sort(newarr))

newarr1=np.array([True,False,True])
print(np.sort(newarr1))
[0 1 2 3]
['apple' 'banana' 'cherry']
[False  True  True]
对2-D数组排序

如果在二维数组上使用sort()方法,则将对两个数组分别进行排序

arr=np.array([[3,2,4],[5,0,1]])
print(np.sort(arr))
[[2 3 4]
 [0 1 5]]

NumPy数组过滤

数组过滤

从现有数组中取出一些元素并从中创建新数组称为过滤(filtering)
在NumPy中,我们使用布尔索引列表来过滤数组
布尔索引列表是与数组中的索引相对应的布尔值列表
如果索引处的值为True,则该元素包含在过滤后的数组中,如果索引处的值为False,则该元素将从过滤后的数组中排除,

arr=np.array([61,62,63,64,65])
x=[True,False,True,False,True]
newarr=arr[x]
print(newarr)
[61 63 65]
创建过滤器数组

在上例中,我们对True和False值进行了硬编码,但通常的用途是根据条件创建过滤器数组

# 创建一个仅返回大于62的值的过滤器数组
arr=np.array([61,62,63,64,65])

# 创建一个空列表
filter_arr=[]

#遍历arr中的每个元素
for element in arr:
    # 如果元素大于62,则将值设置为True,否则为False
    if element>62:
        filter_arr.append(True)
    else:
        filter_arr.append(False)
newarr=arr[filter_arr]

print(filter_arr)
print(newarr)
[False, False, True, True, True]
[63 64 65]
# 创建一个过滤器数组,该数组返回原始数组中的偶数元素
arr=np.array([1,2,3,4,5,6,7])

# 创建一个空列表
filter_arr=[]

#遍历arr中的每个元素
for element in arr:
    # 如果元素可以被2整除,则将值设置为True,否则为False
    if element%2==0:
        filter_arr.append(True)
    else:
        filter_arr.append(False)
newarr=arr[filter_arr]

print(filter_arr)
print(newarr)
[False, True, False, True, False, True, False]
[2 4 6]
直接从数组创建过滤器

上例是NumPy中非常常见的任务,NumPy提供了解决问题的好办法
我们可以在条件中直接替换数组而不是iterable变量,它会如我们期待地那样工作

注:什么是iterable?
在Python中,iterable指的是可以迭代的对象。简单地说,如果一个对象可以被遍历,则称它为iterable。一个iterable对象可以返回一个迭代器(iterator),这个迭代器能够遍历该对象中的所有元素。
在Python中,常见的iterable对象包括列表、元组、集合、字典等。此外,字符串、文件对象等也是iterable对象。

arr=np.array([61,62,63,64,65])

filter_arr=arr>62

newarr=arr[filter_arr]
print(filter_arr)
print(newarr)
[False False  True  True  True]
[63 64 65]
# 创建一个过滤器数组,该数组返回原始数组中的偶数元素
arr=np.array([1,2,3,4,5,6,7])

# 创建一个空列表
filter_arr=arr%2==0

newarr=arr[filter_arr]

print(filter_arr)
print(newarr)
[False  True False  True False  True False]
[2 4 6]

更详细教程可关注
https://www.runoob.com/numpy/numpy-tutorial.html

Congratulations!

记录者:ZL-Qin

你可能感兴趣的:(Python,快速上手Python三剑客,numpy,python)