numpy介绍

发布时间 2023-08-16 22:32:39作者: wancy

1.概述

  NumPy是一个Python库,用于数值计算和处理数组。它是其他数据分析和机器学习库的底层库,提供了高效的多维数组运算功能。NumPy完全使用标准C语言实现,以提高运行效率。它是一款开源免费的库。并于1995年由Numeric项目发展而来。在2001年,Numpy被集成到Scipy库中,并进一步扩展了多维数组和矩阵运算的功能。

  numpy的核心:多维数组+数值计算

  1.代码简洁减少Python代码中的循环。

  2.底层实现:厚内核(C)+薄接口(Python),保证性能。

2. numpy基础

  内存中的ndarray对象由两个部分组成,一部分是元数据,是实际的数组数据,它是一个同质数组,即所有元素的数据类型必须相同。另外一部分是元数据,元数据存储对目标数组的描述信息,如:ndimdimensions、dtype、data等。实际数据将与元数据分开存放,一方面提高了内存空间的使用效率,另一方面减少了对实际数据的访问频率,提高了性能。

3.列表转numpy数组

import  numpy as np

ary=np.array([1,2,3,4,5,6])#列表转数组,如果不指定dtype,则默认是int32
print(ary)#[1 2 3 4 5 6]元素与元素之间为空格
print(type(ary))#<class 'numpy.ndarray'>

  注意,numpy数组的元素与元素之间没有,而是空格,这一点与python的列表不同。

4. numpy数组的广播机制

import  numpy as np
#广播机制:数组与一个元素进行计算时,数组中的每一个元素分别进行计算
ary=np.array([1,2,3,4,5,6])#列表转数组
print(ary+3)#[4 5 6 7 8 9]
print(ary*2)#[ 1 4 9 16 25 36]
print(ary==3)#[False False  True False False False]
print(ary+ary)#[ 2  4  6  8 10 12]
print(ary * ary)#[ 1  4  9 16 25 36]

  注意,在python的列表中是没有广播的。

5. numpy常用函数

  常用函数包括array、arange、zeros、ones、zeros_like、ones_like、linspace、astype等。看下面的简单例子。

'''
ndarray数组的基本创建及特点
'''
import  numpy as np
a
=np.arange(0,5,1)#[0 1 2 3 4] #python中的range只能生成整数,不能生成小数,但是np.arange可以生成小数 b=np.arange(0.1,1.1,0.2) print(b)#[0.1 0.3 0.5 0.7 0.9] c=np.zeros(10,dtype='int32')#如果不指定数据类型,默认是小数 print(c)#[0 0 0 0 0 0 0 0 0 0] c=np.zeros(shape=(10,),dtype='int32') print(c) zeros=np.zeros(shape=(2,3),dtype="int8") print(zeros) ones=np.ones(shape=(2,3),dtype="int32") print(ones) #np.zeros_like() ary=np.arange(0,10).reshape(2,5) zeros_like=np.zeros_like(ary) print(zeros_like)#[[0 0 0 0 0][0 0 0 0 0]] ones_like=np.ones_like(ary) print(ones_like)#[[1 1 1 1 1] [1 1 1 1 1]] #生成值全为0.2的数组 r=np.zeros(shape=(10,))+0.2 print(r)#[0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2] #生成-3.14到3.14中的6个数 pai=np.arange(-3.14,3.14,6.18/5) print(pai) #np.linspace(start,stop,个数)#闭区间[] #生成-3.14到3.14中的5个数 pai=np.linspace(-3.14,3.14,5) print(pai)#[-3.14 -1.57 0. 1.57 3.14]

6. numpy数组对象的基本属性

  numpy数组对象常用的属性包括shape、dtype、size等。

import numpy as np
ary=np.arange(1,11)#[ 1  2  3  4  5  6  7  8  9 10]
print(ary.shape)#(10,)

#将一维数据变为二维数据
ary.shape=(2,5)
print(ary)

ary.shape=(1,2,5)
print(ary)

ary.shape=(2,1,5)
print(ary)

#dtype
ary=np.arange(1,9)
print(ary)
print(ary.dtype)#int32

#修改元素数据类型不能直接给dtype赋值
# ary.dtype='float32'#这里表示用float32解析
# print(ary)#[1.4e-45 2.8e-45 4.2e-45 5.6e-45 7.0e-45 8.4e-45 9.8e-45 1.1e-44]

