Python学习——numpy

参考资料:numpy官网

一、基础

NumPy的主要对象是同构多维数组。它是一个元素表(通常是数字),所有类型都相同,由非负整数元组索引。在NumPy维度中称为 axes.
例如,3D空间中的点的坐标[1, 2, 1]具有一个轴。该轴有3个元素,所以我们说它的长度为3.
在下图所示的例子中,数组有2个轴。第一轴的长度为2,第二轴的长度为3。

[[ 1., 0., 0.],
 [ 0., 1., 2.]]

NumPy的数组类被叫做ndarray,也叫做 array。请注意,numpy.array这与标准Python库类不同array.array,后者只处理一维数组并提供较少的功能。ndarray对象更重要的属性是:

  • ndarray.ndim - 数组的轴(维度)的个数。在Python世界中,维度的数量被称为rank。
  • ndarray.shape - 数组的维度。这是一个整数的元组,表示每个维度中数组的大小。对于有 n 行和 m 列的矩阵,shape 将是 (n,m)。因此,shape 元组的长度就是rank或维度的个数 ndim。
  • ndarray.size - 数组元素的总数。这等于 shape 的元素的乘积。
  • ndarray.dtype - 一个描述数组中元素类型的对象。可以使用标准的Python类型创建或指定dtype。另外NumPy提供它自己的类型。例如numpy.int32、numpy.int16和numpy.float64。
  • ndarray.itemsize - 数组中每个元素的字节大小。例如,元素为 float64 类型的数组的 itemsize 为8(=64/8),而 complex32 类型的数组的 itemsize 为4(=32/8)。它等于ndarray.dtype.itemsize 。
  • ndarray.data - 该缓冲区包含数组的实际元素。通常,我们不需要使用此属性,因为我们将使用索引访问数组中的元素。
    举例:
import numpy as np
a = np.arange(15).reshape(3,5)
print(f'a = {a}')
print(f'a的维度:a.ndim = {a.ndim}')
print(f'a的形状:a.shape = {a.shape}')
print(f'a的大小:a.size = {a.size}')
print(f'a的元素类型:a.dtype = {a.dtype}')
print(f'a的每个元素的字节大小:a.itemsize = {a.itemsize}')
print(f'a的包含数组的实际元素:a.data = {a.data}')
print(f'type(a) = {type(a)}')

a = [[ 0  1  2  3  4]
 [ 5  6  7  8  9]
 [10 11 12 13 14]]
a的维度:a.ndim = 2
a的形状:a.shape = (3, 5)
a的大小:a.size = 15
a的元素类型:a.dtype = int32
a的每个元素的字节大小:a.itemsize = 4
a的包含数组的实际元素:a.data = 
type(a) = 

二、数组创建

1.使用array函数从常规Python列表或元组中创建数组。

  1. 从Python列表中元素的类型推导出来。
>>> import numpy as np
>>> a = np.array([2,3,4])
>>> a
array([2, 3, 4])
>>> a.dtype
dtype('int64')
>>> b = np.array([1.2, 3.5, 5.1])
>>> b.dtype
dtype('float64')

不能提供单个数字的列表类型作为参数

>>> a = np.array(1,2,3,4)    # WRONG
>>> a = np.array([1,2,3,4])  # RIGHT
  1. 从Python序列的序列中元组推导出来。
>>> b = np.array([(1.5,2,3), (4,5,6)])
>>> b
array([[ 1.5,  2. ,  3. ],
       [ 4. ,  5. ,  6. ]])
  1. 创建时显式指定数组的类型
>>> c = np.array( [ [1,2], [3,4] ], dtype=complex )
>>> c
array([[ 1.+0.j,  2.+0.j],
       [ 3.+0.j,  4.+0.j]])

2. 创建具有初始占位符内容的数组

  • 函数zeros创建一个由0组成的数组,
  • 函数 ones创建一个完整的数组,
  • 函数empty 创建一个数组,其初始内容是随机的,取决于内存的状态。
  • 默认情况下,创建的数组的dtype是 float64 类型的。
