数组的创建与操作(参照刘顺祥著《从零开始学数据分析与挖掘》)

1.数组的创建

numpy.array(object, dtype = None, copy = True, order = None, subok = False, ndmin = 0)
参数说明

菜鸟教程

numpy数组属性 numpy创建数组 NumPy 从已有的数组创建数组
numpy数据类型

# 导入模块,并重命名为np
import numpy as np
# 单个列表创建一维数组
arr1 = np.array([3,10,8,7,34,11,28,72])
# 嵌套元组创建二维数组
arr2 = np.array(((8.5,6,4.1,2,0.7),(1.5,3,5.4,7.3,9),(3.2,3,3.8,3,3),(11.2,13.4,15.6,17.8,19)))
print('一维数组:\n',arr1)
print('二维数组:\n',arr2)
# 运行结果
一维数组:
 [ 3 10  8  7 34 11 28 72]
二维数组:
 [[ 8.5  6.   4.1  2.   0.7]
 [ 1.5  3.   5.4  7.3  9. ]
 [ 3.2  3.   3.8  3.   3. ]
 [11.2 13.4 15.6 17.8 19. ]]

2.数组元素的获取

注意:如果要在数组中取出某几行和某几列需使用ix_函数

# 一维数组元素的获取
print(arr1[[2,3,5,7]])
# 二维数组元素的获取
# 第2行第3列元素
print(arr2[1,2])
# 第3行所有元素
print(arr2[2,:])
# 第2列所有元素
print(arr2[:,1])
# 第2至4行,2至5行
print(arr2[1:4,1:5])
# 第一行、最后一行和第二列、第四列构成的数组
print(arr2[[0,-1],[1,3]])
# 第一行、最后一行和第一列、第三列、第四列构成的数组
print(arr2[[0,-1],[1,2,3]])
# 第一行、最后一行和第二列、第四列构成的数组
print(arr2[np.ix_([0,-1],[1,3])])
# 第一行、最后一行和第一列、第三列、第四列构成的数组
print(arr2[np.ix_([0,-1],[1,2,3])])

3.数组的常用属性

读取外部文本文件数据

在numpy模块中,可以通过genfromtxt函数读取外部文本文件的数据(主要是csv文件和txt文件)

# 读入数据
stu_score = np.genfromtxt(fname = r'C:\Users\Administrator\Desktop\stu_socre.txt',delimiter='\t',skip_header=1)
# 查看数据结构
print(type(stu_score))
# 查看数据维数
print(stu_score.ndim)
# 查看数据行列数
print(stu_score.shape)
# 查看数组元素的数据类型
print(stu_score.dtype)
# 查看数组元素个数
print(stu_score.size)
# 运行结果
<class 'numpy.ndarray'>
2
(1380, 5)
float64
6900

4.数组的形状处理

改变数组形状

如下所示,虽然reshape和resize都是用来改变数组形状的“方法”,但是reshape方法知识返回改变形状后的预览,但并未真正改变数组arr3的形状;而resize方法则不会返回预览,而是会改变数组arr3的形状,从前后两次打印的形状可发现两者的区别。

arr3 = np.array([[1,5,7],[3,6,1],[2,4,8],[5,8,9],[1,5,9],[8,5,2]])
# 数组的行列数
print(arr3.shape)
# 使用reshape方法更改数组的形状
print(arr3.reshape(2,9))
# 打印数组arr3的行列数
print(arr3.shape)
# 运行结果
(6, 3)
[[1 5 7 3 6 1 2 4 8]
 [5 8 9 1 5 9 8 5 2]]
(6, 3)
None
(2, 9)

将多维数组降为一维数组

利用ravel、flatten、reshape

如下所示,在默认情况下,优先按照数组的行顺序,逐个将元素降至一维;如果按原始数组的列顺序将数组降为一维的话,需要设置order参数为“F”,尽管三者的功能一致,但还是有区别的。

arr4 = np.array([[1,10,100],[2,20,200],[3,30,300]])
print('原数组:\n',arr4)
# 默认排序降维
print('数组降维:\n',arr4.ravel())
print(arr4.flatten())
print(arr4.reshape(-1))
# 改变排序模式的降维
print(arr4.ravel(order = 'F'))
print(arr4.flatten(order = 'F'))
print(arr4.reshape(-1, order = 'F'))
# 运行结果
原数组:
 [[  1  10 100]
 [  2  20 200]
 [  3  30 300]]
数组降维:
 [  1  10 100   2  20 200   3  30 300]
[  1  10 100   2  20 200   3  30 300]
[  1  10 100   2  20 200   3  30 300]
[  1   2   3  10  20  30 100 200 300]
[  1   2   3  10  20  30 100 200 300]
[  1   2   3  10  20  30 100 200 300]

如下结果所示,通过flatten方法实现的降维返回的是复制,因为对降维后的元素做修改,并没有影响到原数组arr4的结果,相反,ravel方法与reshape方法返回的则是视图,通过对视图的改变是会影响到原数组的。