#astype函数
bry=ary.astype('float64')#不会改边原始数据类型
print(ary)#不变[1 2 3 4 5 6 7 8]
print(bry)#[1. 2. 3. 4. 5. 6. 7. 8.]

#数组元素的个数
#np.array.size
ary=np.arange(1,9)
print(ary.size)#8
print(len(ary))#8,最表层的元素个数

ary.shape=(2,4)
print(ary.size)#8
print(len(ary))#2

7. 数组元素索引

#数组元素索引(下标)
#index
ary=np.arange(1,9)
ary.shape=(2,2,2)

print(ary[0])
print(ary[0][0])#[1 2]
print(ary[0][0][0])#1
#另外一种方式索引
print(ary[0,0])#[1 2]
print(ary[0,0,0])#1

  有两种方式,一种是arr[x][y],还有一种是arr[x,y]。

8. numpy内部基本数据类型

  内部基本数据类型包括int、float、str等数据类型。

  • int: int8、int16、int32、int64 、uint8(代表无符号)
  • float: float16、float32、float64
  • str字符串类型
  • int8 表示2**8个数字即 -128到127 有符号
  • uint8表示256个数字 无符号即只有正数 即0到255
  • complex64 complex128 复数型
import numpy as np
#bool_(bool也可以)
ary=np.ones(shape=(2,2),dtype='bool_')
print(ary)#[[ True  True] [ True  True]]
ary=np.ones(shape=(2,2),dtype='bool')
print(ary)#[[ True  True][ True  True]]
#bool可以简写?,后面会再提到
ary=np.ones(shape=(2,2),dtype='?')
print(ary)
ary=np.array([1,2,3],dtype='int32')
print(ary)
#str_类型,每个字符32位,4个字节
#str缩写大写U,表示unicdoe
#为了方便定位,numpy规定每个元素占据的字节数相等
ary=np.array(['a','bc','def'])
print(ary.dtype)#<U3,小于表示小端存储,U3表示unicode,3个字符
print(ary.nbytes)#36字节数 -->3*4(一个字符4个字节)*3(元素个数)   输出占据多少个字节
print(ary.itemsize)#12,最长的字符串字节数

#datetime64日期类型
#'2023-08-16 15:23:22' str
#需要转换为datetime64数据类型,再转换为int64

data=np.array(['2021','2022-01-01','2023-01-01 08:08:08'])
print(data)
print(data.dtype)#<U19
dates=data.astype('datetime64')#会自动补充,精度最高的一个元素为准
print(dates)
dates=data.astype('datetime64[D]')#YMDhms 年月日时分秒   datetime64[D]表示精确到天
print(dates)
res=dates.astype('int64')#时间日期类型转整数int64
print(res)#[18628 18993 19358]#距离1970年1月1日的天数
dates=data.astype('datetime64[s]')#YMDhms 年月日时分秒   datetime64[D]表示精确到天
print(dates)
res=dates.astype('int64')#时间日期类型转整数int64
print(res)#[1609459200 1640995200 1672560488]距离1970年1月1日:00:00:00的秒数

9. 自定义复合类型

  对于较新版本的numpy,同一列的数据类型需要保持相同,列同质,同一行内的可以不同,也就是行可以不同质,但会出现警告。

import numpy as np

data=[('zs',[90,80,85],15),
      ('zf',[80,90,70],20),
      ('wx',[70,90,80],20)
      ]
ary=np.array(data)
print(ary)
"""
[['zs' list([90, 80, 85]) 15]
 ['zf' list([80, 90, 70]) 20]
 ['wx' list([70, 90, 80]) 20]]
"""

ary=np.array(data,dtype='U2,3int32,int32')#后面会提到
print(ary)
'''
[('zs', [90, 80, 85], 15) ('zf', [80, 90, 70], 20)
 ('wx', [70, 90, 80], 20)]
'''
total_age=0.0
for i in data:
    total_age+=i[2]
print(total_age/3)#求平均年龄

10. 访问列数据

  下面这个例子,f表示列,f2表示第3列。

#访问列数据
print(ary['f2'])#第3列数据,[15 20 20]
print(ary['f1'])
print(type(ary['f1']))#<class 'numpy.ndarray'>

11. 类型字符码

  这部分内容了解即可,数据类型int8可以用i1代替(8表示一个字节,8位,所以为i1),float64就是f8.

 12. numpy数组变维

  12.1 视图变维

  视图变维不会修改原始数据的维度,但是两者的数据是共享的(更改一个数据,另一个会变化)下面的例子中ravel()函数用于将多维数组展平为一维数组。reshape(参数)可以将数组维度重新设置,但是数据是共享的。