>>> np.zeros( (3,4) )
array([[ 0.,  0.,  0.,  0.],
      [ 0.,  0.,  0.,  0.],
      [ 0.,  0.,  0.,  0.]])
>>> np.ones( (2,3,4), dtype=np.int16 )                # dtype can also be specified
array([[[ 1, 1, 1, 1],
       [ 1, 1, 1, 1],
       [ 1, 1, 1, 1]],
      [[ 1, 1, 1, 1],
       [ 1, 1, 1, 1],
       [ 1, 1, 1, 1]]], dtype=int16)
>>> np.empty( (2,3) )                                 # uninitialized, output may vary
array([[  3.73603959e-262,   6.02658058e-154,   6.55490914e-260],
      [  5.30498948e-313,   3.14673309e-307,   1.00000000e+000]])

为了创建数字组成的数组,NumPy提供了一个类似于range的函数,该函数返回数组而不是列表。

>>> np.arange( 10, 30, 5 )
array([10, 15, 20, 25])
>>> np.arange( 0, 2, 0.3 )                 # it accepts float arguments
array([ 0. ,  0.3,  0.6,  0.9,  1.2,  1.5,  1.8])

当arange与浮点参数一起使用时,由于有限的浮点精度,通常不可能预测所获得的元素的数量。出于这个原因,通常最好使用linspace函数来接收我们想要的元素数量的函数,而不是步长(step):

>>> from numpy import pi
>>> np.linspace( 0, 2, 9 )                 # 9 numbers from 0 to 2
array([ 0.  ,  0.25,  0.5 ,  0.75,  1.  ,  1.25,  1.5 ,  1.75,  2.  ])
>>> x = np.linspace( 0, 2*pi, 100 )        # useful to evaluate function at lots of points
>>> f = np.sin(x)

打印数组

当您打印数组时,NumPy以与嵌套列表类似的方式显示它,但具有以下布局:

最后一个轴从左到右打印,
倒数第二个从上到下打印,
其余部分也从上到下打印,每个切片用空行分隔。

如果数组太大而无法打印,NumPy会自动跳过数组的中心部分并仅打印角点:
要禁用此行为并强制NumPy打印整个数组,可以使用更改打印选项set_printoptions(threshold=sys.maxsize)。

基本操作

  1. 数组上的算术运算符会应用到 元素 级别
  2. 乘积运算符*在NumPy数组中按元素进行运算。矩阵乘积可以使用**@运算符(在python> = 3.5中)或dot函数**或方法执行
  3. 某些操作(例如+=和 *=)会更直接更改被操作的矩阵数组而不会创建新矩阵数组。
  4. 当使用不同类型的数组进行操作时,结果数组的类型对应于更一般或更精确的数组(称为向上转换的行为)。
  5. 许多一元操作,例如计算数组中所有元素的总和,都是作为ndarray类的方法实现的。
>>> a = np.random.random((2,3))
>>> a
array([[ 0.18626021,  0.34556073,  0.39676747],
       [ 0.53881673,  0.41919451,  0.6852195 ]])
>>> a.sum()
2.5718191614547998
>>> a.min()
0.1862602113776709
>>> a.max()
0.6852195003967595
  1. 默认情况下,这些操作适用于数组,就像它是一个数字列表一样,无论其形状如何。但是,通过指定axis 参数,您可以沿数组的指定轴应用操作:
>>> b = np.arange(12).reshape(3,4)
>>> b
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])
>>>
>>> b.sum(axis=0)                            # sum of each column
array([12, 15, 18, 21])
>>>
>>> b.min(axis=1)                            # min of each row
array([0, 4, 8])
>>>
>>> b.cumsum(axis=1)                         # cumulative sum along each row
array([[ 0,  1,  3,  6],
       [ 4,  9, 15, 22],
       [ 8, 17, 27, 38]])

通函数

