NumPy基本命令汇总整理

NumPy基本命令汇总整理

NumPy(Numerical Python的简称)是Python数值计算最重要的基础包。大多数提供科学计算的包都是用NumPy的数组作为构建基础。本篇总结梳理了数据分析中使用频率相对较高的一些NumPy基本命令。

导入包

import numpy as np

ndarray: 一种多维数组对象

ndarray是一个通用的同构数据多维容器,也就是说,其中的所有元素必须是相同类型的。每个数组都有一个shape(一个表示各维度大小的元组)、一个dtype(一个用于说明数组数据类型的对象)和一个strides(一个用于说明为了前进到当前维度下一个元素需要“跨过”的字节数的跨度元组)。

🔔常用命令

  • 创建ndarray
    • np.array(),将输入数据(列表、元组、数组或其它序列类型)转换为ndarray。要么推断出dtype,要么指定特别dtype。默认直接复制输入数据。
    • np.zeros() : 创建指定长度或形状的全0数组,只需传入一个表示形状的元组。
    • np.zeros_like() : 返回与指定数组同样形状和数据类型的全0数组。
    • np.ones() : 创建指定长度或形状的全1数组,只需传入一个表示形状的元组。
    • np.ones_like() : 返回与指定数组同样形状和数据类型的全1数组。
    • np.empty()| np.empty_like() : 创建没有任何具体值的数组。
    • np.arange():类似于内置的range,但返回的是一个ndarray而不是列表。
    • np.full(shape, fill_value)|np.full_like():用fill_value中的所有值,根据指定的形状和dtype创建数组。
  • 查看shape: a.shape
  • 数据类型
    • 查看数据类型: a.dtype
    • 更改数据类型:a.astype(dtype)
    • 检查是否为某类型:np.issubdtype(a.dtype, np.integer)np.issubdtype(a.dtype, np.floating)np.issubdtype(a.dtype, np.number)
  • 数据重塑
    • 将一维数组转换为多维a.reshape(shape, order = 'C'),它返回的是源数据的视图(不会进行任何复制操作)。注意,作为参数的形状的其中一维可以是-1,它表示该维度的大小由数据本身推断而来。下图说明了order参数所起的作用:
      在这里插入图片描述
    • 将多维数组转换为一维
      • a.ravel():扁平化或散开,不产生源数据的副本
      • a.flatten():扁平化或散开,但产生源数据的副本
    • a.T,用于简单的转置即轴转换,在进行矩阵内积运算时会用到此命令。
    • a.transpose(*axes),用于高维数组,*axes为由轴编号组成的元组。
    • a.swapaxes(axis1, axis2),对axis1axis1进行轴转换。同样返回的是源数据的视图。
  • 数组的合并和拆分
    • np.concatenate((a1,a2,....), axis=0):按指定轴将一个由数组组成的序列(如元组、列表等)连接到一起。
    • np.hstack(tup):将2个矩阵按列合并。
    • np.vstack(tup):将2个矩阵按行合并。
    • np.split(a, indices_or_sections, axis=0):将一个数组沿指定轴拆分为多个数组。
  • 元素的重复操作
    • a.repeat(repeats, axis=None):将各个元素重复一定的数量(repeats)。默认情况下,如果传入的是一组整数,则各个元素可以重复不同的次数。
    • np.tile(A, reps):沿指定轴堆叠数组的副本。reps为表示堆叠布局的元组或标量,如果是标量,默认为水平堆叠。
  • 伪随机数生成
    • np.random.normal():标准正态(高斯)分布样本值
    • np.random.seed():更改随机数生成种子
    • np.random.rand:产生均匀分布的样本值
    • np.random.randint(low,high,size):从给定的上(exclusive)下(inclusive)限范围内随机选取整数
    • np.random.randn:产生正态分布(平均值为0,标准差为1)的样本值
    • np.random.shuffle:对一个序列就地随机排列
    • np.random.permutation:返回一个序列的随机排列或返回一个随机排列的范围

Numpy数组的运算

  • 形状相同的数组间运算
    • shape相同的数组之间的任何算术运算都会将运算应用到元素级
    • 数组与标量的算术运算会将标量值传播到各个元素
    • shape相同的数组之间的比较会生成布尔值数组
  • 形状不同的数组间运算
    • 广播

