NumPy数组的属性和常用创建方法

原文链接:http://www.juzicode.com/archives/2605

NumPy(Numerical Python) 支持多维数组与矩阵运算,提供大量针对数组和矩阵运算的数学函数库。它的前身是Numeric,后来在Numeric中结合了另一个程序库Numarray的特色,并加入了其它功能从而演变成了今天的NumPy。

1、安装和导入

使用pip安装numpy:

pip install numpy

通常约定用如下方式导入numpy,将numpy取别名为np:

import numpy as np

“墙裂”推荐不要使用from numpy import * 的方法导入所有对象,因为在numpy中存在大量和Python内建对象重名。

2、ndarray属性

通过一个例子来看下numpy ndarray的属性:

#juzicode.com,VX:桔子code
import numpy as np
a = np.arange(6).reshape(2,3)
print('a=\n',a)
print('a.ndim=',a.ndim) #维度,也是其shape属性的长度=len(shape)
print('a.itemsize=',a.itemsize) #单个数据长度
print('a.size=',a.size) #总长度,有多少个数据
print('a.nbytes=',a.nbytes) #占用的内存空间=itemsize*size
print('a.dtype=',a.dtype) #数据类型,字符串形式
print('a.shape=',a.shape) #形状,是一个tuple
print('a.data=',a.data) #数据buffer
a=
 [[0 1 2]
 [3 4 5]]
a.ndim= 2
a.itemsize= 4
a.size= 6
a.nbytes= 24
a.dtype= int32
a.shape= (2, 3)
a.data= <memory at 0x000002647CCF0110>

上面这个例子中a是一个2行3列的二维数组,它的维度ndim=2,每个元素默认为int32型dtype=’int32’,所以单个元素占用4个字节itemsize=4,因为是2行3列的二维数组,所以元素的数量size=6,形状shape=(2,3)。

1)shape和ndim

再来看个例子对比下ndarray的shape和ndim

#juzicode.com,VX:桔子code
import numpy as np

a=np.arange(6)
b=np.arange(6).reshape(2,3)
c=np.arange(30).reshape(2,3,5)
print('a=\n',a)
print('b=\n',b)
print('c=\n',c)
print('a.ndim=',a.ndim)
print('b.ndim=',b.ndim)
print('c.ndim=',c.ndim)
print('a.shape=',a.shape)
print('b.shape=',b.shape)
print('c.shape=',c.shape)
a=
 [0 1 2 3 4 5]
b=
 [[0 1 2]
 [3 4 5]]
c=
 [[[ 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]]]
a.ndim= 1
b.ndim= 2
c.ndim= 3
a.shape= (6,)
b.shape= (2, 3)
c.shape= (2, 3, 5)

我们可以从ndim属性得出ndarray的维数,其shape属性的长度值等于ndim,也可以通过打印出来的数组形式查看其维数,一个小技巧是这个数组的边界括号有几个,它的维数就是几,下图是几个不同维数数组的例子。

另外需要注意的是一维数组的形状是a.shape= (6,) ,注意“ (6,) ”是一个元组类型的数据,是一个只包含了一个元素的元组。 单元素元组的为什么要这么表示,可以参考这篇文章:好冷的Python–tuple和逗号的恩怨情仇

2)dtype、size、itemsize、nbytes

接下来看下数组的长度相关的属性:

#juzicode.com,VX:桔子code
#numpy数组size对比
import numpy as np

a = np.arange(16,dtype='int8')
print('-----a.dtype=',a.dtype) #数据类型
print('a.size=',a.size) #总长度,数据的量
print('a.itemsize=',a.itemsize) #单个数据长度
print('a.nbytes=',a.nbytes) #总内存空间

a = np.arange(16,dtype='int16')
print('-----a.dtype=',a.dtype) #数据类型
print('a.size=',a.size) #总长度,数据的量
print('a.itemsize=',a.itemsize) #单个数据长度
print('a.nbytes=',a.nbytes) #总内存空间

a = np.arange(16,dtype='int32')
print('-----a.dtype=',a.dtype) #数据类型
print('a.size=',a.size) #总长度,数据的量
print('a.itemsize=',a.itemsize) #单个数据长度
print('a.nbytes=',a.nbytes) #总内存空间

a = np.arange(16,dtype='int64')
print('-----a.dtype=',a.dtype) #数据类型
print('a.size=',a.size) #总长度,数据的量
print('a.itemsize=',a.itemsize) #单个数据长度
print('a.nbytes=',a.nbytes) #总内存空间
-----a.dtype= int8
a.size= 16
a.itemsize= 1
a.nbytes= 16
-----a.dtype= int16
a.size= 16
a.itemsize= 2
a.nbytes= 32
-----a.dtype= int32
a.size= 16
a.itemsize= 4
a.nbytes= 64
-----a.dtype= int64
a.size= 16
a.itemsize= 8
a.nbytes= 128

