Python Numpy知识点

一、Numpy简介

    一个用python实现的科学计算,包括:1、一个强大的N维数组对象Array;2、比较成熟的(广播)函数库;3、用于整合C/C++和Fortran代码的工具包;4、实用的线性代数、傅里叶变换和随机数生成函数。numpy和稀疏矩阵运算包scipy配合使用更加方便。
    NumPy(Numeric Python)提供了许多高级的数值编程工具,如:矩阵数据类型、矢量处理,以及精密的运算库。专为进行严格的数字处理而产生。多为很多大型金融公司使用,以及核心的科学计算组织如:Lawrence Livermore,NASA用其处理一些本来使用C++,Fortran或Matlab等所做的任务。

                                                                                                                         ---《百度百科》

二、Numpy知识点

1.安装Numpy包,并且导入

pip install numpy
import numpy as np

2.创建数组

a = np.array([1, 2, 3, 4, 5])
b = np.arange(0, 6, 1)
c = np.random.random((3, 3))
d = np.random.randint(0, 9, size=(3, 3))
print("a:", a)
print("b:", b)
print("c:", c)
print("d:", d)

①np.array直观创建数组,输入是啥生成就是啥。

②np.arange创建数组,需要给定起始值、终止值的后一位数字、步长。

③np.random.random创建数组,需要给定数组的维度,其元素是0-1之间的随机数。

④np.random.randint创建一个N阶数组,需要给定元素属于的区间、数组的维度。元素是整数。

a: [1 2 3 4 5]
b: [0 1 2 3 4 5]
c: [[0.10739085 0.99541616 0.76174493]
 [0.30140398 0.87467374 0.30959958]
 [0.23803194 0.47848497 0.38842102]]
d: [[2 0 4]
 [7 0 7]
 [3 4 5]]

3.特殊函数

zeros = np.zeros((1, 4))
ones = np.ones((2, 2))
full = np.full((2, 3), 9)
eye = np.eye(3)

①np.zeros生成指定维数,元素全为0的数组

②np.ones生成指定维数,元素全为1的数组

③np.full需要指定数组的维度以及填充数组的数字

④np.eye生成N阶数组,除了对角线元素为1,其它元素为0

zero: [[0. 0. 0. 0.]]
ones: [[1. 1.]
 [1. 1.]]
full [[9 9 9]
 [9 9 9]]
eye: [[1. 0. 0.]
 [0. 1. 0.]
 [0. 0. 1.]]

注意:数组中的数据类型必须是一致的,包括整型以及浮点型。

扫描二维码关注公众号,回复: 15448524 查看本文章

4.数据类型

数据类型 描述 唯一标识符
bool 用一个字节存储的布尔类型(True或False) b
int8 一个字节大小,-128 至 127 i1
int16 整数,16 位整数(-32768 ~ 32767) i2
int32 整数,32 位整数(-2147483648 ~ 2147483647) i4
int64 整数,64 位整数(-9223372036854775808 ~ 9223372036854775807) i8
uint8 无符号整数,0 至 255 u1
uint16 无符号整数,0 至 65535 u2
uint32 无符号整数,0 至 2 ** 32 - 1 u4
uint64 无符号整数,0 至 2 ** 64 - 1 u8
float16 半精度浮点数:16位,正负号1位,指数5位,精度10位 f2
float32 单精度浮点数:32位,正负号1位,指数8位,精度23位 f4
float64 单精度浮点数:64位,正负号1位,指数11位,精度52位 f8
complex64 复数,分别用两个32位浮点数表示实部和虚部 c8
complex128 复数,分别用两个64位浮点数表示实部和虚部 c16
object_ python对象 U
string_ 字符串 S
unicode_ unicode类型 U

①创建数组指定数据类型

zeros = np.zeros((1, 4), dtype='int16')
ones = np.ones((2, 2), dtype='float32')
zero: [[0 0 0 0]]
ones: [[1. 1.]
 [1. 1.]]

②查询数据类型

full = np.full((2, 3), 9, dtype='int8')
eye = np.eye(3, dtype='float16')

print(full.dtype)
print(eye.dtype)
int8
float16

③修改数据类型

full = np.full((2, 3), 9, dtype='int8')
print(full.dtype)
full = full.astype('int16')
print(full.dtype)
int8
int16

注意:

  1.Numpy是基于C语言编写的,引用了C语言的数据类型。

  2.针对不同的数据赋予不同的数据类型,可以有效节省空间。

5.多维数组

(大白话来说,第一个出现的数字前面有多少个'[',那么这个数组就是几维的。)

①定义1维、2维、3维数组

