Numpy基础笔记

Basic Numpy

ndarray对象基础

什么是ndarray对象?即是N-dimentional array,也就是n维数组对象。

指定ndarray类型的对象——dtype(data type,就是n维数组对象内的基本元素类型)

numpy数组的基本知识

数组的基本属性

  1. shape属性,即是数组的形状,用元组来描述(储存着几行几列的信息)
  2. axis属性,即是数组的轴,有0、1、2……轴(在参数列表中的axis代表着以哪个轴作为基准)
  3. ndim属性,即是数组的维数,用元组来表示(其实就是反映数组有几个轴)
  4. size属性,返回数组的长度(就是看数组里面一共有多少基本元素,不要与len()函数返回值混淆,len与ndim返回值一致)
  5. dtype属性,即是数组元素的类型(也可以在外面直接创造复杂dtype类型,并把它与一个变量绑定,可以节省代码量)
  6. itemsize属性,即是数组中每个元素的长度(以字节形式表示)

数据类型(主要在结构化数组中应用)

全部数据类型

Python Data Analysis P34,不过一般很少使用

结构化数组中的数据类型
bytes b1
int i1, i2, i4, i8
usigned ints u1, u2, u4, u8
floats f2, f4, f8
complex c8, c16
fixed length strings a

可以通过type函数来查看元素类型或查看ndarray的dtype属性


创建数组(包含特殊数组创建)

  1. arr = np.array([1, 2, 3]) 
    //array接收序列参数,通常用list, tuple(且他们地位等价,即互相嵌套可以换位)
    
  2.  np.arange(1, 100, 2) 
       //arange在给定范围内生成一个一维数组,为闭开区间,为比较常用的方法。
       //接收一个参数时默认从0开始,数字型参数-初始,结束,步长(步长可以为小数,与range不同,这十分特殊!!!!!)
       // 记住reshape函数!!!即可接收元组也可直接接受元组内的参数,通常使用
       c = np.arange(0, 16).reshape((4, 4)) 
       //reshape方法可以返回一个按参数指定形状的多维数组
       np.arange(0, 16).resize((4, 4)) 
       //resize方法与reshape方法的不同之处在于resize直接修改原对象,但是resize并不常用,我们希望对象更安全
       //但是reshape产生的新视图,其实是一个引用,即使两者形状不一样,但是他们指向内存的同一块区域,如果要更改其中之一,请使用copy函数来避免这种事情发生
    
  3. arr = np.linspace(0, 10, 5) 
    //linspace函数接收:起始,结束,份数。它与arange相对应,只不过第三个参数从步长变为了份数
    //其余像与shape, reshape方法的配合与arange一直(本质是对对象应用,只不过它们通常成对出现)
    // 其实linspace与arange是一样的,只不过使用的方式略有区别而已
    // linspace中的重要参数,restep(导致linspace返回一个元组,前半部分是生成的array,后部分是步长),linspace与arange的不同之处在于
    linspace默认包括右端而arange并不是,可以通过将endpoint设置为False,就可不取右端点
    
  4.  //快速创建特殊数组
     // 注意!zeros、ones、random只能接收元组类参数!注意与reshape、shape区别!
       // 零数组
       np.zeros((3, 3))
       array([[0., 0., 0.],
              [0., 0., 0.],
              [0., 0., 0.]])
       //zeros_like函数!跟ones_like一模一样
       
       //一数组
       np.ones((3, 3))
       array([[1., 1., 1.],
              [1., 1., 1.],
              [1., 1., 1.]])
       arr = np.array([1, 2, 3])
       // one_like函数!可以根据已有数组的形状创建一数组
       np.ones_like(arr)
       
       //随机数组
       np.random.random((3, 3))
       array([[0.23159009, 0.63306642, 0.63343724],
              [0.2765953 , 0.57742195, 0.3329211 ],
              [0.02730095, 0.86618645, 0.98329664]])
        
       // 创建一个空数组(随机分配的垃圾值)
       np.empty((2, 3))
       np.empty_like(arr)
       
       // 最一般的特殊数组创建函数!full函数
       np.full(((2, 3), 7.1))
       // 创建一个2x3的7.1充满的数组
       np.full_like(arr, 7.1)
       //请注意,full_like函数在填充时会根据arr内类型进行类型转换,比如arr的数据类型原来为int型,会将7.1变为7
        
       //创建diagnal(一般是主对角线)
       np.eye(5)
    [[1. 0. 0. 0. 0.]
     [0. 1. 0. 0. 0.]
     [0. 0. 1. 0. 0.]
     [0. 0. 0. 1. 0.]
     [0. 0. 0. 0. 1.]]
    
      eye的k参数,正数代表向右平移,负数代表向左平移(是指主对角线漂移)
      // 通过已有数组创建元素类型不同的数组
      arr = arr.astype(np.float)
    
  5. //创建结构化数组示例
    // 我可能想复杂了,其实往往不需要在后面写生dtype,除非有特殊需求
    
    structured = np.array([(1, 'First', 0.5, 1+2j), (2, 'Second', 1.3, 2-2j), (3, 'Third', 0.8, 1+3j)], 
                          dtype=[('id', 'i2'), ('position', 'a6'), ('value', 'f4'), ('complexs', 'c8')])
    //这样就可以通过像字典一样的形式来操作结构化数组
    array([(1, b'First', 0.5, 1.+2.j), (2, b'Second', 1.3, 2.-2.j),
           (3, b'Third', 0.8, 1.+3.j)],
          dtype=[('id', '<i2'), ('position', 'S6'), ('value', '<f4'), ('complexs', '<c8')])
    
    // 另一种方法来制定各字段名称
    structured = np.array([(1, 'First', 0.5, 1+2j), (2, 'Second', 1.3, 2-2j), (3, 'Third', 0.8, 1+3j)], 
                          dtype=['i2', 'a6', 'f4', 'c8'])
    structured.dtype.names = ['id', 'position', 'value', 'complexs'] 
    //改变dtype属性的names字段,这是给列取名字!!!
    //这样就可以像字典一样使用了,
    
    //结构化数组调用示例
    structured['id']
    

