python从入门到入土教程(4)——numpy

一、numpy简介

NumPy是使用Python进行科学计算的基础软件包。 它包含以下内容:

(1)一个强大的N维数组对象

(2)复杂(广播)功能

(3)用于集成C / C ++和Fortran代码的工具

(4)非常有用的线性代数,傅里叶变换和随机数操作

(5)除了其明显的科学用途,NumPy也可以用作通用数据的高效多维容器。 可以定义任意数据类型。 这使NumPy能够无缝地,快速地与各种数据库集成。

可能大家对"广播"一词不太了解,广播的意思可以这样理解,当我有两个维度不一样的array(数组)运算时,我可以用低维的数组复制成高维数组参与运算(因为运算要符合一定结构)

例如,在3D空间一个点的坐标[1, 2, 3]是一个秩为1的数组,因为它只有一个轴。那个轴长度为3.又例如,在以下例子中,数组的秩为2(它有两个维度).第一个维度长度为2,第二个维度长度为3.

[[ 1., 0., 0.],
[ 0., 1., 2.]]

Numpy的数组类被称作ndarray。通常被称作数组。注意numpy.array和标准Python库类array.array并不相同,后者只处理一维数组和提供少量功能。更多重要ndarray对象属性有:

  • ndarray.ndim

数组轴的个数,在python的世界中,轴的个数被称作秩

  • ndarray.shape

数组的维度。这是一个指示数组在每个维度上大小的整数元组。例如一个nm列的矩阵,它的shape属性将是(2,3),这个元组的长度显然是秩,即维度或者ndim属性

  • ndarray.size

数组元素的总个数,等于shape属性中元组元素的乘积。

  • ndarray.dtype

一个用来描述数组中元素类型的对象,可以通过创造或指定dtype使用标准Python类型。另外Numpy提供它自己的数据类型。

  • ndarray.itemsize

数组中每个元素的字节大小。例如,一个元素类型为float64的数组itemsiz属性值为8(=64/8),又如,一个元素类型为complex32的数组item属性为4(=32/8).

  • ndarray.data

包含实际数组元素的缓冲区,通常我们不需要使用这个属性,因为我们总是通过索引来使用数组中的元素。

import numpy as np

a = np.arange(15) 

print(a.reshape(3,5))
  • 维度是一组数据的组织形式
  • 数组要求数据类型相同,列表不需要
a = np.array([[0, 1, 2, 3, 4],
          [5, 6, 7, 8, 9]])
print(a)

二、数组的创建和转换

从列表,元组创建,可指定数据类型
np.array函数就可以了,可以用的type指定类型

使用Numpy自带的函数ones,zeros等
ones_like(a),根据a的形状生成一个一样的为1的数组

list1 = [[1,2,3,4],[2,3,4,5],[3,4,5,6]]

# 使用 array 创建np数组
np1 = np.array(list1, dtype=np.int)
print(np1)
# 获取np数 组 的形状
print(np1.shape)
# 获取np数组的维度
print(np1.ndim)
# 获取np数组的元素类型
print(np1.dtype)
# 获取np数组的元素个数
print(np1.size)
np.linspace(1, 10, 4)
np.linspace(1, 10, 4, endpoint = False)#10不作为最后一个值出现

#查看数组的属性 
arr2 = np.array([(1.3, 9, 2.0), (7, 6, 1)]) 
#通过元组创建数组 
print(arr2.shape) 
# 返回矩阵的规格
# result: (2,3) 
print(arr2.ndim) 
# 返回矩阵的秩 
# result: 2 
print(arr2.size)
# 返回矩阵元素总数 
# result: 6 
print(arr2.itemsize) 
# # result: 8 
print(arr2.nbytes) 
# # result: 48 
print(arr2.dtype.name) 
# 返回矩阵元素的数据类型 
# result: float64 
print(type(arr2)) 
# 查看整个数组对象的类型 
# result: <class 'numpy.ndarray'> 
b = np.array([1. + 1.j, 3. + 2.j]) 
b.real 
# result:array([1., 3.]) 
b.imag 
# result:array([1., 2.]) 
b = np.arange(4).reshape(2, 2) 
b.flat 
# result:<numpy.flatiter object at 0x0000024FF4C32CF0> 
b.flat[2] 
# result:2

