大论文也算是写完交一段时间了,回想自己每次要画图的时候也是满世界找方案(GPT问的最多😅)。虽然以后99%不会再画这些图了,但是还是想把论文用到的一些绘图代码记录在此,也许会有有缘人需要🤣🤣🤣。
本文可以学到哪些
在正式进入主题之前,先介绍一下Python读取MAT文件数据的方法。因为本人的实验数据都是MATLAB跑出来的结果,存放在MAT文件中。Python读取并绘图的时候出现了一些问题,在这里记录下。此后,便是一系列绘图示例。
Python读取MAT文件
出现的问题
一般来说,我都是用Scipy库的
io
模块进行MAT文件的读取。scipy.io 模块是 Scipy 库中的一个子模块,用于处理输入输出操作。它提供了许多函数来读取和写入各种格式的文件,包括 MATLAB 文件、wav 文件、图像文件等。下面是一些 scipy.io 模块中常用的功能:scipy.io.loadmat():用于加载 MATLAB 格式的 .mat 文件。
scipy.io.savemat():用于保存数据到 MATLAB 格式的 .mat 文件。
scipy.io.wavfile.read():用于读取 WAV 音频文件。
scipy.io.wavfile.write():用于写入数据到 WAV 音频文件。
scipy.io.load():通用的加载函数,支持多种文件格式,如 .wav、.png、.jpg 等。
scipy.io.save():通用的保存函数,支持多种文件格式,如 .wav、.png、.jpg 等。
但是直到出现这个报错:从报错信息中可以看出是因为MATLAB保存MAT文件使用的是v7.3或更高的版本保存的,换成h5py读取就可以了。可以参考这篇文章的介绍: 使用python读取Matlab的.mat文件 常见问题
读取MAT文件报错
混淆矩阵类
模型分组示例
代码实现:
import matplotlib.pyplot as plt import numpy as np from matplotlib.colors import ListedColormap import matplotlib.patches as mpatches # 创建模拟数据 data_A = np.array([[70, 70, 70, 30, 30, 30], [30, 30, 30, 10, 10, 10]]) # 自定义颜色列表 colors = ['skyblue', 'white', 'salmon'] # 每个矩阵块对应的颜色 # 创建自定义颜色映射 cmap_custom = ListedColormap(colors) # 设置图片尺寸 fig, ax = plt.subplots(dpi = 300) # 绘制热力图,并根据自定义颜色映射显示 im = ax.imshow(data_A, cmap=cmap_custom) # 设置坐标轴刻度和标签 ax.set_xticks(np.arange(6)) ax.set_xticklabels(['1', '2', '3', '4', '5', '6']) ax.set_yticks(np.arange(2)) ax.set_yticklabels(['Group 1', 'Group 2']) # 设置坐标轴标签 ax.set_xlabel('Models', weight='bold') ax.set_ylabel('Families', weight='bold') # 添加图形标题 ax.set_title("Families' partition", weight='bold') legend_elements = [mpatches.Patch(facecolor='skyblue', edgecolor='black', label='DoG Models'), mpatches.Patch(facecolor='salmon', edgecolor='black', label='Gauss Models')] ax.legend(handles=legend_elements, loc='upper right') # 调整子图布局以防止标签被剪裁 plt.tight_layout() # 显示图形 plt.show()
示例结果
模型块对应不同值
代码示例
import numpy as np import matplotlib.pyplot as plt # 设置全局字体和字号 plt.rcParams.update({'font.family': 'sans-serif', 'font.size': 12}) # 创建相关矩阵数据 data_A = np.array([[0.36, 0.29, 0.07], [0.16, 0.11, 0.01]]) data_B = np.array([[1.00, 0, 0], [0, 0, 0]]) # 绘制A图 fig, ax1 = plt.subplots(1, 1, figsize=(5, 4),dpi = 300) im_A = ax1.imshow(data_A, interpolation='nearest', cmap=plt.cm.Blues) cbar_A = plt.colorbar(im_A) ax1.set_xticks(np.arange(data_A.shape[1])) ax1.set_yticks(np.arange(data_A.shape[0])) ax1.set_xticklabels(['1', '2', '3'], fontweight='bold') ax1.set_yticklabels(['DoG', 'Gauss'], fontweight='bold', verticalalignment='center') for i in range(data_A.shape[0]): for j in range(data_A.shape[1]): text_color = 'black' if i == 0 and j == 0: text_color = 'white' text = ax1.text(j, i, data_A[i, j], ha='center', va='center', color=text_color) ax1.set_title('Model probabilities', fontweight='bold', pad=20)
示例结果
小提琴图
两(多)组数据
代码示例
import matplotlib.pyplot as plt import seaborn as sns import numpy as np # 生成随机数据 np.random.seed(0) data1 = np.random.normal(loc=0, scale=1, size=100) # 左脑数据 data2 = np.random.normal(loc=0, scale=1, size=100) # 右脑数据 # 绘制小提琴图 plt.figure(figsize=(5, 5)) sns.violinplot(data=[data1, data2], palette=['#FF5D5C', '#0D5BFF'], alpha=0.7) # 设置图形参数 plt.ylabel("Eccentricity", fontsize=16) plt.xticks(ticks=[0, 1], labels=["Left hemisphere", "Right hemisphere"], fontsize=14) # 显示图形 plt.show()
示例结果
两(多)组比较
代码示例
import matplotlib.pyplot as plt import numpy as np import seaborn as sns import pandas as pd # 生成随机数据 np.random.seed(0) data1 = np.random.normal(loc=0, scale=1, size=100) # 随机生成左脑数据1 data2 = np.random.normal(loc=0, scale=1, size=100) # 随机生成左脑数据2 data3 = np.random.normal(loc=0, scale=1, size=100) # 随机生成右脑数据1 data4 = np.random.normal(loc=0, scale=1, size=100) # 随机生成右脑数据2 # 构建数据框 df1 = pd.DataFrame({'Data': data1, 'Group': ['Group 1'] * len(data1), 'Subgroup': ['Subgroup 1'] * len(data1)}) df2 = pd.DataFrame({'Data': data2, 'Group': ['Group 1'] * len(data2), 'Subgroup': ['Subgroup 2'] * len(data2)}) df3 = pd.DataFrame({'Data': data3, 'Group': ['Group 2'] * len(data3), 'Subgroup': ['Subgroup 1'] * len(data3)}) df4 = pd.DataFrame({'Data': data4, 'Group': ['Group 2'] * len(data4), 'Subgroup': ['Subgroup 2'] * len(data4)}) # 合并数据框 df = pd.concat([df1, df2, df3, df4]) colors = ["#FF5D5C", "#0D5BFF"] # 绘制小提琴图 plt.figure(figsize=(5, 5)) ax = sns.violinplot(x='Group', y='Data', hue='Subgroup', data=df, split=True, inner='quartile', palette=colors, alpha=0.6) # 设置图形参数 plt.xticks(ticks=[0, 1], labels=['Left Hemisphere', 'Right Hemisphere'], fontsize=14) plt.xlabel('') plt.ylabel('Eccentricity (deg)', fontsize=16) legend = ax.legend(fontsize=13, loc='upper right', bbox_to_anchor=(1.35, 1)) legend.get_texts()[0].set_text("Split1") legend.get_texts()[1].set_text("Split2") plt.show()
示例结果
极角直方图
极角直方图没有什么难度,但是如果想在直方图的外圈添加Colorbar又该如何实现那?
参考链接: Plot a (polar) color wheel based on a colormap using Python/Matplotlib
实现代码
import matplotlib.pyplot as plt import numpy as np from matplotlib import cm import matplotlib as mpl import seaborn as sns sns.set_style('ticks') fig = plt.figure(figsize=(5,5)) # 随机数据 ang1 = np.random.uniform(-np.pi/2, np.pi /2 , size=1000) ang2 = np.random.uniform(np.pi/2 , np.pi * 3 / 2, size=1000) # 绘制环形的Colorbar display_axes = fig.add_axes([0.1, 0.1, 0.8, 0.8], projection='polar') norm = mpl.colors.Normalize(np.pi, 3 * np.pi) quant_steps = 2056 cb = mpl.colorbar.ColorbarBase(display_axes, cmap=cm.get_cmap('hsv_r', quant_steps), norm=norm, orientation='horizontal') cb.outline.set_visible(False) display_axes.set_axis_off() # 在大的极坐标子图上绘制直方图 ax = fig.add_axes([0.15, 0.15, 0.7, 0.7], projection='polar') # 调整位置和大小 ax.hist(ang1, bins=30, color='#FF5D5C', edgecolor='none',alpha=0.7, density=True,label = 'Left hemisphere') ax.hist(ang2, bins=30, color='#0D5BFF', edgecolor='none',alpha=0.7, density=True,label = 'Right hemisphere') ax.set_rticks([0.2, 0.5]) # 设置只显示0.5和1.0两个标签 ax.set_xticklabels([]) ax.spines['polar'].set_visible(False) # plt.text(-0.1, 1.07, 'A', transform=ax.transAxes, fontsize=18, fontweight='bold', va='top') plt.legend(loc='upper right',fontsize = 14)
结果示例
均值误差图(带有显著标识)
代码实现
import numpy as np import seaborn as sns import scipy.stats as stats import matplotlib.pyplot as plt plt.rcParams['font.size'] = 16 # 生成随机数据 np.random.seed(0) group1 = np.random.normal(loc=10, scale=3, size=100) group2 = np.random.normal(loc=12, scale=3, size=100) # 计算均值和标准误差 mean_group1 = np.mean(group1) mean_group2 = np.mean(group2) sem_group1 = stats.sem(group1) sem_group2 = stats.sem(group2) plt.figure(figsize=(6,5)) bar = plt.bar(['Contralateral', 'Ipsilateral'], [mean_group1, mean_group2], yerr=[sem_group1, sem_group2], capsize=12, color=['salmon','skyblue']) plt.ylabel('Explained variance (mean)') plt.title('Right hemisphere',y=1.02) # 添加显著性标注 gap = 2.5 # 显著性标注与最大高度的距离 t = max(mean_group1, mean_group2) + gap plt.axhline(y=t, xmin=0.25, xmax=0.75, color='black', linestyle='-', linewidth=2) plt.plot([0, 0], [t, t - 0.3], color='black') plt.plot([1, 1], [t, t - 0.3], color='black') plt.text(0.5, t + 0.1, '***', fontsize=14, fontweight='bold') # 在柱形图顶部标记均值和标准误差 text_gap = 0.5 # 数值标记的高度 for i, rect in enumerate(bar): height = rect.get_height() plt.text(rect.get_x() + rect.get_width()/2, height + text_gap, f'{height:.2f} ± {sem_group1 if i == 0 else sem_group2:.2f}', ha='center', va='bottom') plt.ylim(0, 17) plt.show()
结果示例
平均曲线以及置信区间
代码实现(仅作自用,不多解释)
import pandas as pd import numpy as np import seaborn as sns import matplotlib.pyplot as plt import scipy.io as scio import h5py # 假设有一个数据框 data_df,其中每列代表一个样本曲线的观测值 dataFile = 'E:\\我的论文\\00-论文写作\\AA_sub_half_HRF_12_DOG1_th.mat' mat_data = h5py.File(dataFile,'r') data_df = pd.DataFrame(mat_data['hrf_t1']) plt.rcParams['font.size'] = 16 plt.figure(figsize=(9, 6)) # 计算每个样本曲线的均值和标准误差 # 计算每组数据的均值和标准误差 # data_df= data_df.loc[:,:] mean_values = data_df.mean() se_values = data_df.apply(lambda x: np.std(x) / np.sqrt(len(x))) # 计算置信区间 lower_ci = mean_values - 1.96 * se_values upper_ci = mean_values + 1.96 * se_values # 创建x轴的刻度 x_values = np.arange(1, len(mean_values)+1) # 创建数据框 data_plot = pd.DataFrame({'x': x_values, 'mean': mean_values, 'lower_ci': lower_ci, 'upper_ci': upper_ci}) # 绘制均值曲线和置信区间 plt.plot(data_plot['x'] / 16, data_plot['mean'], color='#E07E35', linewidth=1.1,label = 'DoG-1 HRF') plt.fill_between(data_plot['x'] / 16, data_plot['lower_ci'], data_plot['upper_ci'], color='#E07E35', alpha=0.5) # dataFile = 'E:\\我的论文\\00-论文写作\\hrf_th_dog2.mat' # mat_data = h5py.File(dataFile,'r') data_df = pd.DataFrame(mat_data['hrf_t2']) # 计算每个样本曲线的均值和标准误差 # 计算每组数据的均值和标准误差 # data_df= data_df.loc[:,:] mean_values = data_df.mean() se_values = data_df.apply(lambda x: np.std(x) / np.sqrt(len(x))) # 计算置信区间 lower_ci = mean_values - 1.96 * se_values upper_ci = mean_values + 1.96 * se_values # 创建x轴的刻度 x_values = np.arange(1, len(mean_values)+1) # 创建数据框 data_plot = pd.DataFrame({'x': x_values, 'mean': mean_values, 'lower_ci': lower_ci, 'upper_ci': upper_ci}) # 绘制均值曲线和置信区间 plt.plot(data_plot['x'] / 16, data_plot['mean'], color='#0D5BFF', linewidth=1.1,label = 'DoG-2 HRF',linestyle = 'dashdot') plt.fill_between(data_plot['x'] / 16, data_plot['lower_ci'], data_plot['upper_ci'], color='#0D5BFF', alpha=0.3) dataFile = 'E:\\我的论文\\00-论文写作\\caonical_hrf.mat' mat_data = h5py.File(dataFile,'r') data_df = pd.DataFrame(mat_data['t']) mean_values = data_df.mean() x_values = np.arange(1, len(mean_values)+1) se_values = data_df.apply(lambda x: np.std(x) / np.sqrt(len(x))) data_plot = pd.DataFrame({'x': x_values, 'mean': mean_values}) plt.plot(data_plot['x'] / 16, data_plot['mean'], color='red', linewidth=1.2,label = 'Canonical HRF',linestyle='dashed') # 设置图形属性 plt.xlabel('Time (s)') plt.ylabel('Amplitude (a.u.)') plt.title('Hemodynamic Variability', loc='center', fontsize=16, fontweight='bold') plt.grid(True) plt.legend(fontsize = 13) # plt.savefig('hrf_wm_.pdf', format='pdf', bbox_inches='tight',pad_inches=0) # plt.yticks(np.arange(0, 1,8)) plt.show()
结果示例
图片添加序号
代码实现
这个位置什么的只能一点点尝试了~
plt.text(-0.13, 1.13, 'A', transform=ax.transAxes, fontsize=18, fontweight='bold', va='top')
最后的最后
GPT是个好东西,没事多用用~
$\cdots$ 什么都略懂一点,生活更多彩一些 $\cdots$
$\cdots$ end $\cdots$