欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

数据分析之Numpy库

程序员文章站 2022-06-20 22:00:00
文章目录1 Numpy简介2 ndarray简介3 ndarray与list执行效率的对比4 ndarray的优势5 ndarray数组的属性6 ndarray数组的形状7 ndarray数组的类型8 ndarray数组的生成9 ndarray数组的索引和切片10 ndarray数组形状的修改11 ndarray数组类型的修改12 ndarray数组的去重13 ndarray的运算14 ndrray统计运算相关的函数15 数组间的运算16 矩阵与向量相关1 Numpy简介Numpy(Numerica....

1 Numpy简介

Numpy(Numerical Python)是一个开源的高性能的科学计算和数据分析库,用于快速处理任意维度的数组。并且,Numpy支持常见的数组和矩阵操作。Numpy使用ndarray对象来处理多为数组,ndarray对象是一个快速灵活的大数据容器。

2 ndarray简介

Python中有列表,可当数组使用。Python中也有array模块,但是不支持多维数组。并且列表和array模块都没有科学运算函数。所以,Python不适合做矩阵等科学计算。Numpy没有使用Python本身的数组机制,而是提供了ndarray这个n维数组类型对象,ndarray不仅能够很方便地对数组进行存取,而且拥有丰富的科学计算函数,如向量的加法、减法、乘法等。下面通过实例演示创建一个ndarray多维数组:

# 导入numpy函数库并指定库的别名
import numpy as np
# 创建一维数组
array1 = np.array([1, 2, 3, 4])
# 创建二维数组
array2 = np.array([[1, 2, 3, 4],[5, 6, 7, 8]])
# 创建三维数组
array3 = np.array([[[1, 2, 3, 4],[5, 6, 7, 8],[9, 10, 11, 12]],[[1, 2, 3, 4],[5, 6, 7, 8],[9, 10, 11, 12]]])
array1:array([1, 2, 3, 4])
array2:array([[1, 2, 3, 4],
       [5, 6, 7, 8]])
array3:array([[[ 1,  2,  3,  4],
        [ 5,  6,  7,  8],
        [ 9, 10, 11, 12]],

       [[ 1,  2,  3,  4],
        [ 5,  6,  7,  8],
        [ 9, 10, 11, 12]]])
3 ndarray与list执行效率的对比

使用Python的list可以作为一维数组,通过列表的嵌套可以实现多维数组。那为什么还要使用Numpy的ndarray,其实使用ndarray处理数组,其效率要比list要高很多,下面通过例子来比较下两者的执行效率:

import random
import numpy as np
# 定义一个空列表用于存放(数组)元素
lst = []
# 向lst中添加一千万个元素
for i in range(10000000):
    lst.append(random.random())
%time sum01 = sum(lst) # 使用Python中的sum函数对数组元素进行求和;%time是魔法方法,可以查看当前行代码运行一次需要花费的时间。
lst2 = np.array(lst) # 将lst的存储方式转换成ndarray中的存储方式
%time sum02 = np.sum(lst2) # 使用ndarray中的sum对同样的数组进行求和
第一次运行上面的代码:
CPU times: user 40.8 ms, sys: 70 µs, total: 40.8 ms
Wall time: 40.9 ms
CPU times: user 4.07 ms, sys: 0 ns, total: 4.07 ms
Wall time: 3.87 ms

第一次运行上面的代码:
CPU times: user 41.1 ms, sys: 0 ns, total: 41.1 ms
Wall time: 41.1 ms
CPU times: user 3.86 ms, sys: 0 ns, total: 3.86 ms
Wall time: 3.87 ms

第三次运行上面的代码:
CPU times: user 40.8 ms, sys: 87 µs, total: 40.9 ms
Wall time: 40.9 ms
CPU times: user 4.23 ms, sys: 31 µs, total: 4.26 ms
Wall time: 4.07 ms

很明显使用numpy的ndarray对数组求和的效率要比原生Python的sum函数求和高10倍以上。机器学习最大的特点是需要对大量的数据做运算,如果没有一个快速的解决方案,那么可能Python在机器学习领域就达不到很好的效果。Numpy专门对ndarray的操作和运算进行设计,所以,数组的存储效率和输入输出性能远优于Python中的嵌套列表。数组越大,Numpy的优势就越明显。

4 ndarray的优势
  • 内存块风格:ndarray在存储数据的时候是直接存储,Python的list中的数据不是直接存储,需要先找寻一个地址,然后通过地址找到需要的内容。ndarray中的所有元素的类型都是相同的,所以ndarray在存储元素时,内存是可以连续的。而Python中list中的元素是任意的,所以只能通过寻址的方式找到下一个元素。ndarray在通用性上要输于list,但在科学计算中,Numpy的ndarray就可以省掉很多循环语句,代码使用方面比Python的list要简洁。
  • ndarray支持并行化运算(向量化运算):Numpy内置并行运算功能,当系统有多个核心时,做运算会自动做并行运算。
  • 效率远高于纯Python代码,Numpy底层使用C语言编写,内部解除GIL(全局解释器锁),其对数组的操作速度不受Python GIL的影响。
5 ndarray数组的属性

数组的维度:

# 导入numpy模块并为模块设置别名
import numpy as np
# 创建一个维度是3行4列的ndarray数组
array01 = np.array([
    [80, 78, 98, 88],
    [89, 87, 89, 78],
    [78, 84, 89, 87]
])
array01.shape
Out[](3, 4)

数组的维数:

# 导入numpy模块并为模块设置别名
import numpy as np
# 创建一个维度是3行4列的ndarray数组
array01 = np.array([
    [80, 78, 98, 88],
    [89, 87, 89, 78],
    [78, 84, 89, 87]
])
array01.ndim
Out[]2

数组中的元素数量:

# 导入numpy模块并为模块设置别名
import numpy as np
# 创建一个维度是3行4列的ndarray数组
array01 = np.array([
    [80, 78, 98, 88],
    [89, 87, 89, 78],
    [78, 84, 89, 87]
])
array01.size
Out[]12

一个数组元素的长度(字节):

# 导入numpy模块并为模块设置别名
import numpy as np
# 创建一个维度是3行4列的ndarray数组
array01 = np.array([
    [80, 78, 98, 88],
    [89, 87, 89, 78],
    [78, 84, 89, 87]
])
array01.itemsize
Out[]8

数组元素的类型:

# 导入numpy模块并为模块设置别名
import numpy as np
# 创建一个维度是3行4列的ndarray数组
array01 = np.array([
    [80, 78, 98, 88],
    [89, 87, 89, 78],
    [78, 84, 89, 87]
])
array01.dtype
Out[]:dtype('int64')
6 ndarray数组的形状

一维数组:

import numpy as np
a = np.array([1, 2, 3, 4, 5])
print(a)
print(a.shape)
[1 2 3 4 5]
(5,) # 表示一维数组,5:数组中有5个元素

二维数组:

import numpy as np
b = np.array([
    [1, 2, 3, 4, 5],
    [4, 5, 6, 7, 8]
])
print(b)
print(b.shape)
[[1 2 3 4 5]
 [4 5 6 7 8]]
(2, 5) # 有两个元素,表示的是二维数组。2:二维数组中有两个一维数组;5:一维数组中有5个元素

三维数组(三维数组是二维数组的叠加):

import numpy as np
c = np.array([
    [[1, 2, 3, 4, 5],
    [4, 5, 6, 7, 8]],
    [[9, 10, 11, 12, 13],
    [14, 15, 16, 17, 18]]
])
print(c)
print(c.shape)
[[[ 1  2  3  4  5]
  [ 4  5  6  7  8]]
 [[ 9 10 11 12 13]
  [14 15 16 17 18]]]
(2, 2, 5) # 第一个2:有2个二维数组;第二个2:二维数组中有2个一维数组;3:在一维数组中有3个元素
7 ndarray数组的类型

不指定数组类型(整型):

import numpy as np
a = np.array([
    [[1, 2, 3, 4, 5, 6],
    [7, 8, 9, 10, 11,12],
    [12, 13, 14, 15, 16,17]],
    [[1, 2, 3, 4, 5, 6],
    [7, 8, 9, 10, 11,12],
    [12, 13, 14, 15, 16,12]]
])
a.dtype
dtype('int64')

不指定数组类型(小数):

import numpy as np
a = np.array([
    [[1.1, 2, 3, 4, 5, 6],
    [7, 8, 9, 10, 11,12],
    [12, 13, 14, 15, 16,17]],
    [[1, 2, 3, 4, 5, 6],
    [7, 8, 9, 10, 11,12],
    [12, 13, 14, 15, 16,12]]
])
a.dtype
dtype('float64')

如果不指定,整型默认是int64,小数默认是float64。如果指定数组类型:

指定数组类型,将整型指定为float64类型:

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

 [[ 1.  2.  3.  4.  5.  6.]
  [ 7.  8.  9. 10. 11. 12.]
  [12. 13. 14. 15. 16. 12.]]]
