使用Numpy数组(一)

使用Numpy数组可以使你利用简单的数组表达式完成多种数据操作任务,而无须写些大量循环。这种利用数组表达式来替代显式循环的方法,称为向量化。通常,向量化的数组操作会比纯Python的等价实现在速度上快一到两个数量级(甚至更多),这对所有种类的数值计算产生了最大的影响。

作一个简单的示例,假设我们想要对一些网格数据来计算函数sqrt(x^2 + y^2)的值。np.meshgrid函数接收两个一维数组,并根据两个数组的所有(x,y)对生成一个二维矩阵:

import numpy as np
points = np.arange(-5,5,0.01)
xs,ys = np.meshgrid(points,points)

ys
array([[-5.  , -5.  , -5.  , ..., -5.  , -5.  , -5.  ],
       [-4.99, -4.99, -4.99, ..., -4.99, -4.99, -4.99],
       [-4.98, -4.98, -4.98, ..., -4.98, -4.98, -4.98],
       ...,
       [ 4.97,  4.97,  4.97, ...,  4.97,  4.97,  4.97],
       [ 4.98,  4.98,  4.98, ...,  4.98,  4.98,  4.98],
       [ 4.99,  4.99,  4.99, ...,  4.99,  4.99,  4.99]])

xs
array([[-5.  , -4.99, -4.98, ...,  4.97,  4.98,  4.99],
       [-5.  , -4.99, -4.98, ...,  4.97,  4.98,  4.99],
       [-5.  , -4.99, -4.98, ...,  4.97,  4.98,  4.99],
       ...,
       [-5.  , -4.99, -4.98, ...,  4.97,  4.98,  4.99],
       [-5.  , -4.99, -4.98, ...,  4.97,  4.98,  4.99],
       [-5.  , -4.99, -4.98, ...,  4.97,  4.98,  4.99]])

现在你可以用和两个坐标值相同的表达式来使用函数:

z = np.sqrt(xs ** 2 + ys ** 2)

z
array([[7.07106781, 7.06400028, 7.05693985, ..., 7.04988652, 7.05693985,
        7.06400028],
       [7.06400028, 7.05692568, 7.04985815, ..., 7.04279774, 7.04985815,
        7.05692568],
       [7.05693985, 7.04985815, 7.04278354, ..., 7.03571603, 7.04278354,
        7.04985815],
       ...,
       [7.04988652, 7.04279774, 7.03571603, ..., 7.0286414 , 7.03571603,
        7.04279774],
       [7.05693985, 7.04985815, 7.04278354, ..., 7.03571603, 7.04278354,
        7.04985815],
       [7.06400028, 7.05692568, 7.04985815, ..., 7.04279774, 7.04985815,
        7.05692568]])

一、将逻辑条件作为数组操作

numpy.where函数上三元表达式 x if condition else y 的向量化版本。假设我们有一个布尔值数组和两个数值数组:

xarr = np.array([1.1,1.2,1.3,1.4,1.5])
yarr = np.array([2.1,2.2,2.3,2.4,2.5])
cond = np.array([True,False,True,True,False])

假设cond中的元素为True时,我们取xarr中的对应元素值,否则取yarr中的元素。我们可以通过列表推导式来完成,像代码这样:

result = [(x if c else y) for x,y,c in zip(xarr,yarr,cond)]

result
[1.1, 2.2, 1.3, 1.4, 2.5]

这样会产生多个问题。首先,如果数组很大的话,速度会很慢。其次,当数组上多维时,就无法奏效了。而使用np.where时,就可以非常简单地完成:

result = np.where(cond,xarr,yarr)

result
array([1.1, 2.2, 1.3, 1.4, 2.5])

np.where的第二个和第三个参数并不需要数组,它们可以是标量。where在数据分析中的一个典型用法上根据一个数组来生成一个新的数组,假设你有一个随机生成的矩阵数据,并且你想将其中的正值都替换为2,将所有的负值替换为-2,使用np.where会很容易实现:

arr = np.random.randn(4,4)

arr
array([[-0.15384072, -0.52666358,  0.79846853,  1.65839579],
       [ 0.76100703, -0.40294247, -0.50833117, -1.37770235],
       [-1.0287086 ,  0.2443933 , -0.79481477,  0.41286556],
       [-0.22541371,  0.07460424,  0.75058749,  0.92358304]])

arr > 0
array([[False, False,  True,  True],
       [ True, False, False, False],
       [False,  True, False,  True],
       [False,  True,  True,  True]])

np.where(arr >0,2,-2)
array([[-2, -2,  2,  2],
       [ 2, -2, -2, -2],
       [-2,  2, -2,  2],
       [-2,  2,  2,  2]])

你可以使用np.where将标量和数组联合,例如,像我一样将arr中所有正值替换为常数2:

np.where(arr>0,2,arr) #仅将正值设为2
array([[-0.15384072, -0.52666358,  2.        ,  2.        ],
       [ 2.        , -0.40294247, -0.50833117, -1.37770235],
       [-1.0287086 ,  2.        , -0.79481477,  2.        ],
       [-0.22541371,  2.        ,  2.        ,  2.        ]])

传递给np.where的数组既可以上同等大小的数组,也可以是标量。

猜你喜欢

转载自blog.csdn.net/qq_41205111/article/details/86741189