NumPy提供熟悉的数学函数,例如sin,cos和exp。在NumPy中,这些被称为“通函数”(ufunc)。在NumPy中,这些函数在数组上按元素进行运算,产生一个数组作为输出。

>>> B = np.arange(3)
>>> B
array([0, 1, 2])
>>> np.exp(B)
array([ 1.        ,  2.71828183,  7.3890561 ])
>>> np.sqrt(B)
array([ 0.        ,  1.        ,  1.41421356])
>>> C = np.array([2., -1., 4.])
>>> np.add(B, C)
array([ 2.,  0.,  6.])

另见这些通函数
all, any, apply_along_axis, argmax, argmin, argsort, average, bincount, ceil, clip, conj, corrcoef, cov, cross, cumprod, cumsum, diff, dot, floor, inner, INV , lexsort, max, maximum, mean, median, min, minimum, nonzero, outer, prod, re, round, sort, std, sum, trace, transpose, var, vdot, vectorize, where

索引、切片和迭代

多维的数组每个轴可以有一个索引。这些索引以逗号​​分隔的元组给出:

>>> def f(x,y):
...     return 10*x+y
...
>>> b = np.fromfunction(f,(5,4),dtype=int)
>>> b
array([[ 0,  1,  2,  3],
       [10, 11, 12, 13],
       [20, 21, 22, 23],
       [30, 31, 32, 33],
       [40, 41, 42, 43]])
>>> b[2,3]
23
>>> b[0:5, 1]                       # each row in the second column of b
array([ 1, 11, 21, 31, 41])
>>> b[ : ,1]                        # equivalent to the previous example
array([ 1, 11, 21, 31, 41])
>>> b[1:3, : ]                      # each column in the second and third row of b
array([[10, 11, 12, 13],
       [20, 21, 22, 23]])

当提供的索引少于轴的数量时,缺失的索引被认为是完整的切片:

>>> b[-1]                                  # the last row. Equivalent to b[-1,:]
array([40, 41, 42, 43])

b[i] 方括号中的表达式 i 被视为后面紧跟着 : 的多个实例,用于表示剩余轴。NumPy也允许你使用三个点写为 b[i,…]。

三个点( … )表示产生完整索引元组所需的冒号。例如,如果 x 是rank为5的数组(即,它具有5个轴),则:

x[1,2,...] 相当于 x[1,2,:,:,:],
x[...,3] 等效于 x[:,:,:,:,3]
x[4,...,5,:] 等效于 x[4,:,:,5,:]

形状控制

可以使用各种命令更改数组的形状。请注意,以下三个命令都返回一个修改后的数组,但不会更改原始数组

>>> a = np.floor(10*np.random.random((3,4)))
>>> a
array([[ 2.,  8.,  0.,  6.],
       [ 4.,  5.,  1.,  1.],
       [ 8.,  9.,  3.,  6.]])
>>> a.shape
(3, 4)
>>> a.ravel()  # returns the array, flattened
array([ 2.,  8.,  0.,  6.,  4.,  5.,  1.,  1.,  8.,  9.,  3.,  6.])
>>> a.reshape(6,2)  # returns the array with a modified shape
array([[ 2.,  8.],
       [ 0.,  6.],
       [ 4.,  5.],
       [ 1.,  1.],
       [ 8.,  9.],
       [ 3.,  6.]])
>>> a.T  # returns the array, transposed
array([[ 2.,  4.,  8.],
       [ 8.,  5.,  9.],
       [ 0.,  1.,  3.],
       [ 6.,  1.,  6.]])
>>> a.T.shape
(4, 3)
>>> a.shape
(3, 4)

该reshape函数返回带有修改形状的参数,而该 ndarray.resize方法会修改数组本身

>>> a
array([[ 2.,  8.,  0.,  6.],
       [ 4.,  5.,  1.,  1.],
       [ 8.,  9.,  3.,  6.]])