dtype('float64')

不指定数组类型(字符串):

import numpy as np
a = np.array(['I', 'Like' ,'qianqian'])
a
array(['I', 'Like', 'qianqian'], dtype='<U8')

指定数组类型(字符串):

import numpy as np
a = np.array(['I', 'Like' ,'qianqian'], dtype=np.string_)
a
array([b'I', b'Like', b'qianqian'], dtype='|S8') # S:String;8:数组中最长字符串是8个字母
8 ndarray数组的生成

从已存在的数组中生成数组的两种方法,numpy.arraynumpy.asarray方法,下面通过一个小案例来区别这两种方法:

首先创建一个数组作为已存在数组:

import numpy as np
a = np.array([[1, 2, 3, 4, 5, 6],[7,8,9,10,11,112]])
a
array([[  1,   2,   3,   4,   5,   6],
       [  7,   8,   9,  10,  11, 112]])

使用array在原有数组的基础上生成数组(深度拷贝):

a1 = np.array(a) # 深拷贝
a1[0, 0] = 0
a
array([[  1,   2,   3,   4,   5,   6],
       [  7,   8,   9,  10,  11, 112]])

使用asarray在原有数组的基础上生成数组:(浅拷贝)

a2 = np.asanyarray(a) # 浅拷贝
a2[0, 0] = 0
a
array([[  0,   2,   3,   4,   5,   6],
       [  7,   8,   9,  10,  11, 112]])

