python数组计算cos_NumPy 基础:数组和矢量计算

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值