什么是numpy?
》一个在python中做科学计算的基础库,重在数值计算,也是大部分python科学计算库的基础库,多用于大型、多维数组上执行数值运算
一、数组(numpy)的创建和基本使用
》代码讲解
import numpy as np
import random
# numpy创建数组 都是该类型:<class 'numpy.ndarray'>
t1 = np.array([1, 2, 3]) # [1 2 3]
t2 = np.array(range(10)) # [0 1 2 3 4 5 6 7 8 9]
t3 = np.arange(10) # [0 1 2 3 4 5 6 7 8 9]
# dtype用于查看数组中的数据类型
print(t3.dtype) # int32
# 给数组指定数据类型(以下两种写法皆可)
t4 = np.array(range(1, 4), dtype=float) # [1. 2. 3.]
t41 = np.array(range(1, 4), dtype="float") # [1. 2. 3.]
# numpy中的bool类型
t5 = np.array([1, 1, 0, 0, 1], dtype=bool) # [ True True False False True]
# 调整数据类型
t6 = t5.astype("int8")
print(t6) # [1 1 0 0 1]
print(t6.dtype) # int8
# numpy中的小数
t7 = np.array([random.random() for i in range(4)])
print(t7) # [0.5571627 0.1623156 0.40395393 0.34839485]
print(t7.dtype) # float64
# numpy将小数保留为2位小数
t8 = np.round(t7, 2)
print(t8) # [0.98 0.98 0.82 0.83]
》numpy中常见的更多数据类型
二、数组(numpy)的形状
1、查看数组的形状:shape
》如第8行,(2, 3)即二维数组。第一个值表示行数,第二个值表示列数
》怎么区分几维数组,就看shape属性返回的值的个数。只有一个值时,那么就为一维数组;有两个值时,那么为二维数组…
2、 修改数组的形状:reshape()
》如第17行,(2, 3, 4)即三维数组。第一个值表示2块,第二值表示每块有3行,第三值表示每块有4列
》通常处理二维数组数据较多(或者多维数组转为二维数组使用的情况)
3、 其他:
》flatten() 表示:将数组展开并返回一个一维数组
三、数组(numpy)计算
1. 数组和数的计算
》可以进行 加减乘除的运算,这是numpy的“广播机制”造成的,加减乘除的值被广播到所有的元素上面
》如第36行,数组除0不会报错,只是报警告,依然有返回结果
》nan表示:不是一个数(not a number);inf表示:无穷大(infinite)
2. 数组和数组的计算
》相同数组间运算
》不同数组间运算(当数组之间的某一维度上相同【行维度/列维度】)
》不同数组间运算(当数组之间的某一维度上不相同【行维度/列维度】)【报错!!!】
四、轴(axis)的概念
》在numpy中可以理解为 方向。用0,1,2…数字表示,对于一个一维数组,只有一个0轴,对于二维数组(shape(2,2)
),有0轴和1轴,对于三维数组(shape(2,2,3)
),有0、1、2轴
》如:np.arange(0,10).reshape((2,5))
,reshape中2表示0轴长度,1轴长度为5,2x5一共10个数据
》具体显示如下图:
》axis= 0
对a的 横轴(行) 进行操作,在运算的过程中其运算的方向表现为纵向(列)运算
》axis= 1
对a的 纵轴(列) 进行操作,在运算的过程中其运算的方向表现为横向(行)运算
》案例如下:
a = [[0,1,3],[1,2,2]]
n = np.array(a)
print(n.sum(axis=0)) # 即对横轴(行)进行操作,运算方向为纵轴方向(列),对每一列进行求和
print(n.sum(axis=1)) # 即对纵轴(列)进行操作,运算方向为横轴方向(行),对每一行进行求和
print(n.max(axis=0))
print(n.max(axis=1))
'''
运行结果为:
[1 3 5]
[4 5]
[1 2 3]
[3 2]
'''
五、numpy读取数据
》简单了解即可,以csv文件格式为例。(后续读取文件用pandas,功能更强大)
介绍一下 csv:
CSV:Comma-Separated Value,逗号分隔值文件
显示:表格状态
源文件:换行和逗号分隔行列的格式化文本,每一行的数据表示一条记录
【由于csv便于展示、读取和写入,所以很多地方也是用csv的格式存储和传输中小型的数据】
》用该代码读取文件:np.loadtxt(frame,dtype=np.float,delimiter=None,skiprows=0,usecols=None,unpack=False)
参数 | 解释 |
---|---|
frame | 文件、字符串或产生器,可以是.gz或bz2压缩文件 |
dtype | 数据类型,可选,CSV的字符串以什么数据类型读入数组中,默认:np.float,也可简写:float |
delimiter | 分隔字符串,默认是任何空格,CSV中需要改为:逗号 |
skiprows | 跳过前x行,一般跳过第一行表头 |
usecols | 读取指定的列,索引,元组类型 |
unpack | 如果True,读入属性将分别写入不同数组变量,False读入数据只写入一个数组变量,默认False【一般该参数用于转置(下面案例会提及)】 |
》详细看如下代码:(该csv文件在此链接:us_video.csv)
import numpy as np
# 导入需要处理的csv文件
file_name = "./us_video.csv"
# numpy读取csv文件的一般写法(文件名,分隔符(逗号),数据类型)
t1 = np.loadtxt(file_name, delimiter=",", dtype=int)
print(t1)
'''
[[4394029 320053 5931 46245]
[7860119 185853 26679 0]
[5845909 576597 39774 170708]
...
[1338533 69687 678 5643]
[1056891 29943 878 4046]]
'''
# 在上面的读取文件方法添加参数:unpack,将数据进行转置【即每一列的数据转到每一行上】(如下代码结果,也就是将t1的返回值以对角线进行翻转)
t2 = np.loadtxt(file_name, delimiter=",", dtype=int, unpack=True)
print(t2)
'''
[[4394029 7860119 5845909 ... 1338533 1056891]
[320053 185853 576597 ... 69687 29943]
[5931 26679 39774 ... 678 878]
[46245 0 170708 ... 5643 4046]]
'''
1、关于numpy的转置
2、numpy索引和切片
》详细看如下代码:(该csv文件在此链接:us_video.csv)
import numpy as np
# 导入需要处理的csv文件
file_name = "./us_video.csv"
# numpy读取csv文件的一般写法(文件名,分隔符(逗号),数据类型)
t1 = np.loadtxt(file_name, delimiter=",", dtype=int)
# print(t1)
'''
[[4394029 320053 5931 46245]
[7860119 185853 26679 0]
[5845909 576597 39774 170708]
[2642103 24975 4542 12829]
[1168130 96666 568 6666]
[1311445 34507 544 3040]
[ 666169 8895 289 1071]
[1728614 74062 2180 15297]
[1338533 69687 678 5643]
[1056891 29943 878 4046]]
'''
# 》取行————
# 写法一:
# 取单行
print(t1[2]) # [5845909 576597 39774 170708]
# 取连续多行
print(t1[8:]) # 取索引为8及后面的多行数据
# 取不连续的多行
print(t1[[2, 7, 8]]) # 取2、7、8行
# 写法二:(以逗号为分节点"[,]"; ","左边为行, ","右边为列)
print(t1[2, :]) # 取单行
print(t1[8:, :]) # 取连续多行
print(t1[[2, 7, 8], :]) # 取不连续的多行
# 》取列————
#(以逗号为分节点"[,]"; ","左边为行, ","右边为列)
print(t1[:, 2:]) # 取连续多列
print(t1[:, [0, 2]]) # 取不连续多列
# 》取值————
#(以逗号为分节点"[,]"; ","左边为行, ","右边为列)
print(t1[2, 3]) # 取第三行,第四列的值(取行和列的值)
print(t1[2:5, 1:4]) # 取第三行到第五行,第二列到第四列的值(取多行和多列的值)【取的是行和列交叉点的位置】
# 取多个不相邻的点
print(t1[[0, 2, 2], [0, 1, 3]]) # 选取出来的点是:(0,0)、(2,1)、(2,3)
# 》切片————
# (加上 ":" 切片操作即可)
print(t1[:, 2::2]) # 在38行代码的基础上修改(加上 ":" 切片操作),最终取到第三列隔两列取值
print(t1[2:5, 1:4:2]) # 在44行代码的基础上修改(加上 ":" 切片操作),最终取到第三行到第五行的第二列和第四列中隔两列取值
3、numpy中数值的修改
》直接赋值即可
如:t[: , 2: 4] = 0
将数组中第三列到第四列的数值全部赋值为0
4、numpy中布尔索引
》需求:把数组中小于10的数字替换为3
5、numpy中三元运算符
》常见的python三元运算格式:a = 3 if 3>2 else 4
》需求:把数组中小于3的数字替换为100,把大于3的替换为300【用np.where()
方法】
6、numpy中的clip(裁剪)
》需求:把数组中小于10的数字替换为10,把大于18的替换为18
》上图的nan
即 “not a number”,它是如下操作进行赋值的:
六、numpy中的nan和inf
nan(NAN,Nan)
:not a number 表示不是一个数字inf(-inf,inf)
:infinityinf
表示正无穷、-inf
表示负无穷
》nan 和 inf 都是浮点类型(float)
》什么时候numpy会出现nan:
- 当读取本地的文件为float的时候,如果有缺失,就会出现nan
- 当做了一个不合适的计算的时候(如:无穷大减去无穷大、0除以0等)
》什么时候会出现inf:(包括:-inf、inf)
- 比如一个数字除以0,(python中直接会报错,numpy中是一个inf或者-inf)
nan的注意点:
- 两个
nan
是不相等的 - 用
count_nonzero()
方法计算nan的个数
。np.count_nonzero(t2!=t2)
。np.count_nonzero(np.isnan(t2))
【用np.isnan(t2)
来判断是否有nan
值】 nan
和任何值计算都为nan
》np.isnan(t2)
和t2!=t2
一样,返回的结果都是 布尔型 数组,其中值为nan的返回True,值不为nan的返回False
有关nan的问题:
问: 在一组数据中单纯的把nan替换为0,合适吗?会带来什么样的影响?
答: 比如,全部替换为0后,替换之前的平均值如果大于0,替换后的均值肯定会变小,所以一般的方式是把缺失的数值替换为 均值(中值) 或者是 直接删除有缺失值的一行
》所以下面介绍以下如何计算一组数据的中值或者是均值、还有如何删除有缺失数据的那一行/列(在pandas中会介绍)
numpy中常用统计函数
案例
》结合上面所讲的知识进行串联!!!
》案例:将第2行第3、4列的值为nan,计算每一列的均值,再把均值赋值给nan值的位置上
import numpy as np
t1 = np.arange(12).reshape(3, 4).astype("float") # 二维数组(3行4列),类型为浮点型
t1[1, 2:] = np.nan # 让第2行第3、4列的值为nan
print("未做改变的数组:")
print(t1)
print("="*20)
for i in range(t1.shape[1]): # t1.shape 获取到数组的形状为二维数组(3,4)。t1.shape[1] 获取到二维数组的列,即4
# 遍历每一列
temp_col = t1[:, i] # 获取当前一列
nan_num = np.nonzero(temp_col != temp_col) # 获取到当前一列的nan个数
if nan_num != 0: # 如果不为0,则表示当前这一列中有nan值
# 【temp_col != temp_col 可以获取到为nan的值,反之temp_col == temp_col 获取到不为nan的值】
temp_not_nan = temp_col[temp_col == temp_col] # 获取到当前一列不为nan值的数组
# temp_not_nan.mean():计算不为nan值的数组的均值
# np.isnan(temp_col)和temp_col != temp_col方法一样,获取到为nan的值
temp_col[np.isnan(temp_col)] = temp_not_nan.mean() # 将求到的均值赋值给原本的nan值的位置
print("做改变后的数组:")
print(t1)
'''
输出结果为:
注:❗
未做改变的数组: 》temp_col == temp_col 返回的结果如下:返回布尔型的数组(根据True和False可以判断出:True为非nan值,False为nan值)
[[ 0. 1. 2. 3.] [ True True True]
[ 4. 5. nan nan] [ True True True]
[ 8. 9. 10. 11.]] [ True False True]
==================== [ True False True]
做改变后的数组:
[[ 0. 1. 2. 3.] 》根据上面的布尔型数组,得出temp_not_nan 数组返回的结果如下:(获取到当前不为nan值的数组)
[ 4. 5. 6. 7.] [0. 4. 8.]
[ 8. 9. 10. 11.]] [1. 5. 9.]
[ 2. 10.]
[ 3. 11.]
'''
七、数组的拼接
》数组的拼接
》数组的行列交换
八、numpy的其他方法
- 获取最大值、最小值的位置
-》np.argmax(t, axis=)
-》np.argmin(t, axis=)
- 创建一个全0的数组:
np.zeros((3, 4))
# 创建一个3行4列全为0的数组 - 创建一个全1的数组:
np.ones((3, 4))
# 创建一个3行4列全为1的数组 - 创建一个对角线为1的正方形数组(方阵):
np.eye(3)
# 创建一个3行3列的数组,对角值都为1 - numpy生成随机数,如下图所示:
- numpy的注意点!!! copy 和 view
-a=b
完全不复制,a和b相互影响 【类似浅拷贝】
-a=b[:]
,视图 的操作,一种切片,会 创建新的对象a,但是a的数据完全由b保管,他们两个的数据变化是一致的 【类似浅拷贝】
-a=b.copy()
,复制,a和b互不影响 【类似深拷贝】
- 还有另一种写法:a=a[:]
,即直接在a中进行赋值,不用考虑上面的拷贝问题