Python数据分析入门--Numpy基础学习笔记

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

NumPy(Numerical Python) 是 Python 语言的一个扩展程序库,支持大量的维度数组与矩阵运算,此外也针对数组运算提供大量的数学函数库。

NumPy 是一个运行速度非常快的数学库,主要用于数组计算和数组操作,包含:

1.一个强大的N维数组对象 ndarray
2.广播功能函数
3.整合 C/C++/Fortran 代码的工具
4.线性代数、傅里叶变换、随机数生成等功能
5.对硬盘中数组数据进行读写,对内存映射文件进行操作

NumPy基础

1.NumPy nadarray:多维数组对象

1.1ndarray及其数据类型

ndarray是Python中一个快速、灵活的大型数据集容器,可以批量操作数据,十分高效方便。

刚开始按照惯例引入NumPy库,然后np.random.randn函数生成一个随机二维数组,2行3列的

import numpy as np
arr1 = np.random.randn(2,3)
print(arr1)

#/usr/bin/python3.8/home/ljm/PycharmProject/pythoncode1/code4.py 
[[ 1.07644897 -1.29762086  1.07054724]
 [-0.56406011  0.57453638 -1.1791394 ]]

#Process finished with exit code 0

NumPy生成随机数组非常快,我们这里生成的随机数组的元素没有顺序没有范围,我们也可以通过np.arange函数生成一个有顺序有范围的随机数组

import numpy as np
arr1 = np.arange(8)
print(arr1)

#/usr/bin/python3.8/home/ljm/PycharmProject/pythoncode1/code4.py 
[0 1 2 3 4 5 6 7]

#Process finished with exit code 0

np.array函数的作用是创建一个对象,这个对象就是ndarray,通过下面的案例可以看出,列表和ndarray是两种类,而np.array函数就是两者转换的桥梁。

import numpy as np
data1 = [6,7,8,9,10]
arr1 = np.array(data1)
print(type(data1))
print(type(arr1))

#/usr/bin/python3.8 /home/ljm/PycharmProject/pythoncode1/code4.py 
<class 'list'>
<class 'numpy.ndarray'>

#Process finished with exit code 0

np.zeros函数可以生成一个float64数据类型的全0数组,shape和dtype分别用于查看数组的大小和数据类型。

import numpy as np
arr1 = np.zeros((3,6))
print(arr1.shape)
print(arr1.dtype)
print(arr1)

#/usr/bin/python3.8 /home/ljm/PycharmProject/pythoncode1/code4.py 
(3, 6)
float64
[[0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0.]]

#Process finished with exit code 0

下面是关于ndarray数组对象的基本数据类型
在这里插入图片描述

1.2NumPy数组运算

Numpy数组算术也十分直接便捷,与C语言里面需要利用for循环来对数组一个个元素进行操作不同,Numpy数组操作体现为批量化,向量化,这也为后面大容量管理数据分析数据提供更高可操作性。

import numpy as np
arr1 = np.random.randn(2,3)
arr2 = np.arange(1,7).reshape((2,3))
print(arr1)
print(arr2)
print(arr1*arr2)
print(arr1>arr2)

#/usr/bin/python3.8 /home/ljm/PycharmProject/pythoncode1/code4.py 
[[-0.72017992  0.66197321 -1.33661862]
 [-2.08083356 -1.23011793 -1.42957776]]
[[1 2 3]
 [4 5 6]]
[[-0.72017992  1.32394642 -4.00985585]
 [-8.32333423 -6.15058964 -8.57746657]]
[[False False False]
 [False False False]]

#Process finished with exit code 0

reshape函数会重塑数组的形状,在后面数组的转置用的非常多。上面的案例可以看出,数组之间的运算和比大小也很方便。

1.3基础索引与切片

数组的索引是数组元素的指示标志,和指针里的地址具有同样重要的地位。数组的索引是从0开始的,而不是从1开始的,这里容易出错,NumPy数组的索引为数组的片段操作提供较大的便利性。

import numpy as np
arr1 = np.arange(8)
arr2 = arr1[3:6]
print(arr2)

#/usr/bin/python3.8 /home/ljm/PycharmProject/pythoncode1/code4.py 
[3 4 5]

#Process finished with exit code 0

通过操作数组的切片,切片的数据改变也会映射到原一维数组上,写切片的索引值则只会修改对应索引位的数据,不写切片的索引值[:]则会将原数组的切片映射的数据改为同一个值

import numpy as np   
arr1 = np.arange(8)  
arr_slice = arr1[3:6]
print(arr_slice)     
arr_slice[:] = 9     
print(arr1)          
arr_slice[1] = 8     
print(arr1)    

