数据分析--numpy
一、简介
numpy(Numerical Python),是python语言一个扩展库,用于维度数组与矩阵运算,对数组运算也提供了大量的数学函数库
官网:http://www.numpy.org/
安装:pip install numpy
numpy.ndarray:Numpy的一个N维数组对象ndarray,是一系列同类型数据,且以0下标为开始作为元素的索引的集合。
ndarray数组的形状:ndarray数组的shape属性,返回一个元组,(12,):表示一维数组
(3,4):表示二维数组,元组里面多少个数就是几维数组
ndarray数组的轴(axis):轴可以理解成方向,使用0,1,2...数字表示, 对于一维数组只有一个0轴,对于二维数组有0轴和1轴, 对于三维数组有0,1,2轴...;有了轴概念后,计算会更加方便,比如计算平均值就必须指定那个方向上的平均值;
通过形状判断轴:
二维数组的轴:
三维数组的轴
修改数组的形状:reshape(self, shape, order='C')方法;参数:shape:表示数组的形状,一个元组;返回值:返回一个修改后的数组;注:数组里面的元素个数要和修改后形状元素个数一致
展开数组:flatten()方法:把多维数组转换成一维数组
修改数据类型:astype()方法;(例:t2 = t1.astype("int8"))
二、ndarray数组对象基础
1、ndarray数组的创建
(1)创建新数组
numpy.array(object, dtype=None, copy=True, order=None, subok=False, ndmin=0)
参数:object--可以是一个列表、元组,或嵌套元组列表。或一个可以迭代的对象;dtype--指定数组元素的数据类型
numpy.empty(shape, dtype=None, order='C'):创建一个空数组,注:此时数组元素为随机值,因为他们没有初始化
numpy.zeros(shape, dtype=None, order='C'):创建指定大小的数组,数组元素以0来填充
numpy.ones():与zeros()类似,创建指定大小的数组,数组元素以1来填充
numpy.eye(N):创建一个对角线为1,其余为0,数据类型为float的N行N列矩阵
(2)从已有数组创建新数组
numpy.asarray(a, dtype=None, order=None):参数a--可以是列表,元组,或者列表元组互相嵌套等
numpy.frombuffer(buffer, dtype=None, count=-1, offset=0):用于实现动态数组,接收buffer参数,以流的形式读入转化成ndarray对象;注:bufffer是字符串的时候,python3默认str为Unicode类型,所以要转换成bytestring在原str上加上b。参数buffer:可以是任意对象,会以流的形式读入
(3)从数值范围创建数组
numpy.arange([start,] stop[, step,], dtype=None):与range()方法类似
numpy.linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None,axis=0):创建一个一维数组,数组是一个等差数列构成。其实就是首项为start,公差=(stop-start)/num的等差数列
numpy.logspace(start, stop, num=50, endpoint=True, base=10.0, dtype=None, axis=0):创建一个等比数列,首项为base**start, 公比=(base**stop/base**start)的(num-1)分之一次方
2、numpy数据类型
numpy支持的数据类型比 python内置类型要多,基本可以和C语言数据类型对应上,int8:字节-128~127;int16:字节-32768~32767;uint8;字节0~255;float16:1个符号位,8个指数位,10个位数位...等。
数据类型对象numpy.dtype(object, align,copy):
参数:object -要转换的数据类型对象;align -如果为true,填充字段使其类似C的结构体
;copy -复制dtype对象,如果为false,则是对内置数据类型对象的引用创建结构化数据:
numpy.dtype([("字段名", 数据类型),("字段名", 数据类型)...])
例:dt = numpy.dtype([("age", numpy.int8)])将数据类型应用于ndarray数组:
dt = numpy.dtype([("age", numpy.int8)])
a = numpy.array([(10,), (20, ), (30,)], dtype=dt)
#利用字段名提取数据
print(a["age"])例:创建结构化数据
dt = np.dtype([("age", "int8"), ("height", "float")]) nda = np.array([(22, 150), (15, 180)], dtype=dt) print(nda) print(nda["age"]) print(nda[0]["age"]) #输出结果-------------------------------------------- #[(22, 150.) (15, 180.)] #[22 15] #22
3、ndarray数组的一些属性
ndarray.shape:数组的形状,对于二维数组即矩阵表示n行m列
ndarray.size:数组元素的总个数,对于二维数组即矩阵二维数组n*m个
ndarray.dtype:数组里面元素数据类型
ndarray.ndim:秩,即轴的数量,或维度的数量
4、数组的计算
nan与inf:数组里面元素计算0/0结果就是nan,不为0的数/0结果就是inf
与数字进行计算(如:t1 +2):会把数组里面每个元素都加2,把数组和数字进行加减乘除运算,也类似,会把里面每个元素都进行加减乘除一遍。
数组与数组进行计算(如:t1 + t2):t1与t2形状相同时,会把对应位置元素进行相加,加减乘除也类似,会把对应位置元组进行加减乘除;t1与t2形状不同时,t2为行元组且与t1每一行元素数量相同,会把t1的每一行与t2相加,t2为列元组且与t1每一列元素数量相同,会把t1的每一列与t2相加,加减乘除也类似,会把对应位置元组进行加减乘除;【即:x行y列的数组:可以和x行y列,1行y列,x行1列进行计算】
numpy数组的广播机制:如果两个数组的后缘维度(从末尾开始算起的维度)的轴长度相符或其中一方长度为1,则认为他们是广播兼容的。广播会在缺失或长度为1的维度上进行。如:shape为(3,3,3)数组不能和(3,2)数组进行计算,shape为(3,3,2)数组能和(3,2)数组进行计算
5、修改浮点数小数位数
numpy.round(数组,保留小数位数)函数:对浮点数进行四舍五入,例:【t2 = numpy.round(t1, 2)】
6、numpy读取数据
从csv文件(以逗号分隔值的文件)里面读取数据:numpy.loadtxt(fname, dtype=float, delimiter=None,skiprows=0, usecols=None, unpack=False)方法
作用:读取文件数据,并把数据生成ndarray对象
返回值: 一个二维ndarray对象,文件每一行数据为ndarray对象的一行
三、ndarray对象基本操作
1、ndarray的索引和切片:选择其中某一行、某一列或者某些分散数据;行列索引从0开始
取行列通用方法:nda[取行, 取列]
取行、取列:可以是切片用来取连续数据,也可以是一个行列索引的列表用来取不连续数据
,切片单独只有":" 表示每行或每列数据都要取某一行:t1 = nda[2]
取第三行数据【通用写法:nda[2, :]】
取连续多行:t1 = nda[2:]
取三行及以后数据【通用写法:nda[2:, :]】
取不连续多行:t1 = nda[[1,3]]
取2、4行数据【通用写法:nda[[1, 3], :]】
取一列:t1 = nda[:, 1]
取第二列
取连续多列:t1 = nda[:, 2:]
取第三列及以后的列
取不连续多列:t1 = nda[:, [1, 3]]
取第2、4列
取某一个:t1 = nda[2, 3]
取3行、4列的值:返回一个numpy里面对应的数据类型
取多个相邻的点:t1 = nda[2:4, 2:5]
取3、4行,3、4、5例交点位置的值:返回一个ndarray对象类型
取多个不相邻的点:t1 = nda[[1, 3], [2, 5]]
取(2行,3列),(4行, 6列)交点位置的值
布尔索引
t1[t1 < 10]:选择t1里面小于10的元素
2、ndarray的修改
利用索引或切片选中某些值,然后进行赋值即修改
nda[1:,2] = 88:把第二列2行及以后的值修改为88
nda[nda<10] = 66:把数组里面小于10的元素修改为66
numpy中三元运算符:numpy.where(condition, x=None, y=None)方法
参数:condition--条件;x--满足条件赋值成x的值;y--不满足条件赋值成y的值
返回值:修改后的ndarray;注:不改变原数组
例:np.where(t1<10, 88, 66);返回一个把t1里面小于10的修改成88,大于等于10的修改成66的ndarray数组
import numpy as np t1 = np.arange(24).reshape((4, 6)) t2 = np.where(t1<10, 88, 66) print(t1) print("分-割-线".center(50, "-")) print(t2) #输出结果 """ [[ 0 1 2 3 4 5] [ 6 7 8 9 10 11] [12 13 14 15 16 17] [18 19 20 21 22 23]] ----------------------分-割-线----------------------- [[88 88 88 88 88 88] [88 88 88 88 66 66] [66 66 66 66 66 66] [66 66 66 66 66 66]] """
例:t2 = np.where(t1<10, 88, t1);返回一个把t1里面小于10的修改成88,大于等于10的不变ndarray的数组
ndarray对象的裁剪:clip( a_min, a_max)方法
作用:对数组进行裁剪
参数:小于a_min的替换成a_min;大于a_max的替换成a_max;注:nan不会被替换
返回值:裁剪后的数组,不会修改原数组
3、拼接与交换
(1)拼接
竖直拼接:numpy.vstack((t1, t2))
水平拼接:numpy.hstack((t1, t2))t1 = np.arange(12).reshape((3, 4)) t2 = t1*2 print(np.vstack((t1, t2))) print("分-割-线".center(30, "-")) print(np.hstack((t1, t2))) #运行结果 """ [[ 0 1 2 3] [ 4 5 6 7] [ 8 9 10 11] [ 0 2 4 6] [ 8 10 12 14] [16 18 20 22]] ------------分-割-线------------- [[ 0 1 2 3 0 2 4 6] [ 4 5 6 7 8 10 12 14] [ 8 9 10 11 16 18 20 22]] """
了解:还有水平竖直分割方法
(2)交换(原理:就是赋值)
行交换:t[[1, 2], :] = t[[2, 1], :]
列交换:t[:, [0, 2]] = t[:, [2, 0]]
四、ndarray对象的常用统计函数
1、nan和inf的统计
nan和inf详细介绍:
nan:not a number表示不是一个数字;什么时候会出现nan?【(1)0/0的时候(2)读取本地文件为float的时候,如果有缺失,就会出现nan(3)无穷大-无穷大】nan的特点:与任何数做计算结果都为nan,使用numpy统计函数nan与任何数字做统计结果还是nan
inf:inf表示正无穷,-inf表示负无穷;什么时候出现inf?【非0的数字除以0的时候】
指定一个nan或inf:把值赋值成numpy.nan、或numpy.inf
注:他们的dtype类型,都是float浮点类型
注:两个nan是不相等的,np.nan != np.nan -->True
统计nan的个数:
(1)nda != nda
只有nan的位置是True, 其余为False
例:
t1 = np.arange(24).reshape((4, 6)).astype("float") t1[[1, 3], [2, 4]] = np.nan print(t1) print("分-割-线".center(50, "-")) print(t1 != t1) #运行结果 """ [[ 0. 1. 2. 3. 4. 5.] [ 6. 7. nan 9. 10. 11.] [12. 13. 14. 15. 16. 17.] [18. 19. 20. 21. nan 23.]] ----------------------分-割-线----------------------- [[False False False False False False] [False False True False False False] [False False False False False False] [False False False False True False]] """
(2)numpy.isnan(ndarray)方法
只有nan的位置是True, 其余为False
例
t1 = np.arange(24).reshape((4, 6)).astype("float") t1[[1, 3], [2, 4]] = np.nan print(t1) print("分-割-线".center(50, "-")) print(np.isnan(t1)) #运行结果 """ [[ 0. 1. 2. 3. 4. 5.] [ 6. 7. nan 9. 10. 11.] [12. 13. 14. 15. 16. 17.] [18. 19. 20. 21. nan 23.]] ----------------------分-割-线----------------------- [[False False False False False False] [False False True False False False] [False False False False False False] [False False False False True False]] """
修改值nan位置的元素:
t1[np.isnan(t1)] = 888:把为nan值的元素修改成888
或
t1[t1 != t1] = 888:把为nan值的元素修改成888
修改的原理:就是把True对应位置的数据修改888(即赋的值)
统计的时候对nan的处理:
(1)如全部设置成0,但是全部替换成0后,统计的值会偏大(数为负)或偏小(数为正)
(2)一般是把缺失的值换成均值(把不为nan的值拿出来取平均值)或中值(中位数)或者直接删除有缺失值的一行
2、求和、平均值、标准差等统计函数
(1)求和
sum(axis=None)
t1 = np.arange(24).reshape((4, 6)) print(t1) print("分-割-线".center(30, "-")) print(t1.sum()) #所有元素的和 print("分-割-线".center(30, "-")) print(t1.sum(axis=0)) #每行元素的和 print("分-割-线".center(30, "-")) print(t1.sum(axis=1)) #每列元素的和 #输出结果 """ [[ 0 1 2 3 4 5] [ 6 7 8 9 10 11] [12 13 14 15 16 17] [18 19 20 21 22 23]] ------------分-割-线------------- 276 ------------分-割-线------------- [36 40 44 48 52 56] ------------分-割-线------------- [ 15 51 87 123] """
(2)均值
mean( axis=None)
使用方式与sum( axis=None)类似
(3)最大值
max(axis=None)
使用方式与sum( axis=None)类似
(4)最小值
min(axis=None)
使用方式与sum( axis=None)类似
(5)中值
numpy.median(a, axis=None)
t1 = np.arange(24).reshape((4, 6)) print(t1) print("分-割-线".center(30, "-")) print(np.median(t1)) #所有元素中的中值 print("分-割-线".center(30, "-")) print(np.median(t1, axis=0)) #每行元素的中值 print("分-割-线".center(30, "-")) print(np.median(t1, axis=1)) #每列元素的中值 #运行结果 """ [[ 0 1 2 3 4 5] [ 6 7 8 9 10 11] [12 13 14 15 16 17] [18 19 20 21 22 23]] ------------分-割-线------------- 11.5 ------------分-割-线------------- [ 9. 10. 11. 12. 13. 14.] ------------分-割-线------------- [ 2.5 8.5 14.5 20.5] """
(6)极值
ptp(a, axis=None)
使用方式与numpy.median(a, axis=None)类似
(7)标准差
std(axis=None)
使用方式与sum( axis=None)类似
五、ndarray的视图和复制
t2 = t1 ( t2只是复制t1ndarray对象的引用【类似列表】,t1和i2互相影响)
视图view:切片【t2 = t1[:]】视为视图操作,会创建一个新的对象t2,但是t2的数据完全由t1保管,他们两个数据变化时一致的
复制:t2 = t1.copy()【t2完全复制t1,a和b互不影响】