arr1 = np.array([1,2,3])             # 一维数组
arr2 = np.array([[1,2,3],[4,5,6]])   # 二维数组
arr3 = np.array([                    # 三维数组
    [
        [1,2,3],
        [4,5,6]
    ],  
     [
        [7,8,9],
        [10,11,12]
        ]
])

②数组维度查询

print(arr1.shape)
print(arr2.shape)
print(arr3.shape)

③修改数组形状

a1 = np.array([            # 创建新数组a1
    [
        [1,2,3],
        [4,5,6]
    ],
    [
        [7,8,9],
        [10,11,12]
    ]
])
a2 = a1.reshape((2,6))     # 保持元素个数不变的情况下,修改形状为2*6
a3 = a2.flatten()          # 铺平为一维向量

 ④查看元素个数与所占内存

print(a1.size)               
print(a1.itemsize)
print(a1.itemsize * a1.size)

其中:

  1.a1.size代表数组元素个数

  2.a1.itemsize代表单个元素所占的内存,单位是字节

  3.两者相乘代表数组一共所占用的内存

6.数组索引和切片

①一维数组

a1 = np.arange(10)   # [0 1 2 3 4 5 6 7 8 9]   
print(a1[4])         # 索引操作
print(a1[4:6])       # 切片操作
print(a1[::2])       # 使用步长
print(a1[-1])        # 使用负数作为索引(从右往左数第一位数字)
[0 1 2 3 4 5 6 7 8 9]
4
[4 5]
[0 2 4 6 8]
9

②二维数组

arr2 = np.random.randint(0,10,size=(4,6))
print(arr2[0])            # 获取第0行数据
print(arr2[1:3])          # 获取第1,2行数据
print(arr2[[0, 2, 3]])      # 获取0,2,3行数据
print(arr2[2, 1])          # 获取第二行第一列数据
print(arr2[[1, 2], [4,5]])  # 获取多个数据 例:第一行第四列、第二行第五列数据
print(arr2[1:3, 4:6])      # 获取多个数据 例:第一、二行的第四、五列的数据
print(arr2[:, 1])          # 获取某一列数据 例:第一列的全部数据
print(arr2[:, [1,3]])      # 获取多列数据 例:第一、三列的全部数据

③布尔索引

a3 = np.arange(24).reshape((4,6))
print(a3[a3<10])              # 挑选出小于10的元素
print(a3[(a3 < 5) | (a3 > 10)])    # 挑选出小于5或者大于10的元素

说明:

  1.布尔索引是通过相同数据上的True还是False来进行提取的

  2.同时满足用&,满足其一即可用|

  3.有多个条件时,每个条件用圆括号括起来

7.数组元素值的替换:

①索引

a3 = np.random.randint(0,10,size=(3,5))
a3[1] = 0                      # 将第一行数据全部更换为0
a3[1] = np.array([1,2,3,4,5])  # 将a3数组第一行数据更换为[1,2,3,4,5]

②条件索引

a3[a3 < 3] = 1   # 数组中值小于3的元素全部替换为1

③函数(用where函数来实现替换值)

result = np.where(a3<5,0,1)

代码的作用是a3数组中小于5的值全部更换为0,其余的元素更换为1

8.数组的广播机制

  数组的广播原则:如果两个数组的后缘维度(即从末尾开始算起的维度)的轴长度相符或其中一方的长度为1,那么他们是广播兼容的。广播会在全是和(或)长度为1的维度上进行。

  ①数组与数字运算

a1 = np.random.randint(0,5,size=(3,5))
print(a1*2)                # 数组中的所有元素都乘2
print(a1.round(2))         # 数组中所有的元素只保留2位小数

  ②数组与数组运算

a1 = np.random.randint(0,5,size=(3,5))
a2 = np.random.randint(0,5,size=(3,5)) # a1+a2满足数组广播机制:形状一致
a3 = np.random.randint(0,5,size=(3,4)) # a1+a3不满足:形状不一致的数组不能相加减
a4 = np.random.randint(0,5,size=(3,1)) # a1+a4满足:俩数组行数相同,其中一个数组列数为1
a5 = np.random.randint(0,5,size=(1,5)) # a1+a5满足,俩数组列数相同,其中一个数组行数为1

总结:

  1.数组可以直接和数字进行运算

  2.两个shape想要的数组是可以进行运算的

  3.如果两个shape不同的数组想要进行运算,那要看看二者满不满足广播原则

9.数组形状的操作

  ①数组形状的改变

a1 = np.random.randint(0,10,size=(3,4))
a2 = a1.reshape((2,6))           # 有返回
a1.resize((4,3))                 # 无返回

reshape和resize的区别:

  reshape和resize都是用来修改数组形状的,但是结果不一样。reshape是将数组转换为指定的形状,然后返回转换后的结果。resize是将数组转换为指定的形状,会直接修改数组本身,并且不会返回任何值。

  ②flatten与ravel(都是将多维数组转换为一维数组,但是方式不一样)

a3 = np.random.randint(0,10,size=(3,4))
a4 = a3.flatten()          # 拷贝一份返回
a5 = a3.ravel()            # 返回这个视图的引用

 也就是说:

    修改a4的值不会对a3造成影响;但是修改a5的值会一并修改a3的值。

  ③数组的叠加

  vstack:代表在垂直方向叠加,想要叠加成功必须满足列数一致;

  hstack:代表在水平方向叠加,要想叠加成功必须满足行数一致;

  concatenate:可以手动指定axis参数具体在哪个方向叠加。

        1>axis = 0代表在水平方向叠加

        2>axis = 1代表在垂直方向叠加

        3>axis = None代表先进行叠加,再转化为1维数组

vstack1 = np.random.randint(0,10,size=(3,4))       # 垂直方向待叠加的数组
vstack2 = np.random.randint(0,10,size=(2,4))       # 垂直方向待叠加的数组
vstack3 = np.vstack([vstack1,vstack2])             # 垂直叠加方法一
vstack4 = np.concatenate([vstack1,vstack2],axis=0) # 垂直叠加方法二


h1 = np.random.randint(0,10,size=(3,4))            # 水平方向待叠加的数组
h2 = np.random.randint(0,10,size=(3,1))            # 水平方向待叠加的数组
h3 = np.hstack([h2,h1])                            # 水平叠加方法一
h4 = np.concatenate([h2,h1],axis=1)                # 水平叠加方法二
 
h5 = np.concatenate([h2,h1],axis=None)             # 先识别垂直或者水平叠加,后转换为一维数组
  

    ④数组的切割

  hsplit:代表在水平方向切割,按列进行切割。切割方式如下:

                    1.直接指定平均切割成多少列

                    2.指定切割的下标值

  vsplit:代表在垂直方向切割,按行进行切割。切割方式与hsplit相同。

hs1 = np.random.randint(0, 10, size=(3, 4))
np.hsplit(hs1, 2)                         # 水平方向平均分为2份,要求列数可被此整数整除
np.hsplit(hs1, (1, 2))                     # 水平方向分为1,1,2列(在1,2处切割)
[array([[9, 4],
       [4, 2],
       [4, 7]]), array([[4, 6],
       [9, 6],
       [7, 3]])]
[array([[9],
       [4],
       [4]]), array([[4],
       [2],
       [7]]), array([[4, 6],
       [9, 6],
       [7, 3]])]
vs1 = np.random.randint(0, 10, size=(4, 5)) 
np.vsplit(vs1, 4)                         # 垂直方向平均分为4份
np.vsplit(vs1, (1, 3))                     # 垂直方向分为1,2,1行
[array([[0, 3, 7, 4, 7]]), array([[0, 1, 2, 1, 1]]), array([[9, 8, 4, 7, 5]]), array([[9, 8, 2, 7, 1]])]

[array([[0, 3, 7, 4, 7]]), array([[0, 1, 2, 1, 1],
       [9, 8, 4, 7, 5]]), array([[9, 8, 2, 7, 1]])]

  ⑤矩阵转置

t1 = np.random.randint(0,10,size=(3,4))
t1.T                           # 数组t1转置
t2 = t1.transpose()            # 返回的是一个view,对返回值上进行修改会影响到原来的数组

10.View和拷贝

①如果只是简单的赋值,那么就不会进行拷贝

a = np.arange(12)
b = a
print(b is a)       # 返回为True,说明b和a是相同的

②浅拷贝

  有些情况,会进行变量的拷贝,但他们所指向的内存空间都是一样的,那么这种情况叫做浅拷贝,或者叫做View(视图)

c = a.view()
print(c is a) # 返回false,说明c和a栈区空间不同,但是所指向的内存空间是一样的
c[0] = 100    # 修改c的值,a也会受到影响

③深拷贝

  将之前数据完完整整的拷贝一份放到另外一块内存空间中,这样就是两个完全不同的值了。

d = a.copy()
print(d is a)   # 返回false,说明在不同栈区
d[1]=200        # 数组d被修改,而a原封不动,说明两者内存空间不一样。

总结:

在数组操作中分成三种拷贝:

  1.不拷贝:直接赋值,那么栈区没有拷贝,只是用同一个栈区定义了不同的名称。

  2.浅拷贝:只拷贝栈区,栈区指定的堆区并没有拷贝。 

  3.深拷贝:栈区和堆区都拷贝

未完待续~

猜你喜欢

转载自blog.csdn.net/m0_64007201/article/details/127656327
今日推荐