#/usr/bin/python3.8 /home/ljm/PycharmProject/pythoncode1/code4.py 
[3 4 5]
[0 1 2 9 9 9 6 7]
[0 1 2 9 8 9 6 7]

#Process finished with exit code 0
 

同样的道理在2维,3维,乃至n维数组都同样适用,不过索引的写法就有所区别了。我们可以将索引理解成一种降维后的同级位置,而体现到表象上的就是从外往里拆开同级括号后的位置

import numpy as np                       
arr1 = [[1,2,3],[4,5,6],[7,8,9]]         
arr2 = [[[1,2],[3,4]],[[5,6],[7,8]]]     
print(arr1[1], arr1[1][2])               
print(arr2[1], arr2[1][1], arr2[1][1][1])

#/usr/bin/python3.8 /home/ljm/PycharmProject/pythoncode1/code4.py 
[4, 5, 6] 6
[[5, 6], [7, 8]] [7, 8] 8

#Process finished with exit code 0

二维,三维,乃至n维数组的切片也遵循一样的法则,也是降维拆同级括号后确定位置,不同维度降维的循环次数由切片索引的写法来决定。axis参数将数轴和数组联系起来,不过不是我们常见的x,y,z轴,因为上升到四维数组以后就不够用了,所以将不同的数轴用数字命名,其中0表示最高维,1表示次高维度,2是次次高维度,依次推算下去,最高维到最低维的降维过程表现为从外往里拆同级括号。

import numpy as np
arr1 = np.array([[1,2,3],[4,5,6],[7,8,9]])
arr2 = np.array([[[1,2],[3,4]],[[5,6],[7,8]]])
print(arr1[1:,:1])
print(arr2[1:,:1,1:])

#/usr/bin/python3.8 /home/ljm/PycharmProject/pythoncode1/code4.py 
[[4]
 [7]]
[[[6]]]

#Process finished with exit code 0

1.4布尔索引

布尔索引提供了一种转换介质,它可以通过是非判断将非数字数据与数字数据连结起来,可以用在字符串上判断两个字符串是否相等,也可以用来判断单个字符是否相等,判断后会返回一个布尔值True or False,实质上就是数字1 或 0

import numpy as np
arr1 = np.array([[1,2,3],[4,5,6],[7,8,9],[10,11,12],[13,14,15]])
arr2 = np.array(['a','b','c','b','a'])
print(arr1[arr2 == 'a'])
print(arr2 == 'a')

#/usr/bin/python3.8 /home/ljm/PycharmProject/pythoncode1/code4.py 
[[ 1  2  3]
 [13 14 15]]
[ True False False False  True]

#Process finished with exit code 0

虽然布尔索引只有两种值且只有True的值才能当作索引位,但我们可以利用与(&)和或(|)等逻辑连接符来扩大逻辑判断为True的占比。

import numpy as np
arr1 = np.array([[1,2,3],[4,5,6],[7,8,9],[10,11,12],[13,14,15]])
arr2 = np.array(['a','b','c','b','a'])
print(arr1[(arr2 == 'a')|(arr2 == 'b')])
print((arr2 == 'a')|(arr2 == 'b'))

#/usr/bin/python3.8 /home/ljm/PycharmProject/pythoncode1/code4.py 
[[ 1  2  3]
 [ 4  5  6]
 [10 11 12]
 [13 14 15]]
[ True  True False  True  True]

#Process finished with exit code 0

同样也可以利用布尔索引来进行数组切片,切片操作的原理和普通索引一样,也十分高效。

import numpy as np
arr1 = np.array([[1,2,3],[4,5,6],[7,8,9],[10,11,12],[13,14,15]])
arr1[arr1<7] = 6
print(arr1)

#/usr/bin/python3.8 /home/ljm/PycharmProject/pythoncode1/code4.py 
[[ 6  6  6]
 [ 6  6  6]
 [ 7  8  9]
 [10 11 12]
 [13 14 15]]

#Process finished with exit code 0

1.5神奇索引

神奇索引是NumPy中的术语,用于描述使用整数数组进行数据索引。为了选出一个符合特定顺序的子集,我们可以简单的通过传递一个包含指明所需顺序的列表和数组来实现。当对一个二维数组进行一级神奇索引时,会返回一个二维数组。值得主要的是,如果传递的是负的索引,将从尾部开始选择

import numpy as np
arr1 = np.empty((6,3))
for i in range(6):
    arr1[i] = i
print(arr1[[1,3,5]])
print(arr1[[-1,-3,-5]])

