NumPy笔记(2)—— 使用数组进行面向数组编程

  • 参考:《利用python进行数据分析》第4章
  • 注意,由于本文是jupyter文档转换来的,代码不一定可以直接运行,有些注释是jupyter给出的交互结果,而非运行结果!!

文章目录

  • 1. 生成网格数据:np.meshgrid方法
    • 1.1 np.meshgrid
    • 1.2 使用示例
  • 2. 将条件逻辑作为数组操作:np.where方法
    • 2.1 np.where
    • 2.2 使用示例
      • 2.2.1 基础用法
      • 2.2.2 数组原位替换
  • 3. 数学和统计方法
  • 4. 布尔数组的方法
    • 4.1 统计True的个数
    • 4.2 与、或真值检查
  • 5. 排序
  • 6. 唯一值与其他集合逻辑

  • NumPy 数组允许用户利用简单的数组表达式完成多种数据操作任务,而无需编写大量循环。这种利用数组表达式替代显式循环语句的方法,称为 向量化
  • 通常,向量化的数组操作会比纯Python等价实现快一到两个数量级

1. 生成网格数据:np.meshgrid方法

1.1 np.meshgrid

  • 此方法利用坐标向量返回坐标矩阵,给定n个一维坐标数组 x1,x2,…,xn,生成 N 维坐标数组,可用于 N 维网格上 N 维标量/向量的矢量化表示

  • 原型:np.meshgrid(*xi, copy=True, sparse=False, indexing='xy')

    1. x1,x2,...,xn (array_like):表示网格坐标的一维数组
    2. indexing ({‘xy’,‘ij’},optional):可设为 ‘xy’(输出数组使用笛卡尔索引) 或 ‘ij’(输出数组使用矩阵索引),默认值为’xy’
    3. sparse (bool, optional):如果为True,则返回稀疏网格以节省内存,默认值为False
    4. copy (bool, optional):如果为False,则返回原始数组的视图以节省内存,默认值为True。 请注意sparse=False, copy=False 可能会返回不连续的数组
  • 返回值:n个n维数组 X1, X2,…, XN

    1. 对于输入参数向量 x1, x2,…, ‘xn’,用 Ni=len(xi) 表示各向量长度,则缺省 indexing='xy' 时返回数组形状为 .shape = (N1, N2, N3 ,...Nn)indexing='ij' 时返回数组形状为 (N2, N1, N3,...Nn)
    2. 缺省 indexing='xy' 时,X1的第0轴(行)使用x1重复填充,X2的第1轴(列)使用x2重复填充;indexing='ij' 时X1的第1轴(列)使用x1重复填充,X2的第0轴(行)使用x2重复填充。X1和X2在两种设定下的返回值都是互为转置关系。
    3. 对于更高的维度,可以看作把二维状态下的每个元素扩展为一维向量,indexing 参数不再有作用
  • 说明:indexing参数可以有点抽象,这个参数仅仅对前两个维度有效,举个二维的例子,假设输入两个一维数组x和y,则

    1. indexing='xy' 时,可以像笛卡尔坐标系一样把xy理解为x轴和y轴,返回二维数组的尺寸就是 .shape = (y.size,x.size)
    2. indexing='ij' 时,则像矩阵一样把xy理解为行数和列数,返回二维数组的尺寸就是 .shape = (x.size,y.size)
  • 测试

    import numpy as np
    
    x = np.arange(5)
    y = np.arange(3)
    
    x1,y1 = np.meshgrid(x,y,indexing='ij')
    x2,y2 = np.meshgrid(x,y)
    print('indexing = ij')
    print(x1)
    print(y1,'\n')
    print('indexing = xy')
    print(x2)
    print(y2,'\n')
    
    print('转置关系')
    print(x1[4,2],y1[4,2])
    print(x2[2,4],y2[2,4])
    
    '''
    indexing = ij
    [[0 0 0]
     [1 1 1]
     [2 2 2]
     [3 3 3]
     [4 4 4]]
    [[0 1 2]
     [0 1 2]
     [0 1 2]
     [0 1 2]
     [0 1 2]] 
    
    indexing = xy
    [[0 1 2 3 4]
     [0 1 2 3 4]
     [0 1 2 3 4]]
    [[0 0 0 0 0]
     [1 1 1 1 1]
     [2 2 2 2 2]] 
    
    转置关系
    4 2
    4 2
    '''
    