上面这个例子中,创建了包含16个元素的一维数组,size属性都是16,其类型dtype不一样,可以看到int8,int16,int32,int64类型的单个元素分别占用1,2,4,8个字节(itemsize),其nbytes等于size*itemsize。​

3、ndarray创建方法

3.1、np.arange()

numpy.arange()方法会生成一个按照区间范围分布的一维数组:

numpy.arange([start, ]stop, [step, ]dtype=None)

如果只有1个位置参数,表示传入的是stop,将会生成从从0开始到stop-1步长为1的一维数组 ,数值在不包括stop在内的[1,stop)左闭右开区间内 ;

如果有2个位置参数,表示传入的是start和stop,将会生成从start到stop-1步长为1的一维数组,数值在不包括stop在内的[start,stop)左闭右开区间内;

如果有3个位置参数,表示分别传入的是start、stop和step,将会生成从start到stop-1步长为1的一维数组,数值在不包括stop在内的[start,stop)左闭右开区间内。

#juzicode.com,VX:桔子code
import numpy as np

a=np.arange(6) #arange方法创建一维数组
print('a=\n',a)
a2=np.arange(1,6) #arange方法创建一维数组,声明区间范围,左闭右开
print('a2=\n',a2)
a3=np.arange(1,6,3)#arange方法创建一维数组,声明区间范围,左闭右开,第3个位置参数为步长
print('a3=\n',a3)
a=
 [0 1 2 3 4 5]
a2=
 [1 2 3 4 5]
a3=
 [1 4]

同样还可以使用默认参数dtype声明其数据类型:

#juzicode.com,VX:桔子code
import numpy as np

a=np.arange(6,dtype='int64') #arange方法创建一维数组
print('a=\n',a)
a2=np.arange(1,6,dtype='float32') #arange方法创建一维数组,声明区间范围,左闭右开
print('a2=\n',a2)
a3=np.arange(1,6,3,dtype='float64')#arange方法创建一维数组,声明区间范围,左闭右开,第3个位置参数为步长
print('a3=\n',a3)
a=
 [0 1 2 3 4 5]
a2=
 [1. 2. 3. 4. 5.]
a3=
 [1. 4.]

3.2、np.linspace()

linspace()方法可以创建一个一维数组:

numpy.linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None, axis=0)

第1和第2个位置参数声明区间范围 ,默认左闭右闭[start,stop];

默认参数num为数组的长度或者说包含的元素个数;

如果endpoint=False,表示生成的数组其数值范围为[start,stop),这个时候数组的步长和endpoint=True是有差异的。

如果resstep=True,除了返回构造的数组,还会返回步长,返回的是一个元组:(array, step)。

#juzicode.com,VX:桔子code
import numpy as np

a=np.linspace(1,10)#linspace方法创建一维数组,声明区间范围,默认左闭右闭,默认长度为50
print('a=\n',a)

a2=np.linspace(1,10,10)#linspace方法创建一维数组,声明区间范围,默认左闭右闭,第3个位置参数为数组长度
print('a2=\n',a2)

a3=np.linspace(1,10,num=10)#linspace方法创建一维数组,声明区间范围,默认左闭右闭,num参数指定数组长度,实际从1到20换分为num-1等分
print('a3=\n',a3)

a4=np.linspace(1,10,num=10,endpoint=False)#linspace方法创建一维数组,声明区间范围,不包含最后的数值20,实际是指从1到20划分为num等分
print('a4=\n',a4)

a5=np.linspace(1,10,num=10,retstep=True) #返回数组和步长元组
print('a5=\n',a5)
a=
 [ 1.          1.18367347  1.36734694  1.55102041  1.73469388  1.91836735
  2.10204082  2.28571429  2.46938776  2.65306122  2.83673469  3.02040816
  3.20408163  3.3877551   3.57142857  3.75510204  3.93877551  4.12244898
  4.30612245  4.48979592  4.67346939  4.85714286  5.04081633  5.2244898
  5.40816327  5.59183673  5.7755102   5.95918367  6.14285714  6.32653061
  6.51020408  6.69387755  6.87755102  7.06122449  7.24489796  7.42857143
  7.6122449   7.79591837  7.97959184  8.16326531  8.34693878  8.53061224
  8.71428571  8.89795918  9.08163265  9.26530612  9.44897959  9.63265306
  9.81632653 10.        ]
