用Python+Matplotlib绘制极坐标下的伪彩图(pcolor)

用Python+Matplotlib绘制极坐标下的伪彩图(pcolor)

  • 前言
  • 思路
  • 绘图过程
    • 导入数据
    • 插值
    • 结果图

前言

说在前面,写这个呢仅仅是为了记录下自己在学习过程中的一些问题以及排坑,代码也有很多待优化的地方,大佬们轻喷。

码字不易,转载务必注明出处!

先说下为什么要画这个图吧,本人石油工程研狗,帮老板板砖的时候总免不了画画图,有一天老板甩给我一篇论文,指了指文中一图。
用Python+Matplotlib绘制极坐标下的伪彩图(pcolor)_第1张图片
于是我便开始在网络搜寻画法,百度关键词Python极坐标云图polarpcolor 均未果,仅找到了些许Matlab的代码,无奈实在没找到用python画图的代码,于是开始了自己的摸索。

思路

首先这个是要先建立一个极坐标,然后导入数据插值(此处我有遇坑),最后在极坐标的基础上绘制这种伪色彩图的效果,找到了两种绘图方法pcolorcontourf两种方法,两种方法的区别我百度了一下,知乎-pcolor 和 contourf这两个函数有什么不同?,各位可以参考,也欢迎各位在评论区讨论区别。最终我选择了pcolor。只因为pcolor画出来的图更像吧。

绘图过程

导入数据

数据是老师给的本专业领域的数据,同行看一眼应该就知道是什么了,非同行也不太用了解,就当是个学习资料了。

pos 0 30 60 90
0 1.101447148 1.308827831 1.526038083 1.603848713
30 1.101447148 1.279591136 1.49432297 1.577829862
60 1.101447148 1.204513965 1.435064241 1.52576792
90 1.101447148 1.108569817 1.404547306 1.499676995
120 1.101447148 1.204513965 1.435064241 1.52576792
150 1.101447148 1.279591136 1.49432297 1.577829862
180 1.101447148 1.308827831 1.526038083 1.603848713
210 1.101447148 1.279591136 1.49432297 1.577829862
240 1.101447148 1.204513965 1.435064241 1.52576792
270 1.101447148 1.108569817 1.404547306 1.499676995
300 1.101447148 1.204513965 1.435064241 1.52576792h
330 1.101447148 1.279591136 1.49432297 1.577829862
360 1.101447148 1.308827831 1.526038083 1.603848713
// 导入数据
import numpy as np
import pandas as pd

df = pd.read_csv('data.csv')

# 注意!此处记得转化为弧度!
pos = np.array(df['pos']/180*np.pi)
ind = np.array(df.columns[1:], dtype=np.int)
values = np.array(df[ind.astype('str')])

# 把一维数据转化为二维绘图数据
r, theta = np.meshgrid(ind,pos)

至此数据导入完毕

插值

插值之前,我们可以看一下图片质量。

from matplotlib import pyplot as plt

plt.figure(figsize=(10,10))
ax =  plt.subplot(projection='polar')
ax.contourf(theta,r, values,cmap='jet',vmin=1, vmax=1.65)
ax.set_rgrids([30,60,90])
plt.grid(c='black')

用Python+Matplotlib绘制极坐标下的伪彩图(pcolor)_第2张图片
属实难看。因此选择使用二维插值让图片平滑一点。

本人在此处遇到大坑!!试了一下午没找到原因

首先是插值算法的选择,scipy.interpolate.interp2dscipy.interpolate.griddata两种算法都能满足我的插值需求,即已知x,y,z,通过扩增的X,Y获取Z这种方式。

关于这两种插值的区别在新浪博客-matlab二维插值–interp2与griddata中有提到,但是关于interp2d要求数据单调这一点,我是使用的时候没什么区别。

先是scipy.interpolate.interp2d

from scipy.interpolate import interp2d

#计算插值函数
func = interp2d(pos, ind, values.T,kind='cubic')

#绘图数据点
tnew = np.linspace(0, 2*np.pi, 200) # theta
rnew = np.linspace(0, 90, 100) # r
#
vnew = func(tnew,rnew)
#生成绘图二维数据
tnew, rnew = np.meshgrid(tnew, rnew)

此处我遇到了两个坑,首先是interp2d函数的前两个参数,因为posind在我这里分别是极坐标的角度和径向值,在我最开始插值的时候遇到了以下错误

func = interp2d(pos, ind, values,kind='cubic')
# 运行此语句会提示输入参数shape不对,于是改成了下面
func = interp2d(ind, pos, values,kind='cubic')
# 运行此语句后不会报错,但是拟合数据绘图出现严重偏差!

个人理解,在插值计算的时候,应该把按照theta,r的顺序输入参数。

然后是scipy.interpolate.griddata
用Python+Matplotlib绘制极坐标下的伪彩图(pcolor)_第3张图片
查文档可发现,要求输入的坐标点和值,即要求坐标对(x,y)形式输入point,并且长度要和value的长度一致,故需要先生成数据对

points=[]
for i in range(len(theta.flatten())):
    points.append([theta.flatten()[i], r.flatten()[i]])

这里使用了很笨的办法,因为我尝试了直接以(theta, r)作为point的输入值,结果依然是报错,不flatten直接输入也都会报错。
griddata插值完整代码

from scipy.interpolate import griddata

points=[]
for i in range(len(theta.flatten())):
   points.append([theta.flatten()[i], r.flatten()[i]])
   
tnew_2 = np.linspace(0, 2*np.pi, 200) # x
rnew_2 = np.linspace(0, 90, 100) # y
tnew_2, rnew_2 = np.meshgrid(tnew_2, rnew_2)

vnew_2 = griddata(points, values.flatten(), (tnew_2, rnew_2), method='cubic')

结果图

绘图部分就相对简单了,就是各种调节参数让图好看,大家可以自由发挥了,下面呈上scipy.interpolate.interp2dscipy.interpolate.griddata两种方式的结果图
用Python+Matplotlib绘制极坐标下的伪彩图(pcolor)_第4张图片
scipy.interpolate.interp2d插值结果

用Python+Matplotlib绘制极坐标下的伪彩图(pcolor)_第5张图片
scipy.interpolate.griddata插值结果

图像都还差不多!

你可能感兴趣的:(用Python+Matplotlib绘制极坐标下的伪彩图(pcolor))