【Numpy】数组的创建

前言

本篇总结、介绍创建Numpy数组的几种主要方法 [1] [2]

1. 从列表等其他Python的结构进行转换

1.1 array

numpy.array(object, dtype=None, *, copy=True, order=‘K’, subok=False, ndmin=0):将输入转换为Numpy数组 [3]

  • object:类数组array_like)。官方文档给出的类数组的定义包括数组,公开数组接口的任何对象,__array__方法返回数组的对象,或任何(嵌套)序列
  • dtype:数据类型,可选参数。如果没有指定,那么数据类型将被确定为在序列中保存对象所需的最小类型
  • copy:布尔值,可选参数。如果为true(默认值),则返回的数组会复制对象object(否则只是简单的引用)。需要特别注意的是,numpy.array是深拷贝 [4]。但是,当obj是__array__方法返回数组的对象,obj是嵌套序列,或者需要副本来满足任何其他要求(dtype,顺序等)时,会强行进行复制。这里涉及到Python中赋值引用、浅拷贝、深拷贝的概念 [5]
  • order: {‘K’,‘A’,‘C’,‘F’},可选参数。指定阵列的内存布局。如果object不是数组,则新创建的数组将按C顺序排列(行主要),除非指定了’F’,在这种情况下,它将采用Fortran顺序(列主要)[6] [7]
  • subok:布尔值,可选参数。如果为True,则子类将被传递,否则返回的数组将被强制为基类数组(默认)
  • ndmin:整数值,可选参数。指定结果数组应具有的最小维数。根据需要,将根据需要预先设置形状

注释:
这里,我们需要注意类数组(array_like)和Numpy数组(ndarray)的联系和区别。类数组是一个更广泛、更具一般性的概念,Numpy的很多函数都作用在类数组上,因此不仅可以用于操作Numpy数组,而且可以用于操作Python原生的列表等类数组对象。从这一点上来看,Numpy非常方便和强大。


(1)一维数组:

x = np.array([1, 2, 3])
print(x)
print(type(x))
print(x.shape)

输出

[1 2 3]
<class 'numpy.ndarray'>
(3,)

(2)二维数组:

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

输出

[[1 2 3]
 [4 5 6]]
<class 'numpy.ndarray'>
(2, 3)

(3)dtype参数:

x = np.array([1, 2, 3],dtype=complex)
print(x)
print(type(x))
print(x.shape)

输出

[1.+0.j 2.+0.j 3.+0.j]
<class 'numpy.ndarray'>
(3,)

(4)copy参数:

arr1 = np.array([[1, 2, 3], [4, 5, 6]])
arr2 = np.array(arr1,copy=False)
print(arr1)
print(arr2)
arr1[0] = [0,1,2]
print(arr1)
print(arr2)

输出

[[1 2 3]
 [4 5 6]]
[[1 2 3]
 [4 5 6]]
[[0 1 2]
 [4 5 6]]
[[0 1 2]
 [4 5 6]]
arr1 = np.array([[1, 2, 3], [4, 5, 6]])
arr2 = np.array(arr1,copy=True)
print(arr1)
print(arr2)
arr1[0] = [0,1,2]
print(arr1)
print(arr2)

输出

[[1 2 3]
 [4 5 6]]
[[1 2 3]
 [4 5 6]]
[[0 1 2]
 [4 5 6]]
[[1 2 3]
 [4 5 6]]

(5)subok参数:

np.array(np.mat('1 2; 3 4'))

输出

array([[1, 2],
       [3, 4]])

但是,

np.array(np.mat('1 2; 3 4'), subok=True)

输出

matrix([[1, 2],
        [3, 4]])

(6)ndmin参数:

x = np.array([1, 2, 3],ndmin=2)
print(x)
print(type(x))
print(x.shape)

输出

[[1 2 3]]
<class 'numpy.ndarray'>
(1, 3)

注释:
个人觉得,相比下面的numpy.asarray,numpy.array更常用也更推荐。


1.2 asarray

