numpy

Posted rowry

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了numpy相关的知识,希望对你有一定的参考价值。

1. numpy(numerical python)是科学计算基础库,提供大量科学计算相关功能,比如数据统计,随机数生成等.
2. 其提供最核心类型为多维数组(ndarray),支持大量的维度数组与矩阵运算,numpy支持向量处理ndarray对象,提高程序运算速度.
3. numpy底层由C实现,执行效率很高.
4. numpy中最最最核心的就是数组对象 => ndarray

安装

使用pip安装numpy

pip install numpy

# code01_arange测试安装环境.py
import numpy as np

# np.arange()可以类比 range(), 前者生成一个ndarray对象,后者生成range()对象

a = np.arange(10)  # 创建一个数组
print(a)

# code02_列表向量运算.py

# numpy最经典就是向量处理ndarray
# 一个简答的例子就是对一个数组每个元素进行开方计算

import random
import math
import numpy as np

a = [random.random() * 100 for i in range(10)]

# 1. 普通列表处理
b = [math.sqrt(x) for x in a]
print(b)
# 2. ndarray向量处理
c = np.sqrt(np.array(a))
print(c)

数组的创建

np.array创建ndarray对象

技术图片

# code03_array创建数组.py

import numpy as np

# 使用array创建一维数组
a = np.array([1, 2, 3, 4])  # 传入列表,元组都行
print([1, 2, 3, 4])  # [1, 2, 3, 4] 列表之间是有逗号分隔的
print(type(a))  # <class ‘numpy.ndarray‘>
print(a)  # [1 2 3 4]   是没有逗号的
print("数组的维度", a.shape)

# 使用array创建二维数组
b = np.array([(1, 2, 3), (4, 5, 6), ])
print(b)
print("数组的维度", b.shape)

# 使用array创建三维,四维.....


# array()中dtype的使用 => 指定数组的类型
# 这里使用的是python内置的数据类型, 其实numpy还有非常多额外的数据类型
c = np.array([3, 4, 5], dtype=float)
d = np.array([3, 4, 5], dtype=str)
print(c)
print(d)

# array函数中ndim的使用 => 秩(维度的数量)
e = np.array([3, 4, 5], dtype=float, ndmin=3)
print(e)
print("数组的维度", e.shape)

np.arange创建ndarray对象
技术图片

# code04_arange创建数组.py

import numpy as np

# np.arange(start,end,step,dtype) <=> range(start,end,step)

# 生成一个0-5的数组
a = np.arange(0, 6, dtype=int)
print(a)
b = np.arange(10, 20, 2, dtype=float)
print(b)

随机数创建ndarray对象

1. np.random.random(size=None) 该方法返回[0.0,1.0)范围的随机数
2. np.random.randint(low, high=None, size=None, dtype=int)
    (1) 如果只给low传值,那么就是默认 [0,low)
3. numpy.random.randn(d0,d1,…,dn) randn()返回一个或一组样本,具有标准正态分布(期望为0,方差为1)
    (1) dn表是每个维度
    (2) 返回值为指定为维度的ndarray
4. np.random.normal()  指定期望和方差的正态分布
# code05_随机数创建数组_random.py

import numpy as np

# np.random.random(size) 返回一个[0.0,1.0)
# 创建一维随机数组
a = np.random.random(size=5)
print(type(a))
print(a)

# 创建二维随机数组
b = np.random.random(size=(3, 4))  # 3行4列
print(b)

# 创建三维,四维随机数组...

# code06_随机数创建数组_randint.py

import numpy as np

# 随机整数
#  np.random.randint(low, high=None, size=None, dtype=int)  [low,high)
# 生成0-5的随机整数 一维
a = np.random.randint(0, 5 + 1, size=10)
print(a)
# 生成5-10的随机整数 二维
b = np.random.randint(5, 10 + 1, size=(4, 3))
print(b)
print("dtype的默认值", b.dtype)

# code07_随机数创建数组_randn.py

import numpy as np


# np.random.randn(d0,d1,d2....) 返回一个或一组样本,具有标准正态分布
# 创建一个一维的标准正态分布数组
a = np.random.randn(5)
print(a)

# 创建一个二维的标准正态分布数组
b = np.random.randn(3,5)
print(b)
# 创建一个三维,四维...

# code08_随机数创建数组_normol.py

import numpy as np

# np.random.normal(loc=0.0, scale=1.0, size=None)
a = np.random.normal(size=5)  # 默认期望loc=0.0 方差scale=1.0
print(a)

# 指定期望和方差
b = np.random.normal(loc=2, scale=3, size=(3, 4))
print(b)

