Numpy


系列文章:



Numpy

1、为什么用Numpy

低消的Python for循环
【例】求100万个数的倒数

import time

def compute_reciprocals(values):
    res = []
    for value in values:
        res.append(1/value)
    return  res


values = list(range(1,10000000))
start = time.time()
compute_reciprocals(values)
end = time.time()
print(end-start) #0.5781590938568115
import numpy as np
values = np.arange(1,10000000)
start = time.time()
1/values
end = time.time()
print(end-start) #0.015624761581420898

实现相同计算,Numpy运行速度是Python循环的近40倍

Numpy为什么如此高效
Numpy是由C语言编写的

1、编译型语言VS解释型语言
C语言执行时,对代码进行整体编译,速度更快

2、连续单一类型存储VS分散多变类型存储
(1)Numpy数组内的数据类型必须是统一的,如全部是浮点型,而Python列表支持任意类型数据的填充

(2)Numpy数组内的数据连续存储在内存中,而Python列表的数据分散在内存中
这种存储结构,与一些更加高效的底层处理方式更加的契合

3、多线程VS线程锁
Python语言执行时有线程锁,无法实现真正的多线程并行,而C语言可以

什么时候使用Numpy
在数据处理的过程中,遇到使用“Python for循环” 实现一些向量化、矩阵化操作的时候,要优先考虑用Numpy

2、Numpy数组的创建

从列表开始创建

import numpy as np

x = np.array([1,2,3,4,5])
print(x) #[1 2 3 4 5]
print(type(x)) #<class 'numpy.ndarray'>
print(x.shape) #(5,)
  • 设置数组的数据类型
import numpy as np

x = np.array([1,2,3,4,5], dtype="float32")
print(x[0]) #1.0
print(type(x)) #<class 'numpy.ndarray'>
  • 二维数组
import numpy as np

x = np.array([[1,2,3],[4,5,6]])
print(x)
print(x.shape)
# [[1 2 3]
#  [4 5 6]]
# (2, 3)

2、从头创建数组

(1)创建长度为5的数组,值都为0

print(np.zeros(5,dtype=int)) # [0 0 0 0 0]

(2)创建一个 2*4的浮点型数组,值都为1

print(np.ones((2, 4), dtype=float))
# [[1. 1. 1. 1.]
#  [1. 1. 1. 1.]]

(3)创建一个 3*5 的数组,值都为8.8

print(np.full((3,5), 8.8))
# [[8.8 8.8 8.8 8.8 8.8]
#  [8.8 8.8 8.8 8.8 8.8]
#  [8.8 8.8 8.8 8.8 8.8]]

(4)创建一个 3*3 的单位阵

print(np.eye(3))
# [[1. 0. 0.]
#  [0. 1. 0.]
#  [0. 0. 1.]]

(5)创建一个线性序列数组,从1开始,到15结束,不包含15,步长为2

print(np.arange(1,15,2))
# [ 1  3  5  7  9 11 13]
print(np.arange(1,15,2,dtype=float))
[ 1.  3.  5.  7.  9. 11. 13.]

(6)创建一个4个元素的数组,这四个数均匀的分配到0~1

print(np.linspace(0, 1, 4))
# [0.         0.33333333 0.66666667 1.        ]

(7)创建一个3个元素的数组,形成等比数列

print(np.logspace(0, 9, 3))
# [1.00000000e+00 3.16227766e+04 1.00000000e+09]
print(np.logspace(0, 9, 4))
# [1.e+00 1.e+03 1.e+06 1.e+09]

(8)创建一个 3*3 的, 在0~1之间均匀分布的随机数构成的数组

print(np.random.random((3,3)))
# [[0.54837425 0.44061088 0.52246395]
#  [0.01683814 0.16464237 0.46193482]
#  [0.33568298 0.09123365 0.20578567]]

(9)创建一个 3*3 的, 均值为0, 标准差为1 的正太分布随机数构成的数组