numpy.asarray(a, dtype=None, order=None):将输入转换为Numpy数组

  • a:类数组。可以是列表, 列表的元组, 元组, 元组的元组, 元组的列表,多维数组
  • dtype:数据类型,可选参数。
  • order:{‘K’,‘A’,‘C’,‘F’},可选参数。

注释:
numpy.asarray函数类似numpy.array函数,其都可以将类数组转化为ndarray(笔者注:虽然,numpy.asarray和numpy.array的输入参数都写的是类数组,但是具体描述有差异,详见上述两者的输入参数的解释。因此,两者的作用范围是否一致暂不清楚,目前也没有必要搞的那么清楚。)。两者的主要区别在于当输入对象为Numpy ndarray时,numpy.array默认(copy=True)为深拷贝,而numpy.asarray并不会对输入对象进行拷贝,而是进行了直接引用,除非dtype改变 [4] [8] [9]

Numpy.array:

arr1 = np.array([[1, 2, 3], [4, 5, 6]])
arr2 = np.array(arr1,copy=True)
print(arr1)
print(arr2)
arr1[0] = [0,1,2]
arr1[1][0] = -4
print(arr1)
print(arr2)

输出

[[1 2 3]
 [4 5 6]]
[[1 2 3]
 [4 5 6]]
[[ 0  1  2]
 [-4  5  6]]
[[1 2 3]
 [4 5 6]]

Numpy.asarray:

arr1 = np.array([[1, 2, 3], [4, 5, 6]])
arr2 = np.asarray(arr1)
print(arr1)
print(arr2)
arr1[0] = [0,1,2]
arr1[1][0] = -4
print(arr1)
print(arr2)

输出:

[[1 2 3]
 [4 5 6]]
[[1 2 3]
 [4 5 6]]
[[ 0  1  2]
 [-4  5  6]]
[[ 0  1  2]
 [-4  5  6]]

2. 使用Numpy内部功能函数

2.1 arange

numpy.arange([start,] stop[, step,], dtype=None):以数组形式返回给定区间内均匀间隔的值([]括起来的为可选参数)

  • start:区间的起始位置(包含),可选参数,默认值为0
  • stop:区间的结束位置(不包含,因此是个前闭后开的区间),必须给出的参数
  • step:数值之间的间隔,可选参数,默认为1
  • dtype:数据类型,可选参数。如果未指定数据类型,那么从其他输入参数推断数据类型

注释:
numpy中的arange函数和python中内建的range函数类似,区别在于arange返回的是数组(ndarray)而range返回的是列表(list)。


arange函数返回的是一维数组。arange函数经常与reshape函数一起使用,将一维数组转换为高维数组。

numpy.reshape(a, newshape, order=‘C’):在不改变数据的情况下为数组赋予新的形状

  • a:待重塑的类数组
  • newshape:重塑之后的数组形状(shape),用整数或者整数元组/列表等形式来表示
  • order:数据在计算机内存中的存储顺序,可选参数,可选’C’, ‘F’, 'A’三者中的一个
# 一维数组
x = np.arange(8)
print(x)
print(type(x))
print(x.shape)

# 二维数组
x = np.reshape(x,(2,4)) # 整数组成的元组
print(x)
print(x.shape)

# 三维数组
x = np.reshape(x,(2,2,2)) # 整数组成的元组
print(x)
print(x.shape)

# 由高维数组降维到一维数组
x = np.reshape(x,8) # 整数
print(x)
print(x.shape)

输出

[0 1 2 3 4 5 6 7]
<class 'numpy.ndarray'>
(8,)
[[0 1 2 3]
 [4 5 6 7]]
(2, 4)
[[[0 1]
  [2 3]]

 [[4 5]
  [6 7]]]
(2, 2, 2)
[0 1 2 3 4 5 6 7]
(8,)

注释:
每个Numpy数组的实例也都有自己的reshape方法(注意与函数reshape区别),其语法如下:

a.reshape(shape, order=‘C’):在不改变数据的情况下为数组赋予新的形状(a为Numpy数组实例)