对创建好的数组,可以变换维度,改变类型
reshape不改变原数组,resize改变原数组

通常,数组的元素开始都是未知的,但是它的大小已知。因此,Numpy提供了一些使用占位符创建数组的函数。这最小化了扩展数组的需要和高昂的运算代价。

函数function创建一个全是0的数组,函数ones创建一个全1的数组,函数empty创建一个内容随机并且依赖与内存状态的数组。默认创建的数组类型(dtype)都是float64

三、 numpy基本运算和常用函数

# 使用填充值创建数组 one zero empty
np4 = np.ones((3,4), dtype=np.int)
print(np4)
np5 = np.ones_like(np4)

# 创建单位矩阵
np6 = np.eye(6)
a = np.array([20, 30, 40, 50])
b = np.arange(4)

##加减乘除
a + b
a - b
a * b
b / a
a ** b
np.cos(a) + np.sin(b)
a < 35
c = np.array([[1, 1],
             [2, 2]])
d = np.array([[2, 2],
             [1, 1]])

c += d
c

np.dot(c, d)

c * d

c += d

e = np.exp(c * 1j)
e.dtype.name

d.sum()
d.mean()
d.min()

四、索引、切片和迭代

4.1 一维数组

a = np.array([0, 1, 2, 3])
a[0]
a[0] = 10
a = np.array([11,12,13,14,15])
a[1:3]
a[1:-2]
a[-4:3]

test:假设我们记录一辆汽车表盘上每天显示的里程数为:od = array([21000, 21180, 21240, 22100, 22400]), 计算每天的旅程

4.2 多维数组

a = np.array([[ 0, 1, 2, 3],
           [10,11,12,13]])
a[1, 3]

# 其中,1是行索引,3是列索引,中间用逗号隔开,
#事实上,**Python**会将它们看成一个元组(1,3),然后按照顺序进行对应。

# 可以利用索引给它赋值:

a[1, 3] = -1


a[1]
a = np.array([[ 0, 1, 2, 3, 4, 5],
           [10,11,12,13,14,15],
           [20,21,22,23,24,25],
           [30,31,32,33,34,35],
           [40,41,42,43,44,45],
           [50,51,52,53,54,55]])

a[0, 3:5]
a[4:, 4:]
a[:, 2]
a[2::2, ::2]
a = np.array([0,1,2,3,4])
b = a[2:4].copy()
b[0] = 10
a

##搞懂切片和直接复制之间的区别

4.3 花式索引 (比较花)

a = np.arange(0, 80, 10)
indices = [1, 2, -3]
y = a[indices]
print( y)
mask = np.array([0,1,1,0,0,1,0,0],
            dtype=bool)
a[mask]
from numpy.random import rand
a = rand(10)
mask = a > 0.5
a[mask]
a = np.array([[ 0, 1, 2, 3, 4, 5],
           [10,11,12,13,14,15],
           [20,21,22,23,24,25],
           [30,31,32,33,34,35],
           [40,41,42,43,44,45],
           [50,51,52,53,54,55]])

#####################二维花式索引################
#对于二维花式索引,我们需要给定 row 和 col 的值
#################################
a[(0,1,2,3,4), (1,2,3,4,5)]

a[3:, [0,2,5]]


mask = np.array([1,0,1,0,0,1],
            dtype=bool)
a[mask, 2]

花式索引返回的是复制而不是引用

a = np.arange(64)
a.shape = 4,4,4
y = a[:,:,[2, -1]]
y

4.4 where语句

where 函数会返回所有非零元素的索引。

a = np.array([0, 12, 5, 20])
a > 10
np.where(a > 10)