-
比如,下方的例子中,希望通过减去列平均值的方式对数组的每一列进行距平化处理。因为arr.mean(0)的形状为(3,),而arr的后缘维度为3,其与arr的后缘维度是相同的,所以它们是广播兼容的。广播在行的维度上进行。

# 对数组每一列进行距平均化
>>> arr = np.random.randn(4, 3)
>>> arr
array([[-0.18889954, -2.00928225, -2.3916824 ],
       [-2.46055652, -1.02446526, -1.03097103],
       [ 0.48938275,  0.37362381,  0.63674138],
       [-1.41777675,  0.58666021, -0.86618113]])
>>> arr.mean(0).shape
(3,)
>>> arr - arr.mean(0)
array([[ 0.70556298, -1.49091638, -1.4786591 ],
       [-1.56609401, -0.50609939, -0.11794773],
       [ 1.38384527,  0.89198968,  1.54976468],
       [-0.52331424,  1.10502608,  0.04684216]])

而如果希望对各行减去行平均值,因为arr.mean(1)的形状为(4,),而arr的后缘维度为3,其与arr的后缘维度不同。根据广播原则,要在1轴上广播做减法,较小的那个数组的形状必须是(4,1)

# 对数组每一行进行距平均化
>>> arr
array([[-0.18889954, -2.00928225, -2.3916824 ],
       [-2.46055652, -1.02446526, -1.03097103],
       [ 0.48938275,  0.37362381,  0.63674138],
       [-1.41777675,  0.58666021, -0.86618113]])
>>> arr.mean(1).shape
(4,)
>>> arr - arr.mean(1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: operands could not be broadcast together with shapes (4,3) (4,)
>>> arr - arr.mean(1).reshape((4,1))
array([[ 1.34105519, -0.47932753, -0.86172767],
       [-0.95522558,  0.48086568,  0.47435991],
       [-0.01053323, -0.12629217,  0.1368254 ],
       [-0.85201086,  1.1524261 , -0.30041524]])

对于三维的情况,下图说明了要在三维数组各维度上广播的形状需求:

在这里插入图片描述
在为了广播而添加一个长度为1的新轴时,可以使用np.newaxis属性以及“全”切片来插入新轴:

>>> arr = np.zeros((4,4))
>>> arr
array([[0., 0., 0., 0.],
       [0., 0., 0., 0.],
       [0., 0., 0., 0.],
       [0., 0., 0., 0.]])
>>> arr_3d = arr[:,np.newaxis,:]
>>> arr_3d.shape
(4, 1, 4)
>>> arr_1d = np.random.normal(size=3)
>>> arr_1d
array([-0.53656014, -0.821661  , -0.07331854])
>>> arr_1d[:,np.newaxis]
array([[-0.53656014],
       [-0.821661  ],
       [-0.07331854]])
>>> arr_1d[np.newaxis,:]
array([[-0.53656014, -0.821661  , -0.07331854]])

说明:上述添加新轴的方式同样适用于通过广播进行赋值,只要保证形状兼容即可。

索引和切片

几种索引方式:基本索引、切片索引、布尔式索引、花式索引

基本索引:下图说明了二维数组基本的索引方式:

在这里插入图片描述
🔔常用命令

  • arr[start:end] = some value:给数组中某个切片赋值,当将一个标量值赋值给一个切片时(如arr[5:8]=12),该值会自动传播(即,“广播”)到整个选区。
  • arr[:] = some value:给数组中的所有值赋值。

切片索引:切片默认是沿着第0轴(即第一个轴)切片的,如表达式arr[:2]可以被认为是“选取arr的前两行”。

>>> arr2d =np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
>>> arr2d
array([[1, 2, 3],
       [4, 5, 6],
       [7, 8, 9]])
>>> arr2d[:2]
array([[1, 2, 3],
       [4, 5, 6]])

下图为二维数组切片的简单示例:
在这里插入图片描述
布尔型索引:组合应用多个布尔条件,使用&(和)、|(或)之类的布尔算术运算符,且每个条件需用括号括起来,比如 (cond1) | (cond2)注意:通过布尔型索引选取数组中的数据,将总是创建数据的副本。

花式索引:可以实现以特定顺序选取行子集,只需传入一个用于指定顺序的整数列表或ndarray即可。而使用负数索引将会从末尾开始选取行。同样需注意,花式索引跟切片不一样,它总是将数据复制到新数组中。

一次传入多个索引数组会有一点特别。它返回的是一个一维数组,其中的元素对应各个索引元组,如下方的例子中,最终选出的元素是(1,0)、(5,3)、(7,1),(2,2):

>>> arr = np.arange(32).reshape((8, 4))
>>> arr
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11],
       [12, 13, 14, 15],
       [16, 17, 18, 19],
       [20, 21, 22, 23],
       [24, 25, 26, 27],
       [28, 29, 30, 31]])
