第二章 Python使用入门¶
本文是根据Python数学建模算法与应用这本书中的例程所作的注解,相信书中不懂的地方,你都可以在这里找打答案,建议配合书阅读本文
2.1 Python 概述¶
2.2 Python 基本数据类型¶
2.2.2 字符串¶
In [5]:
代码语言:javascript复制#程序文件ex2_1.py
str1 = "Hello World!"
print(str1) #输出字符串
print(str1[0:-1]) #输出第一个到倒数第2个的所有字符
print(str1[-1]) #输出字符串的最后一个字符
print(str1[2:5]) #输出从第三个开始到第五个的字符
print(str1[2:]) #输出从第三个开始的所有字符
print(str1*2) #输出字符串两次
代码语言:javascript复制Hello World!
Hello World
!
llo
llo World!
Hello World!Hello World!
In [6]:
代码语言:javascript复制#程序文件ex2_2.py
import numpy as np
a=[]
with open("data/02Python使用入门/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)
代码语言:javascript复制[[19 10 21 5]
[10 7 24 8]
[16 12 21 5]
[24 9 10 8]
[14 13 24 4]]
enumerate()¶
enumerate()
函数是 Python 内置的一个函数,用于在迭代过程中同时获取元素的索引和值。它接受一个可迭代对象(如列表、元组、字符串等)作为参数,并返回一个生成器。
生成器会依次生成由索引和对应元素值组成的元组。通过使用 enumerate()
函数,你可以在循环遍历列表或其他可迭代对象时,同时获取元素的索引和值,这样可以更方便地进行处理或记录。
下面是一个简单的示例代码,演示了如何使用 enumerate()
函数:
fruits = ['apple', 'banana', 'orange']
for index, fruit in enumerate(fruits):
print(index, fruit)
输出:
代码语言:javascript复制0 apple
1 banana
2 orange
在上述示例中,enumerate(fruits)
会生成一个生成器对象,它会依次生成包含索引和对应元素值的元组。在每次迭代中,index
变量存储元素的索引,fruit
变量存储元素的值。这样,我们可以方便地同时访问索引和值,进行相应的操作。
with open¶
with open
是 Python 中用于打开文件的一种语法结构。它是一种上下文管理器的写法,可以在代码块执行完毕后自动关闭文件,无需显式地调用 close()
方法来关闭文件。
使用 with open
语法,可以打开一个文件并创建一个文件对象,然后在代码块中执行相关操作。当代码块执行完毕或遇到异常时,文件对象会自动关闭,确保文件资源的正确释放。
下面是一个示例代码,演示了如何使用 with open
打开文件并读取其内容:
with open("file.txt", "r") as f:
content = f.read()
print(content)
在上述示例中,with open("file.txt", "r") as f:
打开名为 "file.txt" 的文件,并将文件对象赋值给变量 f
。在 with
代码块中,我们可以执行各种文件操作,比如读取文件内容、写入数据等。在代码块执行完毕后,文件对象 f
会自动关闭,不再需要手动调用 f.close()
。
这种使用 with open
的写法有助于避免忘记关闭文件的情况,并且可以提高代码的可读性和简洁性。
2.2.3 列表¶
In [17]:
代码语言:javascript复制#程序文件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)
代码语言:javascript复制['abc', 12, 3.45, 'Python', 2.789]
abc
['a', 'b', 'Hello', 'Python', 2.789]
['a', 'b', 2.789]
In [18]:
代码语言:javascript复制#程序文件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)
代码语言:javascript复制[1, 2, 3, 4, 5, 6, 7, 8, 9]
代码创建了一个二维列表 a
,然后使用列表推导式将其展开为一维列表 d
,并打印输出 d
。
具体地,代码中的列表推导式 [c for b in a for c in b]
用于遍历二维列表 a
中的每个子列表 b
,然后遍历子列表 b
中的每个元素 c
,并将其添加到列表 d
中。最终,列表 d
包含了二维列表 a
中的所有元素。
运行这段代码会输出一维列表 d
的内容。假设初始的二维列表 a
是 [[1,2,3],[4,5,6],[7,8,9]]
,则输出结果为 [1, 2, 3, 4, 5, 6, 7, 8, 9]
。
这种列表推导式的写法可以简化列表的操作,将多维列表展开为一维列表,便于处理和使用其中的元素。
第三行的C是什么意思?¶
在第三行的列表推导式中,c
是一个临时变量,用于表示每个子列表 b
中的元素。在列表推导式的语法中,可以使用变量来表示正在遍历的元素。
具体来说,第三行的列表推导式 [c for b in a for c in b]
可以解读为:
- 对于列表
a
中的每个子列表b
, - 对于子列表
b
中的每个元素c
, - 将元素
c
添加到列表中。
因此,变量 c
在这里充当一个临时的迭代变量,用于访问并处理子列表 b
中的元素。
在代码执行过程中,列表推导式会根据循环的嵌套顺序,首先遍历 a
的子列表 b
,然后遍历子列表 b
的元素 c
,并将每个 c
添加到最终的列表 d
中。
需要注意的是,这里的变量 c
只在列表推导式内部有效,不会影响到列表推导式外的代码。
In [21]:
代码语言:javascript复制#程序文件ex2_5_1.py
import os
fn=[filename for filename in
os.listdir("data/02Python使用入门")
if filename.endswith(('.exe','.py'))]
print(fn)
代码语言:javascript复制['ex2_53.py', 'ex2_19.py', 'ex2_37.py', 'ex2_36.py', 'ex2_38_1.py', 'ex2_45.py', 'ex2_16.py', 'ex2_34.py', 'ex2_41.py', 'ex2_52.py', 'ex2_48.py', 'ex2_56.py', 'ex2_29.py', 'ex2_50_1.py', 'ex2_4.py', 'ex2_18.py', 'ex2_8.py', 'ex2_17.py', 'ex2_12_1.py', 'ex2_57.py', 'ex2_42.py', 'ex2_5_1.py', 'ex2_55.py', 'ex2_50_2.py', 'ex2_43.py', 'ex2_38_2.py', 'ex2_13.py', 'ex2_46.py', 'ex2_10.py', 'ex2_11_1.py', 'ex2_14.py', 'ex2_28.py', 'ex2_24.py', 'ex2_3.py', 'ex2_40.py', 'ex2_33.py', 'ex2_11_2.py', 'ex2_20.py', 'ex2_12_3.py', 'ex2_25.py', 'ex2_51.py', 'ex2_1.py', 'ex2_39.py', 'ex2_27.py', 'ex2_26.py', 'ex2_2.py', 'ex2_47.py', 'ex2_23.py', 'ex2_32.py', 'ex2_6.py', 'ex2_15.py', 'ex2_9.py', 'ex2_54.py', 'ex2_35.py', 'ex2_30.py', 'ex2_22.py', 'ex2_44.py', 'ex2_49.py', 'ex2_12_2.py', 'ex2_31.py', 'ex2_21.py', 'ex2_5_2.py', 'ex2_7.py']
In [25]:
代码语言:javascript复制#程序文件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])
代码语言:javascript复制[0, 8]
[0 8]
代码使用 NumPy 生成随机整数,并找到生成的整数数组中的最大值及其索引。
首先,代码中的 from numpy.random import randint
导入了 randint
函数,该函数用于生成指定范围内的随机整数。然后,使用 randint(10, 20, 16)
生成了一个包含 16 个位于区间 [10, 20) 内的随机整数的数组,并将其赋值给变量 a
。
接下来,代码使用列表推导式和 enumerate()
函数查找数组 a
中的最大值 ma
的索引。通过遍历数组 a
的索引和值,列表推导式 [index for index, value in enumerate(a) if value == ma]
将满足条件 value == ma
的索引值收集到列表 ind1
中。
另外,代码还使用了 np.where(a == ma)
,它是 NumPy 中的一个函数,用于在数组中查找满足条件的元素的索引。这个函数返回的是一个包含索引的元组,其中的 [0]
表示取出元组中的第一个数组,即满足条件的元素的索引数组。将这个数组赋值给变量 ind2
。
最后,代码打印输出了 ind1
和 ind2[0]
,即最大值 ma
在数组 a
中的索引。
运行这段代码会输出最大值 ma
在数组 a
中的索引。请注意,在每次运行代码时,由于生成的随机整数不同,结果可能会有所不同。
2.2.4 元组¶
In [27]:
代码语言:javascript复制#程序文件ex2_6.py
T = ('abc', 12, 3.45, 'Python', 2.789)
print(T) #输出完整元组
print(T[-1]) #输出元组的最后一个元素
print(T[1:3]) #输出元组的第二、三元素
代码语言:javascript复制('abc', 12, 3.45, 'Python', 2.789)
2.789
(12, 3.45)
2.2.5 集合¶
In [33]:
代码语言:javascript复制#程序文件ex2_7.py
student = {'Tom', 'Jim', 'Mary', 'Tom', 'Jack', 'Rose'}
print(student)
a = set('abcdabc')
print(a) #每次输出是不一样的,如输出:{'d', 'b', 'a', 'c'}
代码语言:javascript复制{'Mary', 'Jim', 'Tom', 'Rose', 'Jack'}
{'b', 'a', 'c', 'd'}
创建一个空集合必须使用set(),不能使用{},因为{}是创建一个空字典!!!
集合非常有用,如果要删除列表中大量重复元素,可以先使用set()函数将列表转化成集合,在使用list()函数将集合转化成列表
2.2.6 字典¶
In [34]:
代码语言:javascript复制#程序文件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
代码语言:javascript复制123
78.9
In [35]:
代码语言:javascript复制#程序文件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.')) #输出No Exists
print(Dict['address']) #出错
代码语言:javascript复制18
18
Not Exists.
代码语言:javascript复制---------------------------------------------------------------------------
KeyError Traceback (most recent call last)
Cell In[35], line 6
4 print(Dict.get('age')) #输出18
5 print(Dict.get('address','Not Exists.')) #输出No Exists
----> 6 print(Dict['address']) #出错
KeyError: 'address'
In [36]:
代码语言:javascript复制#程序文件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)
代码语言:javascript复制age
score
name
sex
----------
('age', 18)
('score', [98, 97])
('name', 'Zhang')
('sex', 'male')
----------
18
[98, 97]
Zhang
male
In [4]:
代码语言:javascript复制#程序文件ex2_11_1.py
import string
import random
x=string.ascii_letters string.digits
y=''.join([random.choice(x) for i in range(1000)])
#print(y)
#choice()用于从多个元素中随机选择一个
d=dict() #构造空字典
for ch in y:
d[ch]=d.get(ch,0) 1;
for k,v in sorted(d.items()):
print(k,':',v)
代码语言:javascript复制0 : 19
1 : 22
2 : 15
3 : 18
4 : 9
5 : 16
6 : 27
7 : 7
8 : 21
9 : 23
A : 19
B : 16
C : 12
D : 17
E : 15
F : 18
G : 16
H : 14
I : 13
J : 15
K : 15
L : 13
M : 17
N : 12
O : 14
P : 16
Q : 17
R : 16
S : 18
T : 13
U : 14
V : 19
W : 15
X : 16
Y : 17
Z : 15
a : 19
b : 18
c : 12
d : 9
e : 12
f : 19
g : 14
h : 8
i : 15
j : 12
k : 26
l : 17
m : 21
n : 15
o : 21
p : 19
q : 16
r : 27
s : 12
t : 7
u : 18
v : 18
w : 15
x : 17
y : 17
z : 17
这个程序的功能是生成一个包含1000个随机字符的字符串,并统计每个字符在字符串中出现的次数,并按字符的字母顺序输出结果。
这个程序的主要逻辑如下:
- 导入了
string
和random
模块,分别用于生成包含所有字母和数字的字符串以及生成随机字符。 - 定义了变量
x
,它包含了所有字母和数字的字符串。 - 使用列表推导式生成一个包含1000个随机字符的字符串
y
。 - 创建一个空字典
d
,用于存储字符和对应出现次数的键值对。 - 遍历字符串
y
中的每个字符,并使用d.get(ch, 0)
获取字符ch
在字典d
中的值,如果字符不存在,则返回默认值0。 - 将字符
ch
作为键,将其对应的值加1,并更新字典d
。 - 使用
sorted()
函数对字典d
的键值对按照键进行排序。 - 使用
for
循环遍历排序后的键值对,并打印每个键值对的键和值。
注意,在给定的程序中,print(y)
这行代码是注释掉的(使用了#
符号),所以不会执行打印随机字符串的操作。如果你想打印随机字符串,只需将该行注释取消即可。
这个程序的输出将按照字符的字母顺序输出每个字符及其出现的次数。
In [40]:
代码语言:javascript复制#程序文件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)
代码语言:javascript复制0 : 28
1 : 12
2 : 21
3 : 15
4 : 8
5 : 16
6 : 11
7 : 14
8 : 15
9 : 17
A : 17
B : 11
C : 25
D : 9
E : 16
F : 14
G : 16
H : 14
I : 15
J : 20
K : 18
L : 21
M : 13
N : 15
O : 20
P : 13
Q : 27
R : 11
S : 18
T : 19
U : 14
V : 18
W : 14
X : 13
Y : 18
Z : 19
a : 19
b : 14
c : 12
d : 15
e : 20
f : 21
g : 12
h : 20
i : 18
j : 19
k : 19
l : 20
m : 18
n : 16
o : 12
p : 14
q : 12
r : 12
s : 17
t : 12
u : 13
v : 16
w : 16
x : 21
y : 15
z : 12
这个程序的功能与之前的程序相似,也是生成一个包含1000个随机字符的字符串,并统计每个字符在字符串中出现的次数,并按字符的字母顺序输出结果。
这个程序的主要逻辑如下:
- 导入了
string
、random
和collections
模块,分别用于生成包含所有字母和数字的字符串、生成随机字符,以及进行计数操作。 - 定义了变量
x
,它包含了所有字母和数字的字符串。 - 使用列表推导式生成一个包含1000个随机字符的字符串
y
。 - 使用
collections.Counter()
函数对字符串y
进行计数,生成一个字典count
,其中键是字符,值是字符在字符串中出现的次数。 - 使用
sorted()
函数对字典count
的键值对按照键进行排序。 - 使用
for
循环遍历排序后的键值对,并打印每个键值对的键和值。
与之前的程序相比,这个程序使用了collections.Counter()
来进行计数操作,使得代码更加简洁。其他部分逻辑与之前的程序相同。
注意,与之前的程序一样,print(y)
这行代码是注释掉的,如果你想打印随机字符串,只需将该行注释取消即可。
这个程序的输出将按照字符的字母顺序输出每个字符及其出现的次数。
2.3 函数¶
2.3.1 自定义函数¶
In [1]:
代码语言:javascript复制#程序文件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)
代码语言:javascript复制5!=120
1 1 2 3 5 8 13 21 34 55 89 144
In [2]:
代码语言:javascript复制#程序文件ex2_12_2.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
#程序文件ex2_12_3.py
# from ex2_12_2 import factorial, fib
print('%d!=%d'%(5,factorial(5)))
fib(200)
代码语言:javascript复制5!=120
1 1 2 3 5 8 13 21 34 55 89 144
In [4]:
代码语言:javascript复制#程序文件ex2_13.py
def bifurcate_by(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)
代码语言:javascript复制[['beep', 'boop', 'bar'], ['foo']]
给定的代码定义了一个名为 bifurcate_by
的函数,它接受一个列表 L
和一个函数 fn
作为输入。它根据函数 fn
指定的条件将列表 L
分割为两个子列表。函数 fn
是一个 lambda 函数,它检查列表 L
中的元素的首字符是否等于 'b'。函数 bifurcate_by
返回一个包含两个子列表的列表:一个子列表包含满足条件 fn(x)
的元素,另一个子列表包含不满足条件 fn(x)
的元素。
在提供的代码片段中,使用列表 ['beep', 'boop', 'foo', 'bar']
和 lambda 函数 lambda x: x[0] == 'b'
调用了函数 bifurcate_by
。lambda 函数检查字符串的第一个字符是否等于 'b'。
函数调用的结果被存储在变量 s
中。打印 s
将输出以下列表:
[['beep', 'boop', 'bar'], ['foo']]
第一个子列表包含以 'b' 开头的元素('beep'
,'boop'
和 'bar'
),而第二个子列表包含不以 'b' 开头的元素('foo'
)。
因此,代码的输出将是:
代码语言:javascript复制[['beep', 'boop', 'bar'], ['foo']]
lambda¶
lambda函数是Python中的一种匿名函数,也称为"lambda表达式"。它是一种临时定义的小型函数,可以在代码中内联使用,而不必事先使用def
关键字定义一个完整的函数。
lambda函数的语法结构如下:
代码语言:javascript复制lambda arguments: expression
其中,arguments
表示函数的参数,可以是一个或多个,用逗号分隔。expression
是一个表达式,定义了函数的返回值。
lambda函数通常用于简单的函数功能,特别是在需要传递一个函数作为参数的场景中。它们可以在代码中以一种简洁的方式定义和使用,而不必单独定义一个完整的函数。
下面是一个示例,展示了如何使用lambda函数来定义一个简单的加法函数:
代码语言:javascript复制add = lambda x, y: x y
result = add(2, 3)
print(result) # 输出: 5
在这个例子中,lambda函数定义了一个接受两个参数的匿名函数,用于将这两个参数相加。然后,我们使用lambda函数创建了一个名为add
的函数对象,并使用它进行加法运算。
需要注意的是,lambda函数通常用于编写简短的、单行的函数逻辑。如果需要编写较长或复杂的函数逻辑,最好还是使用常规的函数定义方式(使用def
关键字)。
In [6]:
代码语言:javascript复制#程序文件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))
代码语言:javascript复制60
[4, 8, 16]
2.3.2 模块的导入和使用¶
In [18]:
代码语言:javascript复制#程序文件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) #输出a,b,c的值
代码语言:javascript复制3
2
[[1 0 0]
[0 1 1]
[0 1 0]
[0 0 0]]
In [30]:
代码语言:javascript复制#程序文件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)
代码语言:javascript复制[6, 5, 2, 8, 0]
[7 1 9 2 8]
In [32]:
代码语言:javascript复制#程序文件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)
代码语言:javascript复制0.1411200080598672
3.141592653589793
2.718281828459045
3.141592653589793
In [45]:
代码语言:javascript复制#程序文件ex2_18.py
#from .data/02Python使用入门/ex2_12_2 import *
import sys
sys.path.append('./data/02Python使用入门/')
from ex2_12_2 import *
print(factorial(6))
fib(300)
代码语言:javascript复制720
1 1 2 3 5 8 13 21 34 55 89 144 233
关于不同路径下模块的导入¶
是的,你可以通过适当的导入语句来导入不同路径下的 Python 模块。导入语句中的路径可以是绝对路径或相对路径。
- 绝对路径导入:
如果要导入位于不同路径下的 Python 模块,你可以使用绝对路径来指定模块的位置。例如,假设你要导入 module.py
文件,该文件位于 C:pathtomodule.py
路径下,你可以使用以下导入语句:
import sys
sys.path.append('C:pathto')
import module
在这个例子中,我们将模块所在的路径添加到 sys.path
中,然后使用 import module
导入模块。
- 相对路径导入:
如果要导入位于相对路径下的 Python 模块,你可以使用点号(.)表示当前目录。例如,假设你有两个文件 script.py
和 module.py
,它们位于同一目录下。你可以使用以下导入语句在 script.py
中导入 module.py
:
from . import module
这里的点号(.)表示当前目录,然后使用 import module
导入模块。
请根据你的具体情况选择适当的导入方式,确保提供正确的路径和文件名以进行导入操作。
2.3.3 Python常用内置函数的用法¶
In [48]:
代码语言:javascript复制dir(__builtins__) # 此命令将列出所有的内置函数很内置对象
Out[48]:
代码语言:javascript复制['ArithmeticError',
'AssertionError',
'AttributeError',
'BaseException',
'BlockingIOError',
'BrokenPipeError',
'BufferError',
'BytesWarning',
'ChildProcessError',
'ConnectionAbortedError',
'ConnectionError',
'ConnectionRefusedError',
'ConnectionResetError',
'DeprecationWarning',
'EOFError',
'Ellipsis',
'EnvironmentError',
'Exception',
'False',
'FileExistsError',
'FileNotFoundError',
'FloatingPointError',
'FutureWarning',
'GeneratorExit',
'IOError',
'ImportError',
'ImportWarning',
'IndentationError',
'IndexError',
'InterruptedError',
'IsADirectoryError',
'KeyError',
'KeyboardInterrupt',
'LookupError',
'MemoryError',
'ModuleNotFoundError',
'NameError',
'None',
'NotADirectoryError',
'NotImplemented',
'NotImplementedError',
'OSError',
'OverflowError',
'PendingDeprecationWarning',
'PermissionError',
'ProcessLookupError',
'RecursionError',
'ReferenceError',
'ResourceWarning',
'RuntimeError',
'RuntimeWarning',
'StopAsyncIteration',
'StopIteration',
'SyntaxError',
'SyntaxWarning',
'SystemError',
'SystemExit',
'TabError',
'TimeoutError',
'True',
'TypeError',
'UnboundLocalError',
'UnicodeDecodeError',
'UnicodeEncodeError',
'UnicodeError',
'UnicodeTranslateError',
'UnicodeWarning',
'UserWarning',
'ValueError',
'Warning',
'ZeroDivisionError',
'__IPYTHON__',
'__build_class__',
'__debug__',
'__doc__',
'__import__',
'__loader__',
'__name__',
'__package__',
'__spec__',
'abs',
'all',
'any',
'ascii',
'bin',
'bool',
'breakpoint',
'bytearray',
'bytes',
'callable',
'chr',
'classmethod',
'compile',
'complex',
'copyright',
'credits',
'delattr',
'dict',
'dir',
'display',
'divmod',
'enumerate',
'eval',
'exec',
'execfile',
'filter',
'float',
'format',
'frozenset',
'get_ipython',
'getattr',
'globals',
'hasattr',
'hash',
'help',
'hex',
'id',
'input',
'int',
'isinstance',
'issubclass',
'iter',
'len',
'license',
'list',
'locals',
'map',
'max',
'memoryview',
'min',
'next',
'object',
'oct',
'open',
'ord',
'pow',
'print',
'property',
'range',
'repr',
'reversed',
'round',
'runfile',
'set',
'setattr',
'slice',
'sorted',
'staticmethod',
'str',
'sum',
'super',
'tuple',
'type',
'vars',
'zip']
In [53]:
代码语言:javascript复制#程序文件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)
代码语言:javascript复制[16, 18, 14, 13, 15, 11, 9, 20, 12, 17, 10, 19]
[9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
[20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9]
[9, 16, 18, 14, 13, 15, 11, 20, 12, 17, 10, 19]
key参数的用法¶
在 Python 的 sorted
函数中,key
参数用于指定一个函数,该函数将被应用于要排序的每个元素,并返回一个用于排序的值。根据这个排序值,sorted
函数对元素进行排序。
key
参数接受一个函数作为输入,该函数应用于每个元素,并返回一个用于排序的值。这个函数可以是一个普通的命名函数,也可以是一个匿名函数(lambda 函数)。
下面是 sorted
函数的基本语法,包括 key
参数:
sorted(iterable, key=None, reverse=False)
iterable
是要排序的可迭代对象,如列表或元组。key
是一个可选的参数,它是一个函数,用于将每个元素映射为排序值。默认值为None
,表示直接使用元素本身进行排序。reverse
是一个可选的参数,表示是否按降序进行排序,默认为False
,表示按升序排序。
使用 key
参数的作用是根据指定的规则生成排序值,然后根据排序值对元素进行排序。排序将根据生成的排序值进行,而不是直接对元素本身进行比较。
例如,假设有一个列表 nums
,我们想按照数字的绝对值进行排序。我们可以使用 key
参数来指定一个 lambda 函数,该函数将每个数字映射为其绝对值:
nums = [-5, -2, 0, 3, -1, 4]
sorted_nums = sorted(nums, key=lambda x: abs(x))
print(sorted_nums) # 输出: [0, -1, -2, 3, 4, -5]
在这个例子中,我们使用 key=lambda x: abs(x)
来定义一个 lambda 函数,该函数返回每个元素的绝对值。sorted
函数将根据这些绝对值对元素进行排序,而不是直接对元素本身进行比较。
通过使用 key
参数,我们可以灵活地定义排序的规则,以适应不同的排序需求。灵活地定义排序的规则,以适应不同的排序需求。灵活地定义排序的规则,以适应不同的排序需求。灵活地定义排序的规则,以适应不同的排序需求。
In [60]:
代码语言:javascript复制#程序文件ex2_20.py
x1="abcde"
x2=list(enumerate(x1))
for ind,ch in enumerate(x1): print(ch)
代码语言:javascript复制a
b
c
d
e
In [61]:
代码语言:javascript复制#程序文件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)
代码语言:javascript复制46929687
[4, 6, 9, 2, 9, 6, 8, 7]
[False, True, False, False]
map函数¶
map
函数是Python内置函数之一,它用于对可迭代对象(如列表、元组等)中的每个元素应用指定的函数,并返回一个包含应用结果的新可迭代对象。
map
函数的基本语法如下:
map(function, iterable)
function
是一个函数,它将被应用于可迭代对象中的每个元素。iterable
是一个可迭代对象,如列表、元组等。
map
函数的工作原理是将函数 function
应用于 iterable
中的每个元素,然后返回一个包含应用结果的新的可迭代对象。新的可迭代对象具有与 iterable
相同的长度,并且每个元素是将 function
应用于 iterable
中对应位置上的元素所得到的结果。
例如,假设有一个列表 nums
,我们想计算每个元素的平方值,我们可以使用 map
函数来应用一个平方函数到列表的每个元素上:
nums = [1, 2, 3, 4, 5]
squared_nums = map(lambda x: x**2, nums)
print(list(squared_nums)) # 输出: [1, 4, 9, 16, 25]
在这个例子中,我们使用 map(lambda x: x**2, nums)
来定义一个 lambda 函数,该函数将每个元素平方。然后,我们将 nums
列表作为可迭代对象传递给 map
函数,得到一个新的可迭代对象 squared_nums
。最后,通过将 squared_nums
转换为列表来打印出每个元素的平方值。
map
函数在对可迭代对象的每个元素应用相同的操作时非常有用,可以减少代码的重复和冗余。它提供了一种简洁和高效的方式来处理和转换数据。
In [65]:
代码语言:javascript复制#程序文件ex2_22.py
a = filter(lambda x: x>10,[1,11,2,45,7,6,13])
b = filter(lambda x: x.isalnum(),['abc', 'xy12', '***'])
#isalnum()是测试是否为字母或数字的方法
print(list(a)); print(list(b))
代码语言:javascript复制[11, 45, 13]
['abc', 'xy12']
filter 函数¶
filter
函数是Python内置函数之一,它用于对可迭代对象中的元素进行筛选,返回满足指定条件的元素所组成的新的可迭代对象。
filter
函数的基本语法如下:
filter(function, iterable)
function
是一个函数,它将被应用于可迭代对象中的每个元素,并根据返回值来决定是否保留该元素。iterable
是一个可迭代对象,如列表、元组等。
filter
函数的工作原理是将函数 function
应用于 iterable
中的每个元素,并根据函数返回的布尔值来决定是否保留该元素。只有当函数返回值为 True
时,相应的元素才会被保留下来,否则被过滤掉。
例如,假设有一个列表 nums
,我们想筛选出其中大于 10 的元素,我们可以使用 filter
函数来应用一个判断函数到列表的每个元素上:
nums = [1, 11, 2, 45, 7, 6, 13]
filtered_nums = filter(lambda x: x > 10, nums)
print(list(filtered_nums)) # 输出: [11, 45, 13]
在这个例子中,我们使用 filter(lambda x: x > 10, nums)
来定义一个 lambda 函数,该函数判断每个元素是否大于 10。然后,我们将 nums
列表作为可迭代对象传递给 filter
函数,得到一个新的可迭代对象 filtered_nums
,其中只包含大于 10 的元素。最后,通过将 filtered_nums
转换为列表来打印出满足条件的元素。
filter
函数在对可迭代对象进行筛选和过滤时非常有用,可以根据特定条件选择需要的元素。它提供了一种简洁和高效的方式来处理和筛选数据。
filter
函数和 map
函数在 Python 中都用于对可迭代对象进行操作,但它们的功能和使用方式有所不同。
主要区别如下:
- 功能不同:
filter
函数用于过滤可迭代对象中的元素,只保留满足指定条件的元素。map
函数用于对可迭代对象中的每个元素应用指定的函数,并返回一个包含应用结果的新可迭代对象。
- 返回值不同:
filter
函数返回一个新的可迭代对象,其中只包含满足条件的元素。map
函数返回一个新的可迭代对象,其中包含应用函数后的结果。
- 参数不同:
filter
函数接受两个参数,第一个参数是一个函数,第二个参数是可迭代对象。map
函数接受两个参数,第一个参数是一个函数,第二个参数是可迭代对象。
- 函数的返回值不同:
filter
函数中的函数参数应返回一个布尔值,用于判断是否保留该元素。map
函数中的函数参数可以返回任意值,用于对每个元素进行处理或转换。
总结起来,filter
函数用于过滤可迭代对象中的元素,只保留满足指定条件的元素,而 map
函数用于对可迭代对象中的每个元素应用指定的函数,并返回一个包含应用结果的新可迭代对象。它们在功能和使用方式上有所不同,根据具体的需求选择使用哪个函数。
In [68]:
代码语言:javascript复制#程序文件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)
代码语言:javascript复制[1, 3, 5]
In [71]:
代码语言:javascript复制#程序文件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)
代码语言:javascript复制['v1', 'v2', 'v3', 'v4']
[('a', 0), ('b', 1), ('c', 2), ('d', 3)]
这段代码定义了一个名为 ex2_24.py
的程序文件,其中使用了列表推导式和 zip
函数来创建和操作列表,并打印结果。
首先,代码使用列表推导式 s1 = [str(x) str(y) for x, y in zip(['v']*4, range(1,5))]
创建了一个列表 s1
。在这个列表推导式中,我们使用了 zip
函数将两个可迭代对象 'v'*4
和 range(1,5)
组合在一起。其中,'v'*4
表示将字符 'v'
重复四次,range(1,5)
表示生成一个从 1 到 4 的迭代器。然后,通过 for x, y in ...
部分,将 'v'*4
中的每个元素与 range(1,5)
中对应位置上的元素进行组合。最后,通过 str(x) str(y)
将每对元素转换为字符串并拼接起来,生成最终的列表 s1
。
接下来,代码使用 zip
函数将字符串 'abcd'
和迭代器 range(4)
组合在一起,并将结果转换为列表 s2
。这样,每个字符与 range(4)
中对应位置上的元素会被组合在一起,形成一个元组。最终,得到一个包含组合元组的列表 s2
。
最后,通过两个 print
语句将结果分别打印出来,即打印列表 s1
和 s2
。
根据代码的运行结果,可能的输出为:
代码语言:javascript复制['v1', 'v2', 'v3', 'v4']
[('a', 0), ('b', 1), ('c', 2), ('d', 3)]
请注意,每次运行代码时,由于 zip
函数的操作和列表推导式中的内容可能会不同,输出的结果可能会有所不同。
zip函数¶
zip
函数是Python内置函数之一,它用于将多个可迭代对象中对应位置的元素打包成元组的形式,并返回一个新的可迭代对象。
zip
函数的基本语法如下:
zip(*iterables)
iterables
是一个或多个可迭代对象,如列表、元组等。
zip
函数的工作原理是将传入的可迭代对象 iterables
中对应位置的元素打包成元组,并生成一个新的可迭代对象。新的可迭代对象的长度由最短的可迭代对象决定,超出最短长度的元素将被忽略。
例如,假设有两个列表 names
和 ages
,我们想将它们对应位置上的元素组合成元组,可以使用 zip
函数:
names = ['Alice', 'Bob', 'Charlie']
ages = [25, 30, 35]
combined = zip(names, ages)
print(list(combined)) # 输出: [('Alice', 25), ('Bob', 30), ('Charlie', 35)]
在这个例子中,我们将列表 names
和 ages
作为参数传递给 zip
函数,得到一个新的可迭代对象 combined
。通过将 combined
转换为列表,我们可以看到其中的元素是将 names
和 ages
对应位置上的元素打包成元组的结果。
zip
函数在需要同时迭代多个可迭代对象并处理对应位置上的元素时非常有用。它提供了一种简洁和高效的方式来组合和处理数据。请注意,由于返回的是一个迭代器对象,需要将其转换为列表或进行迭代操作才能获取元素。
2.4 NumPy 库¶
2.4.1 NumPy 的基本使用¶
In [80]:
代码语言:javascript复制#程序文件ex2_25.py
import numpy as np
a1 = np.array([1, 2, 3, 4]) #生成整型数组
a2 = a1.astype(float) #将a1数据类型转换成浮点型,并赋值给a2
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,5) #生成数组[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]
print(b)
print(c)
print(d)
print(e)
代码语言:javascript复制int64
float64
float64
[[1 2 3]
[4 5 6]]
[1 2 3 4]
[1. 2. 3. 4.]
[2. 4. 8.]
这段代码定义了一个名为 ex2_25.py
的程序文件,其中使用了 NumPy 库来创建和操作数组,并打印结果。
首先,代码导入了 NumPy 库,并使用 np.array
函数创建了几个不同的数组。
a1 = np.array([1, 2, 3, 4])
创建了一个整型数组a1
,其中包含元素[1, 2, 3, 4]
。a2 = a1.astype(float)
将数组a1
的数据类型转换为浮点型,并赋值给a2
。a3 = np.array([1, 2, 3, 4], dtype=float)
创建了一个浮点型数组a3
,其中指定了数据类型为浮点型。
接着,通过三个 print
语句分别打印出数组 a1
、a2
和 a3
的数据类型,即 dtype
属性。
然后,代码创建了其他几个数组:
b = np.array([[1, 2, 3], [4, 5, 6]])
创建了一个二维数组b
,其中包含两个子数组[[1, 2, 3], [4, 5, 6]]
。c = np.arange(1, 5)
使用np.arange
函数生成了一个数组c
,其中包含从 1 到 4 的整数,即[1, 2, 3, 4]
。d = np.linspace(1, 4, 4)
使用np.linspace
函数生成了一个数组d
,其中包含从 1 到 4 的等间距的四个元素,即[1, 2, 3, 4]
。e = np.logspace(1, 3, 3, base=2)
使用np.logspace
函数生成了一个数组e
,其中包含从 2 的 1 次方到 2 的 3 次方的三个元素,即[2, 4, 8]
。
最后,通过打印语句将数组 a1
、a2
、a3
、b
、c
、d
和 e
的结果依次打印出来。
根据代码的运行结果,可能的输出为:
代码语言:javascript复制int64
float64
float64
[[1 2 3]
[4 5 6]]
[1 2 3 4]
[1. 2. 3. 4.]
[2. 4. 8.]
请注意,由于 NumPy 数组具有固定的数据类型,因此通过 dtype
属性可以查看数组的数据类型。输出结果中的 int64
表示整型,float64
表示浮点型。 表示浮点型。的 int64
表示整型,float64
表示浮点型。
In [94]:
代码语言:javascript复制import numpy as np
a1=np.arange(1,9,1)
print(a1)
a2=a1.astype(float)
a3=np.array([0,1,2,3,4])
a4=np.linspace(1,50,50)
a5=np.logspace(1,8,8,base=2)
print(a5)
代码语言:javascript复制[1 2 3 4 5 6 7 8]
[ 2. 4. 8. 16. 32. 64. 128. 256.]
In [107]:
代码语言:javascript复制#程序文件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数组
这段代码定义了一个名为 ex2_26.py
的程序文件,其中使用了 NumPy 库来创建和操作数组,并打印结果。
首先,代码导入了 NumPy 库,并使用不同的函数创建了多个数组。
a = np.ones(4, dtype=int)
使用np.ones
函数创建了一个含有 4 个元素的数组a
,其中所有元素的值都为 1,并且指定了数据类型为整型。b = np.ones((4,), dtype=int)
与上述的a
数组相同,使用了相同的np.ones
函数和参数。c = np.ones((4, 1))
创建了一个形状为 4 行 1 列的数组c
,其中所有元素的值都为 1。这里使用了元组(4, 1)
来指定数组的形状。d = np.zeros(4)
使用np.zeros
函数创建了一个含有 4 个元素的数组d
,其中所有元素的值都为 0。e = np.empty(3)
使用np.empty
函数创建了一个包含 3 个元素的空数组e
,这里的元素值是未定义的。f = np.eye(3)
创建了一个 3 阶的单位阵f
,即对角线上的元素为 1,其他元素为 0。g = np.eye(3, k=1)
创建了一个 3 阶的方阵g
,其中第 k 条对角线上的元素为 1,其他元素为 0。这里指定k=1
,表示第一条非主对角线上的元素为 1。h = np.zeros_like(a)
使用np.zeros_like
函数创建了一个与数组a
维度相同的全 0 数组h
。
最后,通过打印语句将数组 a
、b
、c
、d
、e
、f
、g
和 h
的结果依次打印出来。
根据代码的运行结果,可能的输出为:
代码语言:javascript复制[1 1 1 1]
[1 1 1 1]
[[1.]
[1.]
[1.]
[1.]]
[0. 0. 0. 0.]
[1.40048413e-311 1.00082600e 030 3.77106462e-061]
[[1. 0. 0.]
[0. 1. 0.]
[0. 0. 1.]]
[[0. 1. 0.]
[0. 0. 1.]
[0. 0. 0.]]
[0 0 0 0]
请注意,由于使用了随机数和未定义的空数组,输出结果中的具体值可能会有所不同。
n阶单位阵¶
n阶单位阵是一个n×n的方阵,对角线上的元素全为1,其余元素全为0。它通常用I_n或者简写为I表示。
例如,2阶单位阵可以表示为:
代码语言:javascript复制I_2 = | 1 0 |
| 0 1 |
3阶单位阵可以表示为:
代码语言:javascript复制I_3 = | 1 0 0 |
| 0 1 0 |
| 0 0 1 |
n阶单位阵的特点是,对任意n维向量v,都有I_n · v = v,即单位阵与任意向量的乘积仍得到该向量本身。这是因为单位阵在矩阵乘法中起到了类似于数学中的乘法单位元的作用。
第k对角线¶
在一个n×n的方阵中,第k对角线是指从左上角到右下角的斜线,其上的元素位于主对角线(k=0)上方或下方k个位置。
具体而言,第k对角线上的元素可以用矩阵中的下标表示为(i,j),其中i - j = k。换句话说,第k对角线上的元素的行索引和列索引之差等于k。
例如,在一个4×4的方阵中,第0对角线就是主对角线,第1对角线在主对角线上方一格,第-1对角线在主对角线下方一格。
下面是一个示例矩阵,以及每个对角线上的元素:
代码语言:javascript复制矩阵:
| a b c d |
| e f g h |
| i j k l |
| m n o p |
第0对角线:a, f, k, p
第1对角线:b, g, l
第-1对角线:e, j, o
需要注意的是,当k超过矩阵的维度时,即|k| > n-1,第k对角线上没有元素。
In [124]:
代码语言:javascript复制#程序文件ex2_27.py
import numpy as np
a = np.arange(0,16,1).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行元素
print(x==1)
代码语言:javascript复制[[ 4 5 6 7]
[12 13 14 15]]
[False True False True]
这段代码定义了一个名为 ex2_27.py
的程序文件,其中使用了 NumPy 库来创建和操作数组,并打印结果。
首先,代码导入了 NumPy 库,并使用了不同的函数和操作符创建了多个数组。
a = np.arange(0, 16, 1).reshape(4, 4)
使用np.arange
函数生成一个从 0 到 15 的一维数组,然后使用reshape
方法将其变形为一个 4 行 4 列的二维数组a
。b = a[1][2]
通过索引操作符[1][2]
,访问数组a
的第二行第三列的元素,并将其赋值给变量b
。因为索引从 0 开始,所以这里对应的元素是 6。c = a[1, 2]
使用逗号分隔的索引操作符a[1, 2]
,同样访问数组a
的第二行第三列的元素,并将其赋值给变量c
。结果也是 6。d = a[1:2, 2:3]
使用切片操作符和逗号分隔的索引操作符a[1:2, 2:3]
,选取数组a
中第二行第三列的元素,并将其作为一个二维数组赋值给变量d
。因为切片操作返回的是视图而不是副本,所以d
是一个形状为 (1, 1) 的二维数组,其中元素值为 6。x = np.array([0, 1, 2, 1])
创建了一个一维数组x
,其中包含元素[0, 1, 2, 1]
。print(a[x==1])
通过布尔索引操作符x==1
,选取数组a
中满足条件x
等于 1 的行,并打印结果。在这个例子中,x==1
会生成一个布尔数组,其中元素为True
的位置对应的行会被选取。因此,结果是打印出数组a
的第二行和第四行的元素。
根据代码的运行结果,可能的输出为:
代码语言:javascript复制[[ 4 5 6 7]
[12 13 14 15]]
在这个例子中,打印出了数组 a
的第二行和第四行的元素。请注意,由于数组 a
的具体数值可能不同,输出结果也可能会有所不同。
print(a[x==1])
是一个打印语句,它使用布尔索引操作来选择数组 a
中满足条件 x
等于 1 的行,并打印选取的结果。
详细解释如下:
x==1
是一个布尔表达式,它生成一个布尔数组,该数组与数组x
的形状相同,元素为布尔值。在这个例子中,x
是一个一维数组,元素为[0, 1, 2, 1]
,所以x==1
的结果是一个布尔数组[False, True, False, True]
,对应位置的元素为True
表示满足条件,而False
表示不满足条件。a[x==1]
使用布尔索引操作符x==1
,将布尔数组作为索引来选择数组a
中满足条件的行。布尔索引操作会返回一个由满足条件的行组成的新数组。在这个例子中,根据布尔数组[False, True, False, True]
,将选取数组a
中第二行和第四行的元素,并将结果作为一个新数组返回。print(a[x==1])
打印选取的结果数组。在这个例子中,会打印出数组a
中满足条件x
等于 1 的行,即第二行和第四行的元素。
根据代码的运行结果,可能的输出为:
代码语言:javascript复制[[ 4 5 6 7]
[12 13 14 15]]
这表示打印出了数组 a
中满足条件 x
等于 1 的行,即第二行和第四行的元素。请注意,由于数组 a
的具体数值可能不同,输出结果也可能会有所不同。
花式索引(Fancy indexing)是指通过整数数组或布尔数组来访问和操作数组中的元素。在代码 print(a[x==1])
中,使用了花式索引来选择数组 a
中满足条件 x
等于 1 的行。
具体解释如下:
x==1
生成一个布尔数组,其中元素为True
的位置表示满足条件x
等于 1。- 使用布尔数组
x==1
作为索引操作符,将其作为索引来选择数组a
中对应位置为True
的行。 - 根据布尔数组
[False, True, False, True]
,数组a
中对应位置为True
的行为第二行和第四行。 - 打印选取的结果数组,即数组
a
中满足条件x
等于 1 的行,即第二行和第四行的元素。
因此,代码 print(a[x==1])
中的 a[x==1]
使用了花式索引,通过布尔数组选择了数组 a
中满足条件 x
等于 1 的行。
2.4.2 矩阵合并与分割¶
In [126]:
代码语言:javascript复制#程序文件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]) #左右合并矩阵
这段代码涉及到了数组的合并操作,使用了NumPy中的函数来进行垂直和水平方向的合并。下面是对代码的解释:
a = np.arange(16).reshape(4,4)
生成一个4行4列的数组a
,其中元素从0到15排列。b = np.floor(5*np.random.random((2, 4)))
生成一个2行4列的随机数组b
,其中元素值在0到5之间,并向下取整。c = np.ceil(6*np.random.random((4, 2)))
生成一个4行2列的随机数组c
,其中元素值在0到6之间,并向上取整。d = np.vstack([a, b])
使用np.vstack()
函数将数组a
和数组b
垂直合并,生成一个新的数组d
。合并后,d
将具有6行4列的形状。e = np.hstack([a, c])
使用np.hstack()
函数将数组a
和数组c
水平合并,生成一个新的数组e
。合并后,e
将具有4行6列的形状。
通过这些合并操作,可以将不同形状的数组按照指定的方向进行拼接。垂直合并是将数组在垂直方向上拼接,水平合并是将数组在水平方向上拼接。
In [127]:
代码语言:javascript复制#程序文件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])
代码语言:javascript复制行分割:
[[0 1 2 3]
[4 5 6 7]]
[[ 8 9 10 11]
[12 13 14 15]]
列分割:
[[ 0]
[ 4]
[ 8]
[12]]
[[ 1]
[ 5]
[ 9]
[13]]
[[ 2]
[ 6]
[10]
[14]]
[[ 3]
[ 7]
[11]
[15]]
这段代码涉及到了数组的分割操作,使用了NumPy中的函数来进行行和列的分割。下面是对代码的解释:
a = np.arange(16).reshape(4,4)
生成一个4行4列的数组a
,其中元素从0到15排列。b = np.vsplit(a, 2)
使用np.vsplit()
函数将数组a
在垂直方向上分割成2个部分,并将结果保存在列表b
中。这里将数组a
分割为两个大小相等的部分,即分别包含前两行和后两行的数组。- 打印分割结果,
print('行分割:n', b[0], 'n', b[1])
打印出分割后的两个部分。b[0]
表示第一个分割部分,即包含前两行的数组;b[1]
表示第二个分割部分,即包含后两行的数组。 c = np.hsplit(a, 4)
使用np.hsplit()
函数将数组a
在水平方向上分割成4个部分,并将结果保存在列表c
中。这里将数组a
分割为4个大小相等的部分,即分别包含前一列、第二列、第三列和最后一列的数组。- 打印分割结果,
print('列分割:n', c[0], 'n', c[1], 'n', c[2], 'n', c[3])
打印出分割后的四个部分。c[0]
表示第一个分割部分,即包含第一列的数组;c[1]
表示第二个分割部分,即包含第二列的数组;c[2]
表示第三个分割部分,即包含第三列的数组;c[3]
表示第四个分割部分,即包含最后一列的数组。
通过这些分割操作,可以将数组按照指定的行或列进行划分,并得到划分后的子数组。行分割是将数组在垂直方向上划分,列分割是将数组在水平方向上划分。
In [129]:
代码语言:javascript复制#程序文件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)数组
代码语言:javascript复制(3,) (1, 3)
这段代码涉及到了数组的求和操作,使用了NumPy中的函数和方法来计算数组元素的和。下面是对代码的解释:
a = np.array([[0, 3, 4], [1, 6, 4]])
创建一个2行3列的数组a
。b = a.sum()
使用数组的sum()
方法求取数组a
中所有元素的和,将结果保存在变量b
中。c1 = sum(a)
使用内置函数sum()
对数组a
进行逐列求和,将每列元素的和累加,将结果保存在变量c1
中。这里的sum()
函数会将每一列作为可迭代对象进行求和。c2 = np.sum(a, axis=0)
使用函数np.sum()
对数组a
进行逐列求和,将每列元素的和累加,将结果保存在变量c2
中。axis=0
表示沿着列的方向进行求和。c3 = np.sum(a, axis=0, keepdims=True)
使用函数np.sum()
对数组a
进行逐列求和,并保持结果的维度。axis=0
表示沿着列的方向进行求和,keepdims=True
表示保持结果的维度,即结果为一个行向量。- 打印结果,
print(c2.shape, c3.shape)
打印出变量c2
和c3
的形状。c2.shape
表示c2
的形状,即一个一维数组,长度为3;c3.shape
表示c3
的形状,即一个二维数组,形状为(1, 3)。
通过这些求和操作,可以计算数组中元素的总和以及沿指定轴进行求和的结果。使用方法 sum()
可以直接对数组进行求和,而函数 np.sum()
则可以指定轴进行求和,并可以保持结果的维度。
2.4.3 矩阵的简单运算¶
1. 求和¶
In [3]:
代码语言:javascript复制#程序文件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)数组
代码语言:javascript复制(3,) (1, 3)
以下是程序文件ex2_30.py的内容解释:
代码语言:javascript复制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)数组
这段代码使用了NumPy库来对矩阵进行求和操作。解释如下:
- 导入NumPy库:
import numpy as np
这行代码将NumPy库导入,并使用np
作为别名,方便后续使用NumPy函数和方法。 - 定义矩阵a: a = np.array([[0, 3, 4], [1, 6, 4]]) 这段代码创建了一个2行3列的二维NumPy数组,表示矩阵a。
- 使用方法求矩阵所有元素的和:
b = a.sum()
这行代码使用了NumPy数组对象的
sum()
方法,对矩阵a中的所有元素进行求和,并将结果赋值给变量b。 - 使用内置函数求矩阵逐列元素的和:
c1 = sum(a)
这行代码使用了Python的内置
sum()
函数,对矩阵a中的每一列元素进行求和。由于NumPy数组是按列存储的,因此对二维数组使用sum()
函数将对每一列进行求和。结果赋值给变量c1。 - 使用函数求矩阵逐列元素的和:
c2 = np.sum(a, axis=0)
这行代码使用了NumPy库的
sum()
函数,并通过axis=0
参数指定按列求和。axis=0
表示沿着第一个轴(行)的方向进行求和,即对每一列元素进行求和。结果赋值给变量c2。 - 逐列求和,并保留维度:
c3 = np.sum(a, axis=0, keepdims=True)
这行代码使用了NumPy库的
sum()
函数,并通过axis=0
参数指定按列求和。keepdims=True
参数保持求和结果的维度与原始矩阵相同,即结果是一个形状为(1,3)的二维数组。结果赋值给变量c3。 - 打印数组形状: print(c2.shape, c3.shape)
这行代码打印了变量c2和c3的形状。shape
属性返回数组的维度信息。输出结果是(3,) (1, 3)
,表示c2是一个一维数组(形状为(3,)),c3是一个二维数组(形状为(1, 3))。
print(c2.shape, c3.shape)
np.sum函数¶
np.sum()
函数是NumPy库中用于求和操作的函数。它可以用于数组的元素求和,以及在指定轴上对数组进行求和。
函数的语法如下:
代码语言:javascript复制np.sum(a, axis=None, dtype=None, keepdims=False)
参数说明:
a
: 输入的数组。axis
: 指定进行求和的轴。默认为None
,表示对整个数组进行求和。可以是整数或元组,用于指定要沿着哪个轴求和。dtype
: 指定求和结果的数据类型,默认为None
,即保持原始数据类型。keepdims
: 指定是否保持求和结果的维度。如果为True
,则结果的维度与输入数组保持相同;如果为False
,则结果将被压缩为一个标量(如果没有指定axis
)或者一个一维数组(如果指定了axis
)。
np.sum()
函数的功能包括:
- 对数组的所有元素进行求和,返回一个标量值。
- 沿着指定轴对数组进行求和,返回一个新的数组。
示例用法:
代码语言:javascript复制import numpy as np
a = np.array([[1, 2, 3],
[4, 5, 6]])
# 对整个数组进行求和
sum_total = np.sum(a)
print(sum_total) # 输出: 21
# 沿着行的方向求和
sum_row = np.sum(a, axis=0)
print(sum_row) # 输出: [5 7 9]
# 沿着列的方向求和
sum_col = np.sum(a, axis=1)
print(sum_col) # 输出: [6 15]
在上述示例中,首先创建了一个2×3的二维数组a
。然后,通过np.sum()
函数对数组进行了不同的求和操作。sum_total
对整个数组进行求和,结果为21。sum_row
对每一列进行求和,结果为[5 7 9]。sum_col
对每一行进行求和,结果为[6 15]。
参数axis
可以指定的值包括以下几种情况:
- 整数:可以使用0、1、2、...来指定对应的轴。其中,0表示沿着第一个轴(行)的方向进行操作,1表示沿着第二个轴(列)的方向进行操作,以此类推。例如,对于一个二维数组,可以通过
axis=0
指定沿着行的方向,axis=1
指定沿着列的方向。 - 元组:可以使用元组来指定多个轴进行操作。例如,
axis=(0, 1)
表示同时沿着第一个轴(行)和第二个轴(列)的方向进行操作。 None
(默认值):当axis
参数为None
时,将对整个数组进行求和,返回一个标量值。
注意:
axis
的取值范围取决于数组的维度。对于一个二维数组,有效的取值范围是0和1。- 可以在不同的操作中多次使用
axis
参数,以便同时在多个轴上进行操作。例如,np.sum(a, axis=(0,2))
表示同时在第一个轴(行)和第三个轴上进行求和操作。个轴上进行求和操作。为[5 7 9]。sum_col
对每一行进行求和,结果为[6 15]。
对于二维数组,axis=0
表示沿着第一个轴(行)的方向进行求和,即逐列求和。
考虑以下示例二维数组 a
:
a = np.array([[1, 2, 3],
[4, 5, 6]])
使用 np.sum(a, axis=0)
对数组 a
进行求和操作,axis=0
表示沿着行的方向进行求和。结果将返回一个一维数组,其中包含每一列元素的和:
[5, 7, 9]
因此,axis=0
是逐列求和,对每一列的元素进行求和,返回一个包含每一列和的一维数组。
keepdims
是np.sum()
函数的一个可选参数,用于指定是否保持求和结果的维度。
当 keepdims=True
时,求和的结果将保持与原始数组相同的维度。
考虑以下示例数组 a
:
a = np.array([[1, 2, 3],
[4, 5, 6]])
如果使用 np.sum(a, axis=0, keepdims=True)
对数组 a
进行求和,并设置 keepdims=True
,结果将保持与原始数组 a
相同的维度。即,结果将是一个形状为 (1, 3)
的二维数组:
[[5, 7, 9]]
相反,当 keepdims=False
或省略 keepdims
参数时,求和的结果将被压缩为一个标量(如果没有指定 axis
)或者一个一维数组(如果指定了 axis
)。
例如,对于 np.sum(a, axis=0, keepdims=False)
,结果将是一个形状为 (3,)
的一维数组:
[5, 7, 9]
在求和操作中使用 keepdims
参数可以控制结果的维度,使结果保持与原始数组的形状一致,有助于在数组计算中保持维度的一致性。
2. 矩阵的逐个元素运算¶
In [20]:
代码语言:javascript复制#程序文件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 * d #d先广播成与a同维数的矩阵,再逐个元素相乘
print(e)
f = np.array([[3],[2]])
g = a * f
print(g)
h = a ** (1/2) #a矩阵逐个元素的1/2次幂。
print(h)
代码语言:javascript复制[[ 0 9 8]
[ 2 18 8]]
[[ 0 9 12]
[ 2 12 8]]
[[0. 1.73205081 2. ]
[1. 2.44948974 2. ]]
以下是程序文件ex2_31.py的内容解释:
代码语言:javascript复制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 * d # d先广播成与a同维数的矩阵,再逐个元素相乘
f = np.array([[3],[2]])
g = a * f
h = a ** (1/2) # a矩阵逐个元素的1/2次幂。
这段代码展示了一些使用NumPy库进行矩阵运算的操作,解释如下:
- 导入NumPy库:
import numpy as np
这行代码将NumPy库导入,并使用np
作为别名,方便后续使用NumPy函数和方法。 - 定义数组a和b: a = np.array([[0, 3, 4], [1, 6, 4]]) b = np.array([[1, 2, 3], [2, 1, 4]]) 这段代码创建了两个二维NumPy数组a和b。
- 矩阵元素相除:
c = a / b
这行代码使用了
/
运算符对数组a和b进行对应元素相除的操作。结果赋值给变量c,得到一个新的数组,其元素为a和b对应位置的元素相除的结果。 - 数组和标量的逐元素相乘: d = np.array([2, 3, 2]) e = a * d 这段代码创建了一个一维数组d,并将其与数组a进行逐元素相乘的操作。数组d被广播(自动扩展)成与a相同的维度,然后进行逐元素相乘。结果赋值给变量e,得到一个新的数组。
- 广播与矩阵的逐元素相乘: f = np.array([[3],[2]]) g = a * f 这段代码创建了一个二维数组f,并将其与数组a进行逐元素相乘的操作。数组f的维度与a不完全匹配,但NumPy会自动广播f,使其与a相同的维度,然后进行逐元素相乘。结果赋值给变量g,得到一个新的数组。
- 矩阵元素的次方运算:
h = a ** (1/2)
这行代码使用了
**
运算符对数组a中的每个元素进行1/2次幂的操作,即开平方。结果赋值给变量h
,得到一个新的数组,其中每个元素是a对应位置元素的开平方结果。
总结:这段代码展示了NumPy库中的一些基本矩阵运算操作,包括矩阵元素相除、数组和标量的逐元素相乘、广播与矩阵的逐元素相乘,以及矩阵元素的次方运算。这些操作在数据分析和科学计算中非常常见,可以方便地进行各种数值计算和数据处理。
3. 矩阵乘法¶
In [25]:
代码语言:javascript复制#程序文件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作为列向量
以下是程序文件ex2_32.py的内容解释:
代码语言:javascript复制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作为列向量
这段代码展示了使用NumPy库进行矩阵乘法的操作,解释如下:
- 导入NumPy库:
import numpy as np
这行代码将NumPy库导入,并使用np
作为别名,方便后续使用NumPy函数和方法。 - 定义数组a和b: a = np.ones(4) b = np.arange(2, 10, 2) 这段代码创建了两个一维NumPy数组a和b。数组a由4个元素组成,每个元素的值都为1。数组b由从2开始、步长为2、不包括10的整数构成。
- 行向量与列向量的矩阵乘法:
c = a @ b # a作为行向量, b作为列向量
这行代码使用
@
运算符对数组a和b进行矩阵乘法的操作。数组a被视为行向量,数组b被视为列向量。根据矩阵乘法的规则,行向量乘以列向量将得到一个标量值。结果赋值给变量c。 - 行向量与二维数组的矩阵乘法:
d = np.arange(16).reshape(4,4) f = a @ d # a作为行向量
这段代码创建了一个二维数组d,其形状为4×4。然后,使用
@
运算符将数组a作为行向量与数组d进行矩阵乘法的操作。根据矩阵乘法的规则,行向量与二维数组的乘法将得到一个新的行向量。结果赋值给变量f。 - 二维数组与列向量的矩阵乘法:
g = d @ a # a作为列向量
这行代码使用
@
运算符将数组d与数组a作为列向量进行矩阵乘法的操作。根据矩阵乘法的规则,二维数组与列向量的乘法将得到一个新的列向量。结果赋值给变量g。
总结:这段代码展示了NumPy库中矩阵乘法的不同应用场景,包括行向量与列向量的乘法、行向量与二维数组的乘法以及二维数组与列向
量的乘法。这些操作可以在数值计算和数据分析中用于处理矩阵和向量之间的乘法运算。
矩阵的乘法运算规则¶
矩阵乘法的规则是基于线性代数中矩阵的定义和性质。以下是矩阵乘法的规则:
维度匹配:要进行矩阵乘法,被乘矩阵的列数必须与乘矩阵的行数相等。如果矩阵 A 的形状为 m×n,矩阵 B 的形状为 n×p,那么它们可以相乘,结果矩阵的形状将为 m×p。
元素计算:对于结果矩阵 C 的第 i 行第 j 列元素 cij,可以通过计算矩阵 A 的第 i 行与矩阵 B 的第 j 列的内积得到。内积的计算方式是将两个向量对应位置的元素相乘,然后将乘积相加。
代码语言:javascript复制c_ij = a_i1 * b_1j a_i2 * b_2j ... a_in * b_nj
其中 aik 表示矩阵 A 的第 i 行第 k 列的元素,bkj 表示矩阵 B 的第 k 行第 j 列的元素。
结合律:矩阵乘法满足结合律,即 (A * B) * C = A * (B * C)。这意味着当有多个矩阵相乘时,它们可以按任意顺序相乘。
分配律:矩阵乘法满足分配律,即 A * (B C) = A * B A * C。这意味着当一个矩阵与多个矩阵的和相乘时,它可以分别与每个矩阵相乘,然后将结果相加。
需要注意的是,矩阵乘法不满足交换律,即 A * B ≠ B * A。乘法顺序的改变将导致结果不同。
这些规则是基于矩阵的数学定义和性质,并且在线性代数中具有重要的应用。矩阵乘法在数值计算、线性代数、机器学习等领域中广泛应用,可以进行复杂的线性变换和数据处理。
假设我们有以下两个矩阵 A 和 B:
代码语言:javascript复制A = [[1, 2, 3],
[4, 5, 6]]
B = [[7, 8],
[9, 10],
[11, 12]]
按照矩阵乘法的规则,我们可以计算它们的乘积 C = A * B。
首先,我们确定维度匹配。矩阵 A 是一个2×3的矩阵,矩阵 B 是一个3×2的矩阵,它们的列数和行数相等,满足维度匹配的条件。因此,它们可以相乘得到一个2×2的结果矩阵。
接下来,我们计算结果矩阵 C 的元素。对于 C 的第 i 行第 j 列元素 cij,我们可以通过计算 A 的第 i 行与 B 的第 j 列的内积得到。
代码语言:javascript复制c_11 = (1 * 7) (2 * 9) (3 * 11) = 58
c_12 = (1 * 8) (2 * 10) (3 * 12) = 64
c_21 = (4 * 7) (5 * 9) (6 * 11) = 139
c_22 = (4 * 8) (5 * 10) (6 * 12) = 154
因此,结果矩阵 C 为:
代码语言:javascript复制C = [[58, 64],
[139, 154]]
这个例子展示了如何按照矩阵乘法的规则计算两个矩阵的乘积。矩阵乘法的结果是一个新的矩阵,其元素是原始矩阵对应行向量和列向量的内积计算结果。
在使用符号 "@" 表示矩阵乘法时,乘法的顺序是与符号的左右位置有关的。通常,我们将 "@" 符号左边的矩阵视为行向量,而将 "@" 符号右边的矩阵视为列向量。
例如,对于矩阵乘法 A @ B,我们可以将 A 视为一个行向量,B 视为一个列向量。具体地说,A 的形状应该是 (1, n),即只有一行,而 B 的形状应该是 (n, 1),即只有一列。
这种视角下,矩阵乘法的运算可以理解为将行向量与列向量的对应元素相乘,并将结果相加,得到一个标量值。
然而,需要注意的是,在实际编程中,我们通常使用具有更高维度的矩阵进行乘法运算,而不仅仅限于行向量和列向量的情况。符号 "@" 的使用方式保持不变,但乘法操作涉及更多的元素和维度。
总结起来,使用符号 "@" 表示的矩阵乘法中,通常将 "@" 左边的矩阵视为行向量,而将 "@" 右边的矩阵视为列向量。但是,这只是一种常见的情况,实际上矩阵乘法可以适用于更一般的情况,涉及更多的元素和维度。
2.4.4 矩阵运算与线性代数¶
1. 范数计算¶
In [12]:
代码语言:javascript复制#程序文件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范数为:', round(d, 4))
代码语言:javascript复制行向量2范数为: [5. 7.2801]
列向量2范数为: [1. 6.7082 5.6569]
矩阵2范数为: 8.8318
这段代码使用了 numpy.linalg.norm
函数来计算矩阵或向量的范数。
np.linalg.norm(a, axis=1)
计算了矩阵a
的行向量的2范数,结果保存在变量b
中。np.linalg.norm(a, axis=0)
计算了矩阵a
的列向量的2范数,结果保存在变量c
中。np.linalg.norm(a)
计算了矩阵a
的2范数,结果保存在变量d
中。
最后,代码打印了行向量2范数、列向量2范数和矩阵2范数的结果。
范数是一个衡量向量或矩阵大小的指标。2范数(也称为欧几里德范数)是指向量或矩阵元素的平方和的平方根。在二维空间中,2范数可以看作是向量的长度或矩阵的最大奇异值。
通过 np.linalg.norm
函数,可以方便地计算矩阵或向量的不同范数。在代码中,通过指定 axis
参数来计算行向量或列向量的范数。当 axis=1
时,计算行向量的范数;当 axis=0
时,计算列向量的范数。如果不指定 axis
参数,则默认计算整个矩阵的范数。
最后,使用 np.round
函数对结果进行四舍五入,以保留一定的小数位数,并打印出范数的结果。
矩阵或向量范数的概念及计算方法¶
范数(Norm)是一种用来衡量向量或矩阵大小的指标,它在数学和应用领域中经常被使用。范数可以看作是向量或矩阵的长度、大小或距离的度量。
对于向量来说,常见的范数有:
- L1范数(曼哈顿范数):定义为向量元素绝对值之和,即 ||x||₁ = |x₁| |x₂| ... |xn|。
- L2范数(欧几里德范数):定义为向量元素平方和的平方根,即 ||x||₂ = √(x₁² x₂² ... xn²)。
- Lp范数:定义为向量元素绝对值的p次方和的1/p次方,即 ||x||ₚ = (|x₁|^p |x₂|^p ... |xn|^p)^(1/p)。其中,p是一个大于1的实数。
- 无穷范数(最大范数):定义为向量元素绝对值的最大值,即 ||x||₊ₒₒ = max(|x₁|, |x₂|, ..., |xn|)。
对于矩阵来说,常见的范数有:
- 矩阵1范数:定义为矩阵列向量的L1范数的最大值,即 ||A||₁ = max(∑|aᵢⱼ|),其中∑表示对所有列的求和。
- 矩阵2范数:定义为矩阵的奇异值分解(SVD)后的最大奇异值,即 ||A||₂ = σ₁,其中σ₁表示最大奇异值。
- 矩阵F范数(Frobenius范数):定义为矩阵元素的平方和的平方根,即 ||A||ₙₓₙ = √(∑|aᵢⱼ|²),其中∑表示对所有元素的求和。
计算范数的方法可以通过数学公式进行计算,也可以使用相关的函数或库进行计算,如NumPy中的numpy.linalg.norm
函数可以用来计算向量或矩阵的范数。通常,可以通过指定axis
参数来计算行向量或列向量的范数,或者不指定axis
参数来计算整个矩阵的范数。
需要注意的是,范数的计算方法和含义会根据具体的范数类型而有所不同。每种范数都有其独特的特点和适用场景,具体使用哪种范数取决于具体的问题和需求。
假设我们有一个向量 x = [3, -4, 5] 和一个矩阵 A = [[1, 2, 3], [4, 5, 6], [7, 8, 9]],我们来计算一些范数的例子:
- L1范数(曼哈顿范数):
- 向量 x 的 L1范数: ||x||₁ = |3| |-4| |5| = 12
- 矩阵 A 的 L1范数: ||A||₁ = max(|1| |4| |7|, |2| |5| |8|, |3| |6| |9|) = 24
- L2范数(欧几里德范数):
- 向量 x 的 L2范数: ||x||₂ = √(3² (-4)² 5²) = √50 ≈ 7.07
- 矩阵 A 的 L2范数: ||A||₂ = 最大奇异值 = σ₁ = 最大特征值 = 16.848
- 无穷范数(最大范数):
- 向量 x 的无穷范数: ||x||₊ₒₒ = max(|3|, |-4|, |5|) = 5
- 矩阵 A 的无穷范数: ||A||₊ₒₒ = max(|1| |2| |3|, |4| |5| |6|, |7| |8| |9|) = 24
- 矩阵F范数(Frobenius范数):
- 矩阵 A 的矩阵F范数: ||A||ₙₓₙ = √(1² 2² 3² 4² 5² 6² 7² 8² 9²) = √285 ≈ 16.881
这些是一些常见范数的计算示例,范数的具体计算方法可以根据不同的范数类型和具体的向量或矩阵进行应用。
2. 求解线性方程组的唯一解¶
例2.34 求线性方程组 3x y=9,x 2y=8
In [29]:
代码语言:javascript复制#程序文件ex2_34.py
import numpy as np
a = np.array([[3, 1], [1, 2]])
b = np.array([9, 8])
x1 = np.linalg.pinv(a) @ b #第一种解法
#上面语句中@表示矩阵乘法
x2 = np.linalg.solve(a, b) #第二种解法
print(x1); print(x2)
代码语言:javascript复制[2. 3.]
[2. 3.]
numpy.linalg¶
numpy.linalg
模块提供了大量的线性代数函数,下面是该模块中的全部函数的详细解释:
numpy.linalg.inv(a)
计算矩阵a的逆矩阵。输入参数a可以是一个2维的NumPy数组。numpy.linalg.det(a)
计算矩阵a的行列式。行列式是一个标量值,表示方阵的某些性质。numpy.linalg.eig(a)
计算矩阵a的特征值和特征向量。返回值是一个包含特征值和对应特征向量的元组。numpy.linalg.eigh(a, UPLO='L')
计算对称或厄米矩阵a的特征值和特征向量。返回值是一个包含特征值和对应特征向量的元组。numpy.linalg.eigvals(a)
计算矩阵a的特征值。返回一个包含所有特征值的一维数组。numpy.linalg.eigvalsh(a, UPLO='L')
计算对称或厄米矩阵a的特征值。返回一个包含所有特征值的一维数组。numpy.linalg.solve(a, b)
求解线性方程组Ax = b,其中a是系数矩阵,b是常数向量。返回值是x,表示方程组的解。numpy.linalg.tensorsolve(a, b, axes=None)
解张量方程Ax = b。a是一个张量,b是一个与a具有相同维度的张量。返回值是x,表示方程的解。numpy.linalg.lstsq(a, b, rcond='warn')
最小二乘法求解线性方程组Ax = b。a是系数矩阵,b是常数向量。返回值是一个元组(x, residuals, rank, s),其中x是最小二乘解,residuals是残差和,rank是矩阵a的秩,s是奇异值。numpy.linalg.pinv(a, rcond=1e-15, hermitian=False)
计算矩阵a的Moore-Penrose伪逆。返回值是一个广义逆矩阵。numpy.linalg.matrix_power(a, n)
计算矩阵a的整数幂n。返回值是a的n次幂。numpy.linalg.matrix_rank(M, tol=None, hermitian=False)
计算矩阵M的秩。返回值是矩阵的秩。numpy.linalg.qr(a, mode='reduced')
对矩阵a进行QR分解。返回值是一个元组(q, r),其中q是正交/酉矩阵,r是上三角矩阵。numpy.linalg.svd(a, full_matrices=True, compute_uv=True)
对矩阵a进行奇异值分解(SVD)。返回值是一个元组(u, s, vh),其中u是左奇异向量,s是奇异值数组,vh是右奇异向量的共轭转置。numpy.linalg.slogdet(a)
计算矩阵a的行列式的符号和自然对数。返回一个元组(sign, logdet),其中sign是行列式的符号,logdet是行列式的自然对数。numpy.linalg.norm(x, ord=None, axis=None)
计算向量或矩阵的范数。ord参数用于指定范数的类型,axis参数用于指定计算范数的轴。如果不指定axis,则计算输入的整体范数。numpy.linalg.cond(x, p=None)
计算矩阵x的条件数。条件数是矩阵的一个度量,用于衡量矩阵的可逆性。
这些函数提供了丰富的线性代数功能,可用于求解线性方程组、特征值和特征向量、矩阵分解等各种线性代数问题。
3. 求超定线性方程组的最小二乘解¶
In [30]:
代码语言:javascript复制import numpy as np
a = np.array([[3, 1], [1, 2], [1, 1]])
b = np.array([9, 8, 6])
c = np.linalg.pinv(a) @ b
print(c)
代码语言:javascript复制[2. 3.16666667]
4. 求矩阵的特征值和特征向量¶
In [32]:
代码语言:javascript复制#程序文件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)
代码语言:javascript复制特征值为: [ 1. -1. 1. -1.]
特征向量为:
[[ 0.70710678 0.70710678 0. 0. ]
[ 0. 0. 0.70710678 -0.70710678]
[ 0. 0. 0.70710678 0.70710678]
[ 0.70710678 -0.70710678 0. 0. ]]
这段代码使用NumPy库进行矩阵操作和特征值计算。下面是代码的解释:
代码语言:javascript复制import numpy as np
a = np.eye(4)
b = np.rot90(a)
c, d = np.linalg.eig(b)
print('特征值为:', c)
print('特征向量为:n', d)
- 导入NumPy库并将其简写为
np
。 - 创建一个4x4的单位矩阵
a
,使用np.eye(4)
函数。 - 使用
np.rot90()
函数对矩阵a
进行90度旋转,生成新的矩阵b
。 - 使用
np.linalg.eig()
函数计算矩阵b
的特征值和特征向量。返回的结果是一个包含特征值的一维数组c
和特征向量组成的二维数组d
。 - 打印特征值和特征向量的结果。
print('特征值为:', c)
:打印特征值。print('特征向量为:n', d)
:打印特征向量。
该代码的输出将给出矩阵b
的特征值和特征向量的结果。
2.5 Pandas 库介绍¶
2.5.1 Pandas 基本操作¶
Pandas库的主要数据结构是Series和DataFrame。这两种数据结构提供了强大的功能和灵活性,用于数据处理、分析和操作。
- Series(序列): Series是一维的带标签的数组。它由两个主要组成部分:索引和数据。索引提供了数据的标签,而数据则是存储在相应的值中。Series可以包含任意数据类型。Series提供了许多方法和属性,用于数据的选择、切片、过滤、聚合等操作。
- DataFrame(数据框): DataFrame是二维的表格型数据结构,类似于关系型数据库中的表格或电子表格。它由行和列组成,每列可以包含不同的数据类型。DataFrame提供了一个强大的数据处理环境,可以进行数据的操作、过滤、选择、合并、重塑等。DataFrame可以从多种数据源创建,例如NumPy数组、Python字典、CSV文件、数据库查询结果等。
除了Series和DataFrame之外,Pandas还提供了其他一些辅助性的数据结构和功能,如Index、MultiIndex、DatetimeIndex等。这些数据结构和功能使得Pandas成为一个功能强大且灵活的数据处理工具,广泛应用于数据分析、数据清洗、数据准备和数据建模等领域。
在最新版本的Pandas(从0.20.0版本开始),Panel已经不再被推荐使用,并且在将来的版本中可能会被弃用。取而代之的是使用更通用和灵活的MultiIndex技术,将多个DataFrame对象组合在一起。
因此,在较新的Pandas版本中,主要的数据结构是Series和DataFrame。Series用于表示一维数据,而DataFrame用于表示二维数据,类似于关系型数据库中的表格。这两种数据结构提供了丰富的功能和方法,可以用于数据的处理、分析和操作。
如果您使用的是较旧的Pandas版本,并且需要使用Panel数据结构,请确保参考您所使用的Pandas版本的文档和相关资料。但是请注意,Panel已不再是Pandas的主要数据结构,并且在未来的版本中可能会被删除。
1. 生成二维数组¶
In [3]:
代码语言:javascript复制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))
好的,我将更详细地解释代码的每一部分。
代码语言:javascript复制import pandas as pd
import numpy as np
# 创建日期范围
dates = pd.date_range(start='20191101', end='20191124', freq='D')
在这里,使用pd.date_range()
函数创建了一个日期范围。start
参数指定起始日期为'20191101',end
参数指定结束日期为'20191124',freq
参数指定频率为'D',表示每日。这将生成一个包含从起始日期到结束日期之间每一天的日期索引。
# 创建具有指定索引和列标签的DataFrame
a1 = pd.DataFrame(np.random.randn(24, 4), index=dates, columns=list('ABCD'))
在这里,使用np.random.randn()
函数生成一个24行4列的随机数数组,其中的值符合标准正态分布。然后,使用这个数组作为数据创建了一个DataFrame对象a1
。index
参数指定了使用上面创建的日期范围作为索引,columns
参数指定了列标签为'A'、'B'、'C'和'D'。
# 创建具有默认索引和列标签的DataFrame
a2 = pd.DataFrame(np.random.rand(24, 4))
这里使用np.random.rand()
函数生成一个24行4列的随机数数组,其中的值是0到1之间的均匀分布的随机数。然后,使用这个数组创建了一个DataFrame对象a2
。由于没有指定索引和列标签,所以将使用默认的整数索引和列标签。
通过以上代码,您创建了两个DataFrame对象:a1
和a2
。其中,a1
具有指定的日期索引和列标签,而a2
具有默认的整数索引和列标签。这些DataFrame对象包含了随机生成的数据,可用于进行数据分析和处理。
2. 读写文件¶
In [3]:
代码语言:javascript复制#程序文件ex2_38_1.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.close()
In [2]:
代码语言:javascript复制#程序文件ex2_38_2.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_4.xlsx', index=False) #不包括行索引
a2.to_csv('data2_38_5.csv', index=False) #不包括行索引
f=pd.ExcelWriter('data2_38_6.xlsx') #创建文件对象
a1.to_excel(f, "Sheet1", index=False) #把a1写入Excel文件
a2.to_excel(f, "Sheet2", index=False) #把a2写入另一个表单中
f.close()
In [24]:
代码语言:javascript复制#程序文件ex2_39.py
import numpy as np
import pandas as pd
#a = pd.read_csv("data2_38_2.csv", usecols=range(1, 5))
b = pd.read_excel("data/02Python使用入门/data2_38_3.xlsx", "Sheet2", usecols=range(1, 5))
print(b.T)
代码语言:javascript复制 0 1 2 3 4 5 6
0 1.213797 1.945913 -1.181196 0.341214 1.108085 -1.372730 -0.548565
1 -0.083503 -2.314180 -1.619163 0.102465 -1.080620 -0.468224 -0.356358
2 0.405542 0.883194 0.016889 0.330536 0.762942 -1.361796 0.953249
3 -1.189722 -1.112954 -0.449746 1.135402 0.573003 0.112269 -0.837776
7 8 9 ... 14 15 16 17
0 -1.261965 0.316968 1.079596 ... -0.039051 -0.829906 1.422983 -0.983532
1 -0.216644 -1.619560 0.211296 ... -1.233724 1.053035 1.453156 0.122333
2 -0.155388 -0.174830 0.959788 ... 0.562188 -2.214180 0.929287 2.035284
3 -1.094786 -0.824761 0.577830 ... -1.568483 0.959265 0.827469 -1.666533
18 19 20 21 22 23
0 -1.354187 -1.784988 0.906286 -0.133222 -0.510842 0.997421
1 -1.902920 0.923422 -0.115585 -0.278630 -0.343483 -0.790728
2 -0.180118 0.242669 -1.676260 0.367361 0.400815 -0.499498
3 -0.558349 0.533557 0.726238 1.287406 0.484269 0.118164
[4 rows x 24 columns]
2.5.2 数据的一些预处理¶
1. 拆分、合并和分组计算¶
In [8]:
代码语言:javascript复制#程序文件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) #数据分组求和
代码语言:javascript复制import pandas as pd
import numpy as np
这两行代码导入了 pandas 和 numpy 库,它们在 Python 中常用于数据处理和分析。
代码语言:javascript复制d = pd.DataFrame(np.random.randint(1, 6, (10, 4)), columns=list("ABCD"))
这行代码创建了一个名为 d
的 DataFrame 对象,它包含了一个 10 行 4 列的随机整数数据,这些整数的取值范围在 1 到 5 之间。列名依次为 'A'、'B'、'C' 和 'D'。
d1 = d[:4]
这行代码通过选择 DataFrame d
的前 4 行创建了一个新的 DataFrame 对象 d1
。
d2 = d[4:]
这行代码通过选择 DataFrame d
的第 5 行及以后的行创建了一个新的 DataFrame 对象 d2
。
dd = pd.concat([d1, d2])
这行代码沿着行轴(纵向)将 DataFrame d1
和 d2
进行合并,生成一个名为 dd
的新 DataFrame,其中包含了 d1
和 d2
的所有行。
s1 = d.groupby('A').mean()
这行代码根据 'A' 列的值对 DataFrame d
进行分组,并计算每个分组的均值。结果存储在一个名为 s1
的新 Series 对象中,其中 'A' 列的值用作索引。
s2 = d.groupby('A').apply(sum)
这行代码根据 'A' 列的值对 DataFrame d
进行分组,并对每个分组应用 sum
函数进行求和。结果存储在一个名为 s2
的新 Series 对象中,与 s1
类似,但是包含每个分组的求和值而不是均值。
总体而言,该程序生成一个随机的 DataFrame,将其拆分为两部分,再将它们合并在一起,最后根据 'A' 列的值计算分组的均值和求和。
groupby
是 pandas 中的一个函数,用于根据一个或多个列的值对 DataFrame 进行分组操作。它可以用于数据聚合、统计和分析。下面是 groupby
函数的详细解释和使用方法:
语法:
代码语言:javascript复制groupby(by=None, axis=0, level=None, as_index=True, sort=True, group_keys=True, squeeze=False, observed=False, **kwargs)
参数:
by
:指定分组的依据,可以是列名、列的列表、Series、数组或多个列的组合。它决定了按照哪些列的值进行分组。axis
:指定分组的轴向,0 表示按行进行分组,1 表示按列进行分组。level
:如果 DataFrame 是多层索引的,则可以指定级别进行分组。as_index
:指定是否将分组的依据列作为结果的索引。默认为 True,即将分组的依据列作为索引,若设置为 False,则索引将为整数序列。sort
:指定分组后的结果是否按照分组依据进行排序,默认为 True。group_keys
:指定是否显示分组依据的标签。默认为 True,显示标签。squeeze
:指定是否在分组结果中删除维度为 1 的索引。默认为 False,即保留维度为 1 的索引。observed
:指定在多层索引中是否观察所有可能的值。默认为 False,只显示观察到的值。
返回值: groupby
函数返回一个 GroupBy
对象,它包含了分组后的数据和相应的操作方法。
GroupBy
对象的常用方法:
mean()
:计算分组后的均值。sum()
:计算分组后的求和。min()
:计算分组后的最小值。max()
:计算分组后的最大值。count()
:计算分组后的计数。agg()
:对分组后的数据进行自定义聚合操作。apply()
:对分组后的数据应用自定义函数。
示例:
代码语言:javascript复制import pandas as pd
# 创建一个示例 DataFrame
data = {
'Name': ['Alice', 'Bob', 'Charlie', 'Alice', 'Bob'],
'Subject': ['Math', 'Science', 'Math', 'Science', 'Science'],
'Score': [90, 85, 92, 88, 91]
}
df = pd.DataFrame(data)
# 按照 'Name' 列进行分组,并计算均值和求和
grouped = df.groupby('Name')
mean_scores = grouped['Score'].mean()
sum_scores = grouped['Score'].sum()
print(mean_scores)
print(sum_scores)
输出:
代码语言:javascript复制Name
Alice 89.0
Bob 88.0
Charlie 92.0
Name: Score, dtype: float64
Name
Alice 178
Bob 176
Charlie 92
Name:
Score, dtype: int64
上述示例中,首先创建了一个包含学生姓名、科目和成绩的 DataFrame。然后,使用 groupby
函数按照 'Name' 列对 DataFrame 进行分组。通过 groupby
后的对象可以调用不同的聚合函数,例如 mean()
和 sum()
,计算每个学生的成绩均值和总和。
2. 数据的选取与清洗¶
In [11]:
代码语言:javascript复制#程序文件ex2_41.py
import pandas as pd
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() #删除有不确定值的行(整行删除!!!)
print(a3)
代码语言:javascript复制 one two three four
b 5.0 3.0 2.0 bar
c 4.0 5.0 3.0 bar
d 4.0 3.0 5.0 bar
e 1.0 1.0 2.0 bar
In [ ]:
代码语言:javascript复制import pandas as pd
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',
这段代码是一个使用 pandas 库进行数据操作的程序。下面是对每行代码的解释:
代码语言:javascript复制import pandas as pd
import numpy as np
这两行代码导入了 pandas 和 numpy 库,它们在 Python 中常用于数据处理和分析。
代码语言:javascript复制a = pd.DataFrame(np.random.randint(1, 6, (5, 3)),
index=['a', 'b', 'c', 'd', 'e'],
columns=['one', 'two', 'three'])
这行代码创建了一个名为 a
的 DataFrame 对象,它包含了一个 5 行 3 列的随机整数数据,这些整数的取值范围在 1 到 5 之间。行索引为 'a'、'b'、'c'、'd' 和 'e',列索引为 'one'、'two' 和 'three'。
a.loc['a', 'one'] = np.nan
这行代码将第一行第一列的值设置为 NaN(缺失值)。使用 .loc
可以通过行和列标签进行索引和修改。
b = a.iloc[1:3, 0:2].values
这行代码提取了 DataFrame a
中第二行到第三行以及第一列到第二列的数据,并将其存储在一个名为 b
的 NumPy 数组中。使用 .iloc
可以通过行和列的整数位置进行索引。
a['four'] = 'bar'
这行代码在 DataFrame a
中增加了一个名为 'four' 的新列,并将其所有行的值设置为 'bar'。
a2 = a.reindex(['a', 'b', 'c', 'd', 'e', 'f'])
这行代码对 DataFrame a
进行重新索引,创建了一个新的 DataFrame a2
,行索引包括 'a'、'b'、'c'、'd'、'e' 和 'f'。如果索引中有原来 DataFrame 中不存在的标签,那么对应的行将会被填充为缺失值。
a3 = a2.dropna()
这行代码删除 DataFrame a2
中含有缺失值的行,并创建一个新的 DataFrame a3
。
综上所述,该程序生成了一个随机的 DataFrame,修改了其中的一个值,提取了部分数据,增加了新的列,然后重新索引,并最终删除了含有缺失值的行。
2.6 文件操作¶
2.6.1 文件操作基本知识¶
1. 内置函数 open()¶
open()
是 Python 的内置函数,用于打开文件并返回一个文件对象。它的语法如下:
open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)
参数说明:
file
: 要打开的文件路径(字符串类型)或文件描述符(整数类型)。mode
: 打开文件的模式,默认为'r'
,表示以只读模式打开文件。常见的模式有:'r'
: 只读模式'w'
: 写入模式,如果文件存在则覆盖内容,不存在则创建新文件'x'
: 写入模式,如果文件存在抛出异常,不存在则创建新文件'a'
: 追加模式,将数据写入文件末尾'b'
: 二进制模式,用于处理二进制文件't'
: 文本模式,用于处理文本文件(默认模式)' '
: 读、写模式(可与其他模式组合使用)
- 其他参数(如
buffering
、encoding
、errors
、newline
、closefd
、opener
)是可选参数,用于控制文件的缓冲、编码、错误处理等。
open()
函数返回一个文件对象,可以使用该对象进行文件的读取、写入等操作。例如:
# 以只读模式打开文件
file = open('example.txt', 'r')
# 读取文件内容
content = file.read()
print(content)
# 关闭文件
file.close()
在使用完文件后,应当使用 close()
方法关闭文件,以释放系统资源。另外,也可以使用 with
语句来自动管理文件的打开和关闭,这样可以确保在退出 with
代码块后文件会被自动关闭,如下所示:
with open('example.txt', 'r') as file:
content = file.read()
print(content)
这样,在 with
代码块结束时,文件会自动关闭,无需手动调用 close()
方法。
open()
函数是进行文件操作的基础函数,可以进行读取、写入、追加、二进制操作等。通过指定不同的模式参数和使用文件对象的不同方法,可以实现各种文件操作需求。
2. 文件对象常用方法¶
文件对象有许多常用的方法,可以用于读取、写入和管理文件。下面是一些常用的文件对象方法:
read(size=-1)
: 从文件中读取指定大小的内容,默认为读取整个文件。返回一个字符串(在文本模式下)或字节对象(在二进制模式下)。readline(size=-1)
: 从文件中读取一行内容,包括行末尾的换行符。如果指定了size
参数,则最多读取指定大小的字符数。readlines(hint=-1)
: 从文件中读取所有行,并将其存储在一个列表中。如果指定了hint
参数,则最多读取指定数量的行。write(string)
: 将指定的字符串内容写入文件。在文本模式下,字符串需要是 Unicode 字符串。返回写入的字符数。writelines(lines)
: 将一个字符串列表或可迭代对象中的所有字符串写入文件。每个字符串都会被写入为一个单独的行。seek(offset, whence=0)
: 移动文件指针到指定位置。offset
参数表示要移动的字节数,whence
参数指定相对于哪个位置进行偏移:0
:相对于文件开头进行偏移(默认值)1
:相对于当前位置进行偏移2
:相对于文件末尾进行偏移
tell()
: 返回当前文件指针的位置,即当前读写位置的偏移量。close()
: 关闭文件。在完成对文件的操作后,应该调用该方法以释放系统资源。
这些方法只是文件对象提供的一小部分功能。根据具体需求,还可以使用其他方法,如 seekable()
、readable()
、writable()
等来检查文件的可读性、可写性和可定位性。
3. 上下文管理语句 with¶
上下文管理语句 with
是 Python 中用于管理资源的一种语法结构。它可以确保在代码块执行完毕后,相关资源会被自动关闭或清理,无论是否发生异常。
with
语句的一般形式是:
with expression as variable:
# 代码块
其中,expression
是一个返回上下文管理器对象的表达式,它必须具有 __enter__()
和 __exit__()
方法。通常,我们使用打开文件的 open()
函数来获取一个文件对象作为上下文管理器。variable
是一个可选的变量,用于引用上下文管理器对象。
with
语句的工作原理如下:
expression.__enter__()
方法被调用,返回上下文管理器对象,并将其赋值给variable
。- 执行代码块中的代码。
- 如果代码块正常执行完毕,或者没有发生异常,则调用
expression.__exit__(exc_type, exc_value, exc_traceback)
方法,其中exc_type
、exc_value
和exc_traceback
是异常信息(如果有的话)。 - 如果代码块中发生了异常,异常会被传递给
expression.__exit__()
方法处理,并且该方法可以选择处理异常,进行清理操作等。如果__exit__()
方法返回True
,则异常被视为已经处理,不会被重新引发;如果返回False
或者抛出新的异常,则异常会被重新引发,可以在上层代码中进行处理。
使用 with
语句可以简化资源的管理,尤其是需要进行打开、关闭等操作的场景,如文件操作、数据库连接、网络连接等。例如,使用 with
语句打开文件并自动关闭:
with open('example.txt', 'r') as file:
content = file.read()
print(content)
在上述示例中,open()
函数返回的文件对象作为上下文管理器,被赋值给 file
变量。代码块中的操作会在执行完毕后,自动调用 file.close()
方法关闭文件,无需手动编写关闭代码。
通过使用 with
语句,可以更加简洁、安全地管理资源,避免资源泄漏和忘记关闭资源的问题。
2.6.2 文本文件操作¶
In [13]:
代码语言:javascript复制#程序文件ex2_42.py
with open('data/02Python使用入门/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_42.txt', 'w') as fp2:
fp2.writelines(data)
代码语言:javascript复制[58, 52, 57, 54, 58]
[57, 51, 56, 53, 57]
对于程序文件ex2_42.py,下面是对每行代码的解释:
代码语言:javascript复制with open('data/02Python使用入门/data2_2.txt') as fp:
L1 = []
L2 = []
for line in fp:
L1.append(len(line))
L2.append(len(line.strip())) #去掉换行符
这部分代码打开名为 'data/02Python使用入门/data2_2.txt'
的文件,并使用 with
语句将文件对象赋值给变量 fp
。然后,通过迭代读取文件的每一行,将每行的字符数添加到列表 L1
中,并将去掉换行符后的字符数添加到列表 L2
中。
data = [str(num) 't' for num in L2] #转换为字符串
这行代码使用列表推导式将 L2
中的每个数转换为字符串,并在末尾添加一个制表符。生成的结果存储在名为 data
的列表中。
print(L1)
print(L2)
这部分代码打印列表 L1
和 L2
的内容。
with open('data2_42.txt', 'w') as fp2:
fp2.writelines(data)
这部分代码打开名为 'data2_42.txt'
的文件,并使用 with
语句将文件对象赋值给变量 fp2
。然后,使用 fp2.writelines()
方法将列表 data
中的内容写入文件中。
这段代码的功能是读取 'data/02Python使用入门/data2_2.txt'
文件的每一行,计算每行的字符数,并将去掉换行符后的字符数写入到 'data2_42.txt'
文件中。
In [5]:
代码语言:javascript复制#程序文件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=',') #存成以逗号分隔的文本文件
b=np.loadtxt("data2_43_1.txt") #加载空格分隔的文本文件
c=np.loadtxt("data2_43_2.csv", delimiter=',') #加载csv文件
对于程序文件ex2_43.py,下面是对每行代码的解释:
代码语言:javascript复制import numpy as np
a = np.random.rand(6, 8) # 生成6×8的[0,1)上均匀分布的随机数矩阵
这行代码导入了 numpy
库,并使用 np.random.rand()
函数生成一个大小为 6×8 的随机数矩阵 a
,其中的元素是在半开区间 [0, 1) 上均匀分布的随机数。
np.savetxt("data2_43_1.txt", a) # 存成以制表符分隔的文本文件
这行代码使用 np.savetxt()
函数将矩阵 a
存储为文本文件 "data2_43_1.txt"
,默认使用制表符作为元素之间的分隔符。
np.savetxt("data2_43_2.csv", a, delimiter=',') # 存成以逗号分隔的文本文件
这行代码使用 np.savetxt()
函数将矩阵 a
存储为 CSV 格式的文本文件 "data2_43_2.csv"
,指定逗号作为元素之间的分隔符。
b = np.loadtxt("data2_43_1.txt") # 加载空格分隔的文本文件
这行代码使用 np.loadtxt()
函数加载空格分隔的文本文件 "data2_43_1.txt"
,并将数据存储在变量 b
中。
c = np.loadtxt("data2_43_2.csv", delimiter=',') # 加载csv文件
这行代码使用 np.loadtxt()
函数加载 CSV 格式的文本文件 "data2_43_2.csv"
,指定逗号作为元素之间的分隔符,并将数据存储在变量 c
中。
这段代码的功能是生成随机数矩阵 a
,并将该矩阵以不同的格式存储为文本文件。然后,通过 np.loadtxt()
函数加载这些文本文件中的数据,并存储在变量 b
和 c
中。
2.7 Scipy 库¶
2.7.1 Scipy 简介¶
Scipy(Scientific Python)是一个开源的科学计算库,它建立在NumPy的基础上,并提供了一组用于科学计算和数据分析的功能。Scipy包含了许多模块,每个模块提供了不同的功能。下面是Scipy库中一些常用模块及其功能的简介:
scipy.constants
:提供了一些科学和数学常量的定义,如数学常数π和自然对数的底e。scipy.integrate
:提供了积分和常微分方程的函数,用于数值积分和求解常微分方程。scipy.optimize
:包含了优化算法的函数,用于最小化或最大化函数的值。包括了最小二乘拟合、非线性最小化、曲线拟合等功能。scipy.interpolate
:提供了插值函数的功能,用于在给定的数据点之间进行插值,如线性插值、样条插值等。scipy.linalg
:包含了线性代数运算的函数,用于矩阵操作、求解线性方程组、特征值和特征向量计算等。scipy.fft
:提供了快速傅里叶变换(FFT)的函数,用于信号处理和频谱分析。scipy.signal
:包含了信号处理的函数,用于滤波、频谱分析、卷积等。scipy.stats
:包含了统计分析的函数,用于概率分布、统计测试、描述统计量等。scipy.spatial
:提供了空间数据结构和算法的函数,用于处理和操作空间数据,如距离计算、最近邻搜索等。scipy.ndimage
:包含了图像处理的函数,用于图像滤波、图像变换、图像分割等。
以上只是Scipy库中一些常用模块的简介,Scipy还包含了其他一些模块和子模块,如稀疏矩阵运算、信号处理、优化算法、图像处理等。Scipy的广泛功能使其成为科学计算、数据分析和工程应用中不可或缺的库之一。
2.7.2 Scipy 基本操作¶
1. 求解非线性方程组¶
In [12]:
代码语言:javascript复制#程序文件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)
代码语言:javascript复制[1.21]
-------------
message: The solution converged.
success: True
status: 1
fun: [-1.233e 69]
x: [ 1.210e 00]
nfev: 319
fjac: [[-1.000e 00]]
r: [ 2.542e 80]
qtf: [ 2.002e 72]
程序文件ex2_44.py中的代码使用了Scipy库中的优化函数进行方程求解。下面是对每行代码的解释:
代码语言:javascript复制from scipy.optimize import fsolve, root
这行代码导入了Scipy库中的优化函数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
这行代码定义了一个名为fx
的匿名函数,表示要求解的非线性方程。
x1 = fsolve(fx, 1.5, maxfev=4000)
这行代码使用fsolve
函数对方程进行求解。第一个参数是要求解的函数fx
,第二个参数是初始猜测值,即方程的近似解,这里取为1.5。maxfev
参数表示函数调用的最大次数,这里设置为4000。结果将赋值给变量x1
。
x2 = root(fx, 1.5)
这行代码使用root
函数对方程进行求解。第一个参数是要求解的函数fx
,第二个参数是初始猜测值,即方程的近似解,这里取为1.5。结果将赋值给变量x2
。
print(x1,'n','-------------')
print(x2)
这部分代码打印求解得到的结果x1
和x2
。
该程序文件使用fsolve
和root
函数分别求解了一个非线性方程。fsolve
函数使用数值方法进行求解,而root
函数则根据方程的性质和初始猜测值选择合适的算法进行求解。结果会打印出来,供查看求解的近似解。
In [11]:
代码语言:javascript复制#程序文件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)
代码语言:javascript复制[0.70710678 0.70710678]
--------------
message: The solution converged.
success: True
status: 1
fun: [ 4.441e-16 0.000e 00]
x: [ 7.071e-01 7.071e-01]
nfev: 9
fjac: [[-8.165e-01 -5.773e-01]
[ 5.773e-01 -8.165e-01]]
r: [-1.732e 00 -5.774e-01 1.633e 00]
qtf: [-3.646e-10 2.578e-10]
程序文件ex2_45.py中的代码同样使用了Scipy库中的优化函数进行方程组的求解。下面是对每行代码的解释:
代码语言:javascript复制from scipy.optimize import fsolve, root
这行代码导入了Scipy库中的优化函数fsolve
和root
,用于求解非线性方程组。
fx = lambda x: [x[0]**2 x[1]**2-1, x[0]-x[1]]
这行代码定义了一个名为fx
的匿名函数,表示要求解的非线性方程组。方程组由两个方程组成,第一个方程是x[0]**2 x[1]**2-1
,第二个方程是x[0]-x[1]
。
s1 = fsolve(fx, [1, 1])
这行代码使用fsolve
函数对方程组进行求解。第一个参数是要求解的函数fx
,第二个参数是初始猜测值,即方程组的近似解,这里取为[1, 1]
。结果将赋值给变量s1
。
s2 = root(fx, [1, 1])
这行代码使用root
函数对方程组进行求解。第一个参数是要求解的函数fx
,第二个参数是初始猜测值,即方程组的近似解,这里取为[1, 1]
。结果将赋值给变量s2
。
print(s1,'n','--------------')
print(s2)
这部分代码打印求解得到的结果s1
和s2
。
该程序文件使用fsolve
和root
函数分别求解了一个由两个非线性方程组成的方程组。结果会打印出来,供查看求解的近似解。
2. 积分¶
In [10]:
代码语言:javascript复制#程序文件ex2_46.py
from scipy.integrate import quad
fun46 = lambda x, a, b: 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)
代码语言:javascript复制(1.1666666666666665, 1.2952601953960159e-14)
(5.666666666666667, 6.291263806209221e-14)
程序文件ex2_46.py中的代码使用了Scipy库中的积分函数进行数值积分。下面是对每行代码的解释:
代码语言:javascript复制from scipy.integrate import quad
这行代码导入了Scipy库中的积分函数quad
,用于进行数值积分。
def fun46(x, a, b):
return a*x**2 b*x
这行代码定义了一个名为fun46
的函数,表示要进行积分的函数。该函数接受变量x
以及两个参数a
和b
,返回值为a*x**2 b*x
。
I1 = quad(fun46, 0, 1, args=(2, 1))
I2 = quad(fun46, 0, 1, args=(2, 10))
这两行代码分别使用quad
函数进行积分。第一个参数是要积分的函数fun46
,第二个和第三个参数是积分的下界和上界,这里取为0和1。args
参数用于传递额外的参数给被积函数,这里分别传入了(2, 1)
和(2, 10)
作为a
和b
的值。结果将分别赋值给变量I1
和I2
。
print(I1)
print(I2)
这部分代码打印求解得到的积分结果I1
和I2
。
该程序文件使用quad
函数对指定的函数进行数值积分,分别计算了两个不同参数下的积分结果。结果会打印出来,供查看积分的近似值。
scipy.integrade¶
Scipy库中的scipy.integrate
模块提供了用于数值积分的函数和工具。该模块包含了多种数值积分方法,可以用于解决单变量和多变量的定积分问题。下面是scipy.integrate
模块中一些常用函数的简介:
quad(func, a, b, args=())
:计算定积分的数值近似值。参数func
为要积分的函数,a
和b
为积分的下界和上界,args
为传递给被积函数的额外参数。dblquad(func, a, b, gfun, hfun, args=())
:计算二重积分的数值近似值。参数func
为要积分的函数,a
和b
为积分的下界和上界,gfun
和hfun
为积分区域的边界函数,args
为传递给被积函数的额外参数。tplquad(func, a, b, gfun, hfun, qfun, rfun, args=())
:计算三重积分的数值近似值。参数func
为要积分的函数,a
和b
为积分的下界和上界,gfun
、hfun
、qfun
和rfun
为积分区域的边界函数,args
为传递给被积函数的额外参数。quad_vec(func, a, b, args=())
:对一组积分区间进行定积分计算,返回每个积分区间的数值结果。
除了上述函数,scipy.integrate
模块还提供了其他函数,如数值微分、常微分方程求解、积分器对象等。这些函数和工具使得在科学计算和数值分析中进行数值积分变得更加便捷和高效。
3. 最小二乘解¶
In [22]:
代码语言:javascript复制#程序文件ex2_47.py
from scipy.optimize import least_squares
import numpy as np
a=np.loadtxt('data/02Python使用入门/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)
代码语言:javascript复制 message: `ftol` termination condition is satisfied.
success: True
status: 2
fun: [-3.433e-01 1.360e-01 -4.966e-01 5.928e-01]
x: [ 1.495e 02 3.600e 02]
cost: 0.3671505584636816
jac: [[-7.586e-01 -6.516e-01]
[-1.199e-01 -9.928e-01]
[-4.738e-01 8.807e-01]
[-8.088e-01 5.881e-01]]
grad: [-8.129e-08 1.814e-08]
optimality: 8.128934214646222e-08
active_mask: [ 0.000e 00 0.000e 00]
nfev: 15
njev: 15
------------
[149.50894329 359.9847955 ]
程序文件ex2_47.py中的代码使用了Scipy库中的最小二乘优化函数进行非线性最小二乘拟合。下面是对每行代码的解释:
代码语言:javascript复制from scipy.optimize import least_squares
import numpy as np
这两行代码导入了Scipy库中的最小二乘优化函数least_squares
以及NumPy库,并将NumPy库重命名为np
。
a = np.loadtxt('data/02Python使用入门/data2_47.txt')
x0 = a[0]
y0 = a[1]
d = a[2]
这部分代码从文件中加载数据,其中data2_47.txt
是包含多行数据的文本文件。这里将数据分别赋值给变量x0
、y0
和d
。
fx = lambda x: np.sqrt((x0 - x[0])**2 (y0 - x[1])**2) - d
这行代码定义了一个名为fx
的匿名函数,表示要进行拟合的目标函数。该函数接受一个参数x
,返回值为(x0 - x[0])**2 (y0 - x[1])**2
的平方根减去d
。
s = least_squares(fx, np.random.rand(2))
这行代码使用least_squares
函数进行最小二乘拟合。第一个参数是要拟合的函数fx
,第二个参数是初始猜测值,这里使用np.random.rand(2)
生成一个长度为2的随机数组作为初始猜测值。结果将赋值给变量s
。
print(s, 'n', '------------', 'n', s.x)
这部分代码打印求解得到的结果s
,其中s.x
表示拟合后的最优解。
该程序文件使用least_squares
函数对给定的非线性函数进行最小二乘拟合,找到使目标函数与数据最匹配的参数值。结果会打印出来,供查看拟合结果。
4. 最大模特征值及对应的特征向量¶
In [10]:
代码语言:javascript复制#程序文件 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)
b,c=np.linalg.eig(a)
d,e=eigs(a,1)
print("最大模特征值:",d)
print("对应的特征向量:",e)
代码语言:javascript复制最大模特征值: [9. 0.j]
对应的特征向量: [[-0.40824829 0.j]
[-0.40824829 0.j]
[-0.81649658 0.j]]
2.8 Sympy 库¶
In [4]:
代码语言:javascript复制#程序文件ex2_49.py
import sympy as sp
a, b, c, x=sp.symbols('a,b,c,x')
f,g=sp.symbols("f,g",cls=sp.Function)
x0=sp.solve(a*x**2 b*x c, x)
print(x0)
代码语言:javascript复制[(-b - sqrt(-4*a*c b**2))/(2*a), (-b sqrt(-4*a*c b**2))/(2*a)]
代码语言:javascript复制import sympy as sp
这行代码导入了SymPy库,SymPy是一个用于符号数学的Python库。
代码语言:javascript复制a, b, c, x = sp.symbols('a, b, c, x')
这行代码使用SymPy库的symbols
函数定义了符号变量a
、b
、c
和x
,用于表示二次方程的系数和变量。
f, g = sp.symbols("f, g", cls=sp.Function)
这行代码使用SymPy库的symbols
函数定义了符号函数f
和g
,并指定它们的类别为Function
。
x0 = sp.solve(a*x**2 b*x c, x)
这行代码使用SymPy库的solve
函数求解了二次方程a*x**2 b*x c
对变量x
的解,并将解赋值给变量x0
。
print(x0)
这行代码打印了二次方程的解。
总体而言,这段代码计算了一个二次方程的解,并将结果显示出来。
In [5]:
代码语言:javascript复制#程序文件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)
代码语言:javascript复制[(-sqrt(2)/2, -sqrt(2)/2), (sqrt(2)/2, sqrt(2)/2)]
In [6]:
代码语言:javascript复制#程序文件ex2_51.py
import numpy as np
import sympy as sp
a = np.identity(4) #单位矩阵的另一种写法
b = np.rot90(a)
c = sp.Matrix(b)
print('特征值为:', c.eigenvals())
print('特征向量为:n', c.eigenvects())
代码语言:javascript复制特征值为: {-1.00000000000000: 2, 1.00000000000000: 2}
特征向量为:
[(-1.00000000000000, 1, [Matrix([
[ 0],
[-0.707106781186548],
[ 0.707106781186548],
[ 0]])]), (1.00000000000000, 1, [Matrix([
[ 0],
[-0.707106781186548],
[-0.707106781186548],
[ 0]])]), (-1.00000000000000, 1, [Matrix([
[ 0.707106781186548],
[ 0],
[ 0],
[-0.707106781186548]])]), (1.00000000000000, 1, [Matrix([
[-0.707106781186548],
[ 0],
[ 0],
[-0.707106781186548]])])]
Matplotlib 库介绍¶
2.9.1 二维绘图¶
1. 折线图¶
In [37]:
代码语言:javascript复制import pylab as plt
import pandas as pd
plt.rc('font',family="SimHei")
plt.rc("font",size=16)
a=pd.read_excel("data/02Python使用入门/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()
2. Pandas 结合 Matplotlib 进行数据可视化¶
In [34]:
代码语言:javascript复制#程序文件 ex2_53.py
import pandas as pd
import pylab as plt
plt.rc('font',family="SimHei")
plt.rc("font",size=16)
a=pd.read_excel("data/02Python使用入门/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()
给定的代码使用Python编写,使用pandas和pylab库从Excel文件中读取数据并创建条形图。
以下是代码的详细说明:
- 导入必要的库,pandas和pylab(matplotlib)。
plt.rc('font', family="SimHei")
这行代码将字体族设置为"SimHei",这是一种中文字体。这行代码用于确保在绘图中能够正确显示中文字符。plt.rc("font", size=16)
这行代码将绘图的字体大小设置为16。a = pd.read_excel("data/02Python使用入门/data2_52.xlsx", header=None)
这行代码从位于"data/02Python使用入门/"目录中的名为"data2_52.xlsx"的Excel文件中读取数据。数据存储在名为a
的pandas DataFrame中。b = a.T
这行代码对DataFramea
进行转置,交换行和列,并将转置后的DataFrame赋值给b
。b.plot(kind="bar")
这行代码使用转置后的DataFrameb
创建条形图。plt.legend(["钻石","铂金"])
这行代码向图表添加一个图例,标签分别为"钻石"和"铂金"。plt.xticks(range(6), b[0], rotation=0)
这行代码设置x轴刻度位置和标签。它使用转置后的DataFrameb
的第一列(b[0]
)的值作为刻度标签。plt.ylabel("数量")
这行代码将y轴标签设置为"数量"。- 最后,
plt.show()
显示绘图。
在运行此代码之前,请确保已安装所需的库并将数据文件("data2_52.xlsx")放置在正确的目录中。
In [39]:
代码语言:javascript复制import pylab as plt
import pandas as pd
import numpy as np
plt.rc('font', family="SimHei")
plt.rc("font", size=16)
# 从Excel文件读取数据
a = pd.read_excel("data/02Python使用入门/data2_52.xlsx", header=None)
# 提取数据
b = a.values
x = b[0]
y = b[1:]
# 计算并列条形的位置
bar_width = 0.35
bar_positions1 = np.arange(len(x))
bar_positions2 = bar_positions1 bar_width
# 绘制并列条形图
plt.bar(bar_positions1, y[0], width=bar_width, color='b', label="钻石")
plt.bar(bar_positions2, y[1], width=bar_width, color='r', label="铂金")
# 设置x轴和y轴标签
plt.xlabel("月份")
plt.ylabel("每月销量")
# 设置x轴刻度标签
plt.xticks(bar_positions1 bar_width / 2, x)
# 添加图例
plt.legend(loc="upper left")
# 添加网格线
plt.grid()
# 显示图形
plt.show()
3. 子图¶
In [42]:
代码语言:javascript复制#程序文件ex2_54.py
import pylab as plt
import numpy as np
plt.rc('text', usetex=True) #调用tex字库
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}(50x)/x$'); plt.show()
当我运行一段程序时,会从第一行开始执行,逐行解释和执行代码。以下是对每行代码的详细解释:
代码语言:javascript复制import pylab as plt
import numpy as np
导入pylab
库并将其命名为plt
,导入numpy
库并将其命名为np
。这两个库是用于科学计算和绘图的常用库。
plt.rc('text', usetex=True) # 调用TeX字库
使用plt.rc
函数调用TeX字库,以便在图形中使用TeX格式的文本。
y1 = np.random.randint(2, 5, 6)
y1 = y1 / sum(y1)
使用np.random.randint
函数生成6个范围在2到5之间的随机整数,并将其存储在y1
变量中。然后,将y1
归一化,使其总和为1。
plt.subplot(2, 2, 1)
创建一个2x2的子图网格,并选择第一个位置作为当前子图。
代码语言:javascript复制labels = ['Apple', 'grape', 'peach', 'pear', 'banana', 'pineapple']
plt.barh(labels, y1)
plt.title("水平条形图")
plt.xlabel("频率")
plt.ylabel("水果")
使用plt.barh
函数绘制水平条形图。将条形的标签设置为labels
列表,高度设置为归一化后的y1
。使用plt.title
、plt.xlabel
和plt.ylabel
函数设置子图的标题、x轴标签和y轴标签。
plt.subplot(2, 2, 2)
选择第二个位置作为当前子图。
代码语言:javascript复制plt.pie(y1, labels=labels)
plt.title("饼图")
使用plt.pie
函数绘制饼图。使用labels
列表作为饼图中每个部分的标签。使用plt.title
函数设置子图的标题。
plt.subplot(2, 1, 2)
选择第三个位置作为当前子图。
代码语言:javascript复制x2 = np.linspace(0.01, 10, 100)
y2 = np.sin(10 * x2) / x2
plt.plot(x2, y2)
plt.title("折线图")
plt.xlabel("$x$")
plt.ylabel("$\mathrm{sin}(10x)/x$")
使用np.linspace
函数生成一个包含100个均匀分布的点的数组作为x轴数据。使用np.sin
函数计算sin(10x)/x作为y轴数据。然后使用plt.plot
函数绘制折线图。使用plt.title
、plt.xlabel
和plt.ylabel
函数设置子图的标题、x轴标签和y轴标签。
plt.subplots_adjust(hspace=0.5)
使用plt.subplots_adjust
函数调整子图之间的间距。通过设置hspace
参数,可以调整垂直方向上的
子图间距。
代码语言:javascript复制plt.show()
显示绘制的图形。
2.9.2 三维绘图¶
1. 三维曲线¶
In [43]:
代码语言:javascript复制import pylab as plt
import numpy as np
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()
这段代码使用了Python中的Matplotlib库来创建一个3D图形。下面是对每一行代码的详细解释:
import pylab as plt
:这行代码导入了Matplotlib库并将其命名为pylab
,同时将其子模块pyplot
命名为plt
,以便在后续代码中使用更简洁的方式调用。import numpy as np
:这行代码导入了NumPy库并将其命名为np
,NumPy是一个用于科学计算的Python库,在本代码中主要用于生成数值数组。ax = plt.axes(projection="3d")
:这行代码创建了一个3D坐标系,将其赋值给变量ax
。plt.axes()
函数用于创建一个Axes对象,通过设置projection
参数为"3d"来指定使用3D投影。z = np.linspace(-50, 50, 1000)
:这行代码使用NumPy库中的linspace()
函数生成一个包含1000个元素的等间距数组。该数组从-50到50之间均匀地取样,将结果赋值给变量z
。这个z
数组将被用作后续代码中的参数。x = z**2 * np.sin(z)
:这行代码使用NumPy的数组运算,将z
数组的每个元素进行平方、再与z
数组的每个元素的正弦值相乘,生成一个新的数组,并将其赋值给变量x
。这个操作将用于生成3D图形中的x坐标。y = z**2 * np.cos(z)
:这行代码与上一行类似,只不过这里将z
数组的每个元素的余弦值与平方相乘,生成一个新的数组,并将其赋值给变量y
。这个操作将用于生成3D图形中的y坐标。ax.plot(x, y, z, "k")
:这行代码调用了ax
对象的plot()
方法,用于绘制三维线条。它接受x
、y
和z
作为参数,分别表示线条上的点的x、y和z坐标。最后的参数"k"
表示绘制的线条颜色为黑色。plt.show()
:这行代码显示绘制的图形。plt.show()
函数用于显示所有已创建的图形,这样我们就可以在屏幕上看到我们所绘制的3D图形。
综上所述,这段代码使用Matplotlib库和NumPy库创建了一个简单的3D图形,图形中的线条由x、y和z数组确定,其中x和y数组根据z数组的数值计算得出。
2. 三维曲面图¶
In [8]:
代码语言:javascript复制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()
In [9]:
代码语言:javascript复制import pylab as plt
import numpy as np
ax=plt.axes(projection="3d")
x=np.linspace(-6,6,1000)
x,y=np.meshgrid(x,x)
z=np.sin(np.sqrt(x**2 y**2))
ax.plot_surface(x,y,z,color="y")
plt.show()
这段代码使用了Matplotlib库创建了一个三维曲面图。下面是对每一行代码的详细解释:
import pylab as plt
:这行代码导入了Matplotlib库并将其命名为pylab
,方便在后续代码中使用更简洁的方式调用。import numpy as np
:这行代码导入了NumPy库并将其命名为np
,NumPy是一个用于科学计算的Python库,在本代码中主要用于生成数值数组。x = np.linspace(-4, 4, 100)
:这行代码使用NumPy的linspace()
函数生成一个包含100个元素的等间距数组。该数组从-4到4之间均匀地取样,将结果赋值给变量x
。这个x
数组将被用作后续代码中的参数。x, y = np.meshgrid(x, x)
:这行代码使用NumPy的meshgrid()
函数生成两个二维数组x
和y
。这两个数组用来创建一个网格,其中x
数组中的每个元素与y
数组中的每个元素对应,构成一个二维坐标系。这个操作将用于生成三维曲面的坐标。z = 50 * np.sin(x y)
:这行代码使用NumPy的数组运算,将x
数组和y
数组的对应元素相加,再取正弦值,并与常数50相乘,生成一个新的数组,并将其赋值给变量z
。这个操作将用于生成三维曲面的高度。ax = plt.axes(projection="3d")
:这行代码创建了一个3D坐标系,将其赋值给变量ax
。plt.axes()
函数用于创建一个Axes对象,通过设置projection
参数为"3d"来指定使用3D投影。ax.plot_surface(x, y, z, color='y')
:这行代码调用了ax
对象的plot_surface()
方法,用于绘制三维曲面。它接受x
、y
和z
作为参数,表示曲面上的点的x、y和z坐标。最后的参数color='y'
表示曲面的颜色为黄色。plt.show()
:这行代码显示绘制的图形。plt.show()
函数用于显示所有已创建的图形,这样我们就可以在屏幕上看到我们所绘制的三维曲面图。
综上所述,这段代码使用Matplotlib库和NumPy库创建了一个简单的三维曲面图,曲面的形状由x
、y
和z
数组确定,其中x
和y
数组通过网格生成,z
数组根据x
和y
数组的数值计算得出。曲面的颜色为
黄色。
In [6]:
代码语言:javascript复制import numpy as np
import pylab as plt
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()
这段代码使用了Matplotlib库创建了一个三维曲面图,并添加了颜色映射和颜色条。下面是对每一行代码的详细解释:
import numpy as np
:这行代码导入了NumPy库并将其命名为np
,NumPy是一个用于科学计算的Python库,在本代码中主要用于生成数值数组。import pylab as plt
:这行代码导入了Matplotlib库并将其命名为pylab
,方便在后续代码中使用更简洁的方式调用。ax = plt.axes(projection="3d")
:这行代码创建了一个3D坐标系,将其赋值给变量ax
。plt.axes()
函数用于创建一个Axes对象,通过设置projection
参数为"3d"来指定使用3D投影。X = np.arange(-6, 6, 0.25)
:这行代码使用NumPy的arange()
函数生成一个包含数值范围的数组。该数组从-6开始,以0.25为步长,直到6结束,将结果赋值给变量X
。这个X
数组将被用作后续代码中的参数。Y = np.arange(-6, 6, 0.25)
:这行代码与上一行类似,生成了另一个与X
相同的数组,并将结果赋值给变量Y
。X, Y = np.meshgrid(X, Y)
:这行代码使用NumPy的meshgrid()
函数生成两个二维数组X
和Y
。这两个数组用来创建一个网格,其中X
数组中的每个元素与Y
数组中的每个元素对应,构成一个二维坐标系。这个操作将用于生成三维曲面的坐标。Z = np.sin(np.sqrt(X**2 Y**2))
:这行代码使用NumPy的数组运算,首先计算X
数组和Y
数组的每个对应元素的平方和的平方根,然后取正弦值,生成一个新的数组,并将其赋值给变量Z
。这个操作将用于生成三维曲面的高度。surf = ax.plot_surface(X, Y, Z, cmap='coolwarm')
:这行代码调用了ax
对象的plot_surface()
方法,用于绘制三维曲面。它接受X
、Y
和Z
作为参数,表示曲面上的点的x、y和z坐标。最后的参数cmap='coolwarm'
表示使用冷暖色彩映射来渲染曲面。plt.colorbar(surf)
:这行代码添加了一个颜色条,用于表示曲面上的颜色与数值的对应关系。plt.colorbar()
函数接受一个图形对象作为参数,在这里是surf
,用于生成对应的颜色条。
plt.show()
:这行代码显示绘制的图形。plt.show()
函数用于显示所有已创建的图形,这样我们就可以在屏幕上看到我们所绘制的三维曲面图。
综上所述,这段代码使用Matplotlib库和NumPy库创建了一个带有颜色映射和颜色条的三维曲面图,曲面的形状由X
、Y
和Z
数组确定,其中X
和Y
数组通过网格生成,Z
数组根据X
和Y
数组的数值计算得出。曲面的颜色根据数值的大小使用冷暖色彩映射渲染,并通过颜色条进行表示。