无论从语法还是功能上来说,Numpy数组的reshape方法和Numpy的reshape函数都一样。两者的主要区别在于,(1)Numpy的reshape函数可以直接对诸如python列表对象进行操作(但返回的依然是Numpy ndarray对象),而Numpy数组的reshape方法则不行。(2)Numpy数组的reshape方法支持形状(shape)参数的每个元素作为单独的参数传入,而Numpy的reshape函数不行。 看一下下面的例子。

我们先来看一下第一点。我们首先看一下Numpy的reshape函数:

list1 = [0,1,2,3,4,5,6,7,8]
x = np.reshape(list1,(3,3))
print(x)

输出

[[0 1 2]
 [3 4 5]
 [6 7 8]]

我们再来看一下Numpy数组的reshape方法:

list1 = [0,1,2,3,4,5,6,7,8]
list1.reshape(list1,(3,3))
print(list1)

输出

AttributeError: 'list' object has no attribute 'reshape'

报错了!

我们再来看一下第二点。我们首先看一下Numpy的reshape函数:

# 形状参数作为一个整体传入
x = np.arange(8)
np.reshape(x,(2,4))

输出

array([[0, 1, 2, 3],
       [4, 5, 6, 7]])

我们再来看一下Numpy数组的reshape方法:

# 形状参数的元素单独传入
x = np.arange(8)
np.reshape(x,2,4) # TypeError: order must be str, not int

我们再来看一下Numpy数组实例的reshape方法:

# 形状参数作为一个整体传入
x = np.arange(8)
x.reshape((2,4))

输出

array([[0, 1, 2, 3],
       [4, 5, 6, 7]])
# 形状参数的元素单独传入
x = np.arange(8)
x.reshape(2,4)

输出

array([[0, 1, 2, 3],
       [4, 5, 6, 7]])

也是可以的!


2.2 linspace

numpy.linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None, axis=0):以数组形式返回给定区间内指定数目的均匀间隔的值

  • start:类数组,表示区间的起始值(从1.16.0版本开始,strat可以为类数组;之前,start只能为标量。下面的stop和start一样。)
  • stop:类数组,表示区间的终点值(返回的数组是否包含终点值,取决于endpoint参数)
  • num:整数型,可选参数。表示生成的样本数目,即返回的数组的长度
  • endpoint:布尔值,可选参数。如果为True,那么生成的数组包含stop;否则,不包含stop
  • retstep:布尔值,可选参数。如果为True,那么将以元组(‘数组’, ‘步长’)的形式返回生成的数组及数组元素之间的间隔
  • dtype:数据类型,可选参数。如果未指定数据类型,那么从其他输入参数推断数据类型
  • axis:整数型,可选参数。指定结果中用于存储样本的轴。只有当start和stop为数组时,该参数才有意义(从1.16.0版本开始才有的新的输入参数)

相比arange,linspace可以指定数组的长度

x1 = np.linspace(2,3,num=5)
x2 = np.linspace(2,3,num=5,endpoint=False)
x3 = np.linspace(2,3,num=5,retstep=True)
x4 = np.linspace(2,3,num=5,dtype=int)
print(x1)
print(x2)
print(x3)
print(x4)

输出

[2.   2.25 2.5  2.75 3.  ]
[2.  2.2 2.4 2.6 2.8]
(array([2.  , 2.25, 2.5 , 2.75, 3.  ]), 0.25)
[2 2 2 2 3] # 将[2.   2.25 2.5  2.75 3.  ]强制转换为整数型

在numpy 1.16.0版本之前,linspace函数和arange函数一样,返回的都是一维数组。因此,linspace函数也可以与reshape函数一起使用,创建更高维数组,在此不再赘述。


注释:
和linspace类似的还有logspacegeomspace,在此不再赘述。


2.3 zeros、zeros_like

numpy.zeros(shape, dtype=float, order=‘C’):创建元素全部为0,形状(shape)和数据类型(dtype)指定的数组

  • shape:数组形状,用整数或者整数元组/列表等形式来表示,比如2,(2,3),[2,3]
  • dtype:数据类型,可选参数
  • order:{‘C’, ‘F’},可选参数