1.2 使用示例

  • 现在要对一些网格数据计算函数 s q r t ( x 2 + y 2 ) sqrt(x^2+y^2) sqrt(x2+y2) 的值,使用 np.meshgrid 生成网格数据

    import matplotlib.pyplot as plt
    
    # 生成网格数据
    points = np.arange(-5,5,0.01)
    xs,ys = np.meshgrid(points,points)
    
    # 计算函数
    z = np.sqrt(xs**2 + ys**2)
    
    # 可视化
    plt.imshow(z,cmap=plt.cm.gray)
    plt.colorbar()
    

    NumPy笔记(2)—— 使用数组进行面向数组编程_第1张图片

2. 将条件逻辑作为数组操作:np.where方法

2.1 np.where

  • 此函数是三元表达式 x if condition else y 的向量化版本
  • 原型:where(condition, [x, y])
    1. condition (array_like,bool):如果为真,则选则 x,否则选则 y
    2. x,y (array_like):可供选择的值,可以是数组,也可以是标量。xycondition 需要可以广播到某种形状
  • 注意:当仅提供 condition 时,此函数是 np.asarray(condition).nonzero() 的简写

2.2 使用示例

2.2.1 基础用法

  • 假设我们有两个数值数组 xarryarr,我们希望依据一个布尔数组cond 选择元素。当 cond 中元素为 True 时,取 xarr 中的对应元素值,否则取 yarr 中的对应元素值。通常我们使用列表推导式完成这种操作

    xarr = np.array([1,2,3,4,5])
    yarr = np.array([6,7,8,9,0])
    cond = np.array([True,False,True,True,False])
    result = [(x if c else y) for x,y,c in zip(xarr,yarr,cond)]
    print(result)
    
    # [1, 7, 3, 4, 0]
    
  • 这样做的问题在于,

    1. 数组很大时,速度缓慢
    2. 仅适用于一维情况

    这时就适于使用np.where 方法

    result = np.where(cond,xarr,yarr)
    print(result) 	# [1 7 3 4 0]
    

2.2.2 数组原位替换

  • np.where 的后两个参数 [x, y] 不一定是数组,也可以是标量。where的一个经典用法,就是根据一定的条件,对数组中元素进行原位替换
    print('随机数组')
    arr = np.random.randn(4,4)
    print(arr,'\n')
    
    print('标量原位替换')
    print(np.where(arr>0,2,-2),'\n')
    
    print('数组原位替换')
    print(np.where(arr>0,2,arr))
    
    '''
    随机数组
    [[ 0.6818313   1.10788644  0.60707372 -0.7961009 ]
     [-0.69947074  1.57684828  1.97240362  0.6681626 ]
     [-0.78550736 -0.65122289  0.44938015 -1.86345715]
     [ 0.18658391 -1.19279691  0.20794079 -0.86630991]] 
    
    标量原位替换
    [[ 2  2  2 -2]
     [-2  2  2  2]
     [-2 -2  2 -2]
     [ 2 -2  2 -2]] 
    
    数组原位替换
    [[ 2.          2.          2.         -0.7961009 ]
     [-0.69947074  2.          2.          2.        ]
     [-0.78550736 -0.65122289  2.         -1.86345715]
     [ 2.         -1.19279691  2.         -0.86630991]]
    '''
    

