zoukankan      html  css  js  c++  java
  • Numpy学习笔记

    1.常用属性

    • 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) # 创建numpy数组,元素为0-14,并调整为3行5列
    print(a)
    """
    [[ 0  1  2  3  4]
     [ 5  6  7  8  9]
     [10 11 12 13 14]]
     """
    print(a.shape)  # (3, 5)
    print(a.ndim)  # 2,表示维度
    print(a.dtype.name)  # int32 ,元素类型
    print(a.itemsize)  # 4 ,元素所占字节数
    print(a.size)  # 15 ,元素个数
    print(type(a))  # <class 'numpy.ndarray'>
    b = np.array([6, 7, 8]) # 用给定的列表创建numpy数组
    print(b)  # [6 7 8]
    print(type(b))  # <class 'numpy.ndarray'>
    
    

    2.创建numpy数组的几种方法

    # 尽量不用原生数组,而使用ndarray,在确定元素的情况下,使用array创建,在不确定元素,但已知元素个数的情况下,使用zeros,ones,empty
    import math
    import numpy as np
    
    
    # 数组元素已知情况下,可直接用np.array()创建数组
    # 自动判断元素类型,自动判断维数,也可指定元素类型
    def arr_given():
        a = np.array([2, 3, 4]) # 利用给定的列表创建numpy数组
        # a = np.array(1, 2, 3, 4)  # 错误用法 ,形参需为序列
        print(a)
        print(a.dtype)
        # 自动判断数组元素类型
        b = np.array([1.2, 3.5, 5.1]) # 自动创建对应元素类型的numpy数组
        print(b.dtype)
        # 将序列的序列转换成二维数组,将序列的序列的序列转换成三维数组
        b = np.array([(1.5, 2, 3), (4, 5, 6)])
        print(b)
        # 在创建时显式指定数组的类型
        c = np.array([[1, 2], [3, 4]], dtype=complex)
        print(c)
    
    
    # NumPy提供了几个函数来创建具有初始占位符内容的数组,用于不知道元素内容,但是知道元素个数
    def arr_unknown():
        np_zeros = np.zeros((3, 4))  # 元素内容全为0
        print(np_zeros)
        np_ones = np.ones((2, 3, 4), dtype=np.int16)  # 元素内容全为1
        print(np_ones)
        np_empty = np.empty((2, 3))  # 元素内容随机,取决于主存单元原本内容,不常用
        print(np_empty)
    
    
    # 生成元素具有某种特定规律的数组
    def arr_create_by_rule():
        np_arange = np.arange(10, 30, 5)  # 形参类似于python内置range函数的形参,返回np数组,以步长为5创建从10 到 30(取不到30)的numpy数组
        print(np_arange)
        print(type(np_arange))
        np_arange2 = np.arange(0, 2, 0.3)
        print(np_arange2)
        # 创建浮点数数组时,建议使用 linspace
        np_linspace = np.linspace(0, 2, 9)
        print(np_linspace)
        x = np.linspace(0, 2 * math.pi, 100)  # useful to evaluate function at lots of points
        print(x)
    
    
    if __name__ == '__main__':
        # arr_given()
        # arr_unknown()
        arr_create_by_rule()
    
    

    3.一些常用的操作

    import math
    import numpy as np
    
    
    def func1():
        a = np.array([20, 30, 40, 50]) # 创建numpy数组,数组元素内容为给定的列表元素(元组)
        b = np.arange(4) # 创建numpy数组 ,数组元素内容为0到4,取不到4
        print(a)  # [20 30 40 50]
        print(b)  # [0 1 2 3]
        c = a - b
        print(c)  # [20 29 38 47]
        print(b ** 2)  # [0 1 4 9]
        print(10 * np.sin(a))  # [ 9.12945251 -9.88031624  7.4511316  -2.62374854]
        print(a < 35)  # [ True True False False] 返回的结果常用于布尔索引数组
    
    
    # 元素乘法和矩阵乘法
    def func2():
        A = np.array([[1, 1],
                      [0, 1]])
        B = np.array([[2, 0],
                      [3, 4]])
        print(A * B)  # 元素对应相乘
        print(A @ B)  # 矩阵乘法
        print(A.dot(B))  # 矩阵乘法
    
    
    # +=和*=会直接更改被操作的矩阵数组而不会创建新矩阵数组。
    def func3():
        a = np.ones((2, 3), dtype=int) # 创建2行3列元素均为1的数组
        b = np.random.random((2, 3)) # 创建2行3列数组,元素随机,不推荐使用
        """
        [[0.15510154 0.08835426 0.5688731 ]
    	[0.92793405 0.2701924  0.6298227 ]]
    
        """
        print('a = ')
        print(a)
        print('b = ')
        print(b)
        a *= 3
        print('a = ')
        print(a)
        b += a
        print('b = ')
        print(b)
        # a += b  # TypeError: Cannot cast ufunc add output from dtype('float64') to dtype('int64') with casting rule 'same_kind'
    
    
    # 当使用不同类型的数组进行操作时,结果数组的类型对应于更一般或更精确的数组(称为向上转换的行为)
    def func4():
        a = np.ones(3, dtype=np.int32)
        b = np.linspace(0, math.pi, 3)
        print(b.dtype.name)
        c = a + b
        print(c)
        print(c.dtype.name)
        d = np.exp(c * 1j)
        print(d)
        print(d.dtype.name)
    
    
    def func5():
        a = np.random.random((2, 3))
        print(a)
        print(a.sum())
        print(a.min())
        print(a.max())
    
    
    # 指定axis参数,可以沿数组的指定轴应用操作
    def func6():
        b = np.arange(12).reshape(3, 4)
        print(b)
        print(b.sum(axis=0))  # sum of each column
        print(b.min(axis=1))  # min of each row
        print(b.cumsum(axis=1))  # cumulative sum along each row
    
    
    if __name__ == '__main__':
        # func1()
        # func2()
        # func3()
        # func4()
        # func5()
        func6()
    

    4.一些简单的通函数

    # 通函数
    import numpy as np
    
    B = np.arange(3)
    print(B)
    print(np.exp(B))
    print(np.sqrt(B))
    C = np.array([2., -1., 4.])
    print(np.add(B, C))
    
    

    5.numpy索引元素

    import numpy as np
    
    
    # 一维的数组可以进行索引、切片和迭代操作的,就像 列表 和其他Python序列类型一样
    def func1():
        a = np.arange(10) ** 3
        print(a)
        print(a[2])
        print(a[2:5])
        a[:6:2] = -1000  # equivalent to a[0:6:2] = -1000; from start to position 6, exclusive, set every 2nd element to -1000
        print(a)
        print(a[::-1])
        for i in a:
            print(i)
    
    
    def f(x, y):
        return 10 * x + y
    
    
    # 多维的数组每个轴可以有一个索引。这些索引以逗号分隔的元组给出:
    def func2():
        b = np.fromfunction(f, (5, 4), dtype=int)
        print(b)
        """
        [[ 0  1  2  3]
         [10 11 12 13]
         [20 21 22 23]
         [30 31 32 33]
         [40 41 42 43]]
        """
        print(b[2, 3]) # 23
        print(b[0:5, 1])  # [ 1 11 21 31 41] # each row in the second column of b
        print(b[:, 1])  # [ 1 11 21 31 41] # equivalent to the previous example
        print(b[1:3, :])  # each column in the second and third row of b
        # [[10 11 12 13]
        #  [20 21 22 23]]
        # 当提供的索引少于轴的数量时,缺失的索引被认为是完整的切片
        print(b[-1])  # the last row. Equivalent to b[-1,:]
    
    
    
    # 对多维数组进行 迭代(Iterating) 是相对于第一个轴完成的:
    def func3():
        b = np.fromfunction(f, (5, 4), dtype=int)
        for row in b:
            print(row)
    
    
    # 但是,如果想要对数组中的每个元素执行操作,可以使用flat属性,该属性是数组的所有元素的迭代器
    def func4():
        b = np.fromfunction(f, (5, 4), dtype=int)
        for element in b.flat:
            print(element)
    
    
    if __name__ == '__main__':
        # func1()
        # func2()
        # func3()
        func4()
    

    6.numpy数组形状

    import numpy as np
    from numpy import newaxis
    
    a = np.floor(10 * np.random.random((3, 4)))
    print(a)
    print(a.shape)
    
    # 可以使用各种命令更改数组的形状。请注意,以下三个命令都返回一个修改后的数组,但不会更改原始数组
    print(a.ravel())     # returns the array, flattened
    print(a.reshape(6, 2))  # returns the array with a modified shape
    print(a.T)  # returns the array, transposed 转置矩阵
    print(a.T.shape)
    print(a.shape)
    
    print(a)
    a.resize((2, 6))  # 这个函数会改变原始数组
    print(a)
    # 如果在 reshape 操作中将 size 指定为-1,则会自动计算其他的 size 大小:
    print(a.reshape(3, -1))
    
    # 将不同数组堆叠在一起
    a = np.floor(10 * np.random.random((2, 2)))
    print(a)
    b = np.floor(10 * np.random.random((2, 2)))
    print(b)
    print(np.vstack((a, b)))
    print(np.hstack((a, b)))
    
    print('*' * 20)
    print(np.column_stack((a, b)))  # with 2D arrays
    a = np.array([4., 2.])
    b = np.array([3., 8.])
    print(np.column_stack((a, b)))  # returns a 2D array
    print(np.hstack((a, b)))  # the result is different
    print(a[:, newaxis])  # this allows to have a 2D columns vector
    print(np.column_stack((a[:, newaxis], b[:, newaxis])))
    print(np.hstack((a[:, newaxis], b[:, newaxis])))  # the result is the same
    
    print('*' * 20)
    # 将一个数组拆分成几个较小的数组
    a = np.floor(10 * np.random.random((2, 12)))
    print(a)
    print(np.hsplit(a, 3))  # Split a into 3
    print(np.hsplit(a, (3, 4)))  # Split a after the third and the fourth column
    
    

    7.numpy深浅拷贝、视图

    import numpy as np
    
    # 当计算和操作数组时,有时会将数据复制到新数组中,有时则不会。有三种情况
    # 1.完全不复制, 简单分配不会复制数组对象或其数据
    a = np.arange(12)
    b = a   # no new object is created
    print(b is a)  # True # a and b are two names for the same ndarray object
    b.shape = 3, 4  # changes the shape of a
    print(a.shape)  # (3, 4)
    # Python将可变对象作为引用传递,因此函数调用不会复制
    def f(x):
        print(id(x))
        
    print(id(a))  # 148293216    # id is a unique identifier of an object
    f(a)  # 148293216
    
    # 2. 视图或浅拷贝 不同的数组对象可以共享相同的数据。该view方法创建一个查看相同数据的 新数组对象。
    c = a.view()
    print(a)
    print(c)
    print(c is a)  # False
    print(c.base is a)  # True # c is a view of the data owned by a
    print(c.flags.owndata)  # False
    c.shape = 2, 6  # a's shape doesn't change
    print(a.shape)  # (3, 4)
    print(a)
    print(c)
    c[0, 4] = 1234  # a's data changes
    print(a)
    print(c)
    # 切片数组会返回一个视图
    s = a[:, 1:3]  # spaces added for clarity; could also be written "s = a[:,1:3]"
    print(s)
    s[:] = 10  # s[:] is a view of s. Note the difference between s=10 and s[:]=10
    print(s)
    print(a)
    
    # 深拷贝  该copy方法生成数组及其数据的完整副本。
    d = a.copy()  # a new array object with new data is created
    print(d is a)  # False
    print(d.base is a)  # False  d doesn't share anything with a
    d[0, 0] = 9999
    print(a)
    print(d)
    
    # 有时,如果不再需要原始数组,则应在切片后调用 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 也会在内存中持久存在。
    
    

    8.numpy广播机制

    import numpy as np
    
    """
    术语广播(Broadcasting)描述了 numpy 如何在算术运算期间处理具有不同形状的数组。
    受某些约束的影响,较小的数组在较大的数组上“广播”,以便它们具有兼容的形状。
    广播提供了一种矢量化数组操作的方法,以便在C而不是Python中进行循环。
    它可以在不制作不必要的数据副本的情况下实现这一点,通常导致高效的算法实现。
    然而,有些情况下广播是一个坏主意,因为它会导致内存使用效率低下,从而减慢计算速度。
    
    """
    # NumPy 操作通常在逐个元素的基础上在数组对上完成。在最简单的情况下,两个数组必须具有完全相同的形状,如下例所示:
    a = np.array([1.0, 2.0, 3.0])
    b = np.array([2.0, 2.0, 2.0])
    print(a * b)  # array([2., 4., 6.])
    # 当数组的形状满足某些约束时,NumPy的广播规则放宽了这种约束。当一个数组和一个标量值在一个操作中组合时,会发生最简单的广播示例:
    a = np.array([1.0, 2.0, 3.0])
    b = 2.0
    print(a * b)  # array([2., 4., 6.]) 第二个示例中的代码比第一个示例中的代码更有效,因为广播在乘法期间移动的内存较少(b是标量而不是数组)。
    
    # 一般广播规则 在两个数组上运行时,NumPy会逐元素地比较它们的形状。
    # 数组不需要具有相同 数量 的维度。例如,如果有一个256x256x3 RGB值数组,并且希望将图像中的每种颜色缩放不同的值,
    # 则可以将图像乘以具有3个值的一维数组。根据广播规则排列这些数组的尾轴的大小,表明它们是兼容的:
    x = np.arange(4)
    xx = x.reshape(4, 1)
    y = np.ones(5)
    z = np.ones((3, 4))
    print(x)
    print(xx)
    print(y)
    print(z)
    # print(x + y)  # ValueError: operands could not be broadcast together with shapes (4,) (5,)
    
    print(xx.shape)  # (4, 1)
    print(y.shape)  # (5,)
    print((xx + y).shape)  # (4, 5)
    print(xx + y)
    print(x.shape)
    print(z.shape)
    print((x + z).shape)
    print(x + z)
    
    

    9.高级索引

    import numpy as np
    import matplotlib.pyplot as plt
    
    # 花式索引和索引技巧
    # 1. 使用索引数组进行索引
    a = np.arange(12) ** 2  # the first 12 square numbers
    print(a)
    i = np.array([1, 1, 3, 8, 5])  # an array of indices
    print(i)
    print(a[i])  # array([ 1,  1,  9, 64, 25])  the elements of a at the positions i
    j = np.array([[3, 4], [9, 7]])  # a bidimensional array of indices
    print(a[j])  # array([[9, 16],[81, 49]]) the same shape as j
    
    print('*' * 40)
    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]])
    print(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]]])
    
    # 还可以为多个维度提供索引。每个维度的索引数组必须具有相同的形状。
    print('*' * 20 + '为多个维度提供索引数组' + '*' * 20)
    a = np.arange(12).reshape(3, 4)
    print(a)
    i = np.array([[0, 1], [1, 2]])  # indices for the first dim of a
    j = np.array([[2, 1], [3, 3]])  # indices for the second dim
    print(a[i, j])  # i and j must have equal shape
    print(a[i, 2])
    print(a[:, j])  # i.e., a[ : , j]
    # 可以按顺序(比如列表)放入i,j然后使用列表进行索引。
    l = [i, j]
    # print(a[l])  # 弃用!!! equivalent to a[i,j]
    # 但是,不能通过i和j放入数组来实现这一点,因为这个数组将被解释为索引a的第一个维度。
    s = np.array([i, j])
    # a[s]  # not what we want
    # Traceback (most recent call last):
    #   File "<stdin>", line 1, in ?
    # IndexError: index (3) out of range (0<=index<=2) in dimension 0
    print(a[tuple(s)])  # same as a[i,j]
    # 使用数组索引的另一个常见用法是搜索与时间相关的系列的最大值
    print('*' * 20 + '搜索与时间相关的系列的最大值' + '*' * 20)
    time = np.linspace(20, 145, 5)  # time scale
    data = np.sin(np.arange(20)).reshape(5, 4)  # 4 time-dependent series
    print(time)
    print(data)
    ind = data.argmax(axis=0)  # index of the maxima for each series
    print(ind)
    time_max = time[ind]  # times corresponding to the maxima
    data_max = data[ind, range(data.shape[1])]  # => data[ind[0],0], data[ind[1],1]...
    print(time_max)
    print(data_max)
    print(np.all(data_max == data.max(axis=0)))  # True
    
    # 2. 使用布尔数组进行索引
    print('*' * 20 + '使用同型布尔数组进行索引' + '*' * 20)
    a = np.arange(12).reshape(3, 4)
    b = a > 4
    print(b)
    print(a[b])  # 1d array with the selected elements
    a[b] = 0  # All elements of 'a' higher than 4 become 0
    print(a)
    # 使用布尔索引生成Mandelbrot集的图像
    print('*' * 20 + '使用布尔索引生成Mandelbrot集的图像' + '*' * 20)
    
    
    def mandelbrot(h, w, maxit=20):
        """Returns an image of the Mandelbrot fractal of size (h,w)."""
        y, x = np.ogrid[-1.4:1.4:h * 1j, -2:0.8:w * 1j]
        c = x + y * 1j
        z = c
        divtime = maxit + np.zeros(z.shape, dtype=int)
    
        for i in range(maxit):
            z = z ** 2 + c
            diverge = z * np.conj(z) > 2 ** 2  # who is diverging
            div_now = diverge & (divtime == maxit)  # who is diverging now
            divtime[div_now] = i  # note when
            z[diverge] = 2  # avoid diverging too much
    
        return divtime
    
    
    plt.imshow(mandelbrot(400, 400))
    plt.show()
    
    # 使用布尔值进行索引的第二种方法更类似于整数索引; 对于数组的每个维度,我们给出一个1D布尔数组,选择我们想要的切片
    a = np.arange(12).reshape(3, 4)
    b1 = np.array([False, True, True])  # first dim selection
    b2 = np.array([True, False, True, False])  # second dim selection
    
    print(a[b1, :])  # selecting rows
    print(a[b1])  # same thing
    print(a[:, b2])  # selecting columns
    print(a[b1, b2])  # a weird thing to do
    
    

    10. numpy.ix_()函数

    import numpy as np
    
    # ix_函数可用于组合不同的向量,以便获得每个n-uplet的结果。
    # 例如,如果要计算从每个向量a,b和c中取得的所有三元组的所有a + b * c
    a = np.array([2, 3, 4, 5])
    b = np.array([8, 5, 4])
    c = np.array([5, 4, 6, 8, 3])
    ax, bx, cx = np.ix_(a, b, c)
    print(ax)
    print(bx)
    print(cx)
    print(ax.shape)
    print(bx.shape)
    print(cx.shape)
    result = ax + bx * cx
    print(result)
    print(result[3, 2, 4])
    print(a[3] + b[2] * c[4])
    
    

    11.线性代数中的常用基本运算

    # 基本的线性代数运算
    import numpy as np
    
    a = np.array([[1.0, 2.0], [3.0, 4.0]])
    print(a)
    print(a.transpose())
    print(np.linalg.inv(a))
    u = np.eye(2)  # unit 2x2 matrix; "eye" represents "I"
    print(u)
    j = np.array([[0.0, -1.0], [1.0, 0.0]])
    print(j @ j)  # matrix product
    print(np.trace(u))  # trace
    y = np.array([[5.], [7.]])
    print(np.linalg.solve(a, y))
    print(np.linalg.eig(j))
    
    

    12.其它

    使用-1自动计算维度

    import matplotlib.pyplot as plt
    import numpy as np
    
    # 使用-1自动计算对应维的个数
    a = np.arange(30)
    a.shape = 2, -1, 3  # -1 means "whatever is needed"
    print(a.shape)  # (2, 5, 3)
    print(a)
    

    直方图的使用

    import matplotlib.pyplot as plt
    import numpy as np
    # histogram应用于数组的NumPy 函数返回一对向量:数组的直方图和bin的向量。
    # 注意: matplotlib还有一个构建直方图的功能(在Matlab中称为hist),与NumPy中的直方图不同。
    # 主要区别在于pylab.hist自动绘制直方图,而 numpy.histogram只生成数据。
    
    
    # Build a vector of 10000 normal deviates with variance 0.5^2 and mean 2
    mu, sigma = 2, 0.5
    v = np.random.normal(mu, sigma, 10000)
    # Plot a normalized histogram with 50 bins
    plt.hist(v, bins=50, density=1)  # matplotlib version (plot)
    plt.show()
    
    # Compute the histogram with numpy and then plot it
    (n, bins) = np.histogram(v, bins=50, density=True)  # NumPy version (no plot)
    plt.plot(.5 * (bins[1:] + bins[:-1]), n)
    plt.show()
    
    
  • 相关阅读:
    查看mysql版本的四种方法及常用命令
    newInstance和new的区别(good)
    Citrix 服务器虚拟化之六 Xenserver虚拟机创建与快照
    Java实现 蓝桥杯 算法训练 排序
    Java实现 蓝桥杯 算法训练 排序
    Java实现 蓝桥杯 算法训练 排序
    Java实现 蓝桥杯 算法训练 2的次幂表示
    Java实现 蓝桥杯 算法训练 2的次幂表示
    Java实现 蓝桥杯 算法训练 前缀表达式
    Java实现 蓝桥杯 算法训练 前缀表达式
  • 原文地址:https://www.cnblogs.com/ericling/p/15500467.html
Copyright © 2011-2022 走看看