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相一致,如下图所示。另外需要注意,索引会降低一个维度,而切片不会。Numpy学习入门I

布尔型索引和切片

利用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])

注意:

  • 通过花式索引将获得副本,而不是原数组的视图。

相关文章:

  • 2021-11-16
  • 2021-07-04
  • 2021-12-03
  • 2021-09-25
  • 2021-10-12
  • 2021-05-13
  • 2022-02-05
  • 2021-11-28
猜你喜欢
  • 2021-07-31
  • 2021-09-22
  • 2021-04-17
  • 2021-06-28
  • 2021-05-17
  • 2021-06-10
相关资源
相似解决方案