第2章 Python使用入门
2.1 Python概述
2.1.1 常用库
表2.1 Win Python 3.8.9 包含的常用库
库名 | 库说明 | 版本号 |
numpy+mkl | 科学计算和数据分析的基础库 | 1.20.2 |
SciPy | Numpy基础上的科学计算库 | 1.6.2 |
SymPy | 符号计算库 | 1.8 |
Pandas | Numpy基础上的数据分析库 | 1.2.4 |
Matplotlib | 数据可视化库 | 3.4.1 |
Scikit-learn | 机器学习库 | 0.24.1 |
Statsmodels | SciPy统计函数的补充库 | 0.12.2 |
NetworkX | 图论和复杂网络库 | 2.5.1 |
Cvxpy | 凸优化库 | 1.1.12 |
NLTK | 自然语言库 | 3.6.1 |
PIL | 数字图像处理库 | (pillow)8.2.0 |
2.1.2 Python核心工具库
Python有十几万个第三方库,下载这些库文件推荐下面两个网址:
SciPy上的6个核心工具库。
1. Numpy——Python用于科学计算的基础工具库
(1)强大的多维数组对象;
(2)复杂的函数功能;
(3)集成C/C++和FORTRAN代码的工具;
(4)有用的线性代数、傅里叶变换和随机数功能等。
import numpy as np
2. SciPy——完善Numpy的功能
提供文件输入、输出功能,为多种应用提供大量工具和算法,如基本函数、特殊函数、积分、优化、插值、傅里叶变换、信号处理、线性代数、系数特征值、稀疏图、数据结构、数理统计和多维图像处理等。
3. Matplotlib——一个包含各种绘图模块的库
能根据数组创建高质量的图形,并交互式地显示它们。
Matplotlib提供了pylab接口,pylab包含许多像MATLAB一样的绘图组件。
import matplotlib.pyplot as plt
或者
import pylab as plt
4. IPython——满足Python交互式shell命令的需要
基于shell、Web浏览器和应用程序接口的Python版本,具有图形化集成、自定义指令、丰富的历史记录和并行计算等增强功能。它通过脚本、数据和相应结果清晰又有效地说明了各种操作。
5. Sympy——一个Python的科学计算库
用一套强大的符号计算体系完成诸如多项式求值、求极限、解方程、求积分、微分方程、级数展开、矩阵运输等计算问题。
6. Pandas——处理Numpy和SciPy所不能处理的数据问题
可以处理包含不同类型数据的复杂表格和时间序列。Pandas可轻松加载各种形式的数据,可随意对数据进行切片、切块、处理缺失元素、添加、重命名、聚合、整形和可视化等操作。
import pandas as pd
2.1.3 Python编程规范
(1)严格使用缩进体现代码的逻辑从属关系;
(2)每个import只导入一个模块,按标准库、扩展库、自定义库顺序依次导入;
(3)建议在类、函数定义、完整功能代码后空一行,运算符两侧空格、逗号后空格;
(4)避免语句过长,适当使用 "\",或圆括号;
(5)书写复杂表达式时,可适当使用圆括号;
(6)进行必要的注释,# 、""" """;
(7)冒号和缩进通常配合使用;
(8)程序第一行或解释器提示符后第一列,前面不能空格;语句以回车符结束;同一行多条语句间用 ;分隔。
2.2 Python 基本数据类型
2.2.1 数字(number)
(1)整型(int),浮点型(float),复数型(complex),布尔型(bool)
(2)数据转换
int(a)
float(b)
complex(c,d)
2.2.2 字符串(string)
字符串用 ' 或 " 括起来。创建字符串:
str1 = "Hello World!"
访问字符串,使用 [ ] 截取字符串,基本语法:
变量 [ 头下标 : 尾下标 ]
从左往右索引以0开始,从右往左索引以-1开始。
例2.1 字符串
#程序文件 ex2_1.py
str1 = "Hello World!"
print(str1) # 输出字符串
print(str1[0:-1]) # 输出第一个到倒数第二个的所有字符
print(str1[-1]) # 输出字符串的最后一个字符
print(str1[2:5]) # 输出从第三个到第五个的字符
print(str1[2:]) # 输出从第三个开始的所有字符
print(str1 * 2) # 输出字符串两次
除可使用内置函数和运算符对字符串进行操作,Python字符串对象本身还提供大量方法用于字符串的检测、替换和排版等操作。注意:字符串对象是不可变的,所以字符串对象提供的涉及字符“修改”的方法都时返回修改后的新字符串,并不对原始字符串做任何修改。
(1)find( )、rfind( )、index( )、rindex( )、count( )
find( )和rfind( )分别用来查找一个字符串在另一个字符串指定范围中首次和最后一次出现的位置,如果不存在则返回-1;
index( )和rindex( )用来返回一个字符串在另一个字符串指定范围中首次和最后一次出现的位置,如果不存在则抛出异常;
count( )用来返回一个字符串在另一个字符串中出现的次数,如果不存在则返回0。
(2)split( )、rsplit( )
split( )和rsplit( )分别用来以指定字符为分隔符,从字符串左端和右端开始将其分割成多个字符串,并返回包含分割结果的列表。
若不指定分隔符,则字符串中任何空白字符(包括空格、换行符、制表符等)的连续出现都将被认为是分隔符,并且自动删除字符串两侧的空白字符,返回包含最终分割结果的列表。
(3)point( )
point( )用来将列表中多个字符串进行连接,并在相邻两个字符串之间插入指定字符,返回新字符串。
(4)strip( )、rstrip( )、lstrip( )
分别用来将删除两端、右端或左端连续的空白字符或指定字符。
(5)startswith( )、endswith( )
用来判断字符串是否以指定字符串开始或结束,可以接收两个整数参数来限定字符串的检测范围。
还可接收一个字符串元组作为参数来表示前缀或后缀。
例2.2 统计下列5行字符串中字符a、c、g、t出现的频数。
#程序文件ex2_2.py
import numpy as np
a = []
with open('data2_2.txt') as f:
for (i, s) in enumerate(f):
a.append([s.count('a'), s.count('c'), s.count('g'), s.count('t')])
b = np.array(a)
print(b)
【enumerate() 函数用于将一个可遍历的数据对象(如列表、元组或字符串)组合为一个索引序列,同时列出数据和数据下标,一般用在 for 循环当中。】
2.2.3 列表(List)
列表中元素的类型可以不同,支持数字、字符串,可嵌套其它列表。
列表是写在 [ ] 里,用逗号分隔开的元素列表,可以被索引和截取,截取后返回一个新列表。
例 2.3 列表
# 程序文件ex2_3.py
L = ['abc', 12, 3.45, 'Python', 2.789]
print(L) # 输出完整列表
print(L[0]) # 输出列表的第一个元素
L[0] = 'a' # 修改列表的第一个元素
L[1:3] = ['b', 'Hello'] # 修改列表的第二、三个元素
print(L)
L[2:4] = [] # 删除列表的第三、第四个元素
print(L)
例 2.4 使用列表推导式实现嵌套列表的平铺
# 程序文件ex2_4.py
a = [[1,2,3], [4,5,6], [7,8,9]]
d = [c for b in a for c in b]
print(d)
例 2.5 (1) 在列表推导式中使用 if 过滤不符合条件的元素
# 程序文件 ex2_5_1.py
import os
fn = [filename for filename in
os.listdir('D:\Programs\Python\Python37')
if filename.endswith(('.exe', '.py'))]
print(fn)
(2) 使用列表推导式查找数组中最大元素的所有位置
# 程序文件 ex2_5_2.py
from numpy.random import randint
import numpy as np
a = randint(10, 20, 16) # 生成16个[10, 20)上的随机整数
ma = max(a)
ind1 = [index for index, value in enumerate(a) if value == ma]
ind2 = np.where(a == ma) # 第二种方法求最大值的地址
print(ind1)
print(ind2[0])
2.2.4 元组(tuple)
元组是逗号分隔的对象序列(不带括号的列表),不能被修改。
my_tuple = 1, 2, 3 # 第一个元组
my_tuple = (1, 2, 3) # 与上面相同
singleton = 1, # 逗号表明该对象是一个元组
(1)元组通过 ( ) 构成。a = ( ) 表示空元组,b1 = (9, ) 表示只有一个元素 9 的元组,b2 = (9) 表示 b2 为整数 9 。
(2)元组仍是一种序列,获取列表元素的索引方法亦适用。
(3)元组知识存储数据的不可变容器,只有 count 和 index 可用,用法与列表一样。
例 2.6 元组
# 程序文件 ex2_6.py
T = ('abc', 12, 3.45, 'Python', 2.789)
print(T) # 输出完整元组
print(T[-1]) # 输出元组的最后一个元素
print(T[1:3]) # 输出元组的第二、第三元素
2.2.5 集合(set)
集合是一个无序不重复元素的序列。基本功能是进行成员关系测试和删除重复元素。
创建集合:(1)大括号内多个用逗号分隔的数据;
(2)set( ) 函数将字符串、列表、元组等类型的数据转换为集合类型的数据。
要删除列表中大量重复的元素,可先 set( ) 将列表转换为集合,再 list ( ) 转换为列表。
例 2.7 集合操作示例
# 程序文件 ex2_7.py
student = {'Tom', 'Jim', 'Mary', 'Tom', 'Jack', 'Rose'}
print(student)
a = set('abcdabc')
print(a) # 每次输出是不一样的
2.2.6 字典(dictionary)
字典是无序的对象集合,元素通过键存取,而不是通过索引值存取。
字典是一种映射类型,用 { } 标识,是一个无序的键(key) : 值(value)对集合。key唯一,但value不必唯一,值可以取任意数据类型,键是不可变的,如字符串、数字或元组。
例 2.8 字典
# 程序文件 ex2_8.py
dict1 = {'Alice': '123', 'Beth': '456', 'Cecil': 'abc'}
print(dict1['Alice']) # 输出 123
dict1['new'] = 'Hello' # 增加新的键值对
dict1['Alice'] = '1234' # 修改已有键值对
dict2 = {'abc': 123, 456: 78.9}
print(dict2[456]) # 输出78.9
get( ) 用来放回指定“键”对应的“值”,并且允许指定该键不存在时返回特定的“值”。
例 2.9 get( )
# 程序文件 ex2_9.py
Dict = {'age': 18, 'score': [98, 97], 'name': 'Zhang', 'sex': 'male'}
print(Dict['age']) # 输出 18
print(Dict.get('age')) # 输出 18
print(Dict.get('address', 'Not Exists.')) # 输出 Not Exists.
print(Dict['address']) # 出错
可以对字典对象进行迭代或遍历,默认遍历“键”,若需遍历字典的元素,必须使用 items( ),若需遍历“值”,必须使用 values( )。
例 2.10 字典元素的访问
# 程序文件 ex2_10.py
Dict = {'age': 18, 'score': [98,97], 'name': 'Zhang', 'sex': 'male'}
for item in Dict: # 遍历输出字典的“键”
print(item)
print("----------")
for item in Dict.items(): # 遍历输出字典的元素
print(item)
print("----------")
for value in Dict.values(): # 遍历输出字典的值
print(value)
例 2.11 首先生成包含1000个随机字符的字符串,然后统计每个字符的出现次数
# 程序文件 ex2_11_1.py
import string
import random
x = string.ascii_letters + string.digits
y = ''.join([random.choice(x) for i in range(1000)])
# choice() 用于从多个元素中随机选择一个
d = dict() # 构造空字典
for ch in y:
d[ch] = d.get(ch, 0) +1
for k,v in sorted(d.items()):
print(k, ':', v)
也可使用 collections 模块的 Counter( ) 直接做出统计。
# 程序文件 ex2_11_2.py
import string, random, collections
x = string.ascii_letters + string.digits
y = ''.join([random.choice(x) for i in range(1000)])
count = collections.Counter(y)
for k,v in sorted(count.items()):
print(k, ':', v)
2.3 函数
2.3.1 自定义函数
1. 函数定义及调用
def functionName (formalParameters):
functionBody
函数体不可为空,可用 pass 来表示空语句。
(1)函数定义须在调用前;
(2)返回值不是必需的,若没有 return,默认返回值 None。
例 2.12 分别编写求 n! 和输出斐波那契数列的函数,并调用测试
# 程序文件 ex2_12_1.py
def factorial(n): # 定义阶乘函数
r = 1
while n>1:
r *= n
n -= 1
return r
def fib(n): # 定义输出斐波那契数列函数
a, b = 1, 1
while a<n:
print(a, end = ' ')
a, b = b, a+b
print('%d! = %d'%(5,factorial(5)))
fib(200)
也可将函数保存为 .py 文件,供其它程序调用。
例 2.13 数据分组
# 程序文件 ex2_13.py
def bifurcate(L, fn):
return[[x for x in L if fn(x)],
[x for x in L if not fn(x)]]
s = bifurcate_by(['beep', 'boop', 'foo', 'bar'], lambda x: x[0] == 'b')
print(s)
2. 匿名函数
使用 lambda 句柄创建匿名函数。
lambda arg1[, arg2, ..., argn]: expression
例 2.14 用匿名函数,求3个数的乘积及列表元素的值
# 程序文件 ex2_14.py
f = lambda x, y, z: x*y*z
L = lambda x: [x**2, x**3, x**4]
print(f(3, 4, 5))
print(L(2))
2.3.2 模块的导入与使用
公共类、函数都可以放在独立文件中,这样独立文件就称为模块。
标准库中有与时间相关的 time、datetime 模块,随机数的 random 模块,与操作系统交互的 os 模块,对 Python 解释器相关操作的 sys 模块,数学计算的 math 模块等。
1. 标准库与扩展库中对象的导入与使用
(1)import 模块名 [as 别名]
导入模块后,使用时需在对象之前加上模块名前缀——模块名. 对象名。
例 2.15 加载模块
# 程序文件 ex2_15.py
import math # 导入标准库 math
import random # 导入标准库 random
import numpy.random as nr # 导入 numpy 库中的 random 模块
a = math.gcd(12, 21) # 计算最大公约数,a = 3
b = random.randint(0, 2) # 获得[0, 2)区间上的随机整数
c = nr.randint(0, 2, (4, 3)) # 获得[0, 2)区间上的 4*3 随机整数矩阵
print(a);print(b);print(c)
(2)from 模块名 import 对象名 [as 别名]
仅导入指定的对象,可以减少查询次数,提高访问速度,同时减少输入的代码量,不须使用模块名作为前缀。
例 2.16 导入模块
# 程序文件 ex2_16.py
from random import sample
from numpy.random import randint
a = sample(range(10), 5) # 在[0, 9]区间上选择不重复的5个整数
b = randint(0, 10, 5) # 在[0, 9]区间上生成5个随机整数
print(a); print(b)
(3)from 模块名 import *
一次导入模块中的所有对象,直接使用模块中的对象而无需模块名前缀。一般不推荐。
例 2.17 导入模块
# 程序文件ex2_17.py
from math import *
a = sin(3) # 求正弦值
b = pi # 常数 Π
c = e # 常数 e
d = radians(180) # 把角度转换为弧度
print(a); print(b); print(c); print(d)
2. 自定义函数的导入
Python中,每个包含函数的Python文件可以作为一个模块,模块名就是文件名。
2.3.3 Python常用内置函数用法
dir(__builtins__) # 查看所有内置函数和内置对象
help(functiName) # 查看某个函数的用法
abs(x) | 返回实数 x 的绝对值或复数 x 的模 |
chr(x) | 返回 Unicode 编码为 x 的字符 |
enumerate(iterable[ , start]) | 返回包含元素形式为 (0, iterable[0]), (1, iterable[1]), (2, iterable[2]) 等的迭代器对象,start 表示索引的起始值 |
eval(s) | 计算并返回字符串 s 中表达式的值 |
filter(func, iterable) | 用于过滤序列。以函数 func 为条件,对每个元素进行判断,过滤掉 func 返回 False 的元素 |
hash(obj) | 返回对象 obj 的哈希值 |
help(obj) | 返回对象 obj 的帮助信息 |
len(obj) | 返回对象 obj 包含的元素个数 |
map(func, *iterables) | 返回包含若干函数值的 map 对象,函数 func 的参数分别来自 iterable 指定的一个或多个迭代对象 |
max(iterable) max(arg1, arg2, ..., argn) | 返回可迭代对象或多个参数中的最大值 |
min(iterable) min(arg1, arg2, ..., argn) | 返回可迭代对象或多个参数中的最小值 |
ord(x) | 返回一个字符 x 的 Unicode 编码 |
pow(x, y[ , z]) | 计算 x 的 y 次幂;若给定 z, 则对结果取模,最终结果 pow(x, y) % z |
range(stop) range(start, stop[ , step]) | 返回 range 对象,[0, stop) 上的整数或 [start, stop) 上步长 step 的整数 |
reversed(seq) | 返回参数 seq 序列的逆向序列的迭代器对象 |
round(x[ , 小数位数]) | 对 x 四舍五入,若不指定小数位数,返回整数 |
sorted(iterable, key = None, reverse = False) | 返回排序后的列表,key 指定排序规则,reverse 指定升序或降序 |
str(obj) | 把对象 obj 直接转换为字符串 |
sum(x, start = 0) | 返回序列 x 所有元素之和,要求 x 所有元素支持加法运算 |
zip(seq1[ , seq2[ , ...]]) | 返回 zip 对象,其中元素为 (seq1[i], seq2[i], ...) 形式的元组,最终结果中包含的元素个数取决于所有参数序列或可迭代对象中最短的那个 |
1. 排序
例 2.19 sorted( )
# 程序文件 ex2_19.py
import numpy.random as nr
x1 = list(range(9, 21))
nr.shuffle(x1) # shuffle()用来随机打乱顺序
x2 = sorted(x1) # 按照从小到大排序
x3 = sorted(x1, reverse = True) # 按照从大到小排序
x4 = sorted(x1, key = lambda item: len(str(item))) # 以指定的规则排序
print(x1); print(x2); print(x3); print(x4)
2. 枚举
例 2.20 enumerate( )
# 程序文件 ex2_20.py
x1 = 'abcde'
x2 = list(enumerate(x1))
for ind, ch in enumerate(x1):
print(ch)
3. map( ) 函数
例2.21 map( )
# 程序文件 ex2_21.py
import random
x = random.randint(1e5, 1e8) # 生成一个随机整数
y = list(map(int, str(x))) # 提出每位上的数字
z = list(map(lambda x, y: x%2 == 1 and y%2 == 0, [1, 3, 2, 4, 1], [3, 2, 1, 2]))
print(x); print(y); print(z)
4. filter( ) 函数
例 2.22 filter( )
# 程序文件 ex2_22.py
a = filter(lambda x: x>0, [1, 11, 2, 45, 7, 6, 13])
b = filter(lambda x: x.isalnum(), ['abc', 'xy12', '***'])
# isalnum() 是测试是否为字母或数字的方法
print(list(a)); print(list(b))
例 2.23 过滤重复值
# 程序文件 ex2_23.py
def filter_non_unique(L):
return [item for item in L if L.count(item) == 1]
a = filter_non_unique([1, 2, 2, 3, 4, 4, 5])
print(a)
5. zip( ) 函数
例 2.24 zip( ) 使用示例
# 程序文件 ex2_24.py
s1 = [str(x)+str(y) for x, y in zip(['v']*4, range(1, 5))]
s2 = list(zip('abcd', range(4)))
print(s1); print(s2)
2.4 Numpy 库
2.4.1 Numpy 的基本使用
列表中所保存的是对象的指针。
array 对象直接保存数值。
Numpy 提供两种基本对象:ndarray 存储单一数据类型的多维数组;
ufunc 是能够对数组进行处理的函数。
1. 模块导入
import numpy as np
2. 数组的创建
(1)使用 array 将列表或元组转换为 ndarray 数组;
(2)使用 arange 在给定区间创建等差数列,
arange(start = None, stop = None, step = None, dtype = None)
(3)使用 linspace 在给定区间创建间隔相等的数组,
linspace(start, stop, num = 50, endpoint = True)
(4)使用 logspace 在给定区间生成等比数组,
logspace(start, stop, num = 50, endpoint = True, base = 10.0)
例 2.25 数组
# 程序文件 ex2_25.py
import numpy as np
a1 = np.array([1, 2, 3, 4]) # 生成整型数组
a2 = a1.astype(float)
a3 = np.array([1, 2, 3, 4], dtype = float) # 浮点数
print(a1.dtype); print(a2.dtype); print(a3.dtype)
b = np.array([[1, 2, 3], [4, 5, 6]])
c = np.arange(1, 4) # 生成数组 [1, 2, 3, 4]
d = np.linspace(1, 4, 4) # 生成数组 [1, 2, 3, 4]
e = np.logspace(1, 3, 3, base = 2) # 生成数组 [2, 4, 8]
(5)使用 ones,zeros,empty 和 ones_like 等系列函数
例 2.26 数组
# 程序文件 ex2_26.py
import numpy as np
a = np.ones(4, dtype = int) # 输出[1, 1, 1, 1]
b = np.ones((4,), dtype = int) # 同a
c = np.ones((4, 1)) # 输出 4 行 1 列的数组
d = np.zeros(4) # 输出 [0, 0, 0, 0]
e = np.empty(3) # 生成 3 个元素的空数组行向量
f = np.eye(3) # 生成 3 阶单位矩阵
g = np.eye(3, k = 1) # 生成第 k 对角线元素为 1,其它元素为 0 的 3 阶方针
h = np.zeros_like(a) # 生成与 a 同维的全 0 数组
3. 数组元素的索引
(1)对一维数组而言,list 和 array 的切片操作相同;
(2)二维 list 引用方式为 a[i][j],array 应用还可以为 a[i, j];
(3)数组还可以布尔索引及花式索引。
例 2.27 数组元素的索引
# 程序文件 ex2_27.py
import numpy as np
a = np.arange(16).reshape(4,4) # 生成 4 行 4 列的数组
b = a[1][2] # 输出6
c = a[1, 2] # 同 b
d = a[1:2, 2:3] # 输出[[6]]
x = np.array([0, 1, 2, 1])
print(a[x==1]) # 输出 a 的第 2、4 行元素
2.4.2 矩阵合并与分割
1. 矩阵合并
例 2.28 矩阵合并
# 程序文件 ex2_28.py
import numpy as np
a = np.arange(16).reshape(4, 4) # 生成 4 行 4 列的数组
b = np.floor(5*np.random.random((2, 4)))
c = np.ceil(6*np.random.random((4, 2)))
d = np.vstack([a, b]) # 上下合并矩阵
e = np.hstack([a, c]) # 左右合并矩阵
2. 矩阵分割
例 2.29 矩阵分割
# 程序文件 ex2_29.py
import numpy as np
a = np.arange(16).reshape(4, 4) # 生成 4 行 4 列的数组
b = np.vsplit(a, 2) # 行分割
print('行分割:\n', b[0], '\n', b[1])
c = np.hsplit(a, 4) # 列分割
print('列分割:\n', c[0], '\n', c[1], '\n', c[2], '\n', c[3])
2.4.3 矩阵的简单运算
1. 求和
例 2.30 矩阵元素求和
# 程序文件 ex2_30.py
import numpy as np
a = np.array([[0, 3, 4], [1, 6, 4]])
b = a.sum() # 使用方法,求矩阵所有元素的和
c1 = sum(a) # 内置函数求矩阵逐列元素的和
c2 = np.sum(a, axis=0) # 使用函数,求矩阵逐列元素的和
c3 = np.sum(a, axis=0, keepdims=True) # 逐列求和
print(c2.shape, c3.shape) # c2是(3,)数组,c3是(1, 3)数组
2. 矩阵的逐个元素运算
对于 ndarray 数组,+、-、*、/ 都是对应的逐个元素运算。乘幂 ** 也是对应逐个元素运算。
例 2.31 逐个元素运算
# 程序文件 ex2_31.py
import numpy as np
a = np.array([[0, 3, 4], [1, 6, 4]])
b = np.array(([1, 2, 3], [2, 1, 4]))
c = a/b # 两个矩阵对应元素相除
d = np.array([2, 3, 2])
e = a*b # d 先广播成与 a 同维数的矩阵,再逐个元素相乘
f = np.array([[3], [2]])
g = a*f # f 先广播成与 a 同维数的矩阵,再逐个元素相乘
h = a**(1/2) # a 矩阵逐个元素的 1/2 次幂
3. 矩阵乘法
例 2.32 矩阵乘法
# 程序文件 ex2_32.py
import numpy as np
a = np.ones(4)
b = np.arange(2, 10, 2)
c = a @ b # a 作为行向量,b 作为列向量
d = np.arange(16).reshape(4, 4)
f = a @ d # a 作为行向量
g = d @ a # a 作为列向量
2.4.4 矩阵运算与线性代数
函数 | 说明 |
---|---|
norm | 求向量或矩阵的范数 |
inv | 求矩阵的逆阵 |
pinv | 求矩阵的广义逆阵 |
solve | 求解线性方程组 |
det | 求矩阵的行列式 |
lstsq | 最小二乘法求解超定线性方程组 |
eig | 求矩阵的特征值和特征向量 |
eigvals | 求矩阵的特征值 |
svd | 矩阵的奇异值分解 |
qr | 矩阵的QR分 |
1. 范数计算
norm(x, ord=None, axis=None, keepdims=False)
例 2.33 求下列矩阵各个行向量的 2 范数,各个列向量的 2 范数和矩阵 2 范数。
# 程序文件 ex2_33.py
import numpy as np
a = np.array([[0, 3, 4], [1, 6, 4]])
b = np.linalg.norm(a, axis = 1) # 求行向量 2 范数
c = np.linalg.norm(a, axis = 0) # 求列向量 2 范数
d = np.linalg.norm(a) # 求矩阵 2 范数
print('行向量 2 范数为:', np.round(b, 4))
print('列向量 2 范数为:', np.round(c, 4))
print('矩阵 2 范数为:', np.round(d, 4))
2. 求解线性方程组
例 2.34 求线性方程组
# 程序文件 ex2_34.py
import numpy as np
a = np.array([[3, 1],[1, 2]])
b = np.array([9, 8])
x1 = np.linalg.inv(a) @ b # 第一种解法
x2 = np.linalg.solve(a, b) # 第二种解法
print(x1); print(x2)
3. 求超定线性方程组的最小二乘解
例 2.35 求线性方程组
# 程序文件 ex2_35.py
import numpy as np
a = np.array([[3, 1], [1, 2], [1, 1]])
b = np.array([9, 8, 6])
x = np.linalg.pinv(a) @ b
print(np.round(x, 4))
例 2.36 求矩阵的特征值和特征向量
# 程序文件 ex2_36.py
import numpy as np
a = np.eye(4)
b = np.rot90(a)
c, d = np.linalg.eig(b)
print('特征值为:', c)
print('特征向量为:\n', d)
2.5 Pandas 库
2.5.1 Pandas 基本操作
三种数据结构:
(1)Series:带标签的一维数据
(2)DataFrame:带标签且大小可变的二维表格结构
(3)Panel:带标签且大小可变的三维数组
例 2.37 生成服从标准正态分布的 24*4 随机数矩阵,并保存为DataFrame。
# 程序文件 ex2_37.py
import pandas as pd
import numpy as np
dates = pd.date_range(start = '20191101', end = '20191124', freq = 'D')
a1 = pd.DataFrame(np.random.randn(24, 4), index = dates, columns = list('ABCD'))
a2 = pd.DataFrame(np.random.rand(24, 4))
例 2.38 数据写入文件
# 程序文件 ex2_38.py
import pandas as pd
import numpy as np
dates = pd.date_range(start = '20191101', end = '20191124', freq = 'D')
a1 = pd.DataFrame(np.random.randn(24, 4), index = dates, columns = list('ABCD'))
a2 = pd.DataFrame(np.random.randn(24, 4))
a1.to_excel('data2_38_1.xlsx')
a2.to_csv('data2_38_2.csv')
f = pd.ExcelWriter('data2_38_3.xlsx') # 创建文件对象
a1.to_excel(f, "Sheet1") # 把 a1 写入excel文件
a2.to_excel(f, "Sheet2") # 把 a2 写入另一个表单中
f.save()
例 2.39 从文件读入数据
# 程序文件 exx2_39.py
import pandas as pd
a = pd.read_csv('data2_38_2.csv', usecols = range(1, 5))
b = pd.read_excel('data2_38_3.xlsx', "Sheet2", usecols = range(1, 5))
print(a); print(b)
2.5.2 数据的一些预处理
例 2.40 DataFrame 数据的拆分、合并和分组计算
# 程序文件 ex2_40.py
import pandas as pd
import numpy as np
d = pd.DataFrame(np.random.randint(1, 6, (10, 4)), columns = list('ABCD'))
d1 = d[:4] # 获取前 4 行数据
d2 = d[4:] # 获取第 5 行以后的数据
dd = pd.concat([d1, d2]) # 数据行合并
s1 = d.groupby('A').mean() # 数据分组求均值
s2 = d.groupby('A').apply(sum) # 数据分组求和
例 2.41 DataFrame数据操作
# 程序文件 ex2_41.py
import pandas as pa
import numpy as np
a = pd.DataFrame(np.random.randint(1, 6, (5, 3)),
index = ['a', 'b', 'c', 'd', 'e'],
columns = ['one', 'two', 'three'])
a.loc['a', 'one'] = np.nan # 修改第 1 行第 1 列的数据
b = a.iloc[1:3, 0:2].values # 提取第 2、3 行,第 1、2 列数据
a['four'] = 'bar' # 增加第 4 列数据
a2 = a.reindex(['a', 'b', 'c', 'd', 'e', 'f'])
a3 = a2.dropna() # 删除有不确定值的行
2.6 文件操作
2.6.1 文件操作基本知识
1. open( )
open( ) 可以指定模式打开指定文件并创建文件对象,该函数完整用法如下:
open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, clodefd=True, opener=None)
(1)file 制定要打开或创建的文件名,若文件不在当前目录,可使用相对路径或绝对路径;
(2)encoding 指定对文本进行编码和解码的方式,如 GBK、UTF-8、CP396等;
(3)mode 指定打开文件的处理方式;
模 式 | 说 明 |
r | 读模式(默认,可省),若文件不存在,抛出异常 |
w | 写模式,若文件已存在,先清空原有内容 |
x | 写模式,创建新文件,若文件已存在,抛出异常 |
a | 追加模式,不覆盖文件中原有内容 |
b | 二进制模式(可与其它模式组合),使用时不允许指定 encoding 参数 |
t | 文本模式(默认,可省) |
+ | 读、写模式(可与其它模式组合) |
2. 文件对象常用方法
方法 | 功能说明 |
close( ) | 把缓冲区内容写入文件,同时关闭文件,并释放文件对象 |
read( [ size ] ) | 从文本文件读取 size 个字符并返回,或从二进制文件读取指定数量字节并返回,若省略 size 则表示读取所有内容 |
readline( ) | 从文本文件读取一行内容作为结果返回 |
readlines( ) | 把文本文件中每行文本作为一个字符串存入列表并返回 |
seek( offset[, whence ] ) | 把文件指针移动到指定位置,offset 表示相对于 whence 的偏移量,whence 为 0 表示从头开始计算(默认),1 表示从当前位置开始计算,2 表示从文件尾开始计算 |
tell( ) | 返回文件指针的当前位置 |
write( s ) | 把字符串 s 的内容写入文件 |
writelines( s ) | 把字符串列表写入文本文件,不添加换行符 |
3. 上下文管理语句 with
with 可以自动管理资源,确保不管是否异常都会执行必要的“清理”操作,释放资源,如自动关闭。
with open(filename, mode, encoding) as fp: # 通过文件对象 fp 读写文件内容
2.6.2 文本文件操作
例 2.42 遍历文件 data2_2.txt 中所有行,统计每一行中字符的个数
# 程序文件 ex2_42.py
with open('data2_2.txt') as fp:
L1=[]; L2=[];
for line in fp:
L1.append(len(line))
L2.append(len(line.strip())) # 去掉换行符
data = [str(num)+'\t' for num in L2] # 转换为字符串
print(L1); print(L2)
with open('data2_2.txt', 'w') as fp2:
fp2.writelines(data)
例 2.43 随机产生一个数据矩阵,存入具有不同分隔符格式的文本文件,再把数据提取出来
# 程序文件 ex2_43.py
import numpy as np
a = np.random.rand(6, 8) # 生成 6*8 的[0, 1)上均匀分布的随机数矩阵
np.savetxt("data2_43_1.txt", a) # 存在以制表符分隔的文本文件
np.savetxt("data2_43_2.csv", a, delimiter=',') # 存成以逗号分隔的 CSV 文件
b = np.loadtxt("data2_43_1.txt") # 加载空格分隔的文本文件
c = np.loadtxt("data2_43_2.csv", delimiter=',') # 加载 CSV 文件
2.7 SciPy库
2.7.1 SciPy 简介
模块 | 功能 |
scipy.cluster | 聚类分析等 |
scipy.constants | 物理和数学常数 |
scipy.fftpack | 傅里叶变换 |
scipy.integrate | 积分 |
scipy.interpolate | 插值 |
scipy.io | 数据输入和输出 |
scipy.linalg | 线性代数 |
scipy.ndimage | n 维图像 |
scipy.odr | 正交距离回归 |
scipy.optimize | 优化 |
scipy.signal | 信号处理 |
scipy.sparse | 稀疏矩阵 |
scipy.spatial | 空间数据结构和算法 |
scipy.special | 特殊函数 |
scipy.stats | 统计 |
2.7.2 SciPy 基本操作
1. 求解非线性方程(组)
from scipy.optimize import fsolve
from scipy.optimize import root
例 2.44 求方程 在给定初值 1.5 附近的一个实根。
# 程序文件 ex2_44.py
from scipy.optimize import fsolve, root
fx = lambda x: x**980-5.01*x**979+7.398*x**978\
-3.388*x**977-x**3+5.01*x**2-7.398*x+3.388
x1 = fsolve(fx, 1.5, maxfev = 4000) # 函数调用4000次
x2 = root(fx, 1.5)
print(x1, '\n', '--------------------'); print(x2)
例 2.45 求下列方程组的一组数值解
# 程序文件 ex2_45.py
from scipy.optimize import fsolve, root
fx = lambda x:[x[0]**2+x[1]**2-1, x[0]-x[1]]
s1 = fsolve(fx, [1, 1])
s2 = root(fx, [1, 1])
print(s1, '\n', '----------------'); print(s2)
2. 积分
积分分为两类:一种是对给定函数的数值积分,另一种是对给定离散点的数值积分,trapz。
函数 | 说明 |
quad(func, a, b, args) | 计算一重数值积分 |
dblquad(func, a, b, gfun, hfun, args) | 计算二重数值积分 |
tplquad(func, a, b, gfun, hfun, qfun, rfun) | 计算三重数值积分 |
nquad(func, ranges, args) | 计算多变量积分 |
例 2.46 分别计算 a = 2, b = 1; a = 2, b = 10,时, 的值。
# 程序文件 ex2_46.py
from scipy.integrate import quad
def fun46(x, a, b):
return a*x**2+b*x
I1 = quad(fun46, 0, 1, args = (2, 1))
I2 = quad(fun46, 0, 1, args = (2, 10))
print(I1); print(I2)
3. 最小二乘解
from scipy.optimize import least_squares
least_squares(fun, x0)
例 2.47 已知4个观测站的位置坐标,每个观测站都探测到距未知信号的距离,已知数据见表 2.9,试定位未知信号的位置坐标。
站号 | 1 | 2 | 3 | 4 |
245 | 164 | 192 | 232 | |
442 | 480 | 281 | 300 | |
126.2204 | 120.7509 | 90.1854 | 101.4021 |
# 程序文件 ex2_47.py
from scipy.optimize import least_squares
import numpy as np
a = np.loadtxt("/home/aistudio/chapter2/data2_47.txt")
x0 = a[0]; y0 = a[1]; d = a[2]
fx = lambda x: np.sqrt((x0-x[0])**2+(y0-x[1])**2)-d
s = least_squares(fx, np.random.rand(2))
print(s, '\n', '----------------', '\n', s.x)
例 2.48 求下列矩阵的最大模特征值及对应的特征向量
# 程序文件ex2_48.py
from scipy.sparse.linalg import eigs
import numpy as np
a = np.array([[1, 2, 3], [2, 1, 3], [3, 3, 6]], dtype = float) # 必须加 float,否则出错
b, c = np.linalg.eig(a)
d, e = eigs(a, 1)
print('最大模特征值为:', d)
print('对应的特征向量为:\n', e)
2.8 SymPy库
符号计算的特点:
(1)运算以推理方式进行,不受截断误差和累积误差问题的影响;
(2)符号计算的速度比较慢。
# 定义符号变量或符号函数
import sympy as sp
x, y, z = sp.symbols('x, y, z') # 或 x, y, z = sp.symbols('x y z')
f, g = sp.symbols('f, g', cls = sp.Function) # 定义多个符号函数
y = sp.Function('y') # 定义符号函数
# 也可使用 var 函数定义符号变量或符号函数
import sympy as sp
sp.var('x, y, z')
sp.var('a b c') # 中间分隔符更换为空格
sp.var('f, g', cls = sp.Function) # 定义符号函数
S = solve(f, *symbols) # f 为符号方程(组),symbols 为符号变量
例 2.49 利用 solve 求符号代数方程的解
# 程序文件 ex2_49.py
import sympy as sp
a, b, c, x = sp.symbols('a, b, c, x')
x0 = sp.solve(a*x**2+b*x+c, x)
print(x0)
例 2.50 求方程组的符号解
# 程序文件 ex2_50_1.py
import sympy as sp
sp.var('x1, x2')
s = sp.solve([x1**2+x2**2-1, x1-x2], [x1, x2])
print(s)
或使用符号数组
# 程序文件 ex2_50_2.py
import sympy as sp
x = sp.var('x:2') # 定义符号数组
s = sp.solve([x[0]**2+x[1]**2-1, x[0]-x[1]], x)
print(s)
例 2.51 求矩阵的特征值和特征向量的符号解
# 程序文件 ex2_51.py
import sympy as sp
a = sp.Matrix([[0, 0, 0, 1], [0, 0, 1, 0], [0, 1, 0, 0], [1, 0, 0, 0]])
print('特征值为:', a.eigenvals())
print('特征向量为:\n', a.eigenvects())
2.9 Matplotlib 库
可以绘制多种形式图形,包括折线图、散点图、饼图、柱状图、雷达图等。
2.9.1 二维绘图
1. 折线图
plot(x, y, linestyle, linewidth, color, marker, markersize, markeredgecolor, markerfacecolor, markeredgewidth, label, alpha)
例 2.52 已知某店铺商品的销售量如表 2.11 所列,画出商品销售趋势图。
月份 | 1月 | 2月 | 3月 | 4月 | 5月 | 6月 |
钻石销量/个 | 13 | 10 | 27 | 33 | 30 | 45 |
铂金销量/个 | 1 | 10 | 7 | 26 | 20 | 25 |
# 程序文件 ex2_52.py
import pandas as pd
import pylab as plt
plt.rc('font', family = 'SimHei') # 用来正常显示中文标签
plt.rc('font', size = 16) # 设置显示字体大小
a = pd.read_excel("data2_52.xlsx", header = None)
b = a.values # 提取其中数据
x = b[0]; y = b[1:]
plt.plot(x, y[0], '-*b', label='钻石')
plt.plot(x, y[1], '--dr', label='铂金')
plt.xlabel('月份'); plt.ylabel('每月销量')
plt.legend(loc='upper left'); plt.grid(); plt.show()
# matplotlib 画图显示中文时通常为乱码,若想显示中文、负号等,添加以下代码
rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签
rcParams['ases.unicode_minus'] = False # 用来正常显示负号
# 或者等价地写为
rc('font', family = 'SimHei')
rc('axes', unicode_minus = False)
2. pandas 结合 matplotlib 进行数据可视化
例 2.53 画出表 2.11 销售数据的柱状图
# 程序文件 ex2_53.py
%matplotlib inline
import pandas as pd
import pylab as plt
plt.rc('font', family = 'SimHei')
plt.rc('font', size = 16)
a = pd.read_excel('data2_52.xlsx', header=None)
b = a.T
b.plot(kind='bar')
plt.legend(['钻石', '铂金'])
plt.xticks(range(6), b[0], rotation=0)
plt.ylabel('数量')
plt.show()
3. 子图
例 2.54 把一个窗口分成 3 个子窗口(1)柱状图;(2)饼图;(3)曲线
# 程序文件 ex2_54.py
import pylab as plt
import numpy as np
#plt.rc('text', usetex = True) # 调用字库
y1 = np.random.randint(2, 5, 6)
y1 = y1/sum(y1)
plt.subplot(2, 2, 1)
str = ['apple', 'grape', 'peach', 'pear', 'banana', 'pineapple']
plt.barh(str, y1) # 水平条形图
plt.subplot(222)
plt.pie(y1, labels = str) # 饼图
plt.subplot(212)
x2 = np.linspace(0.01, 10, 100)
y2 = np.sin(10*x2)/x2
plt.plot(x2, y2)
plt.xlabel('$x$')
plt.ylabel('$\\mathrm{sin}(10x)/x$')
plt.show()
2.9.2 三维绘图
1. 三维曲线
例 2.55 画出三维曲线 的图形
# 程序文件 ex2_55.py
import pylab as plt
import numpy as np
plt.rcParams['axes.unicode_minus']=False
ax = plt.axes(projection='3d')
z = np.linspace(-50, 50, 1000)
x = z**2*np.sin(z)
y = z**2*np.cos(z)
ax.plot(x, y, z, 'k')
plt.show()
2. 三维曲面图
例 2.56 画出三维曲面
# 程序文件 ex2_56.py
import pylab as plt
import numpy as np
x = np.linspace(-4, 4, 100)
x, y = np.meshgrid(x, x)
z = 50*np.sin(x+y)
ax = plt.axes(projection = '3d')
ax.plot_surface(x, y, z, color = 'y')
plt.show()
例 2.57 画出三维表面图
# 程序文件 ex2_57.py
import pylab as plt
import numpy as np
ax = plt.axes(projection = '3d')
X = np.arange(-6, 6, 0.25)
Y = np.arange(-6, 6, 0.25)
X, Y = np.meshgrid(X, Y)
Z = np.sin(np.sqrt(X**2+Y**2))
surf = ax.plot_surface(X, Y, Z, cmap= 'coolwarm')
plt.colorbar(surf)
plt.show()