a2=
 [ 1.  2.  3.  4.  5.  6.  7.  8.  9. 10.]
a3=
 [ 1.  2.  3.  4.  5.  6.  7.  8.  9. 10.]
a4=
 [1.  1.9 2.8 3.7 4.6 5.5 6.4 7.3 8.2 9.1]
a5=
 (array([ 1.,  2.,  3.,  4.,  5.,  6.,  7.,  8.,  9., 10.]), 1.0)

从上面的例子中,对比a3,a4,我们可以看到步长的差异,如果endpoint=False,对应a4,步长step=(stop-start)/num=(10-1)/10=0.9。如果endpoint=True,对应a3,步长step=(stop-start)/(num-1)=(10-1)/(10-1)=1。

3.3、np.array()

np.array()可以创建一个n维数组:

numpy.array(object, dtype=None, *, copy=True, order='K', subok=False, ndmin=0)

第1个位置参数是一个list或者tuple,如果要表示多维数组,就在该list或者tuple内部再嵌套list或者tuple。

dtype声明数据类型。

#juzicode.com,VX:桔子code
import numpy as np

a=np.array([1,2,3,4,5,6])#用一个list创建一维数组
print('a=\n',a)
a2=np.array((1,2,3,4,5,6))#用一个tuple创建一维数组
print('a2=\n',a2)

c=np.array([[1,2,3],[4,5,6]])#list中嵌套list创建二维数组
print('c=\n',c)
c2=np.array(([1,2,3],[4,5,6]))#tuple中嵌套list创建二维数组
print('c2=\n',c2)
c3=np.array(((1,2,3),(4,5,6)))#tuple中嵌套tuple创建二维数组
print('c3=\n',c3)
c4=np.array([(1,2,3),(4,5,6)])#list在嵌套tuple创建二维数据
print('c4=\n',c4)
a=
 [1 2 3 4 5 6]
a2=
 [1 2 3 4 5 6]
c=
 [[1 2 3]
 [4 5 6]]
c2=
 [[1 2 3]
 [4 5 6]]
c3=
 [[1 2 3]
 [4 5 6]]
c4=
 [[1 2 3]
 [4 5 6]]

同时也可以声明dtype类型:

#juzicode.com,VX:桔子code
import numpy as np

a2=np.array((1,2,3,4,5,6),dtype='int16')#用一个tuple创建一维数组
print('a2=\n',a2)

c=np.array([[1,2,3],[4,5,6]],dtype='float32')#list中嵌套list创建二维数组
print('c=\n',c)
a2=
 [1 2 3 4 5 6]
c=
 [[1. 2. 3.]
 [4. 5. 6.]]

3.3、np.zeros()

np.zeros()返回一个数值全1的数组:

numpy.zeros(shape, dtype=None, order='C')

第1个位置参数传入shape。

dtype参数声明其数据类型。

#juzicode.com,VX:桔子code
import numpy as np

a=np.zeros((2,3),dtype='int16') 
print('a=\n',a)
a=
 [[0 0 0]
 [0 0 0]]

3.4、np.ones()

np.ones()生成全1的数组:

numpy.ones(shape, dtype=None, order='C')

第1个位置参数传入shape。

dtype参数声明其数据类型。

#juzicode.com,VX:桔子code
import numpy as np

a=np.ones((2,3),dtype='float32')
print('a=\n',a)
a=
 [[1. 1. 1.]
 [1. 1. 1.]]

3.5、np.empty()

empty()方法创建一个未初始化的数组:

numpy.empty(shape, dtype=float, order='C')

第1个位置参数传入shape。

dtype参数声明其数据类型。

#juzicode.com,VX:桔子code
import numpy as np

a=np.empty((5,3),dtype='float32')
print('a=\n',a)

第1次执行:

a=
 [[0.000000e+00 0.000000e+00 0.000000e+00]
 [0.000000e+00 0.000000e+00 0.000000e+00]
 [0.000000e+00 0.000000e+00 0.000000e+00]
 [0.000000e+00 1.877740e-42 0.000000e+00]
 [0.000000e+00 9.091843e-39 0.000000e+00]]

第2次执行的结果(如果在jupyter中,需要重新复位一次kernel,能观察到2次执行得到不同的结果)

a=
 [[0.000e+00 0.000e+00 0.000e+00]
 [0.000e+00 0.000e+00 0.000e+00]
 [0.000e+00 0.000e+00 0.000e+00]
 [0.000e+00 1.878e-42 0.000e+00]
 [0.000e+00 0.000e+00 0.000e+00]]

3.6、np.full()

前面的ones(),zeros()方法可以创建全1和全0的数组,如果要创建全部为其他某个值就可以使用full()方法,

 numpy.full(shape, fill_value, dtype=None, order='C')