#/usr/bin/python3.8 /home/ljm/PycharmProject/pythoncode1/code4.py 
[[1. 1. 1.]
 [3. 3. 3.]
 [5. 5. 5.]]
[[5. 5. 5.]
 [3. 3. 3.]
 [1. 1. 1.]]

#Process finished with exit code 0

当对二维数组进行二级神奇索引时,会返回一个一维数组。推广到更高维的数组中,神奇索引的级数和数组的维数共同决定了返回数组的维数。值得注意的是,神奇索引与切片不同,它总是将数据复制到一个新的数组中。

import numpy as np
arr1 = np.empty((6,6))
for i in range(6):
    for j in range(6):
       arr1[i][j] = i*6+j
print(arr1[[1,3,5],[0,2,4]])

#/usr/bin/python3.8 /home/ljm/PycharmProject/pythoncode1/code4.py 
[ 6. 20. 34.]

#Process finished with exit code 0

1.6数组转置和换轴

NumPy数组的转置是一个数据重组的过程,十分高效好用,不用像C语言中复杂的行列移项操作,就可以返回底层的数据视图。数组拥有transpose方法,也有特殊的T属性,利用T属性可以直接快速实现数组的转置换轴。

import numpy as np
arr1 = np.arange(9).reshape(3,3)
arr2 = np.arange(27).reshape(3,3,3)
print(arr1)
print(arr1.T)
print(arr2)
print(arr2.T)

#/usr/bin/python3.8 /home/ljm/PycharmProject/pythoncode1/code4.py 
[[0 1 2]
 [3 4 5]
 [6 7 8]]
[[0 3 6]
 [1 4 7]
 [2 5 8]]
[[[ 0  1  2]
  [ 3  4  5]
  [ 6  7  8]]

 [[ 9 10 11]
  [12 13 14]
  [15 16 17]]

 [[18 19 20]
  [21 22 23]
  [24 25 26]]]
[[[ 0  9 18]
  [ 3 12 21]
  [ 6 15 24]]

 [[ 1 10 19]
  [ 4 13 22]
  [ 7 16 25]]

 [[ 2 11 20]
  [ 5 14 23]
  [ 8 17 26]]]

#Process finished with exit code 0

当进行矩阵计算时,会经常用到一些特定操作,np.dot可以用来计算矩阵内积。而对于更高维度的数组,transpose方法可以接收包含轴编号的元组,用于按指定顺序置换轴

import numpy as np
arr1 = np.arange(9).reshape(3,3)
arr2 = np.arange(27).reshape(3,3,3)
print(np.dot(arr1.T,arr1))
print(arr2.transpose((1,0,2)))

#/usr/bin/python3.8 /home/ljm/PycharmProject/pythoncode1/code4.py 
[[45 54 63]
 [54 66 78]
 [63 78 93]]
[[[ 0  1  2]
  [ 9 10 11]
  [18 19 20]]

 [[ 3  4  5]
  [12 13 14]
  [21 22 23]]

 [[ 6  7  8]
  [15 16 17]
  [24 25 26]]]

#Process finished with exit code 0

2.通用函数

通用函数(ufunc)是一种在ndarray数据中进行逐元素操作的函数,通用函数是对简单函数的标量化封装。一元通用函数像np.sqrt用来对数组内部进行逐元素求x^1/2 ,np.exp则用于数组内部逐元素求e^x等

import numpy as np
arr1 = np.arange(8)
print(np.sqrt(arr1))
np.set_printoptions(suppress=True) #抑制使用科学记数法
print(np.exp(arr1))
print(np.square(arr1))

#/usr/bin/python3.8 /home/ljm/PycharmProject/pythoncode1/code4.py 
[0.         1.         1.41421356 1.73205081 2.         2.23606798
 2.44948974 2.64575131]
[   1.            2.71828183    7.3890561    20.08553692   54.59815003
  148.4131591   403.42879349 1096.63315843]
[ 0  1  4  9 16 25 36 49]

#Process finished with exit code 0

以下是一元通用函数汇总

函数名描述
abs、fabs逐个元素地计算整数、浮点数或复数地绝对值
sqrt计算每个元素的平方根(与arr ** 0.5相等)
square计算每个元素地平方(与arr ** 2相等)
exp计算每个元素的自然指数值e^x次方
log、log10、log2、log1p分别对应(自然指数(e为底)、对数10为底、对数2为底、log(1+x))
sign计算每个元素的符号值:1(正数)、0(0)、-1(负数)
ceil计算每个元素的最高整数值(即大于等于给定数值的最小整数)
floor计算每个元素的最小整数值(即小于等于给定整数的最大整数)
rint将元素保留到整数位,并保持dtype
modf分别将数组的小数部分与整数部分按数组形式返回
isnan返回数组元素是否是一个NaN(非数值),形式为布尔值数组
isfinite、isinf分别返回数组中的元素是否有限(非inf、非NaN)、是否无限的,形式为布尔值数组
cos、cosh、sin、sinh、tan、tanh常规三角函数及双曲三角函数
arccos、arccosh、arcsin、arcsinh、arctan、arctanh反三角函数
logical_not对数组元素按位取反

