美文网首页数据处理Python之旅我爱编程
NumPy 基础:数组和矢量计算

NumPy 基础:数组和矢量计算

作者: 昱灬岩 | 来源:发表于2016-05-08 14:20 被阅读6814次

    NumPy 基础:数组和矢量计算

    NumPy 的 ndarray : 一种多维数组对象

    import numpy as np
    data = np.array()
    data.shape  #对象的结构,如(2,3)
    data.dtype  #对象元素的数据类型
    data.ndim  #对象的维度
    

    创建ndarray

    data = []  #创建一个list对象
    arr = np.array(data)  #传递一个list对象创建ndarray对象
    np.zeros(10)  #创建长度为10的全0数组
    np.ones(10)  #创建长度为10的全1数组
    np.zeros((3,6))  #创建3行6列的全0二维数组
    np.arrange(10)  #对应python内置的range函数  
    

    数组创建函数

    函数 说明
    array 将输入数据(列表、元祖、数组或其他序列类型)转换为ndarray。
    asarray 将输入转换为ndarray,如果输入本身就是一个ndarray就不进行复制。
    arrange 类似于内置的range。
    ones、ones_like 根据指定的形状和dtype创建一个全1数组。ones_like以另一个数组为参数。
    zeros、zeros_like 同上
    empty、empty_like 创建新数组,只分配内存空间但不填充任何值。
    eye、identity 创建一个正方的NxN单位矩阵(对角线为1,其余为0)

    ndarray的数据类型

    arr1 = np.array([1, 2, 3], dtype=np.float64)
    arr2 = np.array([1, 2, 3], dtype=np.int32)
    float_arr1 = arr1.astype(np.float64)  #data.astype()显式转换数据类型
    float_arr2 = arr2.astype(arr1.dtype)
    

    调用astype无论如何都会常见一个新的数组(原始数组的一份拷贝),即使新dtype跟老dtype相同也是如此。

    基本的索引和切片

    一维数组跟Python列表的功能差不多,跟列表最重要的区别在于,数组切片是原始数组的视图,并非拷贝。如果要想得到的是ndarray切片的一个副本而非视图,就需要显式的进行复制操作,例如==arr[5:8].copy()==。

    以下两种方式是等价的

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

    切片索引

    ndarray的切片语法跟Python列表这样的一维对象差不多。高维度对象的花样更多,可以在一个或多个轴上进行切片,也可以跟整数索引混合使用。

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

    布尔型索引

    names = np.array(['Bob', 'Joe', 'Will', 'Bob', 'Will', 'Joe', 'Joe'])
    data = randn(7,4)  //使用numpy.random中的randn函数生成一些正态分布的随机数据。
    data
    Out: 
    array([[-0.29387507,  0.17205361,  0.66953008,  1.52117065],
           [ 1.10443341,  1.38657273, -0.07698117,  0.14266073],
           [ 0.76090409,  0.971822  , -0.32016532,  0.8410247 ],
           [-0.16898366,  0.18393705, -0.68519614,  1.22744236],
           [ 0.50100988, -0.75611675,  0.18750586, -1.64240784],
           [-0.3859573 ,  0.53440464, -0.74281885,  0.83665929],
           [-0.52089554,  0.65959834, -0.17651269, -1.58237464]])
    names == 'Bob'
    Out: array([ True, False, False,  True, False, False, False], dtype=bool)
    
    data[names == 'Bob']
    Out: 
    array([[-0.29387507,  0.17205361,  0.66953008,  1.52117065],
           [-0.16898366,  0.18393705, -0.68519614,  1.22744236]])
    
    

    布尔型数组的长度必须跟被索引的轴长度一致。还可以跟切片、整数(或整数序列)混合使用:

    data[names == 'Bob',2:]
    Out: 
    array([[ 0.66953008,  1.52117065],
           [-0.68519614,  1.22744236]])
    
    

    要选择“Bob”以外的其他值,既可以使用不等于号(!=),也可以通过负号(-)对条件进行否定:

    data[names != 'Bob']
    data[-(names == 'Bob')]
    

    如果需要对布尔条件进行组合使用,可以使用&(和)、|(或)之类的布尔算数运算符即可:

    mask = (names == 'Bob') | (names == 'Will')
    
    mask
    Out: array([ True, False,  True,  True,  True, False, False], dtype=bool)
    
    data[mask]
    Out: 
    array([[-0.29387507,  0.17205361,  0.66953008,  1.52117065],
           [ 0.76090409,  0.971822  , -0.32016532,  0.8410247 ],
           [-0.16898366,  0.18393705, -0.68519614,  1.22744236],
           [ 0.50100988, -0.75611675,  0.18750586, -1.64240784]])
    
    

    通过布尔型索引选取数组中的数据,总是创建数据的副本,即使返回一模一样的数组也是如此。
    ==Python关键字and和or在布尔型数组中无效。==

    可以对数组中的一些符合条件的数据进行重新赋值:

    data[data < 0] = 0
    
    data
    Out: 
    array([[ 0.        ,  0.17205361,  0.66953008,  1.52117065],
           [ 1.10443341,  1.38657273,  0.        ,  0.14266073],
           [ 0.76090409,  0.971822  ,  0.        ,  0.8410247 ],
           [ 0.        ,  0.18393705,  0.        ,  1.22744236],
           [ 0.50100988,  0.        ,  0.18750586,  0.        ],
           [ 0.        ,  0.53440464,  0.        ,  0.83665929],
           [ 0.        ,  0.65959834,  0.        ,  0.        ]])
    
    

    花式索引

    即利用整数数组进行索引。

    为了以特定的书序选取行子集,只需传入一个用于指定顺序的整数列表或ndarray即可:

    arr = np.empty((8, 4))
    for i in range(8):
        arr[i] = i
    arr
    Out: 
    array([[ 0.,  0.,  0.,  0.],
           [ 1.,  1.,  1.,  1.],
           [ 2.,  2.,  2.,  2.],
           [ 3.,  3.,  3.,  3.],
           [ 4.,  4.,  4.,  4.],
           [ 5.,  5.,  5.,  5.],
           [ 6.,  6.,  6.,  6.],
           [ 7.,  7.,  7.,  7.]])
    
    arr[[4, 3, 0, 6]]
    Out: 
    array([[ 4.,  4.,  4.,  4.],
           [ 3.,  3.,  3.,  3.],
           [ 0.,  0.,  0.,  0.],
           [ 6.,  6.,  6.,  6.]])
    
    

    一次传入多个索引数组返回的是一个以为数组,其中的元素对应各个索引元组:

    arr = np.arange(32).reshape((8, 4))
    arr
    Out: 
    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]]  #返回的是元素(1,0)、(5,3)、(7,1)和(2,2)。
    Out: array([ 4, 23, 29, 10])
    
    

    我们可以通过以下方式获取矩阵的行列子集:

    arr[[1, 5, 7, 2]][:, [0, 3, 1, 2]]
    Out: 
    array([[ 4,  7,  5,  6],
           [20, 23, 21, 22],
           [28, 31, 29, 30],
           [ 8, 11,  9, 10]])
    
    

    还可以通过使用np.ix函数,它可以将两个一维整数数组转换为一个用于选取方形区域的所引器:

    arr[np.ix_([1, 5, 7, 2], [0, 3, 1, 2])]
    Out: 
    array([[ 4,  7,  5,  6],
           [20, 23, 21, 22],
           [28, 31, 29, 30],
           [ 8, 11,  9, 10]])
    
    

    ==花式索引总是将数据复制到新数组中。==

    数组转置和轴对换

    ==转置是重塑的一种特殊形式,它返回的事源数据的视图(不会进行任何复制操作)==。数组不仅有transppose方法,还有一个特殊的T属性:

    arr = np.arange(15).reshape((3, 5))
    arr
    Out: 
    array([[ 0,  1,  2,  3,  4],
           [ 5,  6,  7,  8,  9],
           [10, 11, 12, 13, 14]])
    
    arr.T
    Out: 
    array([[ 0,  5, 10],
           [ 1,  6, 11],
           [ 2,  7, 12],
           [ 3,  8, 13],
           [ 4,  9, 14]])
           
    arr = np.random.randn(6, 3)
    np.dot(arr.T, arr)  #利用np.dot计算矩阵内积X.T*X
    

    对于高维数组,transpose需要得到一个由轴编号组成的元组才能对这些轴进行转置(比较费脑子):

    arr = np.arange(16).reshape((2, 2, 4))
    arr
    Out: 
    array([[[ 0,  1,  2,  3],
            [ 4,  5,  6,  7]],
    
           [[ 8,  9, 10, 11],
            [12, 13, 14, 15]]])
    
    arr.transpose(1,0,2)
    Out: 
    array([[[ 0,  1,  2,  3],
            [ 8,  9, 10, 11]],
    
           [[ 4,  5,  6,  7],
            [12, 13, 14, 15]]])
    
    

    ndarray还有一个swapaxes方法,它接受一对轴编号:

    arr
    Out: 
    array([[[ 0,  1,  2,  3],
            [ 4,  5,  6,  7]],
    
           [[ 8,  9, 10, 11],
            [12, 13, 14, 15]]])
    
    arr.swapaxes(1,2)
    Out: 
    array([[[ 0,  4],
            [ 1,  5],
            [ 2,  6],
            [ 3,  7]],
    
           [[ 8, 12],
            [ 9, 13],
            [10, 14],
            [11, 15]]])
    
    

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

    一元ufunc

    函数 说明
    abs、fabs 计算整数、浮点数或复数的绝对值。对于复数数值,可以使用更快的fabs。
    sqrt 计算各元素的平方根
    square 计算各元素的平方
    exp 计算各元素的指数e^x
    log、log10、log2、log1p 分别为自然对数、底数为10的log、底数为2的log、log(1 + x)
    sign 计算各元素的正负号:1(正数)、0(零)、-1(负数)
    ceil 计算各元素的ceiling值
    floor 计算各元素的floor值
    rint 四舍五入到正数,保留dtype
    modf 将数组的小数和整数部分以两个独立数组的形式返回
    isnan 返回一个表示“哪些值是NaN”的布尔型数组
    isfinite、isinf 分别返回一个表示“哪些元素是有穷的”或“哪些元素是无穷的”的布尔型数组
    cos、cosh、sin、sinh、tan、tanh 普通型和双曲型三角函数
    arccos、arccosh、arcsin、arcsinh、arctan、arctanh 反三角函数
    logical_not 计算各元素not x的真值。想到与-arr

    二元ufunc

    函数 说明
    add 将数组中对应的元素相加
    subtract 从第一个数组中减去第二个数组中的元素
    multiply 数组元素相乘
    divide、floor_divide 除法或向下圆整除法
    power 对第一个数组中的元素A,根据第二个数组中的相应元素B,计算A的B次方
    maximum、fmax 元素级的最大值计算。fmax忽略NaN
    minmum、fmin 元素级的最小值计算。fmin忽略NaN
    mod 元素级的求模计算
    copysign 将第二个数组中的值得负号复制到第一个数组中的值
    greate、greate_equal、less、less_equal、equal、not_equal 执行元素级的比价运算,最终产生布尔型的数组。相当于运算符>、>=、<、<=、==、!=
    logical_and、logical_or、logical_xor 执行元素级的真值逻辑运算。相当于中缀运算符&、 、^

    利用数组进行数据处理

    将条件逻辑表述为数组运算

    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])
    result = [(x if c else y)
       .....: for x, y, c in zip(xarr, yarr, cond)]
    result
    Out: [1.1000000000000001, 2.2000000000000002, 1.3, 1.3999999999999999, 2.5]
    

    这样做会有许多问题。首先,对于大的数组,它不会很快(因为所有的工作都是有纯Python来做的)。其次,对于多维数组,它不能工作。使用 np.where 你可以像这样非常简洁的编写:

    result = np.where(cond, xarr, yarr)
    result
    Out: array([ 1.1, 2.2, 1.3, 1.4, 2.5])
    

    np.where 的第一个和第二个参数不需要是数组;它们中的一个或两个可以是纯量。 在数据分析中 where 的典型使用是生成一个新的数组,其值基于另一个数组。假如你有一个矩阵,其数据是随机生成的,你想要把其中的正值替换为2,负值替换为-2,使用 np.where 非常容易:

    arr = randn(4, 4)
    arr
    Out:
    array([[ 0.6372, 2.2043, 1.7904, 0.0752],
           [-1.5926, -1.1536, 0.4413, 0.3483],
           [-0.1798, 0.3299, 0.7827, -0.7585],
           [ 0.5857, 0.1619, 1.3583, -1.3865]])
    np.where(arr > 0, 2, -2)
    Out:
    array([[ 2, 2, 2, 2],
           [-2, -2, 2, 2],
           [-2, 2, 2, -2],
           [ 2, 2, 2, -2]])
    
    np.where(arr > 0, 2, arr) # 仅设置正值为 2
    Out:
    array([[ 2. , 2. , 2. , 2. ],
           [-1.5926, -1.1536, 2. , 2. ],
           [-0.1798, 2. , 2. , -0.7585],
           [ 2. , 2. , 2. , -1.3865]])
    

    np.where 可以嵌套使用。

    数学统计方法

    一组数学函数,计算整个数组或一个轴向上数据的统计,和数组函数一样是容易访问的。聚合(通常被称为 reductions ),如 sum , mean ,标准偏差 std 可以使用数组实例的方法,也可以使用顶层NumPy的函数:

    arr = randn(5,4)
    arr
    Out: 
    array([[ 0.39013323, -0.65003199, -1.7659255 ,  0.50657869],
           [ 1.49064958, -2.12313076, -0.06437275, -1.74020972],
           [ 0.58393273, -2.54944833,  1.3207072 ,  0.4929906 ],
           [ 0.29181077,  0.24600015, -0.88524769,  0.1694354 ],
           [-1.29550423, -0.67156125,  0.04152137,  0.6270823 ]])
    
    arr.mean()
    Out: -0.27922950905899768
    
    np.mean(arr)
    Out: -0.27922950905899768
    
    arr.sum()
    Out: -5.5845901811799532
    
    np.sum(arr)
    Out: -5.5845901811799532
    
    

    像 mean 和 sun 函数可以有一个可选的 axis参数,它对给定坐标轴进行统计,结果数组将会减少一个维度:

    arr.mean(axis=1)
    Out[84]: array([-0.37981139, -0.60926591, -0.03795445, -0.04450034, -0.32461545])
    arr.sum(0)
    Out[86]: array([ 1.46102209, -5.74817217, -1.35331736,  0.05587727])
    
    

    像 cumsum 和 cumprod 这些函数并不聚集,而是产生一个中间结果组成的数组:

    arr = np.array([[0, 1, 2], [3, 4, 5], [6, 7, 8]])
    arr.cumsum(axis=0)
    Out: 
    array([[ 0,  1,  2],
           [ 3,  5,  7],
           [ 9, 12, 15]])
    arr.cumprod(axis=0)
    Out: 
    array([[ 0,  1,  2],
           [ 0,  4, 10],
           [ 0, 28, 80]])
    
    

    数学统计方法清单

    方法 描述
    sum 对数组的所有或一个轴向上的元素求和。零长度的数组的和为灵。
    mean 算术平均值。灵长度的数组的均值为NaN。
    std, var 标准差和方差,有可选的调整自由度(默认值为n)。
    min, max 最大值和最小值
    argmin, argmax 索引最小和最大元素。
    cumsum 从0元素开始的累计和。
    cumprod 从1元素开始的累计乘。

    用于布尔型数组的方法

    在上面的方法中,布尔值被强制为1( True )和0a( False )。因此, sum 经常被用来作为对一个布尔数组中的 True 计数的手段:

    arr = randn(100)
    (arr > 0).sum() # 正值的个数
    Out: 44
    

    有两个额外的方法, any 和 all ,对布尔数组尤其有用。 any 用来测试一个数组中是否有一个或更多的 True ,而 all 用来测试所有的值是否为 True :

    bools = np.array([False, False, True, False])
    bools.any()
    Out: True
    bools.all()
    Out: False
    

    ==这些方法这些方法也可以工作在非布尔型数组上,非零元素作为 True 。==

    排序

    arr.sort(axis=None)会就地排序修改数组本身,而np.sort(arr,axis=None)返回的是数组的已排序数组。计算数组分位数最简单的方法是对其进行排序,然后选取特定位置的值:

    large_arr = randn(1000)
    large_arr.sort()
    large_arr[int(0.05 * len(large_arr))] # 5% 分位点
    Out: -1.5791023260896004
    

    唯一化以及其他的集合逻辑

    Numpy有一些基本的针对一维ndarrays的集合操作。最常使用的一个可能是 np.unique ,它返回一个数组的经过排序的 unique 值:

    names = np.array(['Bob', 'Joe', 'Will', 'Bob', 'Will', 'Joe', 'Joe'])
    np.unique(names)
    Out:
    array(['Bob', 'Joe', 'Will'],
          dtype='|S4')
    ints = np.array([3, 3, 3, 2, 2, 1, 1, 4, 4])
    np.unique(ints)
    Out: array([1, 2, 3, 4])
    

    另一个函数 np.in1d 用于测试一个数组中的值在另一个数组中的成员资格,返回一个布尔型数组:

    values = np.array([6, 0, 0, 3, 2, 5, 6])
    np.in1d(values, [2, 3, 6])
    Out: array([ True, False, False, True, True, False, True], dtype=bool)
    
    函数 说明
    unique(x) 计算x单一的元素,并对结果排序
    intersect1d(x, y) 计算x和y相同的元素,并对结果排序
    union1d 结合x和y的元素,并对结果排序
    in1d(x, y) 得到一个布尔数组指示x中的每个元素是否在y中
    setdiff1d(x, y) 差集,在x中但不再y中的集合
    setxor1d(x, y) 对称差集,不同时在两个数组中的元素

    用于数组的文件输入输出

    NumPy 能够保存数据到磁盘和从磁盘加载数据,不论数据是文本或二进制的。

    将数组以二进制格式保存到磁盘

    np.save 和 np.load 是两个主力功能,有效的保存和加载磁盘数据。数组默认保存为未经过压缩的原始二进制数据,文件扩展名为 .npy :

    arr = np.arange(10)
    np.save('some_array', arr)
    

    如果文件路进并不是以 .npy 结尾,扩展名将会被自动加上。在磁盘上的数组可以使用 np.load 加载:

    np.load('some_array.npy')
    Out: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
    

    可以使用 np.savez 并以关键字参数传递数组来保存多个数组到一个zip的归档文件中:

    np.savez('array_archive.npz', a=arr, b=arr)
    

    加载一个 .npz 文件时,会得到一个字典对象,该对象会对各个数组进行延时加载:

    arch = np.load('array_archive.npz')
    arch['b']
    Out: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
    

    存取文本文件

    从文件加载文本是一个相当标准的任务。对一个新人来说,Python的文件加读取和写入函数的景象可能有一点儿混乱,因此我将主要集中在pandas的 read_csv 和 read_table 函数上。有时使用 np.loadtxt 或更专门的 np.genfromtxt 对于加载数据到普通的 NumPy 数组是很有用的。

    # Windows下用type
    !cat array_ex.txt
    0.580052,0.186730,1.040717,1.134411
    0.194163,-0.636917,-0.938659,0.124094
    -0.126410,0.268607,-0.695724,0.047428
    -1.484413,0.004176,-0.744203,0.005487
    2.302869,0.200131,1.670238,-1.881090
    -0.193230,1.047233,0.482803,0.960334
    
    # 直接将文件加载到一个二维数组中
    arr = np.loadtxt('array_ex.txt', delimiter=',')
    arr
    Out:
    array([[ 0.5801, 0.1867, 1.0407, 1.1344],
    [ 0.1942, -0.6369, -0.9387, 0.1241],
    [-0.1264, 0.2686, -0.6957, 0.0474],
    [-1.4844, 0.0042, -0.7442, 0.0055],
    [ 2.3029, 0.2001, 1.6702, -1.8811],
    [-0.1932, 1.0472, 0.4828, 0.9603]])
    

    np.savatxt 执行相反的操作:将数组写到以某种分隔符隔开的文本文件中。 genfromtxt 与 loadtxt 相似,但是它是面向结构数组和缺失数据处理的。

    线性代数

    dot 函数,是数组的一个方法和 numpy 命名空间中的一个函数,用来进行矩阵乘法运算:

    x = np.array([[1., 2., 3.], [4., 5., 6.]])
    In [195]: y = np.array([[6., 23.], [-1, 7], [8, 9]])
    
    x.dot(y) # 等价于 np.dot(x, y)
    Out:
    array([[ 28., 64.],
           [ 67., 181.]])
    

    numpy.linalg 有一个关于矩阵分解和像转置和行列式等的一个标准集合。

    from numpy.linalg import inv, qr
    

    常见numpy.linalg

    函数 描述
    diag 返回一个方阵的对角线(或非对角线)元素为一个一维数组,或者转换一个一维数组到一个方阵(非对角线元素为零)
    dot 矩阵乘积
    trace 计算对角线上元素的和
    det 计算矩阵行列式
    eig 计算方阵的特征值和特征向量
    inv 计算方阵的逆
    pinv 计算方阵 Moore-Penrose 伪逆
    qr 计算 QR 分解
    svd 计算奇异值分解(SVD)
    solve 求解线性系统方程 Ax = b 的x,其中A是一个方阵
    lstsq 计算 y = Xb 的最小二乘解

    随机数生成

    numpy.random 模块对 Python 内置的 random 进行了补充,增加了一些用于高效生成多种概率分布的样本值得函数。

    numpy.random 函数

    函数 说明
    seed 确定随机数生成数的种子
    permutation 返回一个序列的随机排列或返回一个随机排列的范围
    shuffle 对一个序列就地随机排列
    rand 产生均匀分布的样本值
    randint 从给定的上下限范围内(不包括上限)随机选取整数
    randn 产生标准正态分布的样本值
    binomial 产生二项分布的样本值
    normal 产生正态(高斯)分布的样本值
    beta 产生Beta分布的样本值
    chisquare 产生卡方分布的样本值
    gamma 产生Gamma分布的样本值
    uniform 产生在[0,1]中均匀分布的样本值

    模拟随机漫步

    多个随机漫步

    nwalks = 5000
    nsteps = 1000
    draws = np.random.randint(0, 2, size=(nwalks, nsteps)) # 0 or 1
    steps = np.where(draws > 0, 1, -1)
    walks = steps.cumsum(1)
    walks
    Out:
    array([[ 1, 0, 1, ..., 8, 7, 8],
           [ 1, 0, -1, ..., 34, 33, 32],
           [ 1, 0, -1, ..., 4, 5, 4],
           ...,
           [ 1, 2, 1, ..., 24, 25, 26],
           [ 1, 2, 3, ..., 14, 13, 14],
           [ -1, -2, -3, ..., -24, -23, -22]])
    
    # 我们可以获得所有游走的最大和最小值     
    walks.max() In [229]: walks.min()
    Out: 138 Out[229]: -133
    
    # 在这些游走中,让我们来计算到达30或-30的最短时间。这有一点儿狡猾,
    # 因为不是所有的5000个游走都能到达30。我们可以使用 any 方法来检测
    hits30 = (np.abs(walks) >= 30).any(1)
    hits30
    Out: array([False, True, False, ..., False, True, False], dtype=bool)
    hits30.sum() # 30或-30的个数
    Out: 3410
    
    # 我们可以使用这个布尔数组来选择这些游走中跨过绝对值30的行,并调用 argmax 来取得坐标轴1的穿越时间:
    crossing_times = (np.abs(walks[hits30]) >= 30).argmax(1)
    crossing_times.mean()
    Out[234]: 498.88973607038122
    

    相关文章

      网友评论

        本文标题:NumPy 基础:数组和矢量计算

        本文链接:https://www.haomeiwen.com/subject/pwusrttx.html