第1个位置参数传入shape。

第2个位置参数传入设置的值。

dtype声明其数据类型。

下面这个例子创建一个3行5列的值全为9的数组:

#juzicode.com,VX:桔子code
import numpy as np
a = np.full((3,5),9)
print('a=\n',a)
a=
 [[9 9 9 9 9]
 [9 9 9 9 9]
 [9 9 9 9 9]]

3.7、np.eye()

eye()创建对角线全为1的二维数组:

numpy.eye(N, M=None, k=0, dtype=<class 'float'>, order='C')

第1个位置参数N根据M是否传值决定,如果M没有传值,表示要创建一个行列数值都为N的二维数组,如果M传值,N表示要创建数组的行数;

M如果传入表示要创建二维数组的列数。

k表示从第1行开始的对角线起始位置,默认是0,表示从左上角第1个元素开始。

dtype表示数据类型。

下面这个例子创建一个行列都是5的二维数组,在对角线上数值都为1

#juzicode.com,#VX:桔子code
import numpy as np
a = np.eye(5)
print(a)
[[1. 0. 0. 0. 0.]
 [0. 1. 0. 0. 0.]
 [0. 0. 1. 0. 0.]
 [0. 0. 0. 1. 0.]
 [0. 0. 0. 0. 1.]]

下面这个例子创建一个5行9列的二维数据,从左上角0,0开始的位置对角线上的数值为1。

#juzicode.com,#VX:桔子code
import numpy as np
a = np.eye(5,M=9)
print(a)
[[1. 0. 0. 0. 0. 0. 0. 0. 0.]
 [0. 1. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 1. 0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 1. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 1. 0. 0. 0. 0.]]

下面这个例子创建一个5行9列的二维数组a,从a[0,3]开始的对角线上的数值为1。

#juzicode.com,#VX:桔子code
import numpy as np
a = np.eye(5,M=9,k=3)
print(a)
[[0. 0. 0. 1. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 1. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 1. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 1. 0. 0.]
 [0. 0. 0. 0. 0. 0. 0. 1. 0.]]

3.8、np.random.random()、np.random.random_sample()

np.random.random是np.random.random_sample的别名,二者效果一样,创建一个随机数数组,取值范围在[0.0, 1.0)的左闭右开区间:

numpy.random.random(size=None)

size参数表明数组的形状。如果size不传入,生成单个随机浮点数。

下面的例子生成一个shape=(3,5)和shaple=(3,5,2)的随机数数组:

#juzicode.com,#VX:桔子code
import numpy as np
a = np.random.random(size=(3,5))
print('a=',a)
print()
b = np.random.random_sample(size=(3,5,2))
print('b=',b)
a= [[0.92983833 0.19477253 0.31031306 0.41988556 0.23968697]
 [0.01502652 0.93812291 0.33067462 0.95677838 0.48026054]
 [0.03937766 0.63973569 0.98440503 0.43141201 0.92480903]]

b= [[[0.19002425 0.12686835]
  [0.33958788 0.98835553]
  [0.40396663 0.99271205]
  [0.26539006 0.59437947]
  [0.00174069 0.33001523]]

 [[0.36393857 0.31010785]
  [0.65423116 0.61476768]
  [0.7228634  0.54502141]
  [0.71480998 0.00757582]
  [0.30172954 0.09397801]]

 [[0.31201275 0.44994804]
  [0.0057338  0.04429699]
  [0.97511748 0.9523512 ]
  [0.65516386 0.5268285 ]
  [0.76128253 0.35939234]]]

利用该方法还可以产生其他范围内的随机数,比如下面这个例子可以生成左开右闭(0,5]范围内的随机数:

#juzicode.com,#VX:桔子code
import numpy as np
a = np.random.random(size=(3,5))
b = 5-a*5
print(b)
[[1.68676526 1.19105431 4.03721232 2.06490676 4.94086172]
 [0.22297892 4.73681044 2.51339416 4.3387627  2.30372225]
 [4.37637269 4.75808474 4.38773596 0.44839368 2.20599255]]

3.9、np.random.rand()

np.random.rand()创建一个随机数数组,取值范围在[0.0, 1.0)的左闭右开区间:

numpy.random.rand(d0, d1, ..., dn)

注意该方法的入参,不同于np.random.random()传入一个tuple作为size,而是直接传入0到多个整数作为其shape参数,当不传入参数时,生成一个随机浮点数。rand()方法实际是random_sample()的一种封装形式。

