利用Python进行数据分析笔记(使用数组进行面向数组编程)

  • 使用NumPy数组可以使你利用简单的数组表达式完成多种数据操作任务,而无须写些大量循环。这种利用数组表达式来代替显示循环的方法,成为向量化。通常,向量化的数组操作会比纯Python的等价实现在速度上快一到两个量级(甚至更多),这对所有种类的数值计算产生了最大的影响。
  • 作为一个简单的示例,假设我们想要对一些网格数据来计算函数sqrt(x ^2 + y ^2)的值。np.meshgrid函数接收两个一维数组,并根据两个数组的所有(x,y)对生成一个二维矩阵:
>>> points = np.arange(-5,5,0.01) # 1000 equally spaced points
>>> 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]])
  • 现在,你可以用和两个坐标值同样的表达式来使用函数:
>>> 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 d 的向量化版本。假设我们有一个布尔值数组和两个数值数组:
>>> 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]
  • 这样会产生多个问题。首先,如果数组很大的话,速度会很慢(因为所有的工作都是通过解释器解释Python代码完成)。其次,当数组是多维时,就无法奏效了。而是用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([[-2.3624117 , -1.96653044, -0.89714196, -0.68149659],
       [ 0.70245615,  1.14386905,  1.12898706, -1.23815808],
       [-0.56145414,  0.58495615,  1.95468701,  0.4702848 ],
       [-1.37148413, -0.00377742,  1.80542236, -1.41635326]])
>>> arr > 0
array([[False, False, False, False],
       [ True,  True,  True, False],
       [False,  True,  True,  True],
       [False, False,  True, False]])
>>> 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([[-2.3624117 , -1.96653044, -0.89714196, -0.68149659],
       [ 2.        ,  2.        ,  2.        , -1.23815808],
       [-0.56145414,  2.        ,  2.        ,  2.        ],
       [-1.37148413, -0.00377742,  2.        , -1.41635326]])
  • 传递给np.where的数组既可以是同等大小的数组,也可以是标量。

数学和统计方法

  • 许多关于计算整个数组统计值或关于轴向数据的数学函数,可以作为数组类型的方法被调用。你可以使用聚合函数(通常也叫缩减函数),比如sum、mean和std(标准差),既可以直接调用数组实例的方法,也可以使用顶层的NumPy函数。
  • 此处我生成了一些正态分布的随机数,并计算了部分聚合统计数据:
>>> arr = np.random.randn(5,4)
>>> arr
array([[-1.80797791,  1.33606592,  0.46795816,  1.53387629],
       [-0.25954537,  0.4898996 , -2.4211862 ,  0.01197818],
       [ 0.34866204,  0.24130813,  0.67829309, -0.30678474],
       [ 0.24134156, -0.14722192, -0.16460745, -0.04512704],
       [-0.39224254, -0.51723372,  0.71783118, -1.55365385]])
>>> arr.mean()
-0.0774183287914044
>>> np.mean(arr)
-0.0774183287914044
>>> arr.sum()
-1.548366575828088
  • 像mean、sum等函数可以接收一个可选参数axis,这个参数可以用于计算给定轴上的统计值,形成一个下降一维度的数组:
>>> arr.mean(axis=1)
array([ 0.38248062, -0.54471345,  0.24036963, -0.02890371, -0.43632473])
>>> arr.sum(axis=0)
array([-1.86976222,  1.40281802, -0.72171122, -0.35971116])
  • arr.mean(1)表示“计算每一列的平均值”,而arr.sum(0)表示“计算行轴向的类和”。
  • 其他的方法,例如cumsum和cumprod并不会聚合,它们会产生一个中间结果:
>>> arr = np.array([0,1,2,3,4,5,6,7])
>>> arr.cumsum()
array([ 0,  1,  3,  6, 10, 15, 21, 28], dtype=int32)
  • 在多维数组中,像cumsum这样的累计函数返回相同长度的数组,但是可能在指定轴向上根据较低维度的切片进行部分聚合:
>>> arr = np.array([[0,1,2],[3,4,5],[6,7,8]])
>>> arr
array([[0, 1, 2],
       [3, 4, 5],
       [6, 7, 8]])
>>> arr.cumsum(axis=0) #对该函数有疑问的详见https://blog.csdn.net/Kevin_Xie86/article/details/110923130
array([[ 0,  1,  2],
       [ 3,  5,  7],
       [ 9, 12, 15]], dtype=int32)
>>> arr.cumprod(axis=1)
array([[  0,   0,   0],
       [  3,  12,  60],
       [  6,  42, 336]], dtype=int32)
  • 下表是统计方法的列表,我们将会在后面的章节中看到这些方法的大量示例。
    在这里插入图片描述

布尔值数组的方法

  • 在前面介绍的方法,布尔值会被强制为1(True)和0(False)。因此,sum通常可以用于计算布尔值数组中的True的个数:
>>> arr = np.random.randn(100)
>>> (arr > 0).sum() # 正值的个数
53
  • 对于布尔值数组,有两个非常有用的方法any和all。any检查数组中是否至少有一个True,而all检查是否每个值都是True:
>>> bools = np.array([False,False,True,False])
>>> bools.any()
True
>>> bools.all()
False
  • 这些方法也可适用于非布尔值数组,所有的非0元素都会按True处理。

排序

  • 和Python的内建列表类型相似,NumPy数组可以使用sort方法按位置排序:
>>> arr = np.random.randn(6)
>>> arr
array([ 0.11418273, -1.41277321,  1.69985834, -0.03271853, -2.3744435 ,
        2.20253339])
>>> arr.sort()
>>> arr
array([-2.3744435 , -1.41277321, -0.03271853,  0.11418273,  1.69985834,
        2.20253339])
  • 你可以在多维数组中根据传递的axis值,沿着轴向对每个一维数组段进行排序:
>>> arr = np.random.randn(5,3)
>>> arr
array([[ 0.15801241, -1.52346998, -0.51402114],
       [ 0.79141373, -1.02397976, -0.11795965],
       [ 0.27084299, -0.20892054, -0.63789455],
       [ 0.50918216,  0.19572398,  0.42971156],
       [-0.57140424,  0.23773035,  0.54311631]])
>>> arr.sort(1)
>>> arr
array([[-1.52346998, -0.51402114,  0.15801241],
       [-1.02397976, -0.11795965,  0.79141373],
       [-0.63789455, -0.20892054,  0.27084299],
       [ 0.19572398,  0.42971156,  0.50918216],
       [-0.57140424,  0.23773035,  0.54311631]])
  • 顶层的np.sort方法返回的是已经排序好的数组拷贝,而不是对原数组按位置排序。下面的例子计算的是一个数组的分位数,并选出分位数所对应的值,这是一种应急的方式:
>>> large_arr = np.random.randn(1000)
>>> large_arr.sort()
>>> large_arr[int(0.05 * len(large_arr))] # 5% quantile
-1.8030598888891862

唯一值与其他集合逻辑

  • NumPy包含一些针对一维ndarray的基础集合操作。常用的一个方法是np.unique,返回的是数组中唯一值排序后形成的数组:
>>> names = np.array(['Bob','Joe','Will','Bob','Will','Joe','Joe'])
>>> np.unique(names)
array(['Bob', 'Joe', 'Will'], dtype='<U4')
>>> ints = np.array([3,3,3,2,2,1,1,4,4])
>>> np.unique(ints)
array([1, 2, 3, 4])
  • 将np.unique和Python实现相比较:
>>> sorted(set(names))
['Bob', 'Joe', 'Will']
  • 另一个函数,np.in1d,可以检查一个数组中的值是否在另外一个数组中,并返回一个布尔值数组:
>>> values = np.array([6,0,0,3,2,5,6])
>>> np.in1d(values,[2,3,6])
array([ True, False, False,  True,  True, False,  True])
  • 下表是NumPy中集合函数的列表。
    在这里插入图片描述
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值