注意到 where 的返回值是一个元组。

使用元组是由于 where 可以对多维数组使用,此时返回值就是多维的。

在使用的时候,我们可以这样:

a = np.array([[0, 12, 5, 20],
           [1, 2, 11, 15]])
loc = np.where(a > 10)
a[loc]
rows, cols = np.where(a>10)
a[rows, cols]

五、排序和方法

5.1 排序

names = np.array(['bob', 'sue', 'jan', 'ad'])
weights = np.array([20.8, 93.2, 53.4, 61.8])

np.sort(weights)
ordered_indices = np.argsort(weights)
ordered_indices
names[ordered_indices]
#沿着最后一维开始排序
a = np.array([
        [.2, .1, .5], 
        [.4, .8, .3],
        [.9, .6, .7]
    ])
np.sort(a)
np.sort(a, axis = 0)
#默认沿着每一行排序
searchsorted(sorted_array, values)

searchsorted 接受两个参数,其中,第一个必需是已排序的数组。

sorted_array = np.linspace(0,1,5)
values = np.array([.1,.8,.3,.12,.5,.25])
np.searchsorted(sorted_array, values)

searchsorted 返回的值相当于保持第一个数组的排序性质不变,将第二个数组中的值插入第一个数组中的位置:

例如 0.1[0.0, 0.25]之间,所以插入时应当放在第一个数组的索引 1 处,故第一个返回值为 1

from numpy.random import rand
data = rand(100)
data.sort()

bounds = .4, .6

low_idx, high_idx = np.searchsorted(data, bounds)

data[low_idx:high_idx]

5.2 方法

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

arr.mean()

np.mean

arr.sum()

np.sum(arr)
arr.mean(axis=1)
arr.sum(0)
arr = np.array([[0, 1, 2], [3, 4, 5], [6, 7, 8]])
arr.cumsum(axis=0)
arr.cumprod(axis=0)
# fromfunction函数的第一个参数为计算每个数组元素的函数,第二个参数为数组的大小(shape)
#因为 它支持多维数组,所以第二个参数必须是一个序列,本例中用(10,)创建一个10元素的一维数组 
def func(i): 
    return i % 4 + 1 

print(np.fromfunction(func, (10,)))

创建一个二维数组表示九九乘法表,输出的数组a中的每个元素a[i, j]都等于func2(i, j)

def func2(i, j):
    return (i + 1) * (j + 1)


a = np.fromfunction(func2, (9, 9))
print(a)

#求积
a.prod()
np.prod(a, axis=0)
a.min()
a.min(axis=0)

a.max()
a.max(axis=0)

a.argmin()
a.argmin(axis=0)

a.argmax()
a.argmax(axis=0)
a.clip(30,50)
#把数值限定在30和50之间
a.ptp(axis=1)
a.ptp()
#最大值和最小值之差
# np.reshape(np1, (2,6)) # 返回形状为(2,6)的新矩阵
# np.ravel(np1) # 返回元素平铺
# np.vstack((np1, np2)) # 纵向连接
# np.hstack((np1, np2)) # 横向连接
# np.vsplit(np1, n) # 纵向拆分(横向hsplit)
# np.concatnate((np1,np2), axis) # 按轴拼接
# np.where(cond, v1, v2) # 符合cond条件,返回v1,否则v2
# np1.T # transpose() : 求取转置矩阵
# np.swapaxes(np1, 0, 1) # 交换轴元素
# np.abs(np1) # fabs(np1) : 求取元素级整数,浮点数的绝对值
# np.sqrt(np1) # 求取各元素的平方根,相当于np1 ** 0.5
# np.square(np1) # 求取元素级的平方,相当于np1 ** 2
# np.exp(np1) # 对各元素求取e^*,组成新数组返回
# np.log #  log10, log2, log1p : 对各元素求取底数为e,10, 2,(1+x)的对数
# np.sign(np1) # 计算各元素的符号,正数为1,零为0, 负数为-1
# np.ceil() # floor(), rint(): 圆整,ceil求取大于等于该元素的最小整数,rint是四舍五入
# np.modf(np1) # 返回浮点数的小数和整数两个数组
# np.isnan() # isfinite, isinf : 对各元素的判断,返回bool型数组,不是一个数字,有穷的,无穷的
# np.cos() # cosh(), sin(), sinh() : 三角函数