>>> a.resize((2,6))
>>> a
array([[ 2.,  8.,  0.,  6.,  4.,  5.],
       [ 1.,  1.,  8.,  9.,  3.,  6.]])

如果在 reshape 操作中将 size 指定为-1,则会自动计算其他的 size 大小:

>>> a.reshape(3,-1)
array([[ 2.,  8.,  0.,  6.],
       [ 4.,  5.,  1.,  1.],
       [ 8.,  9.,  3.,  6.]])

将不同数组堆叠在一起

  • np.vstack((a,b))
  • np.hstack((a,b))
>>> a = np.floor(10*np.random.random((2,2)))
>>> a
array([[ 8.,  8.],
       [ 0.,  0.]])
>>> b = np.floor(10*np.random.random((2,2)))
>>> b
array([[ 1.,  8.],
       [ 0.,  4.]])
>>> np.vstack((a,b))
array([[ 8.,  8.],
       [ 0.,  0.],
       [ 1.,  8.],
       [ 0.,  4.]])
>>> np.hstack((a,b))
array([[ 8.,  8.,  1.,  8.],
       [ 0.,  0.,  0.,  4.]])

column_stack 将1D数组作为列堆叠为2D数组,当输入2D数组时,与hstack等价。

>>> from numpy import newaxis
>>> np.column_stack((a,b))     # with 2D arrays
array([[ 8.,  8.,  1.,  8.],
       [ 0.,  0.,  0.,  4.]])
>>> a = np.array([4.,2.])
>>> b = np.array([3.,8.])
>>> np.column_stack((a,b))     # returns a 2D array
array([[ 4., 3.],
       [ 2., 8.]])
>>> np.hstack((a,b))           # the result is different
array([ 4., 2., 3., 8.])
>>> a[:,newaxis]               # this allows to have a 2D columns vector
array([[ 4.],
       [ 2.]])
>>> np.column_stack((a[:,newaxis],b[:,newaxis]))
array([[ 4.,  3.],
       [ 2.,  8.]])
>>> np.hstack((a[:,newaxis],b[:,newaxis]))   # the result is the same
array([[ 4.,  3.],
       [ 2.,  8.]])

concatenate可以选择堆叠的轴。

在复杂的情况下,r_和c c_于通过沿一个轴堆叠数字来创建数组很有用。它们允许使用范围操作符(“:”)。

>>> np.r_[1:4,0,4]
array([1, 2, 3, 0, 4])

与数组一起用作参数时, r_ 和 c_ 在默认行为上类似于 vstack 和 hstack ,但允许使用可选参数给出要连接的轴的编号。

将一个数组拆分成几个较小的数组

使用hsplit,可以沿数组的水平轴拆分数组,方法是指定要返回的形状相等的数组的数量,或者指定分割点应该在其之后进行分割的列:

  numpy.hsplit(array, indices_or_sections)
  • array 是要分割的输入数组。
  • indices_or_sections 是用于指定分割点的参数。它可以有以下几种形式:
    • 整数:表示分成多少个相等大小的子数组。例如,2 表示将数组分成两个子数组。
    • 一维整数数组:表示分割点的索引位置。例如,[1, 3] 表示在索引 1 和 3 处分割数组。
    • 一个序列(列表、元组等),包含整数和/或一维整数数组,表示多个分割点。

vsplit 沿着垂直轴分割,array_split 允许选择沿着哪个轴分割.

复制与视图

1. 无复制–赋值

简单的赋值不会复制对象或他们的数据:

>>> a = np.array([[ 0,  1,  2,  3],
              [ 4,  5,  6,  7],
              [ 8,  9, 10, 11]])
>>> b = a            # no new object is created
>>> b is a           # a and b are two names for the same ndarray object
True

Python将可变对象作为引用传递,因此函数调用不会复制。

>>> def f(x):
>>>     print(id(x))

>>> id(a)  # id is a unique identifier of an object 
148293216  # may vary
>>>f(a)   
148293216  # may vary

