Matplotlib 等高线图中相交的等高线

5

我正在尝试使用Python中的Matplotlib制作以下数据的等高线图。该数据的格式如下:

# x       y      height
  77.23  22.34     56
  77.53  22.87     63
  77.37  22.54     72
  77.29  22.44     88

实际上,这些数据包含近10000个点,我从一个输入文件中读取。然而,z的可能值的集合很小(介于50-90之间,为整数),我希望对于每个这样不同的z,都有一条等值线。

以下是我的代码 -

import matplotlib
import numpy as np
import matplotlib.cm as cm
import matplotlib.mlab as mlab
import matplotlib.pyplot as plt
import csv
import sys

# read data from file
data = csv.reader(open(sys.argv[1], 'rb'), delimiter='|', quotechar='"')
x = []
y = []
z = []

for row in data:
    try:
        x.append(float(row[0]))
        y.append(float(row[1]))
        z.append(float(row[2]))
    except Exception as e:
        pass
        #print e

X, Y = np.meshgrid(x, y)        # (I don't understand why is this required)

# creating a 2D array of z whose leading diagonal elements
# are the z values from the data set and the off-diagonal
# elements are 0, as I don't care about them.
z_2d = []
default = 0
for i, no in enumerate(z):
    z_temp = []
    for j in xrange(i): z_temp.append(default)
    z_temp.append(no)
    for j in xrange(i+1,  len(x)): z_temp.append(default)
    z_2d.append(z_temp)
Z = z_2d

CS = plt.contour(X, Y, Z, list(set(z)))
plt.figure()
CB = plt.colorbar(CS, shrink=0.8, extend='both')
plt.show()

这里是一小部分数据的图表 - enter image description here 这是上面图表中一个区域的近距离观察(请注意重叠/交叉线)- enter image description here 我不明白为什么它看起来不像等高线图。线条相交,这不应该发生。可能出了什么问题?请帮忙解答。
1个回答

6

尝试使用以下代码。这可能会对您有所帮助--这是在Cookbook中的相同内容:

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.mlab import griddata

# with this way you can load your csv-file really easy -- maybe you should change
# the last 'dtype' to 'int', because you said you have int for the last column
data = np.genfromtxt('output.csv', dtype=[('x',float),('y',float),('z',float)],
                     comments='"', delimiter='|')

# just an assigning for better look in the plot routines
x = data['x']
y = data['y']
z = data['z']

# just an arbitrary number for grid point
ngrid = 500

# create an array with same difference between the entries
# you could use x.min()/x.max() for creating xi and y.min()/y.max() for yi
xi = np.linspace(-1,1,ngrid)
yi = np.linspace(-1,1,ngrid)

# create the grid data for the contour plot
zi = griddata(x,y,z,xi,yi)

# plot the contour and a scatter plot for checking if everything went right
plt.contour(xi,yi,zi,20,linewidths=1)
plt.scatter(x,y,c=z,s=20)
plt.xlim(-1,1)
plt.ylim(-1,1)
plt.show()

我用高斯分布在二维平面上生成了一个样本输出文件。使用以上代码后,我的结果如下:

Gaussian distribution in 2D

注意:

也许你会发现图形的边缘有些裁剪。这是由于griddata函数创建掩码数组所导致的。我的意思是,绘图边界由外部点创建而成,超出边界的点不会被绘制。如果你的数据点在一条直线上,那么你将无法绘制任何等高线。这很合理。我提到这一点是因为你发布的四个数据点看起来可能会出现这种情况。也许你没有这种情况=)

更新:

我稍微修改了代码。你的问题可能是你没有正确解决输入文件的依赖关系。使用以下代码后,绘图应该可以正常工作。

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.mlab import griddata
import csv

data = np.genfromtxt('example.csv', dtype=[('x',float),('y',float),('z',float)],
                     comments='"', delimiter=',')

sample_pts = 500
con_levels = 20

x = data['x']
xmin = x.min()
xmax = x.max()

y = data['y']
ymin = y.min()
ymax = y.max()

z = data['z']

xi = np.linspace(xmin,xmax,sample_pts)
yi = np.linspace(ymin,ymax,sample_pts)

zi = griddata(x,y,z,xi,yi)

plt.contour(xi,yi,zi,con_levels,linewidths=1)
plt.scatter(x,y,c=z,s=20)
plt.xlim(xmin,xmax)
plt.ylim(ymin,ymax)
plt.show()

使用这段代码和你的小样本我得到了以下的图形:

The sample plot

尝试使用我的片段并进行一些修改。例如,我不得不将给定的csv文件的分隔符从|更改为,。我为您编写的代码并不是非常好,但它是直截了当地编写的。

对于晚回复我很抱歉。


这是我按照你的代码得到的图表 - http://www.mediafire.com/?9slrkypn6t9s6qv。 这是我期望的(使用Matlab绘制的) - http://www.mediafire.com/?3c63voqgol63ubz。 有什么建议吗? - Pushpak Dagade
我并没有看到任何等高线。能否请您发送数据给我,这样我就可以更仔细地查看这个问题了。 - ahelm
嘿PateToni,非常感谢你的帮助。我在这里上传了我的一小部分数据 - http://www.mediafire.com/download.php?ubnsruoe2yistfk。(只是一个提示 - 上面预期的轮廓图的链接是整个数据的链接,而不是我上传的这个样本。) - Pushpak Dagade
谢谢您继续的帮助。它起作用了!但是,我不明白为什么轮廓显示点,它应该只显示线条。此外,我尝试在完整数据上绘图,但出现错误(KeyError:4002)。我在网上发现这可能是特定于Ubuntu而不是您的代码。尽管如此,您可以尝试一下,让我知道是否有效。如果您想尝试,请在此处上传数据 - http://www.mediafire.com/?o4ayhx2lvs4vhys。再次感谢您的帮助。 - Pushpak Dagade
1
KeyError是由于一些NaN值引起的。如果您检查输入文件(您发送给我的那个文件),您会发现有些行没有内容。这就是为什么您会遇到问题的原因。如果您不想要点,则注释掉命令plt.scatter(x,y,c=z,s=20)。我用它来检查轮廓是否正确。我会写一些关于您的代码的东西,只需要更多时间。 - ahelm
非常感谢PateToni!我对Python在这个轮廓问题上几乎失去了希望,但是你帮助我不再失去它! - Pushpak Dagade

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接