创建一个 3x3 的二维数组,并将列按升序排序

创建一个长度为 5 的一维数组,并将其中最大值替换成 0

将随机二维数组按照第 3 列从上到下进行升序排列

从随机一维数组中找出距离给定数值(0.5)最近的数

a = np.array(([1,4,3],[6,2,9],[4,7,2]))

返回每列最大值

返回每行最小值

返回每列最大值索引

返回每行最小值索引

统计数组各列的中位数

统计数组各行的算术平均值

统计数组各列的加权平均值

统计数组各行的方差

统计数组各列的标准偏差

六、数组形状

6.1 更改形状

b = np.arange(24).reshape(2, 3, 4)
print(b)

print(b.ravel())

print(b.flatten())

b.shape = (6, 4)
print(b)

print(b.transpose())
print(b.T)

b.resize((2, 12))
print(b)
#使用 newaxis 增加数组维数
a = np.arange(3)
a.shape

y = a[np.newaxis, :]
np.shape(y)
y = a[np.newaxis, np.newaxis, :]
np.shape(y)

6.2 数组合并

a = np.arange(9).reshape(3, 3)
print(a)


b = 2 * a
print(b)
print(np.vstack((a, b))) #纵向合并数组,由于与堆栈类似,故命名为vstack
print(np.concatenate((a, b), axis=0))
print(np.hstack((a, b))) #横向合并数组
print(np.concatenate((a, b), axis=1))
print(np.dstack((a, b)))
print(np.column_stack((a, b)))
print(np.column_stack((a, b)) == np.hstack((a, b)))
print(np.row_stack((a, b)))
print(np.row_stack((a, b)) == np.vstack((a, b)))
oned = np.arange(2) 
print(oned)

twice_oned = 2 * oned
print(twice_oned)

print(np.column_stack((oned, twice_oned)))
print(np.row_stack((oned, twice_oned)))

6.3 数组分割

a = np.arange(9).reshape(3, 3)
print(a)
print(np.split(a, 3, axis=1))
print(np.hsplit(a, 3)) # 将数组横向分为2部分
print(np.vsplit(a, 3)) 
# 数组纵向分为2部分 
print(np.split(a, 3, axis=0))
c = np.arange(27).reshape(3, 3, 3) 
print(c)
print(np.dsplit(c, 3))

6.4 复制与视图

当运算和处理数组时,它们的数据有时被拷贝到新的数组有时不是。这通常是新手的困惑之源。这有三种情况:

  • 完全不拷贝
  • 简单的赋值不拷贝数组对象或它们的数据。
a = np.arange(12)
b = a            # no new object is created
b is a   
b.shape = 3,4    # changes the shape of a
a.shape 
  • 视图(view)和浅复制
  • 不同的数组对象分享同一个数据。视图方法创造一个新的数组对象指向同一数据。
c = a.view()
c is a 
c.base is a  
c.shape = 2,6                      # a's shape doesn't change
a.shape 
c[0,4] = 1234                      # a's data changesa
a
s = a[ : , 1:3]     # spaces added for clarity; could also be written "s = a[:,1:3]"
s[:] = 10           # s[:] is a view of s. Note the difference between s=10 and s[:]=10
#切片就是返回一个视图
  • 深复制
  • 这个方法完全复制数组和它的数据
d = a.copy()                          # a new array object with new data is created
d is a

题目

a = np.random.randint(10, size=(3, 3))

b = np.random.randint(10, size=(3, 3))

水平拼合数组

垂直拼合数组

沿横轴分割数组

沿纵轴分割数组

七、随机函数