ndarray对象

常用的 (1) ndim (2) shape (3) size (3) itemsize (4) dtype
技术图片

# code09_ndarray对象的属性.py

import numpy as np

# 使用np.random() 创建随机数的一维二维数组都很方便
# 创建一维数组
a = np.array(range(1, 5))
print(a)

# 创建二维数组 (使用随机数创建)
b = np.random.randint(4, 10, size=(2, 3))
print(b)

# 创建三维数组 (标准正态分布)
c = np.random.randn(2, 3, 4)
print(c)

# ndim属性 => 数组的维度的数目
print("ndim:",a.ndim,b.ndim,c.ndim)
# shape属性 => 数组的shape
print("shape:",a.shape,b.shape,c.shape)
# dtype属性
print("dtype:",a.dtype,b.dtype,c.dtype)
# size属性 => 元素的总个数
print("size:",a.size,b.size,c.size)
# itemsize属性 => 数组中每个元素的字节大小
print("itemsize:",a.itemsize,b.itemsize,c.itemsize)

其他方式创建

ndarray数组除了可以使用底层ndarray构造器来创建外,也可以通过一下计中方式来创建.

1. np.zeros(shape, dtype = float, order = ‘C‘) 创建指定大小的数组,数组元素以0来填充
2. np.ones(shape,dtype=None,order=‘C‘) 创建指定形状的数组,数组元素以1来填充
3. np.empty(shape, dtype = float, order = ‘C‘) 创建一个未初始化的数组,里面的元素的值是之前内存的值
4. 参数说明: 
    (1) shape: 数组形状
    (2) dtype: 数据类型,可选
    (3) order: 有"C"和"F"两个选项,分别代表  行优先和列优先, 在计算机内存中存储元素的顺序
5. np.linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None) 用于创建一个一维数组,数组是一个等差数列构成
    (1) start: 序列的起始值
    (2) stop: 序列的终止值,如果endpoint为True,该值包含于数列中
    (3) num: 要生成的等步长样本数量,默认为50
    (4) endpoint: 该值为True,数列中包含stop值,默认为True
    (5) retstep: 如果为True,生成的数组中会显示间距
    (6) dtype: ndarray的数据类型
6. np.logspace(start, stop, num=50, endpoint=True, base=10.0, dtype=None) 用于创建一个等比数列,一维数组
    (1) base: 对数log的底数

# code10_其他方式创建数组.py

import numpy as np

# 1. np.zeros(shape, dtype=float, order=‘C‘)
# shape : int or tuple of ints
a = np.zeros(5)
print(a)
a = np.zeros((5,), dtype=int)  # 指定数据类型
print(a)
a = np.zeros((3, 4))  # 创建二维数组
print(a)

# 2. np.ones(shape, dtype=float, order=‘C‘)
b = np.ones(5)
print(b)
b = np.ones((5,), dtype=int)  # 指定数据类型
print(b)
b = np.ones((3, 4))  # 创建二维数组
print(b)
"""
ones
Return an array of ones with shape and type of input.
empty
Return a new uninitialized array.
zeros
Return a new array setting values to zero.
full
Return a new array of given shape filled with value.
"""
# 3. np.empty()
# 4. np.full(shape,fill_value, dtype=float, order=‘C‘)
c = np.full((3, 4), 3)
print(c)

# 5. np.linspace()   <=> np.arange() 其实功能一致,就是创建等差数数组
# np.linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None, axis=0)
d = np.linspace(1, 10, 10)
print(d)

# 6. np.logspace(start, stop, num=50, endpoint=True, base=10.0, dtype=None,axis=0)
e = np.logspace(0, 9, 10, base=2)  # 公比选择2
print(e)

切片和索引

一维数组的索引与切片

numpy一维数组的索引和切片基本与python的索引与切片一致

1. ndarray对象的内容可以通过索引或切片来访问和修改, 与Python中list的切片操作一样.
2. ndarray数组可以基于0~n的下标进行索引,并设置start,stop以及step参数进行,从原数组切割除一个新数组.
# code11_一维数组的索引和切片.py

import numpy as np

x = np.arange(10)
y = x[2:7:2]
z = x[2:]
print(y)
print(z)

# 切片中的"-step"
print(x[::-1])
print(x[9:5:-1])  # 负索引的起点是可以反着的

# 测试切片后是不是同一个对象
print("x和x[2:7:2]是不是同一个对象", x is y)  # False => 但是确实修改了会一起修改 => 元素存储的是索引而已

