matplotlib 画3D图

有个师弟毕业论文需要画3D图,指导老师让他用matlab画,他就让我帮忙,我不会matlab,但是想到Python里面有个matplotlib包内置了matlab的画图功能,因此就答应了,当作画图的练手

给出一个Excel文件,里面是3个sheet,分别是三种药:吉非替尼,吉西他滨,紫杉醇的结果,要求是用三个sheet做三个三维图

X轴AUC,Y轴癌症类型,Z轴IC50

临床上IC50较难预测,任务是要根据癌症类型、AUC预测IC50

AUC是小于1的小数,癌症类型有五种:大细胞癌,腺癌,鳞状细胞癌,良性肿瘤和未指定,然后IC50是波动比较大的小数,从0-20都有

首先需要读入数据,这里用pandas包读取Excel

# coding=utf-8
import pandas as pd
df = []
for i in range(3): # 读取三个sheet
    dd = pd.read_excel(r"D:\1.xlsx", header=0, sheet_name=i)
    dd = dd[dd.type != "未指定"] # 删除不需要的数据
    dd = dd[dd.type != "良性肿瘤"] # 删除不需要的数据
    dd = dd.sort_values(by="AUC") # 排序后画图会好看点
    class_mapping = {label: idx for idx, label in enumerate(set(dd['type']))} # 将癌症类型映射为0,1,2数字,方便画图
    dd['type'] = dd['type'].map(class_mapping)
    dd = dd.reset_index() # 排序并且映射完后index变化需要reset
    df.append(dd)

首先读取EXCEL数据,然后删除不需要的未指定良性肿瘤类型

接下来是排序,因为画图是根据一个个点顺序连接的,所以最好有序才能看出规律

然后是将离散数据转为连续数据,这里并没有用很高级的编码(比如One-hot),只是简单的将其转化为0,1,2

{'腺癌': 0, '鳞状细胞癌': 1, '大细胞癌': 2}

 接下来是开始画图,这里用的是 Axes3D

# coding=utf-8
from matplotlib import pyplot as plt
import numpy as np
from mpl_toolkits.mplot3d import Axes3D
%matplotlib notebook


def creatdata(data):
    return data['AUC'], data['type'], data['IC50']


X, Y, Z = creatdata(df[0])
X, Z = np.meshgrid(X, Z)
Y, _ = np.meshgrid(Y, Y)
fig = plt.figure()
ax = Axes3D(fig)
ax.plot_surface(X, Y, Z, cmap='rainbow')
ax.set_yticks([0, 1, 2, ])
ax.set_zticks([0, 10, 15])
ax.set_yticklabels(['腺癌', '鳞状细胞癌', '大细胞癌'], rotation=30, fontsize=8) #将图表上的类别0,1,2呈现为中文类型
ax.set_xlabel('AUC')
ax.set_ylabel('癌症类型', labelpad=20)#labelpad用来设置坐标轴标题离坐标轴的距离
ax.set_zlabel('IC50', labelpad=20) 
plt.title(u"吉非替尼", fontsize=20)
plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文
plt.show()

画图的重点是

ax.plot_surface(X, Y, Z, cmap='rainbow')

这里X, Y, Z都要求是二维的,所以需要用np.meshgrid将其一维转化为二维

meshgrid的作用看下列例子

import numpy as np

a = [1, 2, 3]
b = [5, 6, 7, 8]
c, d = np.meshgrid(a, b)
print("c:") # a扩展为3行4列(a的行 b的列)
print(c)
print("d:") # b扩展为4行3列(a的行 b的列)
print(d)

 结果

c:
[[1 2 3]
 [1 2 3]
 [1 2 3]
 [1 2 3]]
d:
[[5 5 5]
 [6 6 6]
 [7 7 7]
 [8 8 8]]

 还有就是,如果要让呈现的图表可以用鼠标拖拽,需要加上

%matplotlib notebook

 以及显示中文

plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文

 由于Y轴是离散数据,所以画出来的图有点奇怪

之前曾经试过三维拟合,但是效果不是很好,所以就放弃了,做成现在这样

结果不是很好,只是记录一下自己近期的工作

猜你喜欢

转载自www.cnblogs.com/leeeeejt/p/10673049.html