Контурный график Matplotlib с пересекающимися контурными линиями - PullRequest
5 голосов
/ 26 февраля 2012

Я пытаюсь создать контурный график следующих данных, используя matplotlib в python.Данные имеют такую ​​форму -

# 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 Ответ

5 голосов
/ 29 февраля 2012

Попробуйте использовать следующий код.Это может вам помочь - это то же самое, что было в 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()

Я создал пример выходного файла с гауссовым распределением в 2D.Мой результат с использованием кода сверху:

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-файла разделитель с | на ,.Код, который я написал для вас, не очень хорош, но он написан предисловием.

Извините за поздний ответ.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...