numpy 概述
- Numerical Python,数值的 Python,补充了 Python 语言所欠缺的数值计算能力。
- Numpy 是其数据分析及机器学习库的底层库。
- Numpy 完全标准 C 语言实现,运行效率充分优化。
- Numpy 开源免费。
numpy 历史
- 1995 年,Numeric,Python 语言数值计算扩充。
- 2001 年,Scipy -> Numarray,多维数组运算。
- 2005 年,Numeric + Numarray -> Numpy。
- 2006 年,Numpy 脱离 Scipy 成为独立项目。
numpy 的核心:多维数组
- 代码简洁:减少 Python 代码中的循环。
- 底层实现:厚内核(C ) + 薄接口(Python),保证性能。
numpy 基础
ndarray 数组
用 np.ndarray
类的对象表示 n
维数组:
import numpy as np
arr = np.array([1, 2, 3, 4, 5, 6])
print(arr, type(arr))
print(arr.shape) # 数组的维度
arr.shape = (2, 3) # 修改数组的维度为 2 行 3 列
print(arr, arr.shape)
arr.shape = (6,)
# 数组的运算
print(arr)
print("arr * 3: ", arr * 3)
print("arr + 3: ", arr + 3)
print("arr > 3: ", arr > 3)
print("arr + arr: ", arr + arr)
"""
[1 2 3 4 5 6] <class 'numpy.ndarray'>
(6,)
[[1 2 3]
[4 5 6]] (2, 3)
[1 2 3 4 5 6]
arr * 3: [ 3 6 9 12 15 18]
arr + 3: [4 5 6 7 8 9]
arr > 3: [False False False True True True]
arr + arr: [ 2 4 6 8 10 12]
"""
内存中的 ndarray 对象
元数组(metadata)
存储对目标数组的描述信息,如:dim count
、shape
、size
、dtype
、data
等。
实际数据
完整的数组数据
将实际数据与元数据分开存放,一方面提高了内存空间的使用效率,另一方面减少对实际数据的访问频率,提高性能。
ndarray 数组对象的特点
- Numpy 数组是同质数组,即所有元素的数据类型必须相同。
- Numpy 数组的下标从
0
开始,最后一个元素的下标为数组长度减1
。
ndarray 数组对象的创建
np.array
(任何可被解释为 Numpy 数组的逻辑结构):import numpy as np a = np.array([1, 2, 3, 4, 5, 6]) print(a) """ [1 2 3 4 5 6] """
np.arange
(起始值(0),终止值,步长(1))import numpy as np a = np.arange(0, 5, 1) print(a) b = np.arange(0, 10, 2) print(b) """ [0 1 2 3 4] [0 2 4 6 8] """
np.zeros
(数组元素个数,dtype='类型')import numpy as np a = np.zeros(10) print(a) """ [0. 0. 0. 0. 0. 0. 0. 0. 0. 0.] """
np.ones
(数组元素个数,dtype='类型')import numpy as np a = np.ones(10) print(a) """ [1. 1. 1. 1. 1. 1. 1. 1. 1. 1.] """
ndarray 对象属性的基本操作
数组的维度:np.ndarray.shape
import numpy as np
arr = np.array([1, 2, 3, 4, 5, 6])
print(type(arr), arr, arr.shape)
arr = np.array([
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
print(type(arr), arr, arr.shape)
"""
<class 'numpy.ndarray'> [1 2 3 4 5 6] (6,)
<class 'numpy.ndarray'> [[1 2 3]
[4 5 6]
[7 8 9]] (3, 3)
"""
元素的数据类型:np.ndarray.dtype
import numpy as np
a = np.array([1, 2, 3, 4, 5, 6])
print(type(a), a, a.dtype)
b = a.astype(float) # 转换 a 的类型为 float
print(type(b), b, b.dtype)
c = a.astype(str) # 转换 a 的类型为 str
print(type(c), c, c.dtype)
"""
<class 'numpy.ndarray'> [1 2 3 4 5 6] int32
<class 'numpy.ndarray'> [1. 2. 3. 4. 5. 6.] float64
<class 'numpy.ndarray'> ['1' '2' '3' '4' '5' '6'] <U11
"""
数组元素的个数:np.ndarray.size
import numpy as np
a = np.array([
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
print(a.shape, a.size, len(a))
"""
(3, 3) 9 3
"""
数组元素索引(下标)
数组对象[..., 页号, 行号, 列号]
下标从 0 开始,到数组 len - 1 结束
import numpy as np
a = np.array([
[[1, 2], [3, 4]],
[[5, 6], [7, 8]]
])
print(a, a.shape)
print(a[0])
print(a[0][0])
print(a[0][1][0])
print(a[0, 1, 0])
"""
[[[1 2]
[3 4]]
[[5 6]
[7 8]]] (2, 2, 2)
[[1 2]
[3 4]]
[1 2]
1
3
"""
ndarray 对象属性操作详解
Numpy 内部基本数据类型
类型名 | 类型表示符 |
---|---|
布尔型 | bool_ |
有符号整数型 | int8 (-128~127)/int16 /int32 /int64 |
无符号整数型 | uint8 (0~255)/uint16 /uint32 /uint64 |
浮点型 | float16 /float32 /float64 |
复数型 | complex64 /complex128 |
字符串型 | str_ ,每个字符用 32 位 Unicode 编码表示 |
自定义复合类型
import numpy as np
data = [
('zs', [90, 80, 85], 14),
('ls', [92, 81, 83], 15),
('ww', [95, 85, 95], 16),
]
# 第一种设置 dtype 的方式
a = np.array(data, dtype='U2, 3int32, int32')
print(a)
print(a[0]['f0'], ':', a[1]['f1'], a[1]['f2'])
# 第二种设置的 dtype 的方式
b = np.array(data, dtype=[
('name', 'str', 2),
('scores', 'int32', 3),
('age', 'int32', 1),
])
print(b, b[2]['age'])
# 第三种设置的 dtype 的方式
c = np.array(data, dtype={
'names': ['name', 'scores', 'age'],
'formats': ['U2', '3int32', 'int32'],
})
print(c)
print(c[1]['name'])
"""
[('zs', [90, 80, 85], 14) ('ls', [92, 81, 83], 15)
('ww', [95, 85, 95], 16)]
[('zs', [90, 80, 85], 14) ('ls', [92, 81, 83], 15)
('ww', [95, 85, 95], 16)] 16
[('zs', [90, 80, 85], 14) ('ls', [92, 81, 83], 15)
('ww', [95, 85, 95], 16)]
ls
"""
类型字符码
类型 | 字符码 |
---|---|
np.bool_ | ? |
np.int8/16/32/64 | i1 /i2 /i4 /i8 |
np.uint8/16/32/64 | u1 /u2 /u4 /u8 |
np.float/16/32/64 | f2 /f4 /f8 |
np.complex64/128 | c8 /c16 |
np.str_ | U<字符数> |
np.datetime64 | M8[Y] M8[M] M8[D] M8[H] M8[m] M8[s] |
字节序前缀
一般用于多字节整数和字符串:
</>/[=]分别表示小端/大端/硬件字节序
类型字符码格式
< 字节序前缀 >< 维度 >< 类型 >< 字节数或字符数 >
3i4
:大端字节序,3 个元素的一维数组,每个元素都是整型,每个整型元素占 4 个字节。<(2,3)u8
:小端字节序,6 个元素 2 行 3 列的二维数组,每个元素都是无符号整型,每个无符号整型元素占 8 个字节。U7
:包含 7 个字符的 Unicode 字符串,每个字符占 4 个字节,采用默认字节序。
ndarray 数组对象维度的操作
视图变维(数据共享)
改变原数组会影响新数组,即数组之间的数据相互共享。
reshape()
和 ravel()
:
import numpy as np
a = np.arange(1, 9)
print(a)
b = a.reshape(2, 4) # 视图变维:变为 2 行 4 列的二维数组
print(b)
c = b.reshape(2, 2, 2) # 视图变维:变维 2 页 2 行 2 列的三维数组
print(c)
d = c.ravel() # 视图变维:变为 1 维数组
a[0]=99
print(d)
"""
[1 2 3 4 5 6 7 8]
[[1 2 3 4]
[5 6 7 8]]
[[[1 2]
[3 4]]
[[5 6]
[7 8]]]
[99 2 3 4 5 6 7 8]
"""
复制变维(数据独立)
改变原数组不会影响新数组,即数组之间的数据相互独立。
import numpy as np
a = np.arange(1, 9)
b = a.reshape(2, 2, 2)
c = b.flatten()
print(c)
b[0][0][0] = 99
print(c)
"""
[1 2 3 4 5 6 7 8]
[1 2 3 4 5 6 7 8]
"""
ndarray 数组切片操作
一维数组
一维数组切片的语法为 [起始下标:结束下标:步长]
,表示从起始下标开始,以指定的步长切割数组,到结束下标为止,但不包括结束下标的元素。
注意:
- 起始下标,结束下标和步长可以省略,起始下标默认为
0
,结束下标默认为数组长度
,步长默认为1
。- 起始下标和结束下标可以为负数,
-1
对应列表最后一个元素,-2
表示倒数第二个,依次类推。步长可以为-1
,-1
表示倒序对数组进行切片。
例如 a[3:6:1]
表示对数组 a
从下标 3
开始,到下标 6
结束(不包括 6
),步长为 1
进行切片,所得元素下标分别为 3,4,5
。
下面是一个综合例子:
import numpy as np
a = np.arange(1, 10)
print(a) # [1 2 3 4 5 6 7 8 9]
print(a[:3]) # [1 2 3]
print(a[3:6]) # [4 5 6]
print(a[6:]) # [7 8 9]
print(a[::-1]) # [9 8 7 6 5 4 3 2 1]
print(a[-1:-4:-1]) # [9 8 7]
print(a[-4:-7:-1]) # [6 5 4]
print(a[-7::-1]) # [3 2 1]
print(a[::]) # [1 2 3 4 5 6 7 8 9]
print(a[:]) # [1 2 3 4 5 6 7 8 9]
print(a[::3]) # [1 4 7]
print(a[1::3]) # [2 5 8]
print(a[2::3]) # [3 6 9]
二维数组
二维数组切片是一维数组切片的扩展,是类似的。语法为 [起始下标:结束下标:步长, 起始下标:结束下标:步长]
,逗号前表示对行元素进行切片,逗号后表示对列元素进行切片。
例如 a[:2, :2]
表示对二维数组进行切片,行下标从 0
开始,到下标 2
为止(不包括 2
),步长默认为 1
;列下标从 0
开始,到下标 2
为止(不包括 2
),步长默认为 1
。
下面是一个综合例子:
import numpy as np
a = np.arange(1, 10)
a.resize(3, 3)
print(a)
print(a[:2, :2])
print(a[::2, ::2])
"""
[[1 2 3]
[4 5 6]
[7 8 9]]
[[1 2]
[4 5]]
[[1 3]
[7 9]]
"""
ndarray 掩码操作
基于 bool 数组的掩码
import numpy as np
a = np.arange(100)
# 输出 3 的倍数
print(a[a % 3 == 0])
"""
[ 0 3 6 9 12 15 18 21 24 27 30 33 36 39 42 45 48 51 54 57 60 63 66 69
72 75 78 81 84 87 90 93 96 99]
"""
基于索引的掩码
import numpy as np
# 基于索引的掩码
names = np.array(['Apple', ' Huawei', 'Mi', 'Oppo', 'vivo'])
rank = [1, 0, 3, 4, 2]
print(names[rank])
"""
[' Huawei' 'Apple' 'Oppo' 'vivo' 'Mi']
"""
多维数组的组合与拆分
水平方向上的组合与拆分
hstack
函数实现数组水平方向上的组合,hsplit
函数实现数组水平方向上的拆分。
import numpy as np
a = np.arange(1, 7).reshape(2, 3)
b = np.arange(7, 13).reshape(2, 3)
# 水平方向完成组合操作,生成新数组
c = np.hstack((a, b))
# 水平方向完成拆分操作,生成两个数组
d, e = np.hsplit(c, 2)
print(c)
print(d)
print(e)
"""
[[ 1 2 3 7 8 9]
[ 4 5 6 10 11 12]]
[[1 2 3]
[4 5 6]]
[[ 7 8 9]
[10 11 12]]
"""
垂直方向上的组合与拆分
vstack
函数实现数组垂直方向上的组合,vsplit
函数实现数组垂直方向上的拆分。
import numpy as np
a = np.arange(1, 7).reshape(2, 3)
b = np.arange(7, 13).reshape(2, 3)
# 垂直方向完成组合操作,生成新数组
c = np.vstack((a, b))
# 垂直方向完成拆分操作,生成两个数组
d, e = np.vsplit(c, 2)
print(c)
print(d)
print(e)
"""
[[ 1 2 3]
[ 4 5 6]
[ 7 8 9]
[10 11 12]]
[[1 2 3]
[4 5 6]]
[[ 7 8 9]
[10 11 12]]
"""
深度方向上的组合与拆分
dstack
函数实现数组深度方向上的组合,dsplit
函数实现数组深度方向上的拆分。
import numpy as np
a = np.arange(1, 7).reshape(2, 3)
b = np.arange(7, 13).reshape(2, 3)
# 深度方向完成组合操作,生成新数组
c = np.dstack((a, b))
# 深度方向完成拆分操作,生成两个数组
d, e = np.dsplit(c, 2)
print(c)
print(d)
print(e)
"""
[[[ 1 7]
[ 2 8]
[ 3 9]]
[[ 4 10]
[ 5 11]
[ 6 12]]]
[[[1]
[2]
[3]]
[[4]
[5]
[6]]]
[[[ 7]
[ 8]
[ 9]]
[[10]
[11]
[12]]]
"""
多维数组组合与拆分的相关函数
通过 axis
作为关键字参数指定组合方向,取值如下:
- 若待组合的数组都是二维数组:
0
:垂直方向组合1
:水平方向组合
- 若待组合的数组都是三维数组:
0
:垂直方向组合1
:水平方向组合2
:深度方向组合
concatenate
函数可以实现数组的组合,split
函数可以实现数组的拆分。
import numpy as np
a = np.arange(1, 7).reshape(2, 3)
b = np.arange(7, 13).reshape(2, 3)
c = np.concatenate((a, b), axis=0)
d, e = np.split(c, 2, axis=0)
print('a:', a)
print('b:', b)
print('c:', c)
"""
a: [[1 2 3]
[4 5 6]]
b: [[ 7 8 9]
[10 11 12]]
c: [[ 1 2 3]
[ 4 5 6]
[ 7 8 9]
[10 11 12]]
"""
ndarray 的其他属性
shape
:维度dtype
:元素类型size
:元素数量ndim
:维数,len(shape)itemsize
:元素字节数nbytes
:总字节数 = size x itemsizereal
:复数数组的实部数组imag
:复数数组的虚部数组T
:数组对象的转置视图flat
:扁平迭代器
import numpy as np
a = np.array([
[1+1j, 2+4j, 3+7j],
[4+2j, 5+5j, 6+8j],
[7+3j, 8+6j, 9+9j]
])
print(a.shape)
print(a.dtype)
print(a.ndim)
print(a.size)
print(a.itemsize)
print(a.nbytes)
print(a.real)
print(a.imag)
print(a.T)
print(a.flat)
"""
(3, 3)
complex128
2
9
16
144
[[1. 2. 3.]
[4. 5. 6.]
[7. 8. 9.]]
[[1. 4. 7.]
[2. 5. 8.]
[3. 6. 9.]]
[[1.+1.j 4.+2.j 7.+3.j]
[2.+4.j 5.+5.j 8.+6.j]
[3.+7.j 6.+8.j 9.+9.j]]
<numpy.flatiter object at 0x55eaebdf7380>
"""