>>> arr[[1,5,7,2],[0,3,1,2]]
array([ 4, 23, 29, 10])

需要说明:除布尔型索引、花式索引外,一般的情况下,数组切片是原始数组的视图。这意味着数据不会被复制,视图上的任何修改都会直接反映到源数组上。

💥注意下方的例子,选取arr的一个切片arr_slice,当修改arr_slice时,原数组也发生了变化!

>>> arr
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> arr_slice = arr[5:8]
>>> arr_slice
array([5, 6, 7])
>>> arr_slice[1] = 12345
>>> arr
array([    0,     1,     2,     3,     4,     5, 12345,     7,     8,
           9])

注意:如果你想要得到的是ndarray切片的一份副本而非视图,就需要明确地进行复制操作,例如arr[5:8].copy()

再看一下下方的例子:

>>> arr = np.arange(10)
>>> arr
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> arr_slice = arr[5:8]
>>> arr_slice
array([5, 6, 7])
>>> arr = np.arange(10)
>>> arr
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> arr_slice = arr[5:8].copy()
>>> arr_slice[1] = 12345
>>> arr_slice
array([    5, 12345,     7])
>>> arr
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

通用函数:快速的元素级数组函数

通用函数(即ufunc)是一种对ndarray中的数据执行元素级运算的函数。

  • 一元(unaryufunc:接受1个数组
  • 二元(binaryufunc:接受2个数组

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

注意:Ufuncs可以接受一个out可选参数,这样就能在数组原地进行操作。

比如下方示例:

>>> arr = np.random.randn(7) * 5
>>> arr
array([-5.93919409, -2.97839885,  1.18773417,  1.61830444, -6.56820877,
        3.94290995, -3.82345097])
>>> np.sqrt(arr)
<stdin>:1: RuntimeWarning: invalid value encountered in sqrt
array([       nan,        nan, 1.08983217, 1.27212595,        nan,
       1.98567619,        nan])
>>> np.sqrt(arr,arr)
array([       nan,        nan, 1.08983217, 1.27212595,        nan,
       1.98567619,        nan])
>>> arr
array([       nan,        nan, 1.08983217, 1.27212595,        nan,
       1.98567619,        nan])
>>>

💥此外,还有一些高级的ufunc应用:

  • reduce(x):通过连续执行原始运算的方式对值进行聚合,比如np.add.reduce(arr)等同于np.sum(arr)
  • accumulate(x):聚合值,保留所有局部聚合结果,比如np.add.accumulate(arr)等同于np.cumsum(arr)
  • reduceat(x,bins):“局部”约简(也就是groupby)。约简数据的各个切片以产生聚合型数组,比如np.add.reduceat(arr,[0,5,8])是在arr[0:5]arr[5:8]以及arr[8:]上执行的求和约简。
  • outer(x,y):对xy中的每对元素应用原始运算。结果数组的形状为x.shape + y.shape

利用数组进行数据处理

NumPy数组使你可以将许多种数据处理任务表述为简洁的数组表达式(否则需要编写循环),即矢量化。一般来说,矢量化数组运算要比等价的纯Python方式快上一两个数量级(甚至更多)。

🔔常用命令

  • np.where(condition, x,y):根据condition选择x中的值或y中的值,是三元表达式x if condition else y的矢量化表达;xy可以是数组,也可以是标量值。
  • 数学和统计方法:
    • a.sum():对数组中全部或某轴向的元素求和
    • a.mean():算术平均数
    • a.std()|a.var():标准差和方差
    • a.min()|a.max():最小值和最大值
    • a.argmin()|a.argmax():最小和最大元素的索引
    • a.cumsum():所有元素的累计和
    • a.cumprod():所有元素的累计积

argmax一个巧妙的用法:获取布尔型数组第一个最大值的索引(True就是最大值)。

比如,希望获取arr第一个大于5的值的位置索引:

>>> arr = np.array([1,3,2,5,4,10,4])
>>> arr
array([ 1,  3,  2,  5,  4, 10,  4])
>>> (arr>4).argmax()
3
  • 用于布尔型数组的方法:
    • .sum():经常被用来对布尔型数组中的True值计数
    • .any():用于测试数组中是否存在一个或多个True
    • .all():用于检查数组中所有值是否都是True
  • 排序:
    • a.sort(axis):在轴向上进行排序,顶级方法np.sort返回的是数组的已排序副本,而就地排序则会修改数组本身。
    • arr[:,::-1],返回一个列反序的列表。
    • arr.argsort():返回用于数组排序的索引。
    • arr.lexsort():类似arr.argsort(),只不过可以一次性对多个键数组执行间接排序。
    • arr.searchsorted(data):在有序数组arr中查找data中的元素插入后的位置索引。

以下为使用argsort()命令实现部分排序数组的示例:

# 根据数组的第一行排序
>>> arr = np.random.randn(3,5)
>>> values = np.array([5,0,1,3,2])
>>> arr[0] =values
>>> arr
array([[ 5.00000000e+00,  0.00000000e+00,  1.00000000e+00,
         3.00000000e+00,  2.00000000e+00],
       [ 1.23514614e+00,  1.35506346e-01, -7.05498872e-04,
         2.53602483e-01, -1.83245736e-01],
       [-7.06630296e-01,  4.26760743e-01, -2.77577070e-01,
        -8.28284581e-01, -2.76283358e+00]])
>>> arr[:,arr[0].argsort()]
array([[ 0.00000000e+00,  1.00000000e+00,  2.00000000e+00,
         3.00000000e+00,  5.00000000e+00],
       [ 1.35506346e-01, -7.05498872e-04, -1.83245736e-01,
         2.53602483e-01,  1.23514614e+00],
       [ 4.26760743e-01, -2.77577070e-01, -2.76283358e+00,
        -8.28284581e-01, -7.06630296e-01]])

以下为使用searchsorted命令实现数据数组面元切分的示例:

# 根据“面元边界”数组拆分数据数组
>>> data = np.floor(np.random.uniform(0,10000,size=50))
>>> bins = np.array([0,100,1000,5000,10000])
>>> data
array([7.194e+03, 1.291e+03, 4.934e+03, 8.405e+03, 8.240e+03, 1.784e+03,
       4.710e+03, 5.545e+03, 3.315e+03, 5.217e+03, 1.110e+02, 2.937e+03,
       7.204e+03, 8.029e+03, 2.849e+03, 3.814e+03, 5.179e+03, 7.877e+03,
       3.910e+02, 4.625e+03, 9.455e+03, 3.580e+02, 3.770e+03, 1.123e+03,
       4.276e+03, 1.846e+03, 4.529e+03, 2.485e+03, 7.122e+03, 7.936e+03,
       7.573e+03, 2.222e+03, 7.643e+03, 7.839e+03, 4.581e+03, 7.493e+03,
       9.578e+03, 1.930e+02, 2.845e+03, 7.794e+03, 4.001e+03, 8.519e+03,
       4.281e+03, 6.000e+00, 8.091e+03, 8.760e+02, 1.220e+03, 2.005e+03,
       7.626e+03, 8.274e+03])
>>> labels = bins.searchsorted(data)
>>> labels
array([4, 3, 3, 4, 4, 3, 3, 4, 3, 4, 2, 3, 4, 4, 3, 3, 4, 4, 2, 3, 4, 2,
       3, 3, 3, 3, 3, 3, 4, 4, 4, 3, 4, 4, 3, 4, 4, 2, 3, 4, 3, 4, 3, 1,
       4, 2, 3, 3, 4, 4], dtype=int64)

Tips: 因为sort方法不可以被设置的降序,这时可以使用类似value[::-1]的方法产生一个反序的数组。

  • 数组的集合运算
    • np.unique():找出数组中的唯一值并返回已排序的结果。
    • np.intersect1d(x,y):计算xy中的公共元素,并返回有序结果。
    • np.union1d(x,y):计算xy的并集,并返回有序结果。
    • in1d(x,y):得到一个表示“x的元素是否包含于y”的布尔型数组。
    • setdiff1d(x,y):集合的差,即元素在x中且不在y中。
    • setxor1d(x,y):集合的对称差,即存在于一个数组中但不同时存在于两个数据中的元素。
  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值