# 索引范围
print("索引0处元素", x[0])
print("索引5处元素", x[5])
print("访问最后一个元素", x[-1])
print("访问倒数第三个元素", x[-3])

二维数组的索引与切片

numpy的多维数组索引和切片与python多维数组的索引切片有些不同了

1. 多维数组获得单个元素(二维数组为例子)
    (1) Python L[x][y]
    (2) numpy L[x,y]
2. 在第一点的基础上,可以实现行和列的分别切片
    (1) 所有列索引1元素  L[:,1]
    (2) 所有行索引2元素  L[2,:]
3. 花式(数组)索引
    (1) 主要就是序列(列表,元组) 作为一个索引  L[(x1,x2,...),(y1,y2,....)]
    (2) 如果只有一个数组索引的话,那么就是行索引  L[[0,2]]  # 选中行索引0和2 两整行
    (3) 如果有两个数组索引的话,前者为行索引,后者为列索引,二者一一对应  L[(1,3),(1,2)]  # 同时选中(1,1) (3,2)的值
4. 布尔索引
    (1) 布尔型索引指的是将一个布尔数组作为数组索引,返回的数据是布尔数组中True对应位置的值.    
    (2) 布尔型索引获取值的时候,使用与C一致的布尔运算值 ==,!=,>,<,....
# code12_二维数组的索引与切片.py

import numpy as np

a = np.linspace(1, 12, 12 - 1 + 1, dtype=int)
print(a)

# 重新修改数组的形状
# (1) 通过属性shape修改 => 原数组对象
# (2) 通过np.reshape(a, newshape, order=‘C‘)修改 => 新的数组对象
a.shape = (4, 3)
b = np.reshape(a, (4, 3))
print(a)
print(b)
print("a和b是不是同一个对象:", a is b)

print(a[2])  # 获取第三行
print(a[1][2])  # 获取第二行 第三列

# 二维数组的切片
# 语法: [行切片/索引,列切片/索引]
print(b[:, :])  # 获取所有行所有列
print(b[:, 1])  # 获取所有行第2列
print(b[:, :2])  # 获取所有行第1,2列
print(b[::2, :])  # 获取奇数行所有列
print(b[2, 1])  # 获取第三行第2列

# 花式索引 => 数组作为索引值
# [(x1,x2,...)[,(y1,y2,...)]]
print(a[1, 2], a[2, 0])  # 这是获取两个不同位置的值(普通写法)
print(a[(1, 2), (2, 0)])  # 两个不同位置的值(花式索引)

# 布尔索引 => 布尔数组作为数组索引,返回的数据是布尔数组中True对应位置的值
student_name = np.array(["Tom", "Lily", "Jack", "Rose"])  # 存储学生姓名的数组
student_score = np.array([[79, 88, 80], [89, 90, 92], [83, 78, 85], [78, 76, 80]])  # 存储学生成绩的数组
# 对student_name和字符串"Jack"通过一个运算符产生一个布尔类型的数组
print(student_name == "Jack")  # [False False  True False]
# 将布尔数组作为索引,返回是True对应的选择
print(student_score[student_name == "Jack", :])

numpy数组的复制

numpy的切片是浅拷贝,修改新数组会跟着影响原数组
np.copy() 进行的深拷贝

# code13_数组的复制.py

import numpy as np

# 创建一个二维的数组
a = np.arange(1, 13).reshape((3, 4))
print(a)
# 对a数组进行切片,获得第1,2行,第1,2列
sub_a = a[0:2, 0:2]  # 这里相当于只是一个浅拷贝
print(sub_a)
print("a和sub_a是不是一个对象", a is sub_a)
# 对sub_a中第一行第一列的值进行修改
sub_a[0][0] = 100
print(sub_a)
print(a)

# 可以使用numpy中的copy方法实现深拷贝
sub_aa = np.copy(a[-1,-1])
print(sub_aa)
sub_aa = -240
print(sub_aa)
print(a)

改变数组的维度

1. 处理数组的一项重要工作就是改变数组的维度,包含提高数组的维度和降低数组的维度,还包括数组的转置.
2. numpy提供大量API可以很轻松地完成这些数组的操作.例如:
    (1) 通过np.reshape() 将一维数组变成二维,三维或者多维数组
    (2) 通过ravel()或者flatten()将多维数组变成一维数组
    (3) 通过设置shape属性(元组类型),或者resize()也可以改变数组的维度
# code14_修改数组的维度.py

import numpy as np

# 创建一维数组
a = np.arange(24)
print(a)
print("数组a的维度", a.shape)
print("-" * 30)