x1 = np.zeros(2)
x2 = np.zeros((2,))
x3 = np.zeros((2,1))

print(x1) 
print(x2) 
print(x3) 

输出:

[0. 0.]
[0. 0.]
[[0.]
 [0.]]

numpy.zeros_like(a, dtype=None, order=‘K’, subok=True, shape=None):返回与给定数组a具有相同形状和数据类型的全0数组(注意数组形状和数据类型都相同)

  • a:类数组
x1 = np.ones((2,3))
x2 = np.zeros_like(x1)
x3 = np.ones((2,3),dtype=int)
x4 = np.zeros_like(x3)
print(x1)
print(x2)
print(x3)
print(x4)

输出:

[[1. 1. 1.]
 [1. 1. 1.]]
[[0. 0. 0.]
 [0. 0. 0.]]
[[1 1 1]
 [1 1 1]]
[[0 0 0]
 [0 0 0]]

注释:
需要注意的且比较有意思的一点是:zeros和zeros_like都可以传入列表、元组等类数组类型,但意义和返回的结果却大相径庭。我们看一下下面的例子。

np.zeros([2,3])

输出

array([[0., 0., 0.],
       [0., 0., 0.]])

np.zeros_like([2,3])

输出

array([0, 0])

一言以蔽之,zeros会将传入的列表直接作为数组形状参数,而zeros_like会将传入的列表的形状作为数组的形状。


2.4 ones、ones_like

numpy.ones(shape, dtype=float, order=‘C’):创建元素全部为1,形状(shape)和数据类型(dtype)指定的数组

numpy.ones_like(a, dtype=None, order=‘K’, subok=True, shape=None):返回与给定数组a具有相同形状和数据类型的全1数组(注意数组形状和数据类型都相同)

ones、ones_like和zeros、zeros_like使用方法一致,详见2.3节。

2.5 empty、empty_like

numpy.empty(shape, dtype = float, order = ‘C’):创建一个形状(shape)和数据类型(dtype)指定,且未初始化的数组

numpy.empty_like(a, dtype=None, order=‘K’, subok=True, shape=None):返回与给定数组a具有相同形状和数据类型的全1数组(注意数组形状和数据类型都相同)

empty、empty_like和zeros、zeros_like使用方法一致,详见2.3节。


注释:
empty、empty_like返回数组的元素为随机数,因为它们没有初始化


2.6 full、full_like

numpy.full(shape, fill_value, dtype=None, order=‘C’):创建一个形状(shape)和数据类型(dtype)指定,且全部元素用“fill_value”填充的数组

  • fill_value:标量或数组
x1 = np.full((2,3),3)
x2 = np.full((2,3),[1,2,3])
print(x1)
print(x2)

输出:

[[3 3 3]
 [3 3 3]]
[[1 2 3]
 [1 2 3]]

注释:
如果fill_value为数组,那么需要注意fill_value的形状和待创建数组的形状满足广播(Broadcast)。

看下面一个例子:

np.full((2,3),[1,2])

会报如下错误:

ValueError: could not broadcast input array from shape (2) into shape (2,3)

numpy.full_like(a, fill_value, dtype=None, order=‘K’, subok=True, shape=None):返回与给定数组a具有相同形状和数据类型,且用指定元素fill_value填充的数组

具体用法请参考2.3节ones_like及full,不再赘述。

2.7 特殊数组

2.7.1 identity

numpy.identity(n, dtype=None):创建一个二维单位数组,即单位矩阵

  • n:整数型,单位矩阵的行/列数
x = np.identity(2)
print(x)

输出

[[1. 0.]
 [0. 1.]]

2.7.2 eye

numpy.eye(N, M=None, k=0, dtype=float, order=‘C’):创建一个二维数组,其对角线位置为1,其余位置为0

  • N:整数,表示二维数组的行数
  • M:整数,表示二维数组的列数,可选参数
  • k:整数,表示对角线的索引,可选参数。0表示主对角线,正数表示主对角线上方的对角线,负数表示主对角线下方的对角线