二元通用函数则会接受两个数组操作后返回一个数组作为结果,典型的有np.add用于两个数组对应元素求和,np.maximum用于两个数组对应元素比大小,十分快捷

import numpy as np
arr1 = np.random.randn(8)
arr2 = np.random.randn(8)
np.set_printoptions(suppress=True)
print(np.add(arr1,arr2))
print(np.maximum(arr1,arr2))

#/usr/bin/python3.8 /home/ljm/PycharmProject/pythoncode1/code4.py 
[-0.76065295 -2.56824583 -1.28345312 -1.43345855  0.12094986  0.18205674
  2.55902137  1.08133763]
[-0.16578757 -0.84749851  0.11708674 -0.53388395  0.24916845  0.58661835
  1.40951202  0.98660414]

#Process finished with exit code 0

以下是二元通用函数汇总

函数名描述
add将数组的对应元素相加
subtract在第二个数组中,将第一个数组中包含的元素去除
multiply将数组的对应元素相乘
divide,floor_divide除或整除(放弃余数)
power将第二个数组的元素作为第一个数组对应元素的幂次方
maximum逐个元素计算最大值,fmax忽略NaN
minimum逐个元素计算最小值,fmin忽略NaN
mod按元素的求模计算(即求除法的余数)
copysign将第一个数组的符号值改为第二个数组的符号值
greater,greater_equal,less,less_equal,equal,not_equal进行逐个元素的比较,返回布尔值数组(与数学操作符>,>=,<,<=,==,!=x效果一致)
logical_and,logical_or,logical_xor进行逐个元素的逻辑操作(与逻辑操作符&、丨、^效果一致)

3.面向数组编程

3.1条件逻辑操作数组

之前讲到在正常的布尔索引下,不加额外操作我们只能利用True作为索引值找对应的元素,但np.where函数提供了快速的简便的解决方法,np.where()括号里一共有三个参数,第一个提供元素为布尔数值的数组,第二和第三个参数可以是数组也可以是标量,np.where也可以用于数组数据的转换

import numpy as np
arr1 = np.random.randn(8)
arr2 = np.random.randn(8)
cond = np.array([True,False,True,False,True,True,False,False])
arr3 = np.where(cond,arr1,arr2)
print(arr3)
print(np.where(arr3>0,1,0))

#/usr/bin/python3.8 /home/ljm/PycharmProject/pythoncode1/code4.py 
[-1.20688419  1.47806134  0.93372575 -0.26374421  0.83253598 -0.81965797
  0.52879235 -0.31592335]
[0 1 1 0 1 0 1 0]

#Process finished with exit code 0

3.2 数学与统计方法

NumPy中很多函数为大量数据的统计和计算提供可操作性,我们统计分析数据时常用的计算方式,如求平均值可以用到np.mean,求方差可以用到np.std,求前几项累加和可以用的np.cumsum

import numpy as np
arr1 = np.random.randn(15).reshape(5,3)
arr2 = np.arange(8)
print(arr1)
print(np.mean(arr1))
print(arr1.mean(axis=0))
print(np.cumsum(arr2))

#/usr/bin/python3.8 /home/ljm/PycharmProject/pythoncode1/code4.py 
[[-0.62913503 -0.63310685  0.85535111]
 [-2.2887065  -0.82526957  2.05261662]
 [-0.50289743 -0.19757957  0.42530239]
 [ 0.26989036 -0.20296011 -0.81589922]
 [-1.49194974 -0.07682046  2.19017846]]
-0.1247323691647298
[-0.92855967 -0.38714731  0.94150987]
[ 0  1  3  6 10 15 21 28]

#Process finished with exit code 0

可以看到,通过给定axis的值我们可以操作特定轴的数据,求和求平均值都适用。

以下是方法汇总

方法说明
sum对数组中全部或者某轴向的元素求和(零长度的数组的sum为0)
mean算数平均数(零长度的数组的mean为NaN)
std, var分别为标准差和方差,自由度可调(默认为n)
min, max最大值和最小值
argmin, argmax分别为最大和最小元素的索引
cumsum所有元素的累计和
cumpord所有元素的累计积