# 使用np.reshape(a, newshape, order=‘C‘)将一维数组变成三维数组
# newshape: Union[int, Iterable, tuple[int]
b = a.reshape((2, 3, 4))
print(b)
print("数组b的维度", b.shape)
print("-" * 30)

# 将多维数组转为一维数组
# (1) np.reshape(-1) => 直接多维变一维
c = np.reshape(b, -1)  # np.reshape(a,-1) a.reshape(-1) 类方法 <=> 实例方法
print(c)
print("数组c的维度", c.shape)
# (2)使用np.ravel()将三维的b变成一维数组
d = np.ravel(a)
print(d)
print("数组d的维度", d.shape)
# (3) 使用np.flatten() 函数,效果于ravel()一致
e = a.flatten()
print(e)
print("数组e的维度", e.shape)

数组的拼接

技术图片

# code15_数组的拼接.py

import numpy as np

a = np.arange(1, 7).reshape((2, 3))
b = np.arange(11, 17).reshape((2, 3))
print(a)
print(b)
# 使用hstack(tup: Iterable)进行水平拼接
r = np.hstack((a, b))  # 把要拼接的列表存入一个列表中
print(r)

# 使用vstack(tup) 进行垂直拼接
r = np.vstack((a, b))
print(r)

# 使用concatenate的使用
# axis=0(默认情况) 按第一维拼接 => 相当于vstack
r = np.concatenate((a, b))
print(r)

# axis=1 => 按照第二维度进行拼接
r = np.concatenate((a,b),axis=1)
print(r)


数组的分隔

np.split()分隔

1. numpy.split()函数沿特定的轴将数组分割成子数组,格式如下:
    numppy.split(ary,indices_or_sections,axis)
2. 参数说明
    (1) ary: 被分割的数组
    (2) indices_or_sections: 如果是一个整数,就用该数平均切分,如果是一个数组,为沿轴切分的位置(传入数组相当于隔板)
    (3) axis:沿着那个维度进行切向,默认为0,横向切向. 为1时,纵向切分

# code16_数组的分隔.py

import numpy as np

# 创建一维数组
a = np.arange(1, 13)
# 调用np.split(ary, indices_or_sections, axis=0)进行分隔
# r = np.split(a,5) # 如果不能被整分就会抛出异常
# (1) 传递整数平均分隔
r = np.split(a, 4)  # [array([1, 2, 3]), array([4, 5, 6]), array([7, 8, 9]), array([10, 11, 12])]
print(r)
# (2) 传递数组 => 按数组进行分隔
r = np.split(a, (4, 6))  # 4,6是每个分隔部分的起点,这里分为三份 索引 [0,3] [4,5] [6:]
print(r)

# 二维数组进行分隔 => 需要指定axis
a = np.arange(1, 17).reshape((4, 4))
# 序列解包 只有r的话r就是一个序列, 现在r,w  想到于序列解包
r, w = np.split(a, 2, axis=0)  # 这是按axis把数组分为了两部分
print(r)
print(w)

r = np.split(a, [1, ], axis=1)  # 按axis=1把数组按1分开
print(r)

# 依照如此还有三个函数
# hsplit() => split(axis=0)
# vsplit() => split(axis=1)
# dsplit() => split(axis=2)

数组的转置

数组转置有两种方法
(1) 属性T
(2) np.transpose()

# code17_数组的转置.py

import numpy as np

# 创建二维数组
a = np.arange(1, 25).reshape(8, 3)
print(a)
# np.transpose(a, axes=None)进行数组转置 a[i][j] => a[j][i]
b = np.transpose(a)
print(b)

# 通过属性T进行转置(也是产生新的数组) => 对于简单的二维数组的转置(行列调换)
c = a.T
print("a和c是不是一个对象", a is c)
print(c)

# 多维数组进行转置
a.shape = (2, 3, 4)
print(a, a.shape)

# axes => 传入一个转置的维度,否则默认就是axis=0 和 axis=2 进行交换
b = a.transpose()
print(b, b.shape)  # (4, 3, 2) 默认transpose就是第一维和最后一维进行交换

c = a.transpose((1, 2, 0))  # (1,2,0) 是传入自己预想的装置后的维度
print(c, c.shape)

数组运算

(1)矢量化运算 (2) 广播机制

1. numpy数组不需要循环遍历,即可对每个元素执行批量的算术运算操作,这个过程叫做矢量化(向量)运算.
2. 如果两个数组的大小(ndarray.shape)不同,则它们进行算术运算时会出现广播机制.

技术图片

# code02_列表向量运算_数组广播.py

# numpy最经典就是向量处理ndarray
# 一个简答的例子就是对一个数组每个元素进行开方计算

import random
import math
import numpy as np

a = [random.random() * 100 for i in range(10)]

# 1. 普通列表处理
b = [math.sqrt(x) for x in a]
print(b)
# 2. ndarray向量处理
c = np.sqrt(np.array(a))
print(c)

# 数组广播

arr1 = np.array(range(4)).reshape((4, 1))
print(arr1, arr1.shape)  # (4, 1)
arr2 = np.array([1, 2, 3])
print(arr2, arr2.shape)  # (3,)

arr3 = arr1 + arr2
print(arr3, arr3.shape)  # (4, 3)

算术函数

1. 如果参与运算的两个对象都是ndarray,并且形状相同,那么会对批次之间进行(+ - * / %)运算.    
    (1) add()  => +
    (2) subtract() => -
    (3) multiply() => *
    (4) divide() => /
    (5) mod() => %
# code18_算术函数.py

import numpy as np

a = np.arange(9).reshape((3, 3))
b = np.array([10, 10, 10])
# 加法
print(np.add(a, b))
print(a + b)
print("-" * 30)

# 减法
print(np.subtract(a, b))
print(a - b)
print("-" * 30)

# 乘法
print(np.multiply(a, b))
print(a * b)
print("-" * 30)

# 除法
print(np.divide(a, b))
print(a / b)
print("-" * 30)

# 模运算
print(np.mod(a, b))
print(a % b)
print("-" * 30)



# out参数的使用 => 把运算结果输出到指定的数组
y = np.empty(a.shape)
np.multiply(a, 10, out=y)  # 把a中每个元素都乘10,结果存储在y中
print(y)


数学函数

1. numpy提供了标准的三角函数: (1)sin() (2) cos() (3) tan()
2. np.around(a,decimals) 返回指定数组的四舍五入值
    (1) 参数 decimals: 舍入的小数位数,默认值为0,如果为负,整数将四舍五入到小数点左侧的位置
3. np.floor() 返回数字的下舍整数
4. np.ceil() 返回数字的上入整数

# code19_数学函数.py


# (1) sin() cos() tan()
# (2) around() floor() ceil()

import numpy as np
from numpy import pi

a = np.array((0, pi / 6, pi / 4, pi / 3, pi / 2, pi))
print(np.sin(a))  # np.sin()
print(np.cos(a))  # np.cos()
print(np.tan(a))  # np.tan()
print("-" * 30)

print(np.around(np.sin(a)))  # np.around() 四舍五入
print(np.floor(np.sin(a)))  # np.floor() 向下取整
print(np.ceil(np.sin(a)))  # np.ceil() 向上取整

聚合函数

numpy中提供了大量的统计函数
技术图片

# code20_统计(聚合)函数.py

import numpy as np

a = np.arange(1, 13).reshape(3, 4)
# 1. np.power(ndarray,指数) 幂运算
b = np.power(a, 2)  # 运算的函数都有out参数,可以指定输出
print(b)

# 2. np.median(a, axis=None, out=None, overwrite_input=False, keepdims=False) 统计中位数
# 一维数组的中位数
# 中位数的计算: 排序后,中间的数 =>奇数不做处理,偶数中间两个数求平均值
b = a.reshape(-1)
print("数组b", b)
print("数组b的中位数", np.median(b))
# 二维数组的中位数 => 要指定axis
print("数组a", a)
print("数组a,axis=0(垂直方向)的中位数", np.median(a, axis=0))
print("数组a,axis=1(水平方向)的中位数", np.median(a, axis=1))

print("-" * 30)

# 3. np.mean(a,axis=None,out=None) 求平均值
# 一维数组求平均值
print("数组b", b)
print("数组b的平均值",np.mean(b))
# 二维数组求平均值 => 要指定axis
print("数组a", a)
print("数组a,axis=0(垂直方向)的平均数", np.mean(a, axis=0))
print("数组a,axis=1(水平方向)的平均数", np.mean(a, axis=1))

print("-" * 30)

# 4. np.sum() np.min() np.max()
# 一样区分一维数组和二维数组

# 5. np.argmax() np.argmin() 最值的下标

以上是关于numpy的主要内容,如果未能解决你的问题,请参考以下文章

'numpy.ndarray':对象不可调用错误

乐哥学AI_Python:Numpy索引,切片,常用函数

对数据进行去均值并转换为 numpy 数组

Jax 矢量化:vmap 和/或 numpy.vectorize?

微信小程序代码片段

VSCode自定义代码片段——CSS选择器