什么是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的注意点

  1. 两个nan是不相等的
In [27]: np.nan == np.nan
Out[27]: False
  1. np.nan != np.nan
In [34]: np.nan != np.nan
Out[34]: True
  1. 利用以上的特性,判断数组中nan的个数
In [38]: t
Out[38]: array([ 1.,  2., nan])

In [39]: np.count_nonzero(t!=t)
Out[39]: 1
  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])
  1. 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. 获取最大值最小值的位置
1. np.argmax(t.axis=0)
2. np.argmin(t.axit=1)
  1. 创建一个全0的数组:np.zero((3, 4))
  2. 创建一个全1的数组:np.ones((3, 4))
  3. 创建一个对角线为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

  1. a = b 完全不复制,a和b相互影响
  2. a = b[:],视图的操作,一种切片,会创建新的对象a,但是a的数据完全由b保管,它们两个完全的数据变化是一致的,
  3. a = b.copy(),复制,a和b互不影响