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()
    
    
  • 相关阅读:
    Android Animations动画使用详解
    android LinearLayout和RelativeLayout实现精确布局
    中国天气网API
    获取中央气象台API 完整城市列表简单方式
    Django框架 连接Oracle -ServerName方式报错
    关于java的动态代理
    Mybatis缓存
    Git使用,将本地项目推送到GitHub上
    使用doxc4j将word转pdf遇到的一个问题
    linux安装jdk
  • 原文地址:https://www.cnblogs.com/ericling/p/15500467.html
Copyright © 2011-2022 走看看