生成固定范围的数组:

创建等差数列的数组,指定数量,使用的函数是:linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None,axis=0)

import numpy as np
arr = np.linspace(0,21,6) # start:0,序列的起始值; stop:20,序列的终止值; num:5, 要生成的等间隔样例数量, 默认是50。endpoint:序列中是否是否包含stop值,默认是True
arr
array([ 0. ,  4.2,  8.4, 12.6, 16.8, 21. ])

创建等差数列的数组,指定步长,使用的函数:arange(start=None, *args, **kwargs)

import numpy as np
arr = np.arange(0, 20, 2, dtype=np.int64) # step:2,步长;dtype:数据类型
arr
array([ 0,  2,  4,  6,  8, 10, 12, 14, 16, 18])

创建等比数列,使用的函数:logspace(start, stop, num=50, endpoint=True, base=10.0, dtype=None,axis=0)

import numpy as np
# 注意这里是生成10的多少次方
arr = np.logspace(0, 2, 3) # num是要生成等比数列的数量;0、2的意思分别是10的0次方~10的2次方;3:生成3个数
arr
array([  1.,  10., 100.])

创建随机数组(正太分布方式),使用np.random模块创建正太分布有三种方式,分别是:randn(*dn),normal(loc=0.0, scale=1.0, size=None),standard_normal(size=None)。

  • randn:从标准动态分布中返回一个或多个样本值。
  • normal:返回指定形状的标准正太分布数组。loc:此动态分布的均值(对应着整个分布的中心);scale:概率分布的标准差,值越大越矮胖,反之越瘦高。size:输出的是shape,默认是None,只输出一个值。
  • standard_normal:返回指定形状的标准正太分布的数组

生成均值为1.75,标准差为1的100000000个正态分布数据。使用到的函数:normal(loc=0.0, scale=1.0, size=None)

# 导入相关模块
import numpy as np
import matplotlib.pyplot as plt
# 数据的准备
x = np.random.normal(1.75, 1, 100000000) # array是一维数组,也就是一个列表
# 创建画布
plt.figure(figsize=(8,4), dpi=100)
# 绘制图像(绘制直方图)
plt.hist(x, 1000) # 1000:1000组数据
# 显示图像
plt.show()

数据分析之Numpy库
模拟生成一组股票的涨跌幅数据:随机生成4支股票1周的交易日涨幅数据(随机生成涨跌幅在某个正太分布内,如均值是0,方差是1):

import numpy as np
arr = np.random.normal(0, 1, (4,5))
arr
array([[ 1.39648189,  0.17949331, -0.0393186 ,  1.54571909, -0.89729191],
       [-1.30231063, -0.21940802,  0.43169118, -0.68724142, -1.11523206],
       [-1.93539031, -2.21212029, -1.39101401, -2.27047266, -0.1254774 ],
       [ 1.67693295, -2.22111556,  1.5863305 ,  0.69848128,  2.25766984]])

创建随机数组(均匀分布方式),使用np.random模块创建正太分布有三种方式,分别是:rand(*dn),uniform(low=0.0, high=1.0, size=None),randint(low, high=None, size=None, dtype=‘l’)

  • rand:返回[0.0,1.0)内的一组均匀分布的数。
  • uniform:从一个均匀分布[low=0.0, hegh=1.0, size=None)中随机采样,low是采用下界,float类型,默认是0;high是采样下界,float类型,默认值是1。size是输出样本的数目,int或元祖类型。如size=(m,n,k)则输出mnk个样本,缺省时输出1个值。返回值:ndarray类型,其形状和参数size中的描述一致。
  • randint:从一个均匀分布中随机采样,生成一个整数或N维整数数组。对于取数范围,如果high不是None时,取[low,high)之间的随机数,否则取值[low,high)之间随机整数。
# 导入模块
import numpy as np
# 准别数据,生成均匀分布的数据
x = np.random.uniform(-1, 1, 100000000)
# 创建画布
plt.figure(figsize=(8,4), dpi=100)
# 绘制图像(绘制直方图)
plt.hist(x, 1000) # 1000:1000组数据
# 显示图像
plt.show()

数据分析之Numpy库

9 ndarray数组的索引和切片
  • 一维数组的索引和切片
import numpy as np
arr = np.array([1, 2, 3, 4])
print(arr)
arr[0]
[1 2 3 4]
1
  • 二维数组的索引和切片
import numpy as np
arr2 = np.array([[1, 2, 3, 4],[5, 6, 7, 8]])
print(arr2)
arr2[1,1]
[[1 2 3 4]
 [5 6 7 8]]
6
  • 三维数组的索引和切片
import numpy as np
arr3 = np.array([[[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]], [[13, 14, 15, 16], [17, 18, 19, 20], [21, 21, 22, 23]]])
print(arr3)
arr3[1, 1, 1]
[[[ 1  2  3  4]
  [ 5  6  7  8]
  [ 9 10 11 12]]

 [[13 14 15 16]
  [17 18 19 20]
  [21 21 22 23]]]
18
10 ndarray数组形状的修改
  • reshape(self, shape, order='C ')函数的应用
import numpy as np
arr = np.array([[1, 2, 3, 4, 5, 6], [7, 8, 9, 10, 11, 12], [13, 14, 15, 16, 17, 18]])
# 打印这个数组的形状
print(arr.shape)
# 修改数组的形状
arr2 = arr.reshape([6, 3])
# 打印改变后数组的形状
print(arr2.shape)
arr2
(3, 6)
(6, 3)
array([[ 1,  2,  3],
       [ 4,  5,  6],
       [ 7,  8,  9],
       [10, 11, 12],
       [13, 14, 15],
       [16, 17, 18]])

当不知到有多少列的时候:

import numpy as np
arr = np.array([[1, 2, 3, 4, 5, 6], [7, 8, 9, 10, 11, 12], [13, 14, 15, 16, 17, 18]])
# 打印这个数组的形状
print(arr.shape)
# 修改数组的形状
arr2 = arr.reshape([6, -1])
# 打印这个数组的形状
print(arr2.shape)
arr2
(3, 6)
(6, 3)
array([[ 1,  2,  3],
       [ 4,  5,  6],
       [ 7,  8,  9],
       [10, 11, 12],
       [13, 14, 15],
       [16, 17, 18]])

当不知道有多少行的时候:

import numpy as np
arr = np.array([[1, 2, 3, 4, 5, 6], [7, 8, 9, 10, 11, 12], [13, 14, 15, 16, 17, 18]])
# 打印这个数组的形状
print(arr.shape)
# 修改数组的形状
arr2 = arr.reshape([-1, 2])
# 打印这个数组的形状
print(arr2.shape)
arr2
(3, 6)
(9, 2)
array([[ 1,  2],
       [ 3,  4],
       [ 5,  6],
       [ 7,  8],
       [ 9, 10],
       [11, 12],
       [13, 14],
       [15, 16],
       [17, 18]])
  • resize(self, new_shape, refcheck=True)函数的应用,要区别与reshape方法,其返回结果并不是新的数组,而是把原来的数组给修改了
