Numpy学习(一)
ndarray是什么?
Numpy中最重要的数据结构,ndarray是一个通用的同构多维数组,也就是说,所有元素都是相同类型的。
每个ndarray对象都有两个重要的属性:dtype和shape。
##创建ndarray
-
np.array()
将序列类型(如list,tuple等)转换为ndarray,要么推断出dtype,要么显示的指定dtype。默认直接复制参数序列。
a = np.array([1,2,3,4])
a = np.array(range(10), dtype=np.float32)
-
np.asarray()
功能与np.array类似,不同的是,当参数序列为ndarray类型时,不复制序列。 -
np.arange()
类似于python中内置的range函数。 -
np.ones(), np.ones_like()
根据指定的shape和dtype创建一个全1的ndarray数组。ones_like的参数为一个ndarray数组,根据其shape和dtype创建一个全1的数组。 -
np.zeros(), np.zeros_like()
产生全0的数组。 -
np.empty(),np.empty_like()
产生空数组,值不是零,完全随机的。 -
np.eye(),np.identity()
产生一个N×N的单位阵。
a = np.eye(5)
a = np.identity(5,dtype=np.float32)
ndarray的数据类型dtype
dtype类型如下表:
| 类型 | 类型代码 | 说明 |
|---|---|---|
| int8,uint8 | i1,u1 | 有符号或无符号的8bit整型 |
| int16,uint16 | i2,u2 | 有符号或无符号的16bit整型 |
| int32,uint32 | i4,u4 | 有符号或无符号的32bit整型 |
| int64,uint64 | i8,u8 | 有符号或无符号的64bit整型 |
| float16 | f2 | 半精度浮点数 |
| float32 | f4或f | 标准单精度 |
| float64 | f8或d | 标准双精度double |
| float128 | f16或g | 扩展精度浮点数 |
| complex64,complex128,complex256 | c8,c16,c32 | 复数 |
| bool | ? | 布尔型,True或False |
| object | O | Python对象类型 |
| string_ | S | 字符串类型,每个字符一个字节 |
| unicode_ | U | unicode类型,字节数有平台决定 |
可以通过 np.astype() 显示的转换dtype,并创建一个新的ndarray数组。
a = np.array([1,2,3,4]) #dtype is np.int64
b = a.astype(np.float32) #b.dtype is np.float32
如果将浮点数转换成整数,则小数部分将会被截断。
ndarray数组之间的算术运算
-
数组与数的运算
相当于数组中各个元素与这个数的运算。
a = np.array(range(10))
b = 10 * a
#b is array([ 0, 10, 20, 30, 40, 50, 60, 70, 80, 90])
-
相同shape数组之间的运算
相当于element-wise的运算
a = np.array(range(10))
b = a * a
#b is array([ 0, 1, 4, 9, 16, 25, 36, 49, 64, 81])
-
不同shape数组之间的运算
叫做广播broadcasting,后面再补充。
基本的索引和切片
ndarray的索引和切片与python的列表很相似。需要注意以下内容:
- 对切片赋一个标量值是,会广播到整个切片选区。
a = np.array(range(10))
a[2:7] = 5
#a is array([0, 1, 5, 5, 5, 5, 5, 7, 8, 9])
- ndarray的切片是原数组的视图,即对切片的更改也会对原数组更改。
a = np.array(range(10))
a_slice = a[2:7]
a_slice[:] = 5
#a is array([0, 1, 5, 5, 5, 5, 5, 7, 8, 9])
这样设计的原因是,Numpy是为了处理大量数据,若切片就复制的话,会产生速度和存储等问题。若要复制而非视图,可以使用.copy()函数,如b = a[2:7].copy()。
-
ndarray在索引时,可以使用类似python中的递归索引方式,比如对于一个二维数组arr2d,可以用
arr2d[0][0],但更为常见的是利用逗号隔开的索引列表来索引和切片ndarray数组,如arr2d[0,0]。 -
各个维度索引时
:的用法,与Python相一致,如下图所示。另外需要注意,索引会降低一个维度,而切片不会。
布尔型索引和切片
利用dtype为bool的ndarray数组去索引数组,如下面的例子,
>>> names = np.array(['Lily','Lucy','Kate','Hanmeimei','Lucy'])
>>> names
array(['Lily', 'Lucy', 'Kate', 'Hanmeimei', 'Lucy'], dtype='<U9')
>>> data = np.random.randn(5,4)
>>> data
array([[ 0.4233692 , -0.12770443, 0.75904085, -0.57535587],
[ 1.11805545, -0.47608307, 0.07137917, -0.12198458],
[-0.37634685, 1.03288427, 0.26873987, 0.38593625],
[-0.3106364 , -0.71935568, 2.37381352, 1.31056359],
[ 0.268878 , 0.0029276 , -1.08219147, 0.62530336]])
names中是有重复的,我们数组与标量之间的运算==,得到一个bool型的数组。这个数组可以用作索引。
>>> names == 'Lucy'
array([False, True, False, False, True])
>>> data[names == 'Lucy']
array([[ 1.11805545, -0.47608307, 0.07137917, -0.12198458],
[ 0.268878 , 0.0029276 , -1.08219147, 0.62530336]])
注意:
- 布尔型数组的长度必须跟被索引的轴长度一致。
- ndarray数组间的bool运算不是python的
and,or,not,而是&, | , ~, 应该是没有重载那些运算符。 - 通过布尔型索引将获得副本,而不是原数组的视图。
利用布尔型索引可以是某些运算变得非常简单,比如,将data中所有<0的数据都赋值为0,
>>> data[data < 0] = 0
>>> data
array([[0.4233692 , 0. , 0.75904085, 0. ],
[1.11805545, 0. , 0.07137917, 0. ],
[0. , 1.03288427, 0.26873987, 0.38593625],
[0. , 0. , 2.37381352, 1.31056359],
[0.268878 , 0.0029276 , 0. , 0.62530336]])
花式索引
花式索引(Fancy Indexing)是一个Numpy术语,指利用整数ndarray数组或整数list进行索引。利用基本的切片只能切出一个连续的区域,而不能切出离散的区域。利用花式索引可以切出离散的行、列、元素等,还可以相互调换顺序。如下面例子,
>>> arr = np.arange(32).reshape((8,4))
>>> arr
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]])
取出这个数组的第0,5,2,1行,
>>> arr[[0,5,2,1]]
array([[ 0, 1, 2, 3],
[20, 21, 22, 23],
[ 8, 9, 10, 11],
[ 4, 5, 6, 7]])
取出这个数组的第2,0列,
>>> arr[:,[2,0]]
array([[ 2, 0],
[ 6, 4],
[10, 8],
[14, 12],
[18, 16],
[22, 20],
[26, 24],
[30, 28]])
下面程序不能得到第0,5,2,1行,第2,0列,
>>> arr[[0,5,2,1],[2,0]]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: shape mismatch: indexing arrays could not be broadcast together with shapes (4,) (2,)
若要得到第0,5,2,1行,第2,0列,有如下两种方式:
- 递归的索引,先索引行,再索引列
- 利用
np.ix_()函数产生对应的坐标
>>> arr[[0,5,2,1]][:,[2,0]]
array([[ 2, 0],
[22, 20],
[10, 8],
[ 6, 4]])
>>> arr[np.ix_([0,5,2,1],[2,0])]
array([[ 2, 0],
[22, 20],
[10, 8],
[ 6, 4]])
当给定的数组索引长度相等时,索引对应位置的元素。下面代码索引的是(0,2)和(5,0)位置的元素。
>>> arr[[0,5],[2,0]]
array([ 2, 20])
注意:
- 通过花式索引将获得副本,而不是原数组的视图。