3.3 排序和集合操作

NumPy数组可以使用sort方法按位置给元素排序,元素是数字的话会返回从小到大的视图,相较C语言中需要使用多个for循环来比较实现从小到大的排序更加快捷方便,同样的也可以通过传递axis的值来控制指定轴上数据的排序。

import numpy as np
arr1 = np.random.randn(9).reshape(3,3)
print(arr1)
print(np.sort(arr1))
print(np.sort(arr1,axis=0))

#/usr/bin/python3.8 /home/ljm/PycharmProject/pythoncode1/code4.py 
[[ 0.51531326  1.71943946  0.07990949]
 [-0.73413877 -1.48582995  1.0795675 ]
 [ 0.33891088  0.01670139 -0.25762643]]
[[ 0.07990949  0.51531326  1.71943946]
 [-1.48582995 -0.73413877  1.0795675 ]
 [-0.25762643  0.01670139  0.33891088]]
[[-0.73413877 -1.48582995 -0.25762643]
 [ 0.33891088  0.01670139  0.07990949]
 [ 0.51531326  1.71943946  1.0795675 ]]

#Process finished with exit code 0

NumPy库包含一些针对一维ndarray对象的基础集合操作,可以对集合元素进行操作,如np.unique可以返回唯一值排序后的数组;也可以对不同集合元素进行操作,如np.in1d可以检查一个数组的元素是否在另一个数组中并返回一个布尔值数组

import numpy as np
arr1 = np.array(['a','b','c','b','a'])
print(np.unique(arr1))
arr2 = np.arange(8)
print(np.in1d(arr2,[1,3,5,7]))

#/usr/bin/python3.8 /home/ljm/PycharmProject/pythoncode1/code4.py 
['a' 'b' 'c']
[False  True False  True False  True False  True]

#Process finished with exit code 0

以下是集合操作方法汇总

方法描述
unique(x)查找数组的唯一元素
intersect1d(x,y)找到两个数组的交集
union1d(x,y)找到两个数组的并集
in1d(x,y)测试一维数组的每个元素是否也存在于第二个数组中
setdiff1d(x,y)找到两个数组的集合差
setxor1d(x,y)找到两个数组的集合异或

4.线性代数

线性代数,比如矩阵乘法,矩阵分解,行列式等是所有数组类库的重要组成部分。Matlab中*表示矩阵的点乘积,而NumPy中则表示矩的逐元素乘积。NumPy中的np.dot函数可以直接计算矩阵点乘

import numpy as np
arr1 = np.arange(6).reshape(3,2)
arr2 = np.arange(6).reshape(2,3)
print(np.dot(arr1,arr2))

#/usr/bin/python3.8 /home/ljm/PycharmProject/pythoncode1/code4.py 
[[ 3  4  5]
 [ 9 14 19]
 [15 24 33]]

#Process finished with exit code 0

NumPy库中的numpy.linalg有一个矩阵分解的标准函数集,也有可以用来求逆和行列式求解的函数。以下是numpy.linalg函数集常用函数汇总

函数描述
diag将一个方阵的对角元素作为一维数组返回,或者将一维数组转换成一个方阵,并且在非对角上有零点
dot矩阵点乘
trace计算对角元素和
det计算矩阵行列式
eig计算方阵的特征值和特征向量
inv计算方阵的逆矩阵
pinv计算矩阵的Moore-Penrose伪逆
qr计算QR分解
svd计算奇异值分解
solve求解x的线性系统Ax = b,A是方阵
lstsq计算Ax = b的最小二乘解

5.伪随机数生成

numpy.random模块填补了Python内建的random模块的缺陷,可以高效的生成多种概率分布下的完整样本数组,为后续数据样本模拟提供了高度可操作性。例如,normal函数可以随机生成一个正态分布样本数组

import numpy as np
arr1 = np.random.normal(size=(3,3))
print(arr1)

#/usr/bin/python3.8 /home/ljm/PycharmProject/pythoncode1/code4.py 
[[ 0.58355314  0.65129933  0.27403696]
 [-0.83275108 -0.12584927  0.60087492]
 [ 0.01174412 -1.94506775 -0.87492464]]

#Process finished with exit code 0

numpy.random函数集中有一些函数经常用于生成大型样本数组,以下是一些常用函数的汇总

在这里插入图片描述

总结

以上就是笔记的内容,本文简单介绍了NumPy的基础使用,而NumPy提供了大量能使我们快速便捷地处理数据的函数和方法,继续学习一下Numpy进阶

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

szu_ljm

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值