import numpy as np
arr = np.array([[1, 2, 3, 4, 5, 6], [7, 8, 9, 10, 11, 12], [13, 14, 15, 16, 17, 18]])
# 打印这个数组的形状
print(arr.shape)
# 修改数组的形状
arr.resize([2,8])
# 打印这个数组的形状
print(arr.shape)
arr
(3, 6)
(2, 8)
array([[ 1,  2,  3,  4,  5,  6,  7,  8],
       [ 9, 10, 11, 12, 13, 14, 15, 16]])
  • 数组的转置,将数组的行列进行互换,使用数组名.T
# 数组的转置
import numpy as np
arr = np.array([[1, 2, 3, 4, 5, 6], [7, 8, 9, 10, 11, 12], [13, 14, 15, 16, 17, 18]])
arr.T
array([[ 1,  7, 13],
       [ 2,  8, 14],
       [ 3,  9, 15],
       [ 4, 10, 16],
       [ 5, 11, 17],
       [ 6, 12, 18]])
11 ndarray数组类型的修改
  • ndarray.astype(type):返回修改类型之后的数组
# 返回修改了类型之后的数组
import numpy as np
arr = np.array([[1, 2, 3, 4, 5, 6], [7, 8, 9, 10, 11, 12], [13, 14, 15, 16, 17, 18]])
print(arr.dtype)
arr2 = arr.astype(np.float)
arr2
int64
array([[ 1.,  2.,  3.,  4.,  5.,  6.],
       [ 7.,  8.,  9., 10., 11., 12.],
       [13., 14., 15., 16., 17., 18.]])
  • ndarray.tostring([order])或者ndarray.tobytes([order]):构造包含数组原始数据字节的Python字节
# 构造包含数组原始数据字节的Python字节1
import numpy as np
arr = np.array([[1, 2, 3, 4, 5, 6], [7, 8, 9, 10, 11, 12], [13, 14, 15, 16, 17, 18]])
str_arr = arr.tostring()
str_arr
b'\x01\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x05\x00\x00\x00\x00\x00\x00\x00\x06\x00\x00\x00\x00\x00\x00\x00\x07\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\t\x00\x00\x00\x00\x00\x00\x00\n\x00\x00\x00\x00\x00\x00\x00\x0b\x00\x00\x00\x00\x00\x00\x00\x0c\x00\x00\x00\x00\x00\x00\x00\r\x00\x00\x00\x00\x00\x00\x00\x0e\x00\x00\x00\x00\x00\x00\x00\x0f\x00\x00\x00\x00\x00\x00\x00\x10\x00\x00\x00\x00\x00\x00\x00\x11\x00\x00\x00\x00\x00\x00\x00\x12\x00\x00\x00\x00\x00\x00\x00'
# 构造包含数组原始数据字节的Python字节2
import numpy as np
arr = np.array([[1, 2, 3, 4, 5, 6], [7, 8, 9, 10, 11, 12], [13, 14, 15, 16, 17, 18]])
str_arr = arr.tobytes()
str_arr
b'\x01\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x05\x00\x00\x00\x00\x00\x00\x00\x06\x00\x00\x00\x00\x00\x00\x00\x07\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\t\x00\x00\x00\x00\x00\x00\x00\n\x00\x00\x00\x00\x00\x00\x00\x0b\x00\x00\x00\x00\x00\x00\x00\x0c\x00\x00\x00\x00\x00\x00\x00\r\x00\x00\x00\x00\x00\x00\x00\x0e\x00\x00\x00\x00\x00\x00\x00\x0f\x00\x00\x00\x00\x00\x00\x00\x10\x00\x00\x00\x00\x00\x00\x00\x11\x00\x00\x00\x00\x00\x00\x00\x12\x00\x00\x00\x00\x00\x00\x00'
12 ndarray数组的去重

数组去重的方法是unique(ar, return_index=False, return_inverse=False,return_counts=False, axis=None):

# 返回修改了类型之后的数组
import numpy as np
arr = np.array([[1, 2, 3, 4, 5, 6], [7, 8, 2, 10, 5, 6], [13, 14, 15, 16, 17, 18]])
arr2 = np.unique(arr)
arr2
array([ 1,  2,  3,  4,  5,  6,  7,  8, 10, 13, 14, 15, 16, 17, 18])
13 ndarray的运算
  • 逻辑运算