# 更改预览值
arr4.flatten()[0] = 2000
print('flatten方法:\n',arr4)
arr4.ravel()[1] = 1000
print('ravel方法:\n',arr4)
arr4.reshape(-1)[2] = 3000
print('reshape方法:\n',arr4)
# 运行结果
flatten方法:
 [[  1  10 100]
 [  2  20 200]
 [  3  30 300]]
ravel方法:
 [[   1 1000  100]
 [   2   20  200]
 [   3   30  300]]
reshape方法:
 [[   1 1000 3000]
 [   2   20  200]
 [   3   30  300]]

vstack用于垂直方向(纵向)的数组堆叠,其功能与row_stack函数一致,而hstack则用于水平方向(横向)的数组合并,其功能与colum_stack函数一致,下面通过具体例子对这四种函数的用法和差异加以说明,如下所示,前两个输出是纵向堆叠的效果,后两个则是横向合并的效果。如果是多个数组的纵向堆叠,必须保证每个数组的列数相同;如果将多个数组按横向合并的话则每个数组的行数必须相同。

arr4 = np.array([[1,10,100],[2,20,200],[3,30,300]])
arr5 = np.array([1,2,3])
print('vstack纵向合并数组:\n',np.vstack([arr4,arr5]))
print('row_stack纵向合并数组:\n',np.row_stack([arr4,arr5]))
arr6 = np.array([[5],[15],[25]])
print('hstack横向合并数组:\n',np.hstack([arr4,arr6]))
print('column_stack横向合并数组:\n',np.column_stack([arr4,arr6]))
# 计算数组的和
print('垂直方向计算数组的和:\n',np.sum(arr4,axis = 0))
print('水平方向计算数组的和:\n',np.sum(arr4, axis = 1))
# 运行结果
vstack纵向合并数组:
 [[  1  10 100]
 [  2  20 200]
 [  3  30 300]
 [  1   2   3]]
row_stack纵向合并数组:
 [[  1  10 100]
 [  2  20 200]
 [  3  30 300]
 [  1   2   3]]
hstack横向合并数组:
 [[  1  10 100   5]
 [  2  20 200  15]
 [  3  30 300  25]]
column_stack横向合并数组:
 [[  1  10 100   5]
 [  2  20 200  15]
 [  3  30 300  25]]
垂直方向计算数组的和:
 [  6  60 600]
水平方向计算数组的和:
 [111 222 333]

数组的基本运算符

1.四则运算

在numpy模块中。实现四则运算的计算既可以使用运算符号,也可以使用函数,具体如下 四则运算中的符号分别是“+-*/”,对应的numpy模块函数分别是np.add、np.subtract、np.multiply和np.divide。

注意:函数只能接受两个对象的运算,如果需要多个对象的运算,就得使用嵌套方法。另外还有三个数学运算符:余数、整除和指数。

可以使用“%、//、**”计算数组元素之间商的余数、整除部分以及数组元素之间的指数。如果使用函数则用np.fmod、np.modf、np.power。但是整除的函数应用稍微复杂,需写成np.modf(arr7/arr8)[1],因为modf可以返回数值的小数部分和整数部分,而整数部分就是要取的整除值。

# 加法运算
math = np.array([98,83,86,92,67,82])
english = np.array([68,74,66,82,75,89])
chinese = np.array([92,83,76,85,87,77])
tot_symbol = math+english+chinese
tot_fun = np.add(np.add(math,english),chinese)
print('符号加法:\n',tot_symbol)
print('函数加法:\n',tot_fun)
# 运行结果
符号加法:
 [258 240 228 259 229 248]
函数加法:
 [258 240 228 259 229 248]