数组的基本操作

运算的前提——广播与广播机制(umm……不太熟)

numpy可以实现元素级操作,同时numpy实现了对不同形状对象的运算,这种机制称为广播

广播机制:将两种不同形状的数组对象进行元素级运算的预处理机制(也就是升维),分为两个阶段。

[1]. 判断两个数组的各个维度是否兼容,如果兼容直接进行[2]。如果不兼容,再判断其中一个数组是否为一维,如果为一维也进行[2],否则不能进行.

[2]. 用已有的元素生成其他的元素

算数基本操作

算数运算符

+, -, *, /, %, **, //等所有算数运算符都是元素级运算符,结果返回新数组

注意:python中的*指的是元素级乘法,采用dot方法计算矩阵积

特殊的运算符:+=,-=(自增、自减最常用)等某等运算符可以直接更改对象


通用函数与运算(Universal function)

通用函数是指元素级操作函数,可以抽象为f(arr)

其中较常用的为dot(矩阵积),等。让人感动的是numpy重复实现了math库中绝大多数函数,以静态方法方式调用。

arr.T //数组转置
arr.flatten() //将数组将为1维,返回新的副本(意味着直接返回全新的数组对象,可以直接修改,注意这是与reshape不同的地方)
np.flat() //将数组将为1维,返回一个1维迭代器,可以用for循环遍历
arr.ravel() //将数组将为1维,返回视图(内存的位置是不变的!!!)
arr.astype(np.float) // 返回一个新数组,将原数组的数据经过float()处理
arr.swapaxes(ax1, ax2) // 将两个维度互换(换轴)
arr.transpose() // 不带参数时,效果相当于转置
arr.transpose(2, 1, 0) // 相当于将arr的三个轴转换到新位置
arr.tolist() //将ndarray转换为列表,如果使用哦那个list()函数转换,其实是相当于向量函数作用在ndarray上,是向量操作,打不傲tolist()的的效果
arr.tostring() // 将ndarray转换为字符串

// arr形状转换等其他实现参照创建数组章节
聚合函数(Group function)

聚合函数是指对一组值(往往是一个数组)进行操作,返回单一值。

其中常用的有:sum, min, max, mean, std(标准差)

索引与切片(花式索引、布尔索引)—— 需要更多的练习

索引的操作与标准库中的list相同,一起回忆一下:

操作相同但是返回值类型有区别:list的切片得到副本,而数组的切片得到视图

副本可以理解为原对象变化不对副本产生影响(当然有深浅copy之分,这里不赘述了),视图就像是SQL数据库中的视图,原对象变化会导致视图对象发生变化,倘若数组想要得到副本可以使用实例方法copy来得到