# 生成10名同学5门课程的分数
import numpy as np
scores = np.random.randint(50, 100, (10, 5))
# 取出最后4名同学的成绩,用于逻辑判断
ret1 = scores[6:, 0:5] # 或者scores[6:, 0:5] 
# 逻辑判断,如果成绩不小于60分,标记为True,否则为False
ret2 = ret1 > 60 # 返回的结果是标记后的
'''
array([[False,  True,  True,  True,  True],
       [ True,  True,  True,  True, False],
       [ True,  True, False,  True,  True],
       [ True,  True, False,  True,  True]])
'''
ret1[ret1 > 60] = 1
ret1
'''
array([[54, 51, 59,  1,  1],
       [ 1,  1,  1,  1,  1],
       [ 1,  1, 60,  1,  1],
       [57,  1,  1,  1,  1]])
'''
  • 通用判断函数

numpy.all方法:

'''
numpy.all方法是:只要有一个不满足条件,就返回False;所有都满足条件,返回True
判断前两名同学的成绩是否都及格
'''
import numpy as np
scores = np.random.randint(50, 100, (10, 5))
print(scores[0:2, :])
ret = np.all(scores[0:2, :] > 90)
ret
[[77 81 89 51 66]
 [78 64 53 53 70]]
False

numpy.any方法:

'''
numpy.any方法是:只要有一个满足条件,就返回True;所有都不满足条件返回False
判断前两名同学的成绩是否有不小于90分的
'''
import numpy as np
scores = np.random.randint(50, 100, (10, 5))
print(scores[0:2, :])
ret = np.any(scores[0:2, :] > 90)
ret
[[82 97 82 79 53]
 [54 81 91 67 64]]
True
  • 三元运算符

通过使用numpy.where能够进行更加复杂的运算:

# 将前四名学生的前四门课程中成绩中大于60的置为1,否则置为0
import numpy as np
scores = np.random.randint(50, 100, (10, 5))[:4, :4]
print(scores)
np.where(scores > 60, 1, 0)
[[76 84 84 52]
 [52 85 50 90]
 [57 71 93 92]
 [90 72 66 67]]
array([[1, 1, 1, 0],
       [0, 1, 0, 1],
       [0, 1, 1, 1],
       [1, 1, 1, 1]])

复合逻辑需要结合np.logical_and和np.logical_or使用:

# 将前四名学生前四门课程中成绩大于60且小于90的置为1,否知置为0
import numpy as np
scores = np.random.randint(50, 100, (10, 5))[:4, :4]
print(scores)
np.where(np.logical_and(scores > 60, scores < 90), 1, 0)
[[61 99 91 92]
 [78 80 78 56]
 [63 88 80 59]
 [84 79 65 86]]
array([[1, 0, 0, 0],
       [1, 1, 1, 0],
       [1, 1, 1, 0],
       [1, 1, 1, 1]])
# 将前四名学生前四门课程中成绩大于90或小于60的置为1,否知置为0
import numpy as np
scores = np.random.randint(50, 100, (10, 5))[:4, :4]
print(scores)
np.where(np.logical_or(scores > 90, scores < 60), 1, 0)
[[76 63 99 78]
 [84 85 74 56]
 [72 72 92 61]
 [56 54 89 60]]
array([[0, 0, 1, 0],
       [0, 0, 0, 1],
       [0, 0, 1, 0],
       [1, 1, 0, 0]])
14 ndrray统计运算相关的函数

max(a, axis)函数的使用:

# 取最大值
import numpy as np
scores = np.random.randint(50, 100, (10, 5))
print(scores)
np.max(scores)
[[82 51 86 57 79]
 [90 87 50 97 90]
 [81 93 72 69 90]
 [86 50 83 65 83]
 [68 66 78 59 65]
 [71 64 56 50 72]
 [79 69 91 97 76]
 [68 67 64 83 54]
 [66 63 60 58 53]
 [87 64 63 55 60]]
97

min(a, axis)函数的使用:

# 取最小值
import numpy as np
scores = np.random.randint(50, 100, (10, 5))
print(scores)
np.min(scores)
[[83 81 55 73 93]
 [57 61 51 60 91]
 [66 77 83 95 56]
 [75 76 58 59 96]
 [90 72 72 53 84]
 [83 67 93 82 57]
 [50 91 51 98 62]
 [83 53 91 78 91]
 [99 77 93 81 99]
 [89 71 73 81 87]]
50

mean(a, axis, dtype)函数的使用:

# 取平均值
import numpy as np
scores = np.random.randint(50, 100, (10, 5))
print(scores)
np.mean(scores)
[[50 90 77 76 78]
 [92 84 76 59 58]
 [77 69 66 73 68]
 [69 57 64 94 75]
 [82 52 97 93 57]
 [73 53 88 64 60]
 [84 98 64 65 88]
 [72 54 67 61 57]
 [99 83 73 80 64]
 [70 63 65 94 58]]
72.6

也可以按照行和列求解最大值、最小值、平均值等,下面以求解最大值、最小值为例子:

# 按照列求最大值
import numpy as np
scores = np.random.randint(50, 100, (10, 5))
print(scores)
np.max(scores, axis=0)  # axis=0表示按照列来求解
[[57 66 72 90 69]
 [85 90 98 95 71]
 [97 75 83 57 55]
 [81 77 95 92 61]
 [79 68 79 54 66]
 [50 52 95 52 96]
 [55 64 86 54 73]
 [63 67 78 56 84]
 [54 76 92 88 89]
 [52 79 75 91 62]]
array([97, 90, 98, 95, 96])
# 按照行求最大值
import numpy as np
scores = np.random.randint(50, 100, (10, 5))
print(scores)
np.max(scores, axis=1)  # axis=1表示按照行来求解
[[54 77 71 85 54]
 [65 89 95 69 75]
 [56 95 54 75 63]
 [62 84 58 94 89]
 [66 51 55 91 85]
 [70 97 75 70 84]
 [94 80 83 59 90]
 [76 70 55 99 74]
 [79 60 81 99 57]
 [96 82 50 57 80]]
array([85, 95, 95, 94, 91, 97, 94, 99, 99, 96])

argmax(a, axis)方法的使用:

# 最大值的下标
import numpy as np
scores = np.random.randint(50, 100, (10, 5))
print(scores)
np.argmax(scores)
[[67 73 95 94 92]
 [52 91 74 96 76]
 [82 70 61 86 81]
 [90 69 57 86 66]
 [50 53 85 69 65]
 [84 69 81 61 52]
 [69 61 65 91 70]
 [87 50 68 78 83]
 [72 93 62 79 89]
 [99 75 77 53 87]]
45
# 按列求最大值的下标
import numpy as np
scores = np.random.randint(50, 100, (10, 5))
print(scores)
np.argmax(scores, axis=0)
[[85 68 60 71 62]
 [65 71 86 60 84]
 [57 81 76 58 95]
 [57 83 66 73 55]
 [88 77 54 81 68]
 [78 53 54 99 54]
 [99 86 63 56 97]
 [92 96 52 83 57]
 [85 83 65 55 76]
 [79 77 67 63 69]]
array([6, 7, 1, 5, 6])
# 按行求最大值的下标
import numpy as np
scores = np.random.randint(50, 100, (10, 5))
print(scores)
np.argmax(scores, axis=1)
[[78 53 79 82 60]
 [61 92 72 56 61]
 [71 64 80 81 81]
 [95 55 81 85 74]
 [63 82 65 89 91]
 [94 62 52 61 93]
 [91 69 98 54 63]
 [76 53 93 86 83]
 [97 98 92 52 95]
 [70 60 75 83 74]]
array([3, 1, 3, 0, 4, 0, 2, 2, 1, 3])

argmin(a, axis)的使用同argmax(a, axis)的相似,统计运算中还可以求中位数[median(a, axis)]、平均值、标准差[std(a, axis, dtype)]和方差[var(a, axis, dtype)]等。

15 数组间的运算

数组与数之间的运算:

执行程序1:

import numpy as np
arr = np.array([[1, 2, 3, 4, 5], [6, 7, 8, 9, 10]])
arr + 3 # 所有元素加3

打印结果:

array([[ 4,  5,  6,  7,  8],
       [ 9, 10, 11, 12, 13]])

执行程序2:

import numpy as np
arr = np.array([[1, 2, 3, 4, 5], [6, 7, 8, 9, 10]])
arr / 2 # 所有元素除以2

打印结果:

array([[0.5, 1. , 1.5, 2. , 2.5],
       [3. , 3.5, 4. , 4.5, 5. ]])

执行程序3:

import numpy as np
arr = np.array([[1, 2, 3, 4, 5], [6, 7, 8, 9, 10]])
arr * 3 # 所有元素乘3

打印结果:

array([[ 3,  6,  9, 12, 15],
       [18, 21, 24, 27, 30]])

