numpy:一个在Python中做科学计算的基础库,重在数值计算,也是大部分Python科学计算库的基础库,多用于在大型、多维数组上执行数值运算
可以使用numpy
的array()
、array(range())
、arange()
方法创建数组,其中arange()
相当于array(range())
import numpy as np
t1 = np.array([1, 2, 3])
print('t1:', t1) # t1: [1 2 3]
print('type(t1):', type(t1)) # type(t1):
t2 = np.array(range(4))
print('t2:', t2) # t2: [0 1 2 3]
# arange()相当于array(range())
t3 = np.arange(4)
print('t3:', t3) # t3: [0 1 2 3]
t4 = np.arange(2, 10, 3)
print('t4:', t4) # t4: [2 5 8]
查看、设置、修改数组的数据类型
1> 使用数组对象的dtype
属性可以查看数组的数据类型
2> 创建数组时使用dtype
参数可以设置数组的数据类型
3> 使用数组对象的astype()
方法可以修改数组的数据类型,原数组不变,返回一个修改后的新数组
4> 使用np.round()
可以修改数组中浮点数的小数位数
import numpy as np
"""查看数组的数据类型"""
t1 = np.arange(3)
print(t1.dtype) # int32
"""设置数组的数据类型"""
# 以下三种方法设置的结果是相同的:float16,[1. 4. 7.]
t2 = np.arange(1, 10, 3, dtype='float16')
t3 = np.arange(1, 10, 3, dtype=np.float16)
t4 = np.arange(1, 10, 3, dtype='f2')
"""修改数组的数据类型"""
t5 = np.array([1, 0, 1, 0, 2], dtype='bool')
print(t5.dtype, t5) # bool [ True False True False True]
t6 = t5.astype(np.int8)
print(t6.dtype, t6) # int8 [1 0 1 0 1]
print(t5.dtype, t5) # bool [ True False True False True]
"""修改数组中浮点数的小数位数"""
t7 = np.array([random.random() for _ in range(3)])
print(t7.dtype, t7) # float64 [0.7459032 0.7121498 0.70406119]
t8 = np.round(t7, 2)
print(t8.dtype, t8) # float64 [0.75 0.71 0.7 ]
数组常见的数据类型
类型 | 类型代码 | 说明 |
---|---|---|
int8、uint8 | i1、u1 | 有符号和无符号的8位(1个字节)整型 |
int16、uint16 | i2、u2 | 有符号和无符号的16位(2个字节)整型 |
int32、uint32 | i4、u4 | 有符号和无符号的32位(4个字节)整型 |
int64、uint64 | i8、u8 | 有符号和无符号的64位(8个字节)整型 |
float16 | f2 | 半精度浮点数 |
float32 | f4或f | 标准的单精度浮点数,与C的float兼容 |
float64 | f8或d | 标准的双精度浮点数,与C的double和Python的float对象兼容 |
float128 | f16或g | 扩展精度浮点数 |
complex64、complex128、complex256 | c8、c16、c32 | 分别用两个32位、64位或128位浮点数表示的复数 |
bool | ? | 存储True和False值的布尔类型 |
import numpy as np
t1 = np.array([1,2,3]) # 创建一个1行3列的数组(一维数组)
t1.shape # 查看数组的形状 -> (3,)
t2 = np.array([[1,2,3],[4,5,6]]) # 创建一个2行3列的数组(二维数组)
t2.shape # 查看数组的形状 -> (2, 3)
t3 = np.array([[[1,2,3],[4,5,6]],[[7,8,9],[10,11,12]]]) # 创建一个三维数组
t3.shape # 查看数组的形状 -> (2, 2, 3)
t3.reshape((3,4)) # 修改数组的形状,将t3从三维数组变为二维数组,返回一个新数组,t3本身不变
t3.flatten() # 将数组展开为一维数组,返回一个新数组,t3本身不变
t4 = np.array(range(12)) # 创建一个一维数组
t4.reshape((2,3,2)) # 修改数组的形状,将t4从一维数组变为三维数组,返回一个新数组,t4本身不变
t3.reshape((12,)) # 修改为一维数组
t3.reshape((12,1)) # 修改为二维数组
t3.reshape((1,12)) # 修改为二维数组,和上面结果不同
数组和数的计算
因为numpy
的广播机制,在运算过程中,数组和数的计算会被广播到所有元素上面
import numpy as np
t1 = np.array([[1,2,3],[4,5,6]]) # 创建一个二维(2, 3)数组
t2 = t1-2 # 计算后会返回一个新的数组,原数组不变 -> [[-1 0 1] [ 2 3 4]]
注:数组和数的计算中,0
可以当做除数,0/0=nan
,正数/0=inf
,负数/0=-inf
,其中nan
意为not a number
(不是一个数字),inf
意为infinite
(无穷的)
数组和数组的计算
t1 = np.array([[1, 2, 3], [4, 5, 6]])
t2 = np.array([[100, 200, 300], [400, 500, 600]])
print(t1+t2) # [[101 202 303] [404 505 606]]
t1 = np.array([[1, 2, 3], [4, 5, 6]])
t3 = np.array([10, 20, 30])
print(t1+t3) # [[11 22 33] [14 25 36]]
t4 = np.array([[100], [200]])
print(t1+t4) # [[101 102 103] [204 205 206]]
t5 = np.array(range(6))
# t1+t5 # ValueError: operands could not be broadcast together with shapes (2,3) (6,)
t6 = np.array(range(9)).reshape((3, 3))
# t1+t6 # ValueError: operands could not be broadcast together with shapes (2,3) (3,3)
广播原则:如果两个数组的后缘维度(即从末尾开始算起的维度)的轴长度相符或其中一方的长度为1,则认为它们是广播兼容的。广播会在缺失和(或)长度为1的维度上进行
(2,3,5,3,6,2) (4,6,2) 不可以计算
(2,3,5,3,6,2) (3,6,2) 可以计算
(2,3,5,3,6,2) (3,6,2,1) 不可以计算
(2,3,5,3,6,2) (1,3,6,2) 可以计算
(2,3,5,3,6,2) (2,) 可以计算
(2,3,5,3,6,2) (1,2) 可以计算
(2,3,5,3,6,2) (2,1) 不可以计算
np.vstack((t1, t2))
:竖直拼接(vertically),参数是需要拼接的数组组成的元组,返回拼接后的数组
np.hstack((t1, t2))
:水平拼接(horizontally),参数是需要拼接的数组组成的元组,返回拼接后的数组
np.vsplit(t3, 2)
:竖直分割(vertically),是竖直拼接的逆向操作,参数是需要分割的数组和分割的份数,默认均等分割,返回分割后的数组组成的列表
np.hsplit(t4, 4)
:水平分割(horizontally),是水平拼接的逆向操作,参数和返回值同竖直分割相同
import numpy as np
t1 = np.arange(12).reshape((2, 6))
t2 = np.arange(12, 24).reshape((2, 6))
"""拼接"""
t3 = np.vstack((t1, t2))
t4 = np.hstack((t1, t2))
"""分割"""
l1 = np.vsplit(t3, 2)
l2 = np.hsplit(t4, 4)
行列交换的意思是指将行与行或者列与列的位置进行互换
import numpy as np
t = np.arange(12).reshape((3, 4))
t[[1, 2], :] = t[[2, 1], :] # 行交换
t[:, [0, 2]] = t[:, [2, 0]] # 列交换
轴的解释:在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轴长度(包含数据的条数)为2,1轴长度为5,2*5一共10个数据
语法:np.loadtxt(fname, dtype=np.float, delimiter=None, skiprows=0, usecols=None, unpack=False)
参数 | 解释 |
---|---|
frame |
文件、字符串或产生器,可以是.gz 或bz2 的压缩文件 |
dtype |
数据类型,可选,文件的内容以数据类型计入数组中,默认是np.float |
delimiter |
分隔字符串,默认是任何空格 |
skiprows |
跳过前x 行,一般用于跳过第一行表头 |
usecols |
读取指定的列,索引,元组类型 |
unpack |
默认为False ,表示读入数据只写入一个数组变量;为True ,表示读入属性将分别写入不同数组变量(可以理解为行列转换,默认的行列和文件中的相同) |
import numpy as np
file_path = './aaaa/bbbb.csv'
t1 = np.loadtxt(file_path, delimiter=',', dtype='int', unpack=True)
转置是一种变换,对于numpy中的数组来说,就是在对角线方向交换数据,目的也是为了更方便的去处理数据。在二维数组中转置的简单理解就是把行和列进行转换,行变为列,列变为行
转置的方法有三种:t.transpose()
、t.T
、t.swapaxes(1,0)
import numpy as np
t = np.arange(24).reshape((4,6))
# 以下三种方法转置的结果相同
t.transpose()
t.T
t.swapaxes(1,0) # 交换轴
numpy的切片和Python中列表的切片类似,不同的是需要在多个维度上进行操作
import numpy as np
file_path = './aaaa/bbbb.csv'
t1 = np.loadtxt(file_path, delimiter=',', dtype='int')
"""取行和列"""
# 取第3行第4列的值
a = t1[2, 3] # 170708,类型为
# 取第3行到第5行,第2列到第4列的值(取的是交叉点的数据)
b = t1[2:5, 1:4] # 类型为
# 取多个不相邻的点
# 取的结果是(0, 0), (2, 1), (2, 3)位置的值
c = t1[[0, 2, 2], [0, 1, 3]] # [4394029 576597 170708]
可以看到,在上面的代码中[]
中的,
前面表示行,,
后面表示列
数组中修改行列的值,只需要取到对应的行列然后赋予一个新的值即可
import numpy as np
t = np.arange(24).reshape((4, 6))
t[:, 2:4] = 100 # 取到对应的数值然后赋予一个新的值
import numpy as np
t = np.arange(24).reshape((4, 6))
print(t)
# t的结果如下:
# [[ 0 1 2 3 4 5]
# [ 6 7 8 9 10 11]
# [12 13 14 15 16 17]
# [18 19 20 21 22 23]]
t1 = t < 10
print(t1)
# t1的结果如下:
# [[ True True True True True True]
# [ True True True True False False]
# [False False False False False False]
# [False False False False False False]]
t[t < 10] = 0
print(t)
# 通过布尔索引筛选,修改数值之后的t如下:
# [[ 0 0 0 0 0 0]
# [ 0 0 0 0 10 11]
# [12 13 14 15 16 17]
# [18 19 20 21 22 23]]
import numpy as np
t = np.arange(24).reshape((4, 6))
print(t)
# t的结果如下:
# [[ 0 1 2 3 4 5]
# [ 6 7 8 9 10 11]
# [12 13 14 15 16 17]
# [18 19 20 21 22 23]]
# np.where()为numpy中的三元运算符,
# 这句代码的意思为:
# 数组t中的值,如果小于10,那么将其修改为0,否则修改为10
t1 = np.where(t < 10, 0, 10)
print(t1)
# t1的结果如下:
# [[ 0 0 0 0 0 0]
# [ 0 0 0 0 10 10]
# [10 10 10 10 10 10]
# [10 10 10 10 10 10]]
nan(NAN,Nan)
:not a number,表示不是一个数字,数据类型为float
什么时候会出现nan
1> 读取本地的文件为float
的时候,如果有缺失,就会出现nan
2> 做不合适计算的时候(比如无穷大减去无穷大)
3> 0/0
的结果为nan
nan的性质
1> 两个nan
是不相等的
2> 利用上述特性判断数组中nan
的数量
import numpy as np
t = np.array([1, 2, np.nan, 3, 4])
a = np.count_nonzero(t != t) # 得到nan的数量 -> 1
3> 判断一个数字是否是nan
,使用np.isnan()
方法,是nan
则返回True
,否则返回False
,同样也可以用来判断nan
的数量
import numpy as np
t = np.array([1, 2, np.nan, 3, 4])
b = np.count_nonzero(np.isnan(t)) # 得到nan的数量 -> 1
4> nan
和任何值的计算结果都为nan
import numpy as np
t = np.array([1, 2, np.nan, 3, 4])
c = sum(t) # 计算数组t的和 -> nan
实际问题中nan的处理方式
因为nan
和任何值的计算结果都为nan
,所以实际问题中遇到nan
会影响数据的处理,而如果单纯地把nan
替换为0
又会影响均值等数据的准确性,所以更好的方法是将nan
(缺失的值)替换为均值(中值)或者直接删除有nan
(有缺失值)的一行或一列
def fill_ndarray(t):
"""
给定一个数组,通过遍历数组中的每一列,将列中为nan的位置替换为当前列中不为nan的均值,返回替换后的数组,
return t
"""
for i in range(t.shape[1]): # 遍历每一列
temp_col = t[:, i] # 当前的一列
nan_num = np.count_nonzero(temp_col != temp_col) # 统计当前列中nan的数量
if nan_num: # 为True说明当前列中有nan
# 取出当前列中不为nan的值
temp_no_nan_col = temp_col[temp_col == temp_col]
# 选中当前列中为nan的位置,把值赋值为不为nan的均值
temp_col[np.isnan(temp_col)] = temp_no_nan_col.mean()
return t
inf(-inf,inf)
:infinity
,无穷的。inf
表示正无穷,-inf
表示负无穷,数据类型为float
一个数字除以0
的结果为inf
,正数/0=inf
,负数/0=-inf
求和:t.sum(axis=None)
均值:t.mean(axis=None)
,受离群点的影响较大
中值:np.median(t,axis=None)
最大值:t.max(axis=None)
最小值:t.min(axis=None)
极差:np.ptp(t,axis=None)
,即最大值和最小值之差
标准差:t.std(axis=None)
以上函数默认返回多维数组全部数值的统计结果,如果指定axis则返回当前轴上的结果
创建一个全为0的数组:np.zeros((3,4))
创建一个全为1的数组:np.ones((3,4))
创建一个对角线全为1的正方形数组(方阵):np.eye(3)
获取最大值、最小值的位置:np.argmax(t,axis=0)
、np.argmin(t,axis=1)
语法 | 说明 |
---|---|
np.random.rand(d0,d1,d2,...,dn) |
创建d0 到dn 维度的均匀分布的随机数数组,浮点数,范围为0-1 |
np.random.randn(d0,d1,d2,...,dn) |
创建d0 到dn 维度的标准正态分布的随机数,浮点数,平均数为0 ,标准差为1 |
np.random.randint(min,max,(shape)) |
随机生成[min,max) 之间的整数组成数组,形状是shape |
np.random.uniform(min,max,(shape)) |
随机生成[min,max) 之间的浮点数组成数组,形状是shape |
np.random.normal(loc,scale,(shape)) |
从指定正态分布中随机生成浮点数,分布中心为loc ,标准差为scale ,形状为shape |
np.random.seed(s) |
随机数种子,s 是给定的种子值。设定相同的种子值之后,后续每次生成的随机数都和第一次生成的相同 |
a = b
:完全不复制,a
和b
相互影响a = b[:]
:视图的操作,一种切片,会创建新的对象a
,但是a
的数据完全由b
保管,他们两个的数据变化是一致的a = b.copy()
:复制,a
和b
互不影响