#视图变维:不会修改原始数据的维度,数据共享
ary=np.arange(1,10)
print(ary)#[1 2 3 4 5 6 7 8 9]
bry=ary.reshape(3,3)
print(ary)#[1 2 3 4 5 6 7 8 9]#ary的维度并没有改变
print(bry)#
#修改ary中的元素
ary[0]=666
print(ary)#[666   2   3   4   5   6   7   8   9]
print(bry)#[[666   2   3][  4   5   6][  7   8   9]]
ary=np.arange(1,10).reshape(3,3)
print(ary)

  12.2 复制变维

  复制变维 不会修改原始数据的维度,数据独立。常用的有flatten()函数。
import numpy as np
# 复制变维 不会修改原始数据的维度,数据独立
ary=np.arange(1,9).reshape(2,2,2)
bry=ary.flatten()
print(ary)#[[[1 2][3 4]] [[5 6][7 8]]]
print(bry)#[1 2 3 4 5 6 7 8]
bry[0]=-1
print(bry)#[-1  2  3  4  5  6  7  8]
print(ary)#没有-出现1,其数据与bry数据是互不影响的

  12.3 就地变维

  就地变维:就地改变原数组,不返回新数组

import numpy as np
ary=np.arange(1,19)#1~18
ary.resize(2,3,3)
print(ary.shape)#(2, 3, 3)

13. numpy数组切片

  直接看下面的例子:

import numpy as np

a=np.arange(1,10)
print(a[:3])#[1 2 3]
print(a[-4:-7:-1])
'''
数组的切片
注意:切片不会降维,索引会降维(一个索引降一个维)
'''
ary=np.arange(1,19).reshape(2,9)
print(ary)
#三维数组[行的操作,列的操作]
#第0行的前两列print(ary[:1,:2])#[[1 2]]
print(ary[0,:2])#[1 2]

ary=np.arange(1,51).reshape(5,10)
print(ary)
#拿到所有行,不要最后一列(二维)
print("拿到所有行,不要最后一列(二维)")
print(ary[:, :-1])
#拿到所有行,只要最后一列(一维)
print("拿到所有行,只要最后一列(一维)")
print(ary[:,-1])

14. numpy数组掩码操作

  14.1布尔掩码

import numpy as np

ary=np.array([1,2,3,4,5,6,7,8,9])
mask=[True,False,True,True,False,True,False,True,True]#mask既可以是数组也可以是列表
print(ary[mask])#[1 3 4 6 8 9]
#求1,100以内3的倍数
ary=np.arange(1,101)
mask=[False,False,True]*33+[False]
print(ary[mask])
mask=ary%3==0
print(ary[mask])
#求1,100以内能够同时被3和7整取的数字
ary=np.arange(1,101)
# mask=ary%3==0 and ary%7==0#会报错,numpy不支持and操作,因为其是C语言写的
mask=(ary%3==0) & (ary%7==0)
print(mask)
print(ary[mask])#[21 42 63 84]

  布尔掩码的元素个数要与被操作的numpy数组元素个数相等,布尔值为True的对应的位置的元素会被保留下来。

  14.2索引掩码

  不解释了,关于用法直接看例子。

import numpy as np
#索引掩码
#索引掩码个数不需要一定与原数组元素个数相等
car=np.array(['BMW','Benz','Audi','BYD','Tesla'])
mask=[3,4,1,0,2]#['BYD' 'Tesla' 'Benz' 'BMW' 'Audi']
print(car[mask])
mask=[3,4]#
print(car[mask])#['BYD' 'Tesla']
mask=[3,4,3,4,3,3]#可以重复
print(car[mask])#['BYD' 'Tesla' 'BYD' 'Tesla' 'BYD' 'BYD']
索引掩码个数不需要一定与原数组元素个数相等。
15. 多维数组的组合与拆分
  先放着,后面补上。

 

 

总结:关于reshape函数,如果想要设置m行,列数由数据总数/m确定,可以设置为-1.如reshape(m,-1)。注意,关于数组切片,切片不会导致降维,而索引会导致降维。

 

参考资料:

https://blog.csdn.net/qq_53763141/article/details/128391160

http://www.taodudu.cc/news/show-4218173.html?action=onClick

https://zhuanlan.zhihu.com/p/478249595