np.random.rand(2, 3, 4)
np.random.randn(2, 3, 4)
m = np.random.randint(20, 300, (3, 4))
m
np.random.seed(10) # 种子
np.random.shuffle(m)
np.random.permutation(m)

随机漫步

随机漫步(Random walk),也称随机游走,是一种数学统计模型,它由一连串轨迹所组成,其中每一次都是随机的,它能用来表示不规则的变动形式,如同一个人乱步所形成的随机记录。
随机游走的一个基本例子是整数线上的随机游走,从0开始,每一步以相同的概率移动+1或-1。

八、线性代数

#一维的数据斜率
c = np.arange(15)
np.gradient(c)
#二维的数据斜率,两个方向
c = np.arange(15).reshape(3,5)
np.gradient(b)
x = np.arange(9).reshape((3,3))
print(x)
# 取对角线上的数据
print(np.diag(x))
# k>0,主对角线之上
print(np.diag(x, k=1))
# k<0,主对角线之下
print(np.diag(x, k=-1))
# 通过对角线上的数据数组创建矩阵
print(np.diag(np.diag(x)))
A = np.arange(9).reshape((3,3))
print(A)
B = np.arange(6).reshape((3,2))
print(B)
print(A.dot(B))
print(np.dot(A,B))
print(A.trace())
print(np.trace(A))

8.1 矩阵求逆

## 创建一个矩阵
A = np.mat("0 1 2; 1 0 3; 4 -3 8")
A
#用INV函数求逆
## 注:矩阵必须是方阵且可逆,否则会抛出LinAlgError异常。
inv = np.linalg.inv(A)
inv
# 验证一下求得对不对
A * inv

广义矩阵的逆

扩充了逆的范围,不局限于方阵了

使用numpy.linalg模块中的pinv函数进行求解。

注:inv函数只接受方阵作为输入矩阵,而pinv函数则没有这个限制

#搞个矩阵
E = np.mat("4 11 14;8 7 -2")
E
#算广义的逆
pinv = np.linalg.pinv(E)
E * pinv

8.2 解方程

函数solve可以求解形如 Ax = b 的线性方程组,其中 A 为矩阵,b 为一维或二维的数组,x 是未知变量

#方程为
#x-2y+z=0
#2y-8z=8
#-4x+5y+9z=-9
B = np.mat("1 -2 1; 0 2 -8; -4 5 9")
b = np.array([0,8,-9])
x = np.linalg.solve(B,b)
x
#验证一波
np.dot(B, x)

8.3 特征值和特征向量

注:特征值(eigenvalue)即方程 Ax = ax 的根,是一个标量。其中 A 是一个二维矩阵,x 是一个一维向量。

特征向量(eigenvector)是关于特征值的向量

函数 eigvals 函数可以计算矩阵的特征值,而 eig 函数可以返回一个包含特征值和对应的特征向量的元组

#来一个矩阵
C = np.mat("3 -2;1 0")

#求一下特征值
c0 = np.linalg.eigvals(C)
c0

# 求特征值和特征根,得到第一个为特征向量,第二个是特征根
np.linalg.eig(C)

8.4 奇异值分解(SVD)

SVD(Singular Value Decomposition,奇异值分解)是一种因子分解运算,将一个矩阵分解为3个矩阵的乘积

函数 svd 可以对矩阵进行奇异值分解,该函数返回3个矩阵--U、Sigma和V,其中U和V是正交矩阵,Sigma包含输入矩阵的奇异值

#搞个矩阵
D = np.mat("4 12 14;8 7 -2")
D

#奇异值分解一波,会生成三个矩阵
U, Sigma, V = np.linalg.svd(D,full_matrices=False)
print ("U:", U)
#将三个矩阵相乘
U * np.diag(Sigma) * V
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,928评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,192评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,468评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,186评论 1 286
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,295评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,374评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,403评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,186评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,610评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,906评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,075评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,755评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,393评论 3 320
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,079评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,313评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,934评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,963评论 2 351