x1 = np.eye(3)
x2 = np.eye(2,3)
x3 = np.eye(3,k=1)
x4 = np.eye(3,k=-1)
x5 = np.eye(3,k=2)

输出为

[[1. 0. 0.]
 [0. 1. 0.]
 [0. 0. 1.]]
[[1. 0. 0.]
 [0. 1. 0.]]
[[0. 1. 0.]
 [0. 0. 1.]
 [0. 0. 0.]]
[[0. 0. 0.]
 [1. 0. 0.]
 [0. 1. 0.]]
 [[0. 0. 1.]
 [0. 0. 0.]
 [0. 0. 0.]]

2.7.3 diag

numpy.diag(v, k=0):提取主对角线或者构造一个对角数组

  • v:如果v是一维数组,那么返回一个二维的主对角数组,其中主对角线元素即为v;如果v是一个二维数组,那么返回其主对角线元素
  • k:整数型,可选参数,表示对角线的索引,默认为0。k>0表示主对角线以上的对角线;反之表示主对角线以下的对角线
# 当输入参数为二维数组时,np.diag返回对角线元素
x = np.arange(9).reshape((3,3))
print(x)
print(np.diag(x))
print(np.diag(x,k=1))

输出

[[0 1 2]
 [3 4 5]
 [6 7 8]]
[0 4 8]
[1 5]
# 当输入参数为一维数组时,np.diag返回该一维数组构造的二维对角数组
x = np.diag([1,2,3])
print(x)

输出

[[1 0 0]
 [0 2 0]
 [0 0 3]]

2.7.4 tri、triu、tril

numpy.tri(N, M=None, k=0, dtype=float):返回一个数组,其在给定对角线上及其下方的元素都为1,而在给定对角线上方的元素都为0,即三角矩阵

  • N:整数型,数组的行数
  • M:整数型,可选参数,数组的列数,默认M=N
  • k:整数型,可选参数,表示对角线的索引,默认为0。k>0表示主对角线以上的对角线;反之表示主对角线以下的对角线
x1 = np.tri(3)
x2 = np.tri(3,4)
x3 = np.tri(3,4,1)
print(x1)
print(x2)
print(x3)

输出


[[1. 0. 0.]
 [1. 1. 0.]
 [1. 1. 1.]]
[[1. 0. 0. 0.]
 [1. 1. 0. 0.]
 [1. 1. 1. 0.]]
[[1. 1. 0. 0.]
 [1. 1. 1. 0.]
 [1. 1. 1. 1.]]

numpy.tril(m, k=0):返回一个二维数组的下三角矩阵

  • m:输入的二维数组
  • k
x = np.arange(9).reshape((3,3))
print(x)
print(np.tril(x))

输出

[[0 1 2]
 [3 4 5]
 [6 7 8]]
[[0 0 0]
 [3 4 0]
 [6 7 8]]

numpy.triu(m, k=0):返回一个二维数组的上三角矩阵

numpy.triu和numpy.tril的用法一模一样,在此不多赘述。


注释:
需要注意的是,第2.7节介绍的这些方法,都只能生成二维数组。


3. 使用特殊的库函数

有些库可用于生成特殊用途的数组,这些库不一而足,在此不一一列出了。可能最常见也最常用的是random库。例如:

np.random.random((2,2))

输出

array([[0.63986367, 0.60182471],
       [0.94717796, 0.9034801 ]])

Reference

[1]: https://www.numpy.org.cn/article/basics/different_ways_create_numpy_arrays.html
[2]: https://www.numpy.org.cn/user/basics/creation.html#%E7%AE%80%E4%BB%8B
[3]: https://blog.csdn.net/hl1hl/article/details/86570046
[4]: https://blog.csdn.net/comedate/article/details/108785483
[5]: https://www.runoob.com/w3cnote/python-understanding-dict-copy-shallow-or-deep.html
[6]: https://www.zhihu.com/question/23798415
[7]: https://blog.csdn.net/zhanggonglalala/article/details/79356653
[8]: https://blog.csdn.net/fu6543210/article/details/83242047
[9]: https://blog.csdn.net/u012333003/article/details/34502651
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值