Unverified Commit 07bea5c1 authored by Kiryuu's avatar Kiryuu
Browse files

Finally finish this series

parent 0f0b0699
# Matplotlib子图与多子图
> 有时需要从多个角度对数据进行比较。matplotlib 为此提出了子图的概念:在较大的图形中放入一组较小的坐标轴。
>
> 本实训我们将介绍四种创建子图的方法。
https://www.educoder.net/shixuns/oyh3q8kl/challenges
## 第1关:手动创建子图
### 任务描述
本关任务:绘制一个包含两个样式不一致的子图。
### 相关知识
为了完成本关任务,你需要掌握:
1. 如何使用 `plt.axes` 创建子图
2. 如何使用 `fig.add_axes()` 创建子图。
#### `plt.axes` 创建子图
前面已经介绍过 `plt.axes` 函数,这个函数默认配置是创建一个标准的坐标轴,填满整张图。
它还有一个可选的参数,由图形坐标系统的四个值构成。这四个值表示为坐标系的[底坐标、左坐标、宽度、高度],数值的取值范围为左下角为 0,右上角为 1。
下面演示在右上角创建一个画中画:
```python
x1 = plt.axes() # 默认坐标轴
ax2 = plt.axes([0.65, 0.65, 0.2, 0.2])
```
![img/01.png](img/01.png)
#### `fig.add_axes()` 创建子图
面向对象画图接口中类似的命令由 `fig.add_axes()`。用这个命令创建两个竖直排列的坐标轴:
```python
fig = plt.figure()
ax1 = fig.add_axes([0.1, 0.5, 0.8, 0.4],
xticklabels=[], ylim=(-1.2, 1.2))
ax2 = fig.add_axes([0.1, 0.1, 0.8, 0.4],
ylim=(-1.2, 1.2))
x = np.linspace(0, 10)
ax1.plot(np.sin(x))
ax2.plot(np.cos(x));
```
![img/02.png](img/02.png)
可以看到两个紧挨着的坐标轴:上子图的(起点 y 坐标为 0.5 位置)与下子图 x 轴刻度是对应的(起点 y 坐标为 0.1,高度为 0.4)。
### 编程要求
根据提示,在右侧编辑器Begin-End处补充代码,根据输入数据绘制一个一行两列的折线图子图。子图一设置输入数据为 x 轴,输入数据的平方为 y 轴;设置颜色为红色;linestyle 为 `--`;线的宽度为 1;透明的为 0.3。子图二设置输入数据为 x 轴,输入数据的自然对数为 y 轴,具体可视化要求如下:
- 图形的 `figsize``(12, 12)`
- 图形保存到 `Task1/img/T1.png`
### 测试说明
平台会对你编写的代码进行测试:
预期输出:`你的答案与正确答案一致`
提示:
```python
#输入数据为x
plt.plot(x,x**2)
plt.plot(x,np.log(x))
```
----
开始你的任务吧,祝你成功!
### 答案
```python
import matplotlib
matplotlib.use("Agg")
import numpy as np
import matplotlib.pyplot as plt
def student(x):
'''
根据输入数据绘制不同的两个子图
:param x: 输入数据,类型为array
:return: None
'''
# ********* Begin *********#
fig=plt.figure(figsize=(12,12))
ax3=fig.add_subplot(1,2,1)
ax3.plot(x, x ** 2,color='r', linestyle='--', linewidth=1,alpha=0.3)
ax4=fig.add_subplot(1,2,2)
ax4.plot(x, np.log(x))
plt.savefig("Task1/img/T1.png")
# ********* End *********#
```
## 第2关:网格子图
### 任务描述
本关任务:编写一个能绘制一个两行四列的网格子图的程序。
### 相关知识
为了完成本关任务,你需要掌握:
1. 如何 `plt.subplot()` 绘制子图
2. 如何调整子图之间的间隔。
#### `plt.subplot()` 绘制子图
若干彼此对齐的行列子图是常见的可视化任务,`matplotlib` 拥有一些可以轻松创建它们的简便方法。最底层且最常用的方法是 `plt.subplot()`
这个函数在一个网格中创建一个子图,该函数由三个整型参数,依次为将要创建的网格子图行数、列数和索引值,索引值从1开始,从左上到右下递增。
```python
for i in range(1, 7):
plt.subplot(2, 3, i)
plt.text(0.5, 0.5, str((2, 3, i)),
fontsize=18, ha='center')
```
![img/03.png](img/03.png)
#### 调整子图之间的间隔
在上图 y 轴的刻度有的已经和前面的子图重叠,`matplotlib` 提供 `plt.subplots_adjust` 命令调整子图之间的间隔。用面向对象接口的命令 `fig.add_subplot()` 可以取得同样的效果。
```python
fig = plt.figure()
fig.subplots_adjust(hspace=0.4, wspace=0.4)
for i in range(1, 7):
ax = fig.add_subplot(2, 3, i)
ax.text(0.5, 0.5, str((2, 3, i)),
fontsize=18, ha='center')
```
![img/04.png](img/04.png)
这里我们通过设置 `plt.subplots_adjust``hspace``wspace` 参数设置与图形高度与宽度一致的子图间距,数值以子图的尺寸为单位。
#### `plt.subplots` 创建网格
当我们需要创建一个大型网格子图时,就没办法使用前面那种亦步亦趋的方法了,尤其是当你想隐藏内部子图的 x 轴与 y 轴标题时。`matplotlib` 提供了 `plt.subplots()` 来解决这个问题。
这个函数不是用来创建单个子图的,而是用一行代码创建多个子图,并放回一个包含子图的 `numpy` 数组。关键参数是行数与列数以及可选参数 `sharex``sharey`
让我们创建一个 2 × 3 的网格子图,同行使用相同的 y 坐标,同列使用相同的 y 轴坐标:
```python
fig, ax = plt.subplots(2, 3, sharex='col', sharey='row')
```
![img/05.png](img/05.png)
设置 `sharex``sharey` 参数后,我们就可以自动去掉网格内部子图的标签。
坐标轴实例网格的放回结果是一个 `numpy` 数组,这样就可以通过标准的数组取值方式轻松获取想要的坐标轴了:
```python
fig, ax = plt.subplots(2, 3, sharex='col', sharey='row')
for i in range(2):
for j in range(3):
ax[i, j].text(0.5, 0.5, str((i, j)),
fontsize=18, ha='center')
```
![img/06.png](img/06.png)
### 编程要求
在右侧编辑器Begin-End处补充代码,绘制不同一个两行四列的网格子图,并设置图形高度与宽度为 0.4,具体可视化要求如下:
- 图形的 `figsize``(10, 10)`
- 图形保存到 `Task2/img/T1.png`
### 测试说明
平台会对你编写的代码进行测试:
预期输出:`你的答案与正确答案一致`
----
开始你的任务吧,祝你成功!
### 答案
```python
import matplotlib
matplotlib.use("Agg")
import numpy as np
import matplotlib.pyplot as plt
def student():
'''
绘制不同一个两行四列的网格子图,并设置图形高度与宽度为0.4
:param: None
:return: None
'''
# ********* Begin *********#
fig = plt.figure(figsize=(10,10))
fig.subplots_adjust(hspace=0.4, wspace=0.4)
for i in range(1, 9):
plt.subplot(2, 4, i)
plt.savefig("Task2/img/T1.png")
plt.show()
# ********* End *********#
```
## 第3关:更复杂的排列方式
### 任务描述
本关任务:编写一个绘制不规则子图的函数。
### 相关知识
为了完成本关任务,你需要掌握:
1. 如何绘制不规则子图,
2. 在不规则子图中作图。
#### 不规则子图
`matplotlib` 还支持不规则的多行多列子图网格。
`plt.GridSpec()` 对象本事不能直接创建一个图形,他只是 `plt.subplot()` 命令可以识别的简易接口。
这里创建了一个带行列间距的 2 × 3 网格:
```python
grid = plt.GridSpec(2, 3, wspace=0.4, hspace=0.3)
```
`plt.GridSpec()` 支持通过类似python切片的语法设置子图的位置和扩展尺寸:
```python
plt.subplot(grid[0, 0])
plt.subplot(grid[0, 1:])
plt.subplot(grid[1, :2])
plt.subplot(grid[1, 2])
```
![img/07.png](img/07.png)
这种灵活的网格排列方式用途十分广泛,接下来我们用它创建多轴频次直方图:
```python
# 创建一些正态分布数据
mean = [0, 0]
cov = [[1, 1], [1, 2]]
x, y = np.random.multivariate_normal(mean, cov, 3000).T
# 设置坐标轴和网格配置方式
fig = plt.figure(figsize=(6, 6))
grid = plt.GridSpec(4, 4, hspace=0.2, wspace=0.2)
main_ax = fig.add_subplot(grid[:-1, 1:])
y_hist = fig.add_subplot(grid[:-1, 0], xticklabels=[], sharey=main_ax)
x_hist = fig.add_subplot(grid[-1, 1:], yticklabels=[], sharex=main_ax)
# 主坐标轴画散点图
main_ax.plot(x, y, 'ok', markersize=3, alpha=0.2)
# 次坐标轴画频次直方图
x_hist.hist(x, 40, histtype='stepfilled',
orientation='vertical', color='gray')
x_hist.invert_yaxis()
y_hist.hist(y, 40, histtype='stepfilled',
orientation='horizontal', color='gray')
y_hist.invert_xaxis()
```
![img/08.png](img/08.png)
### 编程要求
在右侧编辑器Begin-End处补充代码,绘制一个2行4列的不规则子图宽高间隔分别为 0.4、0.3。第 0 行设置 2 个子图,第一个子图占 3,第二个子图占 1。第二行相反,具体可视化要求如下:
- 图形的 `figsize``(10, 10)`
- 图形保存到 `Task3/img/T1.png`
### 测试说明
平台会对你编写的代码进行测试:
预期输出:`你的答案与正确答案一致`
----
开始你的任务吧,祝你成功!
### 答案
```python
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
import warnings
warnings.filterwarnings("ignore")
def student():
'''
绘制一个2行4列的不规则子图宽高间隔分别为0.4、0.3。
第0行设置2个子图,第一个子图占3,第二个子图占1。第二行相反
:param: None
:return: None
'''
# ********* Begin *********#
fig = plt.figure(figsize=(10, 10))
grid=plt.GridSpec(2,4, wspace=0.4, hspace=0.3)
plt.subplot(grid[0,0:3])
plt.subplot(grid[0,-1])
plt.subplot(grid[-1, 0])
plt.subplot(grid[-1, 1:])
plt.savefig("Task3/img/T1.png")
plt.show()
# ********* End *********#
```
\ No newline at end of file
import numpy as np
import test
from PIL import Image
def getDiff(width, high, image): # 将要裁剪成w*h的image照片
diff = []
im = image.resize((width, high))
imgray = im.convert('L') # 转换为灰度图片 便于处理
pixels = list(imgray.getdata()) # 得到像素数据 灰度0-255
for row in range(high): # 逐一与它左边的像素点进行比较
rowStart = row * width # 起始位置行号
for index in range(width - 1):
leftIndex = rowStart + index
rightIndex = leftIndex + 1 # 左右位置号
diff.append(pixels[leftIndex] > pixels[rightIndex])
return diff # *得到差异值序列 这里可以转换为hash码*
def getHamming(diff, diff2): # 暴力计算两点间汉明距离
hamming_distance = 0
for i in range(len(diff)):
if diff[i] != diff2[i]:
hamming_distance += 1
return hamming_distance
if __name__ == '__main__':
x = np.arange(0, 100)
test.student(x)
a=Image.open("Task1/img/T1.png")
b=Image.open("Task1/img1/T2.png")
diff1 = getDiff(32, 32, a)
diff2 = getDiff(32, 32, b)
ans = getHamming(diff1, diff2)
if ans < 1:
print("你的答案与正确答案一致")
else:
print("你的答案与正确答案不一致")
import matplotlib
matplotlib.use("Agg")
import numpy as np
import matplotlib.pyplot as plt
def student(x):
'''
根据输入数据绘制不同的两个子图
:param x: 输入数据,类型为array
:return: None
'''
# ********* Begin *********#
# ********* End *********#
\ No newline at end of file
import numpy as np
import test
from PIL import Image
def getDiff(width, high, image): # 将要裁剪成w*h的image照片
diff = []
im = image.resize((width, high))
imgray = im.convert('L') # 转换为灰度图片 便于处理
pixels = list(imgray.getdata()) # 得到像素数据 灰度0-255
for row in range(high): # 逐一与它左边的像素点进行比较
rowStart = row * width # 起始位置行号
for index in range(width - 1):
leftIndex = rowStart + index
rightIndex = leftIndex + 1 # 左右位置号
diff.append(pixels[leftIndex] > pixels[rightIndex])
return diff # *得到差异值序列 这里可以转换为hash码*
def getHamming(diff, diff2): # 暴力计算两点间汉明距离
hamming_distance = 0
for i in range(len(diff)):
if diff[i] != diff2[i]:
hamming_distance += 1
return hamming_distance
if __name__ == '__main__':
x = np.arange(0, 100)
test.student()
a=Image.open("Task2/img/T1.png")
b=Image.open("Task2/img1/T2.png")
diff1 = getDiff(32, 32, a)
diff2 = getDiff(32, 32, b)
ans = getHamming(diff1, diff2)
if ans < 1:
print("你的答案与正确答案一致")
else:
print("你的答案与正确答案不一致")
import matplotlib
matplotlib.use("Agg")
import numpy as np
import matplotlib.pyplot as plt
def student():
'''
绘制不同一个两行四列的网格子图,并设置图形高度与宽度为0.4
:param: None
:return: None
'''
# ********* Begin *********#
# ********* End *********#
import numpy as np
import test
from PIL import Image
def getDiff(width, high, image): # 将要裁剪成w*h的image照片
diff = []
im = image.resize((width, high))
imgray = im.convert('L') # 转换为灰度图片 便于处理
pixels = list(imgray.getdata()) # 得到像素数据 灰度0-255
for row in range(high): # 逐一与它左边的像素点进行比较
rowStart = row * width # 起始位置行号
for index in range(width - 1):
leftIndex = rowStart + index
rightIndex = leftIndex + 1 # 左右位置号
diff.append(pixels[leftIndex] > pixels[rightIndex])
return diff # *得到差异值序列 这里可以转换为hash码*
def getHamming(diff, diff2): # 暴力计算两点间汉明距离
hamming_distance = 0
for i in range(len(diff)):
if diff[i] != diff2[i]:
hamming_distance += 1
return hamming_distance
if __name__ == '__main__':
x = np.arange(0, 100)
test.student()
a=Image.open("Task3/img/T1.png")
b=Image.open("Task3/img1/T2.png")
diff1 = getDiff(32, 32, a)
diff2 = getDiff(32, 32, b)
ans = getHamming(diff1, diff2)
if ans < 1:
print("你的答案与正确答案一致")
else:
print("你的答案与正确答案不一致")
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
import warnings
warnings.filterwarnings("ignore")
def student():
'''
绘制一个2行4列的不规则子图宽高间隔分别为0.4、0.3。
第0行设置2个子图,第一个子图占3,第二个子图占1。第二行相反
:param: None
:return: None
'''
# ********* Begin *********#
# ********* End *********#
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment