一、有的没的
- NumPy包的核心是ndarray对象,它封装了python原生的同数据类型的n维数组。
- 固定大小、元素数据类型相同、高效
- 矢量化和广播?
二、快速开始
基础知识
- ndarray.ndim 轴:数组的维度
- ndarray.shape 每个元素的维度
- ndarray.dtype 数据类型
- ndarray.itemsize 每个元素的字节大小
- ndarray.data 实际元素
1数组创建
import numpy as np
a=np.array([2,3,4])
#a=np.array(2,3,4) wrong
b=np.array([1.2,3.1,4.0])
c=np.array([(1,2),(3,4)])
#二维数组
d=np.array([[1,2],[3,4]],dtype=complex)
#指定类型
np.zeros(3)=>array([0.,0.,0.])
np.zeros((2,3))=>
array([[0.,0.,0.],
[0.,0.,0.]])
np.ones((2,3,4),dtype=np.int16)
#指定类型的三维数组,元素都是1
np.empty((2,3))
#创建一个内容随机的数组,float64类型
np.arange(1,10,3)
#类似range,有步长
np.linspace(0,2,9)
#0-2的9个元素
2基本操作
算术运算符会应用到元素级别
>>> A = np.array( [[1,1],
... [0,1]] )
>>> B = np.array( [[2,0],
... [3,4]] )
>>> A * B # elementwise product
array([[2, 0],
[0, 4]])
>>> A @ B # matrix product
array([[5, 4]
[3, 4]])
>>> A.dot(B) # another matrix product
array([[5, 4],
[3, 4]])
A@B和A.dot(B)都是获取矩阵乘积的
- +=和*=都会直接更改被操作的矩阵数组
- 当使用不同类型的数组进行操作时,结果数组的类型对应于更一般或更精确的数组(称为向上转换的行为)
a=np.random.random((2,3))
a.sum()
a.min()
a.max()
b=np.arange(12).reshape(3,4)
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
b.sum(axis=0)#按列求和
array([12,15,18,21])
b.min(axis=1)#按行求最小值
b.cumsum(axis=0)
#按列累计求值
array([[ 0, 1, 2, 3],
[ 4, 6, 8, 10],
[12, 15, 18, 21]], dtype=int32)
3通函数
- 在数组上按元素进行计算,产生一个数组作为输出
4索引、切片和迭代
a[:6:2]=100
#a中从0到6的元素,每隔两个赋值为100
>>> def f(x,y):
... return 10*x+y
...
>>> b = np.fromfunction(f,(5,4),dtype=int)
#对每一个元素的索引对都执行f操作后所得为该位置的元素值
>>> b
array([[ 0, 1, 2, 3],
[10, 11, 12, 13],
[20, 21, 22, 23],
[30, 31, 32, 33],
[40, 41, 42, 43]])
a=np.arange(12).reshape(3,2,2)
array([[[ 0, 1],
[ 2, 3]],
[[ 4, 5],
[ 6, 7]],
[[ 8, 9],
[10, 11]]])
a[:,:,1]=>
array([[ 1, 3],
[ 5, 7],
[ 9, 11]])
a[1,...]=>
array([[4, 5],
[6, 7]])
...代表后面的剩余轴均为 :,即全部
- 对多维数组进行 迭代(Iterating) 是相对于第一个轴完成的
- 如果想要对数组中的每个元素执行操作,可以使用
flat
属性,该属性是数组的所有元素的[迭代器]
b=np.arange(48).reshape(2,3,4,2)
array([[[[ 0, 1],
[ 2, 3],
[ 4, 5],
[ 6, 7]],
[[ 8, 9],
[10, 11],
[12, 13],
[14, 15]],
[[16, 17],
[18, 19],
[20, 21],
[22, 23]]],
[[[24, 25],
[26, 27],
[28, 29],
[30, 31]],
[[32, 33],
[34, 35],
[36, 37],
[38, 39]],
[[40, 41],
[42, 43],
[44, 45],
[46, 47]]]])
for e in b.flat:
print(e)
#所有元素
形状操纵
1.改变数组的形状
一个数组的形状是由每个轴的元素数量决定的。a.shape()
a=np.floor(10*np.random.random((3,4)))
array([[9., 6., 2., 5.],
[4., 0., 8., 0.],
[7., 7., 5., 6.]])
#以下均不修改原数组
a.ravel() #铺平
a.reshape(6,2)
a.T #行列翻转
a.resize(2,6)
#会改变原数组
array([[9., 6., 2., 5., 4., 0.],
[8., 0., 7., 7., 5., 6.]])
2.将不同数组堆叠在一起
a=np.array([[1,2],[3,4]])
b=np.array([[5,6],[7,8]])
np.vstack((a,b))
array([[1, 2],
[3, 4],
[5, 6],
[7, 8]])
np.hstack((a,b))
array([[1, 2, 5, 6],
[3, 4, 7, 8]])
hstack 和 column_stack在处理二维以上数组时效果一样,但是当处理以为数组时不同
from numpy import newaxis
a=np.array([1,2])
b=np.array([3,4])
np.column_stack((a,b))
#相当于创建了新轴
array([[1, 3],
[2, 4]])
np.hstack((a,b))
array([1, 2, 3, 4])
a[:,newaxis] #加新轴,增加维度
- row_stack 和 ma.row_stack
3.将一个数组拆分成几个小的
- hsplit(a,n) 将a拆成3个
hsplit(a,(3,5)) 在第三列和第五列
拷贝和视图
1.完全不复制
import numpy as np
a=np.arange(12)
b=a
b is a
#True
b.shape=3,4
Python将可变对象作为引用传递,函数调用不会复制
def f(x):
print(id(x))
id(a)#2022876649392
f(a) #2022876649392
2.视图或浅拷贝
不同的数组对象可以共享相同的数据,该view方法创建一个查看相同数据的新数组对象。
c=a.view()
#c是a的数据的一个视图
c is a
False
c.base is a
True
c.shape=2,6
a.shape#3,4
c[0,4]=1234
a
array([[ 0, 1, 2, 3],
[1234, 5, 6, 7],
[ 8, 9, 10, 11]])
#不改变shape,但是赋值操作会都改变
切片数组返回的是一个视图(浅拷贝)
3.深拷贝
d=a.copy()
d is a
False
d.base is a
False
d[0,0]=999
a
array([[ 0, 1, 2, 3],
[1234, 5, 6, 7],
[ 8, 9, 10, 11]])
当不再需要原始数组的时候,则应该在切片后调用copy。
b=a[:100].copy()
del a 可以删除
若 b=a[:100]
即使del a,a也还会在内存中。
Less基础
广播规则:1.
花式索引和索引技巧
使用索引数组进行索引
- A数组可通过另一个索引数组B来获取A中对应索引的元素
- 为多个维度提供索引。每个维度的索引数组必须具有相同的形状
>>> a=np.arange(12)
>>> a
array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])
>>> a.shape=3,4
>>> a
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
>>> a[0,1]
1
>>> i=array([1,2])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'array' is not defined
>>> i=np.array([1,2])
>>> a[i]
array([[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
>>> i=np.array([[1],[2]])
>>> a[i]
array([[[ 4, 5, 6, 7]],
[[ 8, 9, 10, 11]]])
>>> i=np.array([[0,1],[1,2]])
>>> a[i]
array([[[ 0, 1, 2, 3],
[ 4, 5, 6, 7]],
[[ 4, 5, 6, 7],
[ 8, 9, 10, 11]]])
#为多个维度提供索引。每个维度的索引数组必须具有相同的形状
>>> j=np.array([[2,1],[3,3]])
>>> a[i,j]
array([[ 2, 5],
[ 7, 11]])
>>> time=np.linspace(20,145,5)
>>> time
array([ 20. , 51.25, 82.5 , 113.75, 145. ])
>>> data=np.sin(np.arange(20).reshape(5,4))
>>> data
array([[ 0. , 0.84147098, 0.90929743, 0.14112001],
[-0.7568025 , -0.95892427, -0.2794155 , 0.6569866 ],
[ 0.98935825, 0.41211849, -0.54402111, -0.99999021],
[-0.53657292, 0.42016704, 0.99060736, 0.65028784],
[-0.28790332, -0.96139749, -0.75098725, 0.14987721]])
>>> ind = data.argmax(axis=0)
>>> ind
array([2, 0, 3, 1], dtype=int64)
#沿X轴纵向比较
>>> ind1 = data.argmax(axis=1)
>>> ind1
array([2, 3, 0, 2, 3], dtype=int64)
#沿Y轴横向比较
>>> import numpy as np
>>> a=np.arange(5)
>>> a[[0,1,2]]=9
>>> a
array([9, 9, 9, 3, 4])
>>> a[[0,0,0]]=[1,2,3]
#多次给同一索引赋值,取最后一次
>>> a
array([3, 9, 9, 3, 4])
>>> a[[0,0]]+=1
#这里只做一次运算
>>> a
array([4, 9, 9, 3, 4])
使用布尔数组进行索引
>>> import numpy as np
>>> b=np.arange(12).reshape(3,4)
>>> b
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
>>> a=b>4
#对b中的每个元素进行比较,返回一个和b具有相同形状的布尔数组,值为比较结果
>>> a
array([[False, False, False, False],
[False, True, True, True],
[ True, True, True, True]])
>>> b[a]
#返回为True的一维数组
array([ 5, 6, 7, 8, 9, 10, 11])
>>> b[a]=0
#为符合条件的元素重新赋值
>>> b
array([[0, 1, 2, 3],
[4, 0, 0, 0],
[0, 0, 0, 0]])
再说索引
>>> a=np.arange(12).reshape(3,4)
>>> a
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
>>> a[1,2]
6
>>> a[1]
array([4, 5, 6, 7])
>>> a[1,:]
array([4, 5, 6, 7])
>>> a[:,1]
array([1, 5, 9])
>>> a[[1]]
array([[4, 5, 6, 7]])
>>> a[[1],:]
array([[4, 5, 6, 7]])
>>> a[[1],[2]]
array([6])
>>> a[[1,2],[2]]
array([ 6, 10])
>>> a[[1,2],[2,3]]
array([ 6, 11])
>>> a[[1,2],:]
array([[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
>>> a[[1,2],[2,3]]
array([ 6, 11])
>>> a[:,[2,3]]
array([[ 2, 3],
[ 6, 7],
[10, 11]])
>>> a[[[2,1],[3,3]],:]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: index 3 is out of bounds for axis 0 with size 3
>>> a[[[2,1],[0,0]],:]
array([[[ 8, 9, 10, 11],
[ 4, 5, 6, 7]],
[[ 0, 1, 2, 3],
[ 0, 1, 2, 3]]])
>>> a[[[2,1],[0,0]],[[3,3],[0,2]]]
array([[11, 7],
[ 0, 2]])
ix_()函数
可用于组合不同的向量,只能是一维的。
组合了几个向量,得到的每个向量就是几维的,某向量组合前是一维n个元素的向量,与另外两个组合后,就是三维的,且形状为1:1:n(1,1,n顺序不定)
线性代数
简单数组操作
>>> a
array([1, 2])
>>> a.transpose()
array([1, 2])
>>> a=np.array([[1,2,3],[4,5,6]])
>>> a.transpose()
array([[1, 4],
[2, 5],
[3, 6]])
行列交换对一维数组不起作用
>>> a=np.array([1,2])
>>> a@a
5
>>> a=np.array([[2,1],[3,3]])
>>> a@a
array([[ 7, 5],
[15, 12]])
>>> np.eye(34)
array([[1., 0., 0., ..., 0., 0., 0.],
[0., 1., 0., ..., 0., 0., 0.],
[0., 0., 1., ..., 0., 0., 0.],
...,
[0., 0., 0., ..., 1., 0., 0.],
[0., 0., 0., ..., 0., 1., 0.],
[0., 0., 0., ..., 0., 0., 1.]])
>>> np.eye(4)
array([[1., 0., 0., 0.],
[0., 1., 0., 0.],
[0., 0., 1., 0.],
[0., 0., 0., 1.]])
>>> np.trace(a)
5# 矩阵的迹
>>> a = np.arange(8).reshape((2,2,2))
>>> np.trace(a)
array([6, 8])
>>> b=np.array([[1,2],[3,4]])
>>> b
array([[1, 2],
[3, 4]])
>>> np.trace(b)
5
>>> b=np.array([[1,2,1],[3,4,3]])
>>> np.trace(b)
5
>>> b=np.array([[1,2,1],[3,4,3],[1,2,1]])
>>> np.trace(b)
6
>>> b=np.array([[1,2,1,1],[3,4,3,3],[1,2,1,1]])
>>> np.trace(b)
6
>>> b=np.array([[1,2,1,1],[3,4,3,3],[1,2,1,1],[3,4,3,3]])
>>> np.trace(b)
9
>>>
np.linalg.solve(B,b) 求解线性方程组
np.linalg.eig(C) 求特征值和特征向量
自动整形
>>> a = np.arange(30)
>>> a.shape = 2,-1,3 # -1 means "whatever is needed"
>>> a.shape
(2, 5, 3)
矢量堆叠
x = np.arange(0,10,2) # x=([0,2,4,6,8])
y = np.arange(5) # y=([0,1,2,3,4])
m = np.vstack([x,y]) # m=([[0,2,4,6,8],
# [0,1,2,3,4]])
xy = np.hstack([x,y]) # xy =([0,2,4,6,8,0,1,2,3,4])