#juzicode.com,#VX:桔子code
import numpy as np
a = np.random.rand(3,5)
print('a=',a)
print()
b = np.random.rand(3,5,2)
print('b=',b)
print()
c = np.random.rand( )
print('c=',c)
a= [[0.08035812 0.23724943 0.73945204 0.48840284 0.94331751]
 [0.51696995 0.20435313 0.34513916 0.09002557 0.60626096]
 [0.97534843 0.72119943 0.42024396 0.32285727 0.31477277]]

b= [[[0.85291448 0.87464847]
  [0.76680739 0.7331416 ]
  [0.71075004 0.32622481]
  [0.72154023 0.72806926]
  [0.17847    0.27104941]]

 [[0.7285594  0.41811185]
  [0.74566335 0.59108066]
  [0.43700235 0.90066099]
  [0.33952817 0.30627273]
  [0.42774408 0.66614217]]

 [[0.30010153 0.66949531]
  [0.65392831 0.13873857]
  [0.38096064 0.52001834]
  [0.13686517 0.65874024]
  [0.78744616 0.25515434]]]

c= 0.19159395657543898

3.10、np.random.randint()

np.random.randint()创建一个随机整数型数组:

numpy.random.randint(low, high=None, size=None, dtype=int)

第一个位置参数low是必须的,如果传入high,返回的数据范围是[low,high)的左闭右开区间内的随机整数,如果没有传入high,返回的数据范围是[0,low)的左闭右开区间内的随机整数

size传入数组的shape属性。

dtype传入数据类型,只能是int、或者字符串形式的’int8’、’int32’等numpy整数类型。

#juzicode.com,#VX:桔子code
import numpy as np
a = np.random.randint(3,size=(3,5))
print('a=',a)
print()
b = np.random.randint(3,10,size=(3,5))
print('b=',b)
a= [[0 2 1 0 1]
 [0 0 2 1 2]
 [2 0 2 2 1]]

b= [[6 9 8 7 4]
 [7 4 5 3 5]
 [4 7 5 5 9]]

np.random.random_integers()和 np.random.randomint()功能类似,不过返回的是[1,low]或者[low,high]的全闭区间的整数值,但是在新的numpy版本中 random_integers 已经被 randomint()取代。在numpy v1.19.1以后得版本中如果我们调用random_integers()方法也会打印替代提示:

#juzicode.com,#VX:桔子code
import numpy as np
a = np.random.random_integers(3,size=(3,5))
print('a=',a)
print()
b = np.random.random_integers(3,10,size=(3,5))
print('b=',b)
a= [[1 1 1 2 3]
 [3 3 1 2 2]
 [2 3 2 3 1]]

b= [[ 8  6  9  5  3]
 [ 6  8  8  4  9]
 [ 8 10  5  3  7]]
<ipython-input-73-410966d96449>:3: DeprecationWarning: This function is deprecated. Please call randint(1, 3 + 1) instead
  a = np.random.random_integers(3,size=(3,5))
<ipython-input-73-410966d96449>:6: DeprecationWarning: This function is deprecated. Please call randint(3, 10 + 1) instead
  b = np.random.random_integers(3,10,size=(3,5))

3.11、np.random.randn()

np.random.randn()生成正态分布的随机数:

numpy.random.randn(d0, d1, ..., dn)

入参为传入的数组形状,多少维度就传入多少个int,和np.random.rand()一样。下面这个例子是生成一个一维数组,再通过plt.hist()显示直方图:

#juzicode.com,#VX:桔子code
import numpy as np
import matplotlib.pyplot as plt
plt.rc('font',family='Youyuan',size='9')
plt.rc('axes',unicode_minus='False')

a = np.random.randn(2000)
print('a.shape=',a.shape)
print('a.max=',a.max(),'a.min=',a.min())
print()
plt.hist(a,bins=50)
plt.title('正态分布 by桔子code')
plt.show()
a.shape= (2000,)
a.max= 3.1718286876888175 a.min= -3.1820211445746693

下面这个例子生成一个随机三维数组:

#juzicode.com,#VX:桔子code
import numpy as np
import matplotlib.pyplot as plt
plt.rc('font',family='Youyuan',size='9')
plt.rc('axes',unicode_minus='False')

a = np.random.randn(2000,2)
print('a.shape=',a.shape)
plt.subplots_adjust(wspace=0.2, hspace=0.5)
plt.subplot(221)
plt.title('a[:,:,0]')
plt.hist(a[:,:,0],bins=50) 
plt.subplot(222)
plt.title('a[:,:,1]')
plt.hist(a[:,:,1],bins=50) 
plt.subplot(223)
plt.title('a[:,:,2]')
plt.hist(a[:,:,2],bins=50) 
plt.show()

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注