print(np.random.normal(0, 1, (3,3)))
# [[ 1.8815049   0.03623437 -2.23640662]
#  [ 0.66722861 -0.65323949 -0.71359156]
#  [ 0.24692219  1.1241757  -0.68521722]]

(10)创建一个 3*3 的, 在[0, 10) 之间随机整数构成的数组

print(np.random.randint(0, 10, (3,3)))
# [[9 9 2]
#  [7 7 0]
#  [5 2 5]]

(11)随机重排列

x = np.array([10, 20, 30, 40])
print(np.random.permutation(x))
# [10 40 20 30]
print(x) #[10 20 30 40]
x = np.array([10, 20, 30, 40])
np.random.shuffle(x)
print(x)
# [30 10 40 20]

(12)随机采样

  • 按指定形状采样
x = np.arange(10,25,dtype=float)
print(np.random.choice(x, size=(4, 3)))
# [[10. 18. 18.]
#  [14. 16. 11.]
#  [20. 23. 21.]
#  [23. 17. 22.]]
print(np.random.choice(10, 6))
#[2 8 4 2 9 7]
x = np.arange(5).reshape(1, 5)
print(x) #[[0 1 2 3 4]]
print(x.sum(axis=1, keepdims=True)) #[[10]]
#1表示横轴,方向从左到右
  • 按概率采样
import numpy as np
x = np.arange(50)
print(np.random.choice(x, size=(4,3), p=x/np.sum(x)))
# [[45 45  7]
#  [15 12 32]
#  [23 43 17]
#  [18 49 39]]

Numpy 数组的性质

1、数组的属性

  • 数组的形状shape
  • 数组的维度ndim
  • 数组的大小size
  • 数组的数据类型dtype
x = np.random.randint(10, size=(3,4))
print(x.shape) #(3, 4)
print(x.ndim) #2
print(x.size) #12
print(x.dtype) #int32

2、数组的索引

1、一维数组的索引
支持正向索引和负向索引

x =np.arange(10)
print(x[0]) #0
print(x[-1]) #9

2、多维数组的索引——以二维为例

x = np.random.randint(0,20,(2,3))
print(x)
# [[ 8  2 19]
#  [ 9 15  5]]
print(x[0,0]) #8
print(x[0][0]) #8

注意:numpy数组的数据类型是固定的,当向一个整形数组插入一个浮点值,浮点值会向下进行取整

x[0][0] = 1.618
print(x[0,0]) #1

3、数组的切片

1、一维数组——跟列表一样

import numpy as np
x = np.arange(10)
print(x[:3]) #[0 1 2]
print(x[3:]) ##[3 4 5 6 7 8 9]
print(x[::-1]) #[9 8 7 6 5 4 3 2 1 0]

2、多维数组——以二维数组为例

import numpy as np
x = np.random.randint(20, size=(3,4))
print(x)
# [[15 19  7  7]
#  [16 10 14  7]
#  [15  0 13 14]]

#第一个维度取恰两个  第二个维度取前三
print(x[:2, :3])
# [[15 19  7]
#  [16 10 14]]

#第一个维度取恰两个  第二个维度从0到3,2代表步长
print(x[:2, 0:3:2])
# [[15  7]
#  [16 14]]

print(x[::-1, ::-1])
# [[14 13  0 15]
#  [ 7 14 10 16]
#  [ 7  7 19 15]]

3、获取数组的行和列

x = np.random.randint(20, size=(3,4))
print(x)
# [[ 8 13  7 16]
#  [10 16  5  3]
#  [ 3  2 15  6]]

print(x[1,:]) #第二行,从1计数
# [10 16  5  3]
print(x[1]) #第二行,从1计数
# [10 16  5  3]
print(x[:, 2]) #第三列
# [ 7  5 15]

4、切片获取的是视图,而非副本
注意:视图元素发生修改则原数组也发生相应的修改

