什么是numpy
一个在python中做科学计算的基础库,重在数值计算,也是大部分PYTHON科学计算库的基础库,多用于大型、多维数组上执行数值运算
numpy创建数组(矩阵)
创建数组:
import numpy as np
a = np.array([1, 2, 3, 4, 5])
b = np.array(range(1, 6))
c = np.arange(1, 6)
# 上面a, b, c内容相同,注意arange和range的区别
np.arange的用法:arange([start,] stop[, step,], dtype=None)
数组的类名:
In [1]: a = np.array([1, 2, 3, 4, 5])
In [2]: type(a)
Out[2]: numpy.ndarray
数据的类型
In [3]: a.dtype
Out[3]: dtype('int64')
数据类型的操作
指定创建的数组的数据类型:
In [11]: a = np.array([1, 0, 1, 0], dtype=np.bool) # 或者使用dtype='?'
In [12]: a
Out[12]: array([ True, False, True, False])
修改数组的数据类型:
In [13]: a.astype('i2') # 或者使用a.astype(np.int16)
Out[13]: array([1, 0, 1, 0], dtype=int16)
修改浮点型的小数位数:
In [30]: b
Out[30]:
array([0.07996214, 0.89966202, 0.27985576, 0.84551686, 0.77378861,
0.69867185, 0.83677068, 0.30732802, 0.84521435, 0.88867764])
In [31]: np.round(b, 2)
Out[31]: array([0.08, 0.9 , 0.28, 0.85, 0.77, 0.7 , 0.84, 0.31, 0.85, 0.89])
数组的形状
b = a.reshape(3, 4)
In [36]: b
Out[36]:
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
In [37]: b.shape
Out[37]: (3, 4)
把数据转化为1维度数据
In [38]: b.reshape(1, 12)
Out[38]: array([[ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]])
# 这是一维数组么?
In [39]: b.flatten()
Out[39]: array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])
数组和数的计算
In [43]: a
Out[43]:
array([[ 1, 2, 3, 4, 5],
[ 6, 7, 8, 9, 10]])
加法减法
In [44]: a + 1
Out[44]:
array([[ 2, 3, 4, 5, 6],
[ 7, 8, 9, 10, 11]])
乘法除法
In [45]: a *3
Out[45]:
array([[ 3, 6, 9, 12, 15],
[18, 21, 24, 27, 30]])
这是一个numpy的广播机制造成的,在运算过程中,加减乘除的值被广播到所有的元素上面
不同维度的数组计算
In [46]: a
Out[46]:
array([[ 1, 2, 3, 4, 5],
[ 6, 7, 8, 9, 10]])
In [47]: c = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]
In [48]: a * c
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-48-3f6f667472ca> in <module>()
----> 1 a * c
ValueError: operands could not be broadcast together with shapes (2,5) (3,4)
广播原则
如果两个数组的后缘维度(trailing dimension,即从末尾开始算起的维度)的轴长度相符或其中一方的长度为1,则认为它们是广播兼容的。广播会在缺失和(或)长度为1的维度上进行。
轴(axis)
在numpy中可以理解为方向,使用0,1,2...数字表示,对于一个一维数组,只有一个0轴,对于二维数组(shape(2, 2)),有0轴和1轴,对于三维数组(shape(2, 2, 3)), 有0,1,2轴
有了轴的概念以后,我们计算会更加方便,比如计算一个2维数组的平均值,必须指定是计算哪个方向上面的数字的平均值
numpy读取数据
CSV:Comma-Separated Value,逗号分隔值文件
显示:表格状态
源文件:换行和逗号分隔行列的格式化文本,每一行的数据表示一条记录
由于csv便于展示,读取和写入,所以很多地方也是用csv的格式存储和传输中小型的数据,为了方便教学,我们会经常操作csv格式的文件,但是操作数据库中的数据也是很容易实现的
np.loadtxt(frame, dtype=np.float, delimiter=None, skiprows=0, usecols=None, unpack=False)
参数 | 解释 |
---|---|
frame | 文件、字符串或产生器,可以是.gz或bz2压缩文件 |
dtype | 数据类型,可选,csv的字符串以什么数据类型读入数组中,默认np.float |
delimiter | 分隔字符串,默认是任何空格,改为 逗号 |
skiprows | 跳过前x行,一般跳过第一行表头 |
usecols | 读取指定的列,索引,元组类型 |
unpack | 如果True,读入属性将分别写入不同数组变量,False读入数据只写入一个数组变量,默认False |
numpy中的转置
转置是一种变换,对于numpy中的数组来说,就是在对角线方向交换数据,目的也是为了更方便的去处理数据
In [102]: t = np.array([[0, 1, 2, 3, 4, 5], [6, 7, 8, 9, 10, 11], [12, 13, 14, 15,16, 17]])
In [103]: t.transpose()
Out[103]:
array([[ 0, 6, 12],
[ 1, 7, 13],
[ 2, 8, 14],
[ 3, 9, 15],
[ 4, 10, 16],
[ 5, 11, 17]])
In [104]: t.swapaxes(1, 0)
Out[104]:
array([[ 0, 6, 12],
[ 1, 7, 13],
[ 2, 8, 14],
[ 3, 9, 15],
[ 4, 10, 16],
[ 5, 11, 17]])
In [105]: t.T
Out[105]:
array([[ 0, 6, 12],
[ 1, 7, 13],
[ 2, 8, 14],
[ 3, 9, 15],
[ 4, 10, 16],
[ 5, 11, 17]])
以上的三种方法都可以实现二维数组的转置的效果,大家能够看出来,转置和交换轴的效果一样
numpy索引和切片
对于刚刚加载出来的数据,我如果只想选择其中的某一列(行)我们应该怎么做呢?
其实操作很简单,和python中列表的操作一样
In [118]: a
Out[118]:
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
In [119]: a[1] # 取一行
Out[119]: array([4, 5, 6, 7])
In [120]: a[:,2] # 取一列
Out[120]: array([ 2, 6, 10])
In [121]: a[1:3] # 取多行
Out[121]:
array([[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
In [122]: a[:,2:4] # 取多列
Out[122]:
array([[ 2, 3],
[ 6, 7],
[10, 11]])
In [128]: a[[0, 2],[0, 3]] # 取多个不相邻的点
Out[128]: array([ 0, 11])
numpy中数值的修改
In [132]: t
Out[132]:
array([[ 0, 1, 2, 3, 4, 5],
[ 6, 7, 8, 9, 10, 11],
[12, 13, 14, 15, 16, 17],
[18, 19, 20, 21, 22, 23]])
In [133]: t[:, 2:4]
Out[133]:
array([[ 2, 3],
[ 8, 9],
[14, 15],
[20, 21]])
In [134]: t[:, 2:4] = 0
In [135]: t
Out[135]:
array([[ 0, 1, 0, 0, 4, 5],
[ 6, 7, 0, 0, 10, 11],
[12, 13, 0, 0, 16, 17],
[18, 19, 0, 0, 22, 23]])
numpy中布尔索引
In [142]: t
Out[142]:
array([[ 0, 1, 2, 3, 4, 5],
[ 6, 7, 8, 9, 10, 11],
[12, 13, 14, 15, 16, 17],
[18, 19, 20, 21, 22, 23]])
In [143]: t<10
Out[143]:
array([[ True, True, True, True, True, True],
[ True, True, True, True, False, False],
[False, False, False, False, False, False],
[False, False, False, False, False, False]])
In [144]: t[t<10]
Out[144]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
In [145]: t
Out[145]:
array([[ 0, 1, 2, 3, 4, 5],
[ 6, 7, 8, 9, 10, 11],
[12, 13, 14, 15, 16, 17],
[18, 19, 20, 21, 22, 23]])
In [146]: t[t<10] = 0
In [147]: t
Out[147]:
array([[ 0, 0, 0, 0, 0, 0],
[ 0, 0, 0, 0, 10, 11],
[12, 13, 14, 15, 16, 17],
[18, 19, 20, 21, 22, 23]])
numpy中三元运算符
In [149]: t
Out[149]:
array([[ 0, 0, 0, 0, 0, 0],
[ 0, 0, 0, 0, 10, 11],
[12, 13, 14, 15, 16, 17],
[18, 19, 20, 21, 22, 23]])
In [150]: t = np.arange(24).reshape((4, 6))
In [151]: t
Out[151]:
array([[ 0, 1, 2, 3, 4, 5],
[ 6, 7, 8, 9, 10, 11],
[12, 13, 14, 15, 16, 17],
[18, 19, 20, 21, 22, 23]])
In [152]: np.where(t<10,0,10)
Out[152]:
array([[ 0, 0, 0, 0, 0, 0],
[ 0, 0, 0, 0, 10, 10],
[10, 10, 10, 10, 10, 10],
[10, 10, 10, 10, 10, 10]])
numpy中的clip(裁剪)
In [166]: t
Out[166]:
array([[ 0., 1., 2., 3., 4., 5.],
[ 6., 7., 8., 9., 10., 11.],
[12., 13., 14., 15., 16., 17.],
[18., 19., 20., nan, nan, nan]], dtype=float32)
In [167]: t.clip(10, 18)
Out[167]:
array([[10., 10., 10., 10., 10., 10.],
[10., 10., 10., 10., 10., 11.],
[12., 13., 14., 15., 16., 17.],
[18., 18., 18., nan, nan, nan]], dtype=float32)
小于10的替换为10,大于18的替换为了18,但是nan没有被替换
数组的拼接
In [169]: t1 = np.arange(12).reshape(2, 6)
In [170]: t1
Out[170]:
array([[ 0, 1, 2, 3, 4, 5],
[ 6, 7, 8, 9, 10, 11]])
In [171]: t2 = np.arange(12, 24).reshape(2, 6)
In [172]: t2
Out[172]:
array([[12, 13, 14, 15, 16, 17],
[18, 19, 20, 21, 22, 23]])
In [173]: np.vstack((t1, t2)) # 竖直拼接(vertically)
Out[173]:
array([[ 0, 1, 2, 3, 4, 5],
[ 6, 7, 8, 9, 10, 11],
[12, 13, 14, 15, 16, 17],
[18, 19, 20, 21, 22, 23]])
In [174]: np.hstack((t1, t2)) # 水平拼接(horizontally)
Out[174]:
array([[ 0, 1, 2, 3, 4, 5, 12, 13, 14, 15, 16, 17],
[ 6, 7, 8, 9, 10, 11, 18, 19, 20, 21, 22, 23]])
数组的行列交换
In [216]: t1
Out[216]:
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
In [217]: t1[[1, 2], :] = t1[[2, 1], :]
In [218]: t1
Out[218]:
array([[ 0, 1, 2, 3],
[ 8, 9, 10, 11],
[ 4, 5, 6, 7]])
In [219]: t1[:, [0, 2]] = t1[:, [2, 0]]
In [220]: t1
Out[220]:
array([[ 2, 1, 0, 3],
[10, 9, 8, 11],
[ 6, 5, 4, 7]])
numpy中的nan和inf
nan(NAN, Nan):not a number表示不是一个数字
什么时候numpy中会出现nan:
当我们读取的本地文件为float的时候,如果有缺失,就会出现nan当做了一个不合适的计算的时候(比如无穷大(inf)减去无穷大)
inf(-inf, inf):infinity,inf表示正无穷,-inf表示负无穷
什么时候会出现inf包括(-inf, +inf)
比如一个数字除以0,(python中直接会报错,numpy中是一个inf或者-inf)
numpy中的nan的注意点
- 两个nan是不相等的
In [27]: np.nan == np.nan
Out[27]: False
- np.nan != np.nan
In [34]: np.nan != np.nan
Out[34]: True
- 利用以上的特性,判断数组中nan的个数
In [38]: t
Out[38]: array([ 1., 2., nan])
In [39]: np.count_nonzero(t!=t)
Out[39]: 1
- 由于2,那么如何判断一个数字是否为nan呢?通过np.isnan(a)来判断,返回bool类型比如希望把nan替换为0
In [40]: t
Out[40]: array([ 1., 2., nan])
In [41]: np.isnan(t)
Out[41]: array([False, False, True])
- nan和任何值计算都为nan
那么问题来了,在一组数据中单纯的把nan替换为0,合适么?会带来什么样的影响?
比如,全部替换为0后,替换之前的平均值如果大于0,替换之后的均值肯定会变小,所以更一般的方式是把缺失的数值替换为均值(中值)或者直接删除有缺失值的一行
numpy中常用的统计函数
求和: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则返回一个当前轴上的结果
numpy更多好用的方法
- 获取最大值最小值的位置
1. np.argmax(t.axis=0)
2. np.argmin(t.axit=1)
- 创建一个全0的数组:np.zero((3, 4))
- 创建一个全1的数组:np.ones((3, 4))
- 创建一个对角线为1的正方形数组(方针):np.eye(3)
numpy生产随机数
参数 | 解释 |
---|---|
.rand(d0, d1, ..dn) |
创建d0-dn维度的均匀分布的随机数数组,浮点数,范围从0-1 |
.randn(d0, d1, ..dn) |
创建d0-dn维度的正态分布的随机数数组,浮点数,平均数0,标准差1 |
.randint(low, high, (shape)) |
从给定上下限范围选取随机数整数,范围是low,high, 形状是shape |
uniform(low, high, (size)) |
产生具有均匀分布的数组,low为起始值,high结束值,size形状 |
.normal(loc, scale, (size)) |
从指定正态分布中随机抽取样本,分布中心是loc(概率分布的均值),标准差是scale,形状是size |
seed(s) |
随机数种子,s是给定的种子值。因为计算机生成的是伪随机数,所以通过设定相同的随机数种子,可以生成相同的随机数 |
numpy的注意点copy和view
- a = b 完全不复制,a和b相互影响
- a = b[:],视图的操作,一种切片,会创建新的对象a,但是a的数据完全由b保管,它们两个完全的数据变化是一致的,
- a = b.copy(),复制,a和b互不影响