2. 视图或浅拷贝view()

不同的数组对象可以共享相同的数据。该view方法创建一个查看相同数据的新数组对象。改变shape。但使用的是相同的data。

>>> c = a.view()
>>> c is a
False
>>> c.base is a                        # c is a view of the data owned by a
True
>>> c.flags.owndata
False
>>>
>>> c.shape = 2,6                      # a's shape doesn't change
>>> a.shape
(3, 4)
>>> c[0,4] = 1234                      # a's data changes
>>> a
array([[   0,    1,    2,    3],
       [1234,    5,    6,    7],
       [   8,    9,   10,   11]])

切片数组会返回一个视图:

>>> s = a[ : , 1:3]     # spaces added for clarity; could also be written "s = a[:,1:3]"
>>> s[:] = 10           # s[:] is a view of s. Note the difference between s=10 and s[:]=10
>>> a
array([[   0,   10,   10,    3],
       [1234,   10,   10,    7],
       [   8,   10,   10,   11]])

3. 深复制copy()

赋值数组和数据

d = a.copy()  # a new array object with new data is created
d is a
False
d.base is a  # d doesn't share anything with a
False
d[0, 0] = 9999
a
array([[   0,   10,   10,    3],
       [1234,   10,   10,    7],
       [   8,   10,   10,   11]])

有时,如果不再需要原始数组,则应在切片后调用 copy。例如,假设a是一个巨大的中间结果,最终结果b只包含a的一小部分,那么在用切片构造b时应该做一个深拷贝

>>> a = np.arange(int(1e8))
>>> b = a[:100].copy()
>>> del a  # the memory of ``a`` can be released.

如果改为使用 b = a[:100],则 a 由 b 引用,并且即使执行 del a 也会在内存中持久存在。

花式索引和索引技巧

>>> a = np.arange(12)**2                       # the first 12 square numbers
>>> i = np.array( [ 1,1,3,8,5 ] )              # an array of indices
>>> a[i]                                       # the elements of a at the positions i
array([ 1,  1,  9, 64, 25])
>>>
>>> j = np.array( [ [ 3, 4], [ 9, 7 ] ] )      # a bidimensional array of indices
>>> a[j]                                       # the same shape as j
array([[ 9, 16],
       [81, 49]])

当索引数组a是多维的时,单个索引数组指的是第一个维度a。以下示例通过使用调色板将标签图像转换为彩色图像来显示此行为。

>>> palette = np.array( [ [0,0,0],                # black
...                       [255,0,0],              # red
...                       [0,255,0],              # green
...                       [0,0,255],              # blue
...                       [255,255,255] ] )       # white
>>> image = np.array( [ [ 0, 1, 2, 0 ],           # each value corresponds to a color in the palette
...                     [ 0, 3, 4, 0 ]  ] )
>>> palette[image]                            # the (2,4,3) color image
array([[[  0,   0,   0],
        [255,   0,   0],
        [  0, 255,   0],
        [  0,   0,   0]],
       [[  0,   0,   0],
        [  0,   0, 255],
        [255, 255, 255],
        [  0,   0,   0]]])

我们还可以为多个维度提供索引。每个维度的索引数组必须具有相同的形状

>>> a = np.arange(12).reshape(3,4)
>>> a
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])
>>> i = np.array( [ [0,1],                        # indices for the first dim of a
...                 [1,2] ] )
>>> j = np.array( [ [2,1],                        # indices for the second dim
...                 [3,3] ] )
>>>
>>> a[i,j]                                     # i and j must have equal shape
array([[ 2,  5],
       [ 7, 11]])
>>>
>>> a[i,2]
array([[ 2,  6],
       [ 6, 10]])
>>>
>>> a[:,j]                                     # i.e., a[ : , j]
array([[[ 2,  1],
        [ 3,  3]],
       [[ 6,  5],
        [ 7,  7]],
       [[10,  9],
        [11, 11]]])

你可能感兴趣的:(python,学习,numpy)