import numpy as np
x = np.random.randint(20, size=(3,4))
print(x)
# [[ 9  6 18 16]
#  [17  2  4 14]
#  [12 17  5  3]]

x1 = x[:2,:2]
print(x1)
# [[ 9  6]
#  [17  2]]

x1[0][0]=1
print(x1)
# [[ 1  6]
#  [17  2]]

print(x)
# [[ 1  6 18 16]
#  [17  2  4 14]
#  [12 17  5  3]]

原数据改变,视图中的数据也变

import numpy as np
x = np.random.randint(20, size=(3,4))
print(x)
# [[12 10  4  4]
#  [ 8 14 18  7]
#  [ 2 18 16 17]]
x1 = x[:2,:2]
print(x1)
# [[12 10]
#  [ 8 14]]

x[0][0]=1
print(x1)
# [[ 1 10]
#  [ 8 14]]

print(x1)
# [[ 1 10]
#  [ 8 14]]

修改切片的安全方式:copy

x = np.random.randint(20, size=(3,4))
print(x)
# [[16  1 13 12]
#  [16 10 11  0]
#  [15 12 16 14]]

x1 = x[:2,:2].copy()
print(x1)
# [[16  1]
#  [16 10]]

x1[0,0]=10086
x[2][2]=10010
print(x)
# [[   16     1    13    12]
#  [   16    10    11     0]
#  [   15    12 10010    14]]

print(x1)
# [[10086     1]
#  [   16    10]]

4、数组的变形

x = np.random.randint(0 ,10 ,(12,))
print(x)
# [0 8 5 1 9 7 5 7 2 4 5 4]
print(x.shape) #(12,)
x1 = x.reshape(3, 4)
print(x1)
# [[0 8 5 1]
#  [9 7 5 7]
#  [2 4 5 4]]

注意:reshape返回的是视图,而非副本

一维向量转行向量

x = np.random.randint(0 ,10 ,(12,))
print(x) #[7 2 9 6 4 5 6 5 0 9 4 8]
print(x.shape) #(12,)
print(type(x)) #<class 'numpy.ndarray'>
x1 = x.reshape(1, x.shape[0])

print(x1) #[[7 2 9 6 4 5 6 5 0 9 4 8]]
print(type(x1)) #<class 'numpy.ndarray'>
print(x1.shape) #(1, 12)
x2 = x[np.newaxis,:]
print(x2) #[[7 2 9 6 4 5 6 5 0 9 4 8]]

一维向量转列向量

x = np.random.randint(0 ,10 ,(4,))

x1 = x.reshape(x.shape[0], 1)
print(x1)
# [[6]
#  [0]
#  [5]
#  [7]]
x2 = x[:, np.newaxis]
print(x2)
# [[6]
#  [0]
#  [5]
#  [7]]

多维向量转一维向量
flatten 返回的是副本

x = np.random.randint(0 ,10 ,(2,3))
print(x)
# [[2 1 9]
#  [3 3 6]]
x1 = x.flatten()
print(x1) #[2 1 9 3 3 6]
x1[0] = 996
print(x)
# [[2 1 9]
#  [3 3 6]]

ravel返回的是视图

x = np.random.randint(0 ,10 ,(2,3))
print(x)
# [[8 6 2]
#  [9 4 3]]
x1 = x.ravel()
print(x1) #[8 6 2 9 4 3]
x1[0]=996
print(x)
# [[996   6   2]
#  [  9   4   3]]

reshape返回的是视图

x = np.random.randint(0 ,10 ,(2,3))
print(x)
# [[9 0 2]
#  [9 2 2]]
x1 = x.reshape(-1)
print(x1) #[9 0 2 9 2 2]
x1[0] =996
print(x)
# [[996   0   2]
#  [  9   2   2]]

5、数组的拼接

1、水平拼接——非视图

x1 = np.array([[1,2,3],
               [4,5,6]])