3. 数学和统计方法

  • NumPy提供了许多关于计算整个数组统计值或关于轴向数据的数学函数,可以作为数组类型的方法被调用。

    方法 描述
    sum 沿轴向计算所有元素的累加和,0长度的数组,累加和为0
    mean 数学平均,0长度的数组平均值为NaN
    std, var 标准差和方差,可以选择自由度调整(默认分母为n)
    min, max 最小值 & 最大值
    argmin, argmax 最小值索引 & 最大值索引
    cumsum 从0开始元素累积和
    cumprod 从1开始元素累积积
  • 在调用时有两种等价方法

    1. 直接调用数组示例的方法,如 arr.sum()
    2. 使用顶层的NumPy函数,如 np.sum(arr)
  • 部分测试

    print('生成一些随机数据')
    arr = np.random.randn(5,4)
    print(arr,'\n')
    
    print('数组均值')
    print(np.mean(arr),'\n')
    
    print('数组累加和')
    print(arr.sum(),'\n')
    
    print('第0轴(行)轴向均值')
    print(arr.mean(axis = 0),'\n')
    
    print('第1轴(列)轴向累加和')
    print(arr.sum(axis = 1),'\n')
    
    '''
    生成一些随机数据
    [[-1.14758004 -0.672113   -0.13183887 -2.47382142]
     [-0.41932578 -1.3022716   1.79016834  0.61126159]
     [-0.76037654  0.81149644 -2.15071079 -0.97268024]
     [ 2.12643459  0.44006178  0.57575081 -1.47044089]
     [ 1.11763418  0.72242666 -0.4468634  -1.48691387]] 
    
    数组均值
    -0.26198510217397003 
    
    数组累加和
    -5.239702043479401 
    
    第0轴(行)轴向均值
    [ 1.83357284e-01 -7.99443369e-05 -7.26987828e-02 -1.15851897e+00] 
    
    第1轴(列)轴向累加和
    [-4.42535333  0.67983255 -3.07227113  1.67180629 -0.09371643] 
    '''
    
    arr = np.array([1,2,3,4,5,6,7])
    print('原始数据')
    print(arr,'\n')
    
    print('cumsum返回累加中间结果')
    print(arr.cumsum(),'\n')
    
    print('cumprod返回累积极中间结果')
    print(arr.cumprod(),'\n')
    
    arr = np.array([[0,1,2],[3,4,5],[6,7,8],[9,10,11]])
    print('原始数据')
    print(arr,'\n')
    
    print('第0轴(行)轴向累加')
    print(arr.cumsum(axis=0),'\n')
    
    print('第1轴(列)轴向累积')
    print(arr.cumprod(axis=1))
    
    '''
    原始数据
    [1 2 3 4 5 6 7] 
    
    cumsum返回累加中间结果
    [ 1  3  6 10 15 21 28] 
    
    cumprod返回累积极中间结果
    [   1    2    6   24  120  720 5040] 
    
    原始数据
    [[ 0  1  2]
     [ 3  4  5]
     [ 6  7  8]
     [ 9 10 11]] 
    
    第0轴(行)轴向累加
    [[ 0  1  2]
     [ 3  5  7]
     [ 9 12 15]
     [18 22 26]] 
    
    第1轴(列)轴向累积
    [[  0   0   0]
     [  3  12  60]
     [  6  42 336]
     [  9  90 990]]
    '''
    

4. 布尔数组的方法

4.1 统计True的个数

  • NumPy中布尔值通常会被视作1 (True) 和0 (False),因此可以用sum方法计算布尔数组中 True 的个数

    arr = np.random.randn(100)
    print((arr>0).sum())  # 51
    

4.2 与、或真值检查

  • 布尔数组的典型用法是判断其所有元素的与、或结果,这需要用到两个方法

    1. any:检查数组中是否至少有一个 True,即或结果
    2. all:检查数组中是否全部都是 True,即与结果

    这两个方法也可用于非布尔值数组,所有非零元素按True处理

    bools = np.array([False,False,True,False])
    
    print(bools.any())  # True
    print(bools.all())  # False
    