注意:如果是列表*3,则只会分别粘贴复制3次列表中的元素,组成新的列表

数组与数组的运算:(不同形状的数组是不可以在一起运算的)

测试程序:

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

测试结果:

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-44-18acd144a7ff> in <module>
      2 arr1 = np.array([[1, 2, 3, 4], [5, 6, 7, 8]])
      3 arr2 = np.array([[1, 2, 3, 4, 5], [6, 7, 8, 9, 10]])
----> 4 arr1 + arr2

ValueError: operands could not be broadcast together with shapes (2,4) (2,5) 

广播机制:数组在进行矢量运算时,要求数组的形状是相等的。当形状不相等的数组执行算术运算时,就会出现广播机制,该机制会对数组进行扩展,使数组的形状属性值一样。这样,就可以进行矢量化运算。广播机制实现了两个或两个以上数组的运算,即使这些数组的shape不是完全相同的,只要满足一个条件即可:

  • 数组的某一维度等长
  • 其中一个数组的某一个维度是1

执行程序:

import numpy as np
arr1 = np.array([[1, 2, 3, 4, 5, 6], [7, 8, 9, 10, 11, 12]])
arr2 = np.array([[1], [2]])
print('arr1的形状是:',arr1.shape)
print('arr2的形状是:',arr2.shape)
arr1 + arr2

执行结果:

arr1的形状是: (2, 6)
arr2的形状是: (2, 1)
array([[ 2,  3,  4,  5,  6,  7],
       [ 9, 10, 11, 12, 13, 14]])

广播机制需要扩展维度小的数组,使得它与维度大的数组的shape值相同,以便使用元素级函数或者运算符进行运算。

16 矩阵与向量相关

矩阵和数组的区别是矩阵必须是二维的,而数组可以是多维的。矩阵和向量的区别是向量是特殊的矩阵。
矩阵的加法:行和列相等可以进行加法,对应元素进行加和。
标量乘法:矩阵中的每个元素都要一一和标量进行相乘。
矩阵和向量乘法:m * n阶的矩阵和n * 1阶的向量进行相乘,得到m * 1阶的向量
矩阵乘法:m * n矩阵乘以n * o,得到m*n阶矩阵
矩阵乘法的性质:

  • 矩阵乘法不满足交换律:AxB不等于BxA
  • 矩阵乘法满足结合律:(AxB)xC=Ax(BxC)
  • 单位矩阵:主对角线上的元素都是1,其它元素都是0,这种矩阵是单位矩阵

矩阵的逆:如矩阵是一个m*m矩阵(方阵),如果有逆矩阵,则AA-1=A-1A。低阶矩阵球逆的方法是待定系数法和初等变换
矩阵的转置:矩阵的行转置后变成矩阵的列,矩阵的列变成矩阵的行。
矩阵的运算:矩阵的运算可以使用在大学求最终成绩上,很多位学生(决定矩阵的行数)的平时成绩和期末成绩组成n行2列的矩阵,再乘以0.7和0.3组成的2行1列的矩阵,得到n行1列的矩阵就是每位学生的最终成绩。在numpy库中矩阵乘法使用到matmul和dot函数:两者相同点是都可以做矩阵之间的乘法,不同点是matmul不支持矩阵与标量的乘法,而dot支持

测试两者都可以做矩阵之间的乘法

# 测试dot和matmul函数都可以做矩阵之间的乘法
import numpy as np
a = np.array([[89, 90], [88, 89], [87, 78]])
b = np.array([0.7, 0.3])
arr1 = np.matmul(a, b)
print(arr1)
arr2 = np.dot(a, b)
print(arr2)

测试结果:

[89.3 88.3 84.3]
[89.3 88.3 84.3]

测试只有dot函数支持矩阵与标量的乘法:

# 测试只有dot函数支持矩阵与标量的乘法
import numpy as np
a = np.array([[89, 90], [88, 89], [87, 78]])
arr1= np.dot(2,a)
print(arr1)
arr2= np.matmul(2, a)
[[178 180]
 [176 178]
 [174 156]]
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-59-653e8ec1b561> in <module>
      4 arr1= np.dot(2,a)
      5 print(arr1)
----> 6 arr2= np.matmul(2, a)

ValueError: matmul: Input operand 0 does not have enough dimensions (has 0, gufunc core with signature (n?,k),(k,m?)->(n?,m?) requires 1)

本文地址:https://blog.csdn.net/Thanlon/article/details/107097094