# 除法运算
height = np.array([165,177,158,169,173])
weight = np.array([62,73,59,72,80])
BMI_symbol = weight/(height/100)**2
BMI_fun = np.divide(weight,np.divide(height,100)**2)
print('符号除法:\n',BMI_symbol)
print('函数除法:\n',BMI_fun)
arr7 = np.array([[1,2,10],[10,8,3],[7,6,5]])
arr8 = np.array([[2,2,2],[3,3,3],[4,4,4]])
print('数组arr7:\n',arr7)
print('数组arr8:\n',arr8)
# 求余数
print('计算余数:\n',arr7 % arr8)
# 求整除
print('计算整除:\n',arr7 // arr8)
# 求指数
print('计算指数:\n',arr7 ** arr8)
# 整除部分
print('整除部分:\n',np.modf(arr7/arr8)[1])
# 运行结果
符号除法:
 [22.77318641 23.30109483 23.63403301 25.20920136 26.7299275 ]
函数除法:
 [22.77318641 23.30109483 23.63403301 25.20920136 26.7299275 ]
数组arr7:
 [[ 1  2 10]
 [10  8  3]
 [ 7  6  5]]
数组arr8:
 [[2 2 2]
 [3 3 3]
 [4 4 4]]
计算余数:
 [[1 0 0]
 [1 2 0]
 [3 2 1]]
计算整除:
 [[0 1 5]
 [3 2 1]
 [1 1 1]]
计算指数:
 [[   1    4  100]
 [1000  512   27]
 [2401 1296  625]]
整除部分:
 [[0. 1. 5.]
 [3. 2. 1.]
 [1. 1. 1.]]

2.比较运算

运用比较运算符可以返回bool类型的值,即True和False。

arr7 = np.array([[1,2,10],[10,8,3],[7,6,5]])
arr8 = np.array([[2,2,2],[3,3,3],[4,4,4]])
# 取子集
# 从arr7中取出arr7大于arr8的所有元素
print(arr7)
print('满足条件的二维数组元素获取:\n',arr7[arr7>arr8])
# 从arr9中取出大于10的元素
arr9 = np.array([3,10,23,7,16,9,17,22,4,8,15])
print('满足条件的一维数组元素获取:\n',arr9[arr9>10])
# 判断操作
# 将arr7中大于7的元素改成5,其余的不变
print('二维数组的条件操作:\n',np.where(arr7>7,5,arr7))
# 将arr9中大于10 的元素改为1,否则改为0
print('一维数组的条件操作:\n',np.where(arr9>10,1,0))
# 运行结果
[[ 1  2 10]
 [10  8  3]
 [ 7  6  5]]
满足条件的二维数组元素获取:
 [10 10  8  7  6  5]
满足条件的一维数组元素获取:
 [23 16 17 22 15]
二维数组的条件操作:
 [[1 2 5]
 [5 5 3]
 [7 6 5]]
一维数组的条件操作:
 [0 0 1 0 1 0 1 1 0 0 1]

3.广播运算

当数组形状不想同时,也能够进行数学运算的功能称为数组的广播。但是数组的广播功能是有规则的,如果不满足这些规则,运算时会出错

  • 各输入数组的维度可以不相等,但必须确保从右到左的对应维度值相等。
  • 如果对应维度值不相等,就必须保证其中一个为1.
  • 各输入数组都向其shape最长的数组看齐,shape中不足的部分都通过在前面加一补齐。
# 各输入数组维度一致,对应维度值相等
arr10 = np.arange(12).reshape(3,4)
arr11 = np.arange(101,113).reshape(3,4)
print('3×4的二维矩阵运算:\n',arr10 + arr11)
# 各输入数组维度不一致,对应维度值相等
arr12 = np.arange(60).reshape(5,4,3)
arr10 = np.arange(12).reshape(4,3)
print('维数不一致,但末尾的维度值一致:\n',arr12 + arr10)
# 各输入数组维度不一致,对应维度值不相等,但其中有一个为1
arr12 = np.arange(60).reshape(5,4,3)
arr13 = np.arange(4).reshape(4,1)
print('维数不一致,维度值也不一致,但维度值至少一个为1:\n',arr12 + arr13)
# 加1补齐
arr14 = np.array([5,15,25])
print('arr14的维度自动补齐为(1,3):\n',arr10 + arr14)
# 运行结果
3×4的二维矩阵运算:
 [[101 103 105 107]
 [109 111 113 115]
 [117 119 121 123]]
维数不一致,但末尾的维度值一致:
 [[[ 0  2  4]
  [ 6  8 10]
  [12 14 16]
  [18 20 22]]
 [[12 14 16]
  [18 20 22]
  [24 26 28]
  [30 32 34]]
 [[24 26 28]
  [30 32 34]
  [36 38 40]
  [42 44 46]]
 [[36 38 40]
  [42 44 46]
  [48 50 52]
  [54 56 58]]
 [[48 50 52]
  [54 56 58]
  [60 62 64]
  [66 68 70]]]
维数不一致,维度值也不一致,但维度值至少一个为1:
 [[[ 0  1  2]
  [ 4  5  6]
  [ 8  9 10]
  [12 13 14]]
 [[12 13 14]
  [16 17 18]
  [20 21 22]
  [24 25 26]]
 [[24 25 26]
  [28 29 30]
  [32 33 34]
  [36 37 38]]
 [[36 37 38]
  [40 41 42]
  [44 45 46]
  [48 49 50]]
 [[48 49 50]
  [52 53 54]
  [56 57 58]
  [60 61 62]]]
arr14的维度自动补齐为(1,3):
 [[ 5 16 27]
 [ 8 19 30]
 [11 22 33]
 [14 25 36]]

常用的数学和统计函数

统计函数都有axis参数,该参数的目的是在统计数组元素时需要按照不同的轴方向计算,如果axis=1,则按水平方向计算统计值,即计算每一行的统计值;如果axis=0,则表示按垂直方向计算统计值,即计算每一列的统计值。

arr4 = np.array([[1,10,100],[2,20,200],[3,30,300]])
print(arr4)
print('垂直方向计算数组的和:\n',np.sum(arr4,axis = 0))
print('水平方向计算数组的和:\n',np.sum(arr4, axis = 1))
# 运行结果
[[  1  10 100]
 [  2  20 200]
 [  3  30 300]]
垂直方向计算数组的和:
 [  6  60 600]
水平方向计算数组的和:
 [111 222 333]

线性代数的相关计算

矩阵乘法

点积函数dot,使用在两个一维数组中,实际上是计算两个向量的乘积,返回一个标量;使用在两个二维数组中,即矩阵的乘法,矩阵乘法要求第一个矩阵的列数等于第二个矩阵的行数,否则会报错。

相关知识点:矩阵乘法

发表回复