//一维数组索引示例 (在python中切片与索引(花式索引除外)返回的是副本,但在numpy中只返回视图!!!需要用copy与deep copy来创建副本)
a = np.arange(10)
a[2] = 2 
a[-1] = 9 //反向索引也很常见,相当于从第一个元素反着查

//数组切片示例(结果很显然,不写了)
a[:]
a[1:2] //闭开区间
a[1:]
a[:8]
a[1:9:2] //带步长的切片
a[::-1] // 逆序地去除所有数据

//二维数组切片示例(多维数组以此类推)
A = np.array([range(10), range(10, 20)])
A[1, 2] // 选出第一行、第三列元素
A[1] //相当于选取第二行,当然还有更标准的写法,见下一个
A[1,:] //选取第2行,这相当于是省略了1轴的操作,这个逗号甚至可以省掉
A[:,1] //选取第2列 切记!零轴空操作,就是指前面的那个冒号,是不能被省略的!
// 注意!!!A[1]这种索引式返回结果是降维后的结果!!!而切片式返回的数组与原数组位数相同
// 分别在0轴和1轴上切分,输出为两个轴切出的交集
A[0:2, 0:2] //选取一个子矩阵
// 索引与切片相结合,因为有索引所以降了一个维度哦!
A[1, :2]

// 花式索引!!!
// 还是索引产生的副本!!!这与其他的取法不同!!!
A[[1, 9]:2] //列表(序列均可)可选取我们要拿出来的单列,是花式索引!!!(花式索引甚至可以重复放并且支持负数) 
// 花式索引的另一种情况,将有高维数数组作为索引传入一维数组,会得到与高维数组相同形状的切片!!!
arr = np.arange(9)
b = np.arange(4).reshape(2, 2)
arr[b]
// 花式索引应用在二维数组(不熟)
arr = np.arange(15).reshape(4, 4)

// 布尔索引,也就是布尔数组作为索引,只取出值为True对应的值(不熟)

// 不同种索引相互配合

数组迭代

最初级的方法是使用foreach循环

更pythonic的方法是使用apply_along_axis()函数——直接对行、列整体进行操作

np.apply_along_axis(function, axis, arr)
//下面是对行求平均值的示例
np.apply_along_axis(np.mean, axis=1, arr=A)
//非常值得注意的地方!axis是along which axis的含义!尤其是之后的split都是这样!
//被我们操作的函数可以是自己定义的

数组筛选与bool数组

A = np.arange(-8, 8).reshape((4, 4))

//array([[-8, -7, -6, -5],
//       [-4, -3, -2, -1],
//       [ 0,  1,  2,  3],
//       [ 4,  5,  6,  7]])

A[A > 0] //筛选出数组中符合要求的元素,以一位数组返回

A > 0 //相当于一个元素级操作,返回bool数组

数组的形状变换

包括前面提到过的reshape, shape。

ravel方法可以得到二维数组对应的一维数组(返回新数组)

transpose方法可以实现转置以及换轴(返回新数组)swapaxes也可以实现换轴

数组切分

数组的切分靠split族函数来实现:vsplit,hsplit,split

其实split完全可以代替vsplit与hsplit

//vertival split
[B, C] = np.vsplit(A, 2) //将A切为两部分,默认沿着列
[B, C] = np.hsplit(A, 2) //将A切为两部分,默认沿着行

//更为复杂但更灵活的split函数
[A1, A2, A3] = np.split(A, [1, 3], axis=1) //沿着1轴(就是沿着columns切)将A抽取[1, 3]后分成三部分

数组拷贝

在numpy中唯一为ndarray创建副本的方法是使用copy方法

浅拷贝就是指直接的赋值 a = b

这与python不同,python的copy函数是浅拷贝,deepcopy函数才是深拷贝

数组数据文件的读写

numpy提供 save, load函数来保存与读取二进制文件,getfromtxt从文本文件中读取

data = np.random.random((3, 3))
np.save('sava_data', data) //将data存在save_data.npy文件中,npy是默认保存拓展名
dataget = np.load('save_data.npy') //读取数据

//读取文本文件数据示例
data = getfromtxt('data.csv', delimiter=',', names=True) //delimiter是分隔符,由于为CSV文件,分隔符自然为逗号
                                                         //names代表数据中是否含有标题
    													 //缺失的数据会被补成nan

事实上这些读取的工作常常由pandas来操作

posted @   IamQisir  阅读(79)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端
点击右上角即可分享
微信分享提示