x2 = np.array([[7, 8, 9],
              [0, 1, 2]])
x3 = np.hstack([x1,x2])
print(x3)
# [[1 2 3 7 8 9]
#  [4 5 6 0 1 2]]
x3[0][0]=996
print(x1)
# [[1 2 3]
#  [4 5 6]]
import numpy as np

x1 = np.array([[1,2,3],
               [4,5,6]])
x2 = np.array([[7, 8, 9],
              [0, 1, 2]])
x4 = np.c_[x1, x2]
print(x4)
# [[1 2 3 7 8 9]
#  [4 5 6 0 1 2]]
x4[0][0]=996
print(x1)
# [[1 2 3]
#  [4 5 6]]

2、垂直拼接——非视图

x1 = np.array([[1,2,3],
               [4,5,6]])
x2 = np.array([[7, 8, 9],
              [0, 1, 2]])
x3 = np.vstack([x1,x2])
print(x3)
# [[1 2 3]
#  [4 5 6]
#  [7 8 9]
#  [0 1 2]]
x4 = np.r_[x1,x2]
print(x4)
# [[1 2 3]
#  [4 5 6]
#  [7 8 9]
#  [0 1 2]]

6、数组的分裂

1、split

x = np.arange(10)
print(x) #[0 1 2 3 4 5 6 7 8 9]
x1 ,x2, x3 = np.split(x, [2,7])
print(x1, x2, x3)
# [0 1] [2 3 4 5 6] [7 8 9]

2、hsplit

x = np.arange(1,26).reshape(5,5)
print(x)
# [[ 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]]
left, middle, right = np.hsplit(x, [2,4])
print("left:\n", left)            # 第0~1列
print("middle:\n", middle)        # 第2~3列
print("right:\n", right)          # 第4列
# left:
#  [[ 1  2]
#  [ 6  7]
#  [11 12]
#  [16 17]
#  [21 22]]
# middle:
#  [[ 3  4]
#  [ 8  9]
#  [13 14]
#  [18 19]
#  [23 24]]
# right:
#  [[ 5]
#  [10]
#  [15]
#  [20]
#  [25]]

3、vsplit

x = np.arange(1,26).reshape(5,5)
print(x)
# [[ 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]]
upper, middle, lower = np.vsplit(x, [2,4])
print("upper:\n", upper)         # 第0~1行
print("middle:\n", middle)       # 第2~3行
print("lower:\n", lower)         # 第4行
# upper:
#  [[ 1  2  3  4  5]
#  [ 6  7  8  9 10]]
# middle:
#  [[11 12 13 14 15]
#  [16 17 18 19 20]]
# lower:
#  [[21 22 23 24 25]]

Numpy 四大运算

1、向量化运算

1、与数字的加减乘除

x1 = np.arange(1,6)
print(x1) #[1 2 3 4 5]