5. 排序

  • 类似Python中的列表类型,NumPy数组可以使用sort方法按位置排序
  • 原型 arr.sort(axis=-1, kind=None, order=None)
    1. axis (int, optional):要排序的轴,默认值-1,表示沿最后一个轴排序,设置None代表所有元素拉平后排序
    2. kind ({‘quicksort’, ‘mergesort’, ‘heapsort’, ‘stable’},optional):可选的排序算法,默认为 “quicksort”。注意,“stable” 和 “mergesort” 都在底层使用 timsort,通常,实际实现会因数据类型而异。 保留 “mergesort” 选项是为了向后兼容
    3. order (str 或 str list,optional):多级排序的顺序,需要构建一个field
  • 说明:
    1. 可以在多维数组中,传入axis参数以指定排序的维度
    2. 可以使用两种方式调用排序方法,arr.sort 在原位进行排序;np.sort(arr) 返回一个排序好的数组的拷贝
    3. NumPy中的sort函数仅支持排升序,要排降序,可以用这种技巧 arr = np.sort(arr)[::-1]
  • 示例
    arr = np.random.randn(6)
    print('原数组')
    print(arr)
    print('排升序')
    print(np.sort(arr))
    print('排降序')
    print(np.sort(arr)[::-1],'\n')
    
    arr = np.arange(14,0,-1)
    arr.resize(5,3)
    print('原数组')
    print(arr)
    print('第0轴(行)轴向排序')
    print(np.sort(arr,axis=0))
    print('第1轴(列)轴向排序')
    print(np.sort(arr,axis=1))
    
    '''
    原数组
    [-0.42145353 -0.68593585  0.0829771  -0.23195342 -0.12941807 -1.91235085]
    排升序
    [-1.91235085 -0.68593585 -0.42145353 -0.23195342 -0.12941807  0.0829771 ]
    排降序
    [ 0.0829771  -0.12941807 -0.23195342 -0.42145353 -0.68593585 -1.91235085] 
    
    原数组
    [[14 13 12]
     [11 10  9]
     [ 8  7  6]
     [ 5  4  3]
     [ 2  1  0]]
    第0轴(行)轴向排序
    [[ 2  1  0]
     [ 5  4  3]
     [ 8  7  6]
     [11 10  9]
     [14 13 12]]
    第1轴(列)轴向排序
    [[12 13 14]
     [ 9 10 11]
     [ 6  7  8]
     [ 3  4  5]
     [ 0  1  2]]
    '''
    

6. 唯一值与其他集合逻辑

  • NumPy包含一些针对一维ndarray的基础集合操作

    方法 描述
    unique(x) 计算x的唯一值
    intersect1d(x,y) 计算x和y的交集,并排序
    union1d(x,y) 计算x和y的并集,并排序
    in1d(x,y) 计算x中的元素是否包含在y中,返回一个布尔数组
    setdiff1d(x,y) 差集,在x中但不在y中的元素
    setxor1d(x,y) 异或集,在x或y中,但不属于x , y交集的元素
  • 部分测试

    names = np.array(['Tom','Bob','Bill','Tom','Bob'])
    print(np.unique(names))	# ['Bill' 'Bob' 'Tom']
    
    ints = np.array([1,1,2,2,3,3,3,4,5,6,6,6,6])
    print(np.unique(ints))	# [1 2 3 4 5 6]
    
    values = np.array([6,0,0,3,2,5,6])
    print(np.in1d(values,[2,3,6]))	# [ True False False  True  True False  True]
    
    v1 = np.array([4,3,2,1])
    v2 = np.array([8,7,6,3,1])
    print(np.intersect1d(v1,v2))	# [1 3]
    

你可能感兴趣的:(#,numpy,numpy,ndarray,数组)