print("x1+5", x1+5) #x1+5 [ 6  7  8  9 10]
print("x1-5", x1-5) #x1-5 [-4 -3 -2 -1  0]
print("x1*5", x1*5) #x1*5 [ 5 10 15 20 25]
print("x1/5", x1/5) #x1/5 [0.2 0.4 0.6 0.8 1. ]
print("-x1", -x1) #-x1 [-1 -2 -3 -4 -5]
print("x1**2", x1**2) #x1**2 [ 1  4  9 16 25]
print("x1//2", x1//2) #x1//2 [0 1 1 2 2]
print("x1%2", x1%2) #x1%2 [1 0 1 0 1]

2、绝对值、三角函数、指数、对数
(1)绝对值

x = np.array([1, -1, 2, -2, 0])
print(abs(x)) #[1 1 2 2 0]
print(np.abs(x)) #[1 1 2 2 0]

(2)三角函数

theta = np.linspace(0, np.pi, 3)
print(theta)
# [0.         1.57079633 3.14159265]

print("sin(theta)", np.sin(theta))
print("con(theta)", np.cos(theta))
print("tan(theta)", np.tan(theta))
# sin(theta) [0.0000000e+00 1.0000000e+00 1.2246468e-16]
# con(theta) [ 1.000000e+00  6.123234e-17 -1.000000e+00]
# tan(theta) [ 0.00000000e+00  1.63312394e+16 -1.22464680e-16]

(3)指数运算

x = np.arange(3)
print(x) #[0 1 2]
print(np.exp(x)) #[1.         2.71828183 7.3890561 ]

(4)对数运算

x = np.array([1, 2, 4, 8 ,10])
print("ln(x)", np.log(x))
print("log2(x)", np.log2(x))
print("log10(x)", np.log10(x))
# ln(x) [0.         0.69314718 1.38629436 2.07944154 2.30258509]
# log2(x) [0.         1.         2.         3.         3.32192809]
# log10(x) [0.         0.30103    0.60205999 0.90308999 1.        ]

3、两数组的运算

x1 = np.arange(1,6)
print(x1) #[1 2 3 4 5]
x2 = np.arange(6,11)
print(x2) #[ 6  7  8  9 10]
print("x1+x2:", x1+x2)
print("x1-x2:", x1-x2)
print("x1*x2:", x1*x2)
print("x1/x2:", x1/x2)
x1+x2: [ 7  9 11 13 15]
x1-x2: [-5 -5 -5 -5 -5]
x1*x2: [ 6 14 24 36 50]
x1/x2: [0.16666667 0.28571429 0.375      0.44444444 0.5       ]

2、矩阵的运算

  • 矩阵的转置 x,T
x = np.arange(9).reshape(3,3)
print(x)
# [[0 1 2]
#  [3 4 5]
#  [6 7 8]]
y = x.T
print(y)
  • 矩阵乘法
    A.dot(B) np.dot(A,B) 就是 AB
    B.dot(A) np.dot(B,A) 就是 B
    A
x = np.array([[1, 0],
             [1, 1]])
y = np.array([[0, 1],
             [1, 1]])
print(x.dot(y))
# [[0 1]
#  [1 2]]
print(np.dot(x,y))
# [[0 1]
#  [1 2]]
print(y.dot(x))
# [[1 1]
#  [2 1]]
print(np.dot(y,x))
# [[1 1]
#  [2 1]]

注意跟x*y的区别:x*y就是对应位置相乘

print(x*y)
# [[0 0]
#  [1 1]]

3、广播运算

x = np.arange(3).reshape(1,3)
print(x) #[[0 1 2]]
print(x+5) #[[5 6 7]]

规则:如果两个数组的形状在维度上不匹配,则数组的形式会沿着维度为1的维度进行扩展以匹配另一个数组的形状
Numpy轴、维度理解

x1 = np.ones((3,3))
print(x1)
# [[1. 1. 1.]
#  [1. 1. 1.]
#  [1. 1. 1.]]
x2 = np.arange(3).reshape(1, 3)
print(x2)
# [[0 1 2]]

print(x1+x2)
# [[1. 2. 3.]
#  [1. 2. 3.]
#  [1. 2. 3.]]
x1 = np.logspace(1,10,10,base=2).reshape(2,5)
print(x1)
# [[   2.    4.    8.   16.   32.]
#  [  64.  128.  256.  512. 1024.]]

x2 = np.array([[1, 2, 4, 8, 16]])
print(x2)
# [[ 1  2  4  8 16]]

print(x1/x2)
# [[ 2.  2.  2.  2.  2.]
#  [64. 64. 64. 64. 64.]]
x1 = np.arange(3).reshape(3,1)
print(x1)
# [[0]
#  [1]
#  [2]]
x2 = np.arange(3).reshape(1,3)
# [[0 1 2]]
print(x2)
# [[0 1 2]]

print(x1+x2)
# [[0 1 2]
#  [1 2 3]
#  [2 3 4]]

4、比较运算和掩码

1、比较运算

x1 = np.random.randint(4,size=(2,2))
print(x1)
# [[2 3]
#  [1 2]]
print(x1>2)
# [[False  True]
#  [False False]]

2、操作布尔数组

x = np.random.randint(10, size=(3,4))
print(x)
# [[1 8 8 5]
#  [1 8 4 6]
#  [3 6 4 0]]
print(x>5)
# [[False  True  True False]
#  [False  True False  True]
#  [False  True False False]]
print(np.sum(x>5)) #5

print(np.all(x == 6)) #False

print(np.all(x<9, axis=1)) #按照行
# [ True  True  True]

print((x<9)&(x>5))

3、将布尔数组作为掩码

x = np.random.randint(10, size=(3,4))
print(x)
# [[9 4 3 3]
#  [3 8 4 2]
#  [5 2 9 2]]
print(x>5)
# [[ True False False False]
#  [False  True False False]
#  [False False  True False]]
print(x[x>5])
# [9 8 9]  只输出为True的

5、花哨的索引

1、一维数组

x = np.random.randint(100, size=10)
print(x)
# [14 47 62 59 16 77 44 86 35 86]
ind = [2,6,9]
print(x[ind]) #index为2,6,9的元素
# [62 44 86]

2、多维数组

x = np.arange(12).reshape(3,4)
print(x)
# [[ 0  1  2  3]
#  [ 4  5  6  7]
#  [ 8  9 10 11]]
row = np.array([0,1,2])
col = np.array([1,3,0])
print(x[row,col])
# [1 7 8]
print(row[:, np.newaxis]) #列向量
# [[0]
#  [1]
#  [2]]
print(x[row[:,np.newaxis], col]) #广播机制
# [[ 1  3  0]
#  [ 5  7  4]
#  [ 9 11  8]]

其他Numpy通用函数

1、数值排序

产生新的排序数组

x = np.random.randint(20, 50, size=10)
print(x)
# [37 29 29 48 49 26 22 40 45 23]
np.sort(x) #产生新的结果
print(x) #原数组不变
# [37 29 29 48 49 26 22 40 45 23]

替换原数组

x.sort() #原数组改变
print(x)
# [37 29 29 48 49 26 22 40 45 23]

获得排序索引

x = np.random.randint(20, 50, size=10)
print(x)
# [38 45 35 43 28 48 44 21 30 24]
i = np.argsort(x)
print(i)
# [7 9 4 8 2 0 3 6 1 5]
print(x)
# [38 45 35 43 28 48 44 21 30 24]

2、最大最小值

x = np.random.randint(20, 50, size=10)
print(x)
# [38 20 27 46 38 34 29 42 30 20]
print("max:",np.max(x)) # max: 46
print("min:", np.min(x))
print("maxindex:", np.argmax(x)) #maxindex: 3
print("minidnex:", np.argmin(x)) #minidnex: 1

3、数值求和、求积

x = np.arange(0, 6)
print(x) #[0 1 2 3 4 5]
print(x.sum()) #15
print(np.sum(x)) #15

按行求和

x1 = x.reshape(2, 3)
print(x1)
# [[0 1 2]
#  [3 4 5]]
print(np.sum(x1, axis=1)) #[ 3 12]

按列求和

print(np.sum(x1, axis=0)) #[3 5 7]

全体求和

print(np.sum(x1)) #15

求积

x = np.arange(1, 6)
print(x) #[1 2 3 4 5]
print(x.prod())  #120
print(np.prod(x)) #120

4、中位数、均值、方差、标准差

x = np.random.normal(0, 1, size=10000)
import matplotlib.pyplot as plt
plt.hist(x, bins=50)
plt.show()

在这里插入图片描述
中位数

print(np.median(x))

均值

print(x.mean())
print(np.mean(x))

方差

print(x.var())
print(np.var(x))

标准差

print(np.std)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值