2015-02-04 5 views
0

У меня есть 3 разных параметра X, Y и Z в диапазоне значений, а для каждой комбинации из них - определенное значение V. Чтобы сделать его более ясным, данные будут выглядеть что-то вроде этого.Добавление 4-й переменной в 3D-график в Python

X Y Z V 
1 1 2 10 
1 2 3 15 
etc... 

Я хотел бы, чтобы визуализировать данные с поверхности/контура участка, используя V как цвет, чтобы увидеть его значение в этой точке, но я не вижу, как добавить свою собственную схему окраски в смеси используя Python. Любая идея о том, как это сделать (или эта визуализация совершенно глупо)?

Большое спасибо!

+0

3D-график рассеяния кажется appriopriate, например. http://matplotlib.org/examples/mplot3d/scatter3d_demo.html. – Evert

+0

Создает ли ваши xy-данные прямолинейную сетку или координаты x и y в значительной степени распределены случайным образом? –

+0

Да, X, Y и Z регулярно распределяются. – muffinman

ответ

0

Это действительно зависит от того, как вы планируете строить эти данные. Мне нравится строить графики с gnuplot: это легко, бесплатно и интуитивно понятно. Для того, чтобы построить свой пример с gnuplot вы должны напечатать эти строки в файл (только с теми четырьмя колоннами) и участок, используя код, как в следующем

reset 
set terminal png 
set output "out.png" 
splot "file.txt" using 1:2:3:4 with lines palette 

Предполагая, что вы сохраните данные в файл file.txt. splot обозначает поверхностный участок. Конечно, это минимальный пример.

В качестве альтернативы вы можете использовать matplotlib, но это не так, на мой взгляд, как интуитивно понятное. Хотя это имеет преимущество, сосредоточив всю обработку в python.

3

Matplotlib позволяет передавать листы в качестве аргумента, например. ax.plot_surface.

Это будет означать то, что вы должны выполнить 2D интерполяции на ваш текущего массива цветов, потому что вы в настоящее время только цвета в углах прямоугольных граней (вы сделали упоминание, что у вас есть прямолинейный сетка).

Вы можете использовать scipy.interpolate.interp2d для этого, но, как видно из документации, предлагается использовать scipy.interpolate.RectBivariateSpline.

Чтобы дать вам простой пример:

import numpy as np 
y,x = np.mgrid[1:10:10j, 1:10:10j] # returns 2D arrays 
# You have 1D arrays that would make a rectangular grid if properly reshaped. 
y,x = y.ravel(), x.ravel() # so let's convert to 1D arrays 
z = x*(x-y) 
colors = np.cos(x**2) - np.sin(y)**2 

Теперь у меня есть подобный набор данных, как вы (одномерные массивы для x, y, z и colors). Обратите внимание, что цвета определены для каждой точки (x, y). Но когда вы хотите построить с plot_surface, вы будете генерировать прямоугольные заплаты, из которых углы даются этими точками.

Таким образом, на интерполяции, то:

from scipy.interpolate import RectBivariateSpline 
# from scipy.interpolate import interp2d # could 've used this too, but docs suggest the faster RectBivariateSpline 

# Define the points at the centers of the faces: 
y_coords, x_coords = np.unique(y), np.unique(x) 
y_centers, x_centers = [ arr[:-1] + np.diff(arr)/2 for arr in (y_coords, x_coords)] 

# Convert back to a 2D grid, required for plot_surface: 
Y = y.reshape(y_coords.size, -1) 
X = x.reshape(-1, x_coords.size) 
Z = z.reshape(X.shape) 
C = colors.reshape(X.shape) 
#Normalize the colors to fit in the range 0-1, ready for using in the colormap: 
C -= C.min() 
C /= C.max() 

interp_func = RectBivariateSpline(x_coords, y_coords, C.T, kx=1, ky=1) # the kx, ky define the order of interpolation. Keep it simple, use linear interpolation. 

В этом последнем шаге вы можете также использовали interp2dkind='linear' заменой kx=1, ky=1). Но поскольку документы предлагают использовать более быстрый RectBivariateSpline ...

Теперь вы готовы построить его:

import matplotlib.pyplot as plt 
from mpl_toolkits.mplot3d import Axes3D 
import matplotlib.cm as cm 

fig = plt.figure() 
ax = fig.add_subplot(111, projection='3d') 
r = ax.plot_surface(X,Y,Z, 
    facecolors=cm.hot(interp_func(x_centers, y_centers).T), 
    rstride=1, cstride=1) # only added because of this very limited dataset 

output

Как вы можете видеть, цвет на лицах не имеет ничего общего больше с высотой набора данных.

Обратите внимание, что вы могли подумать, что просто пройти 2D-массив C до facecolors будет работать, и matplotlib не пожаловался бы. Однако результат не является точным, потому что matplotlib будет использовать только подмножество C для facecolors (он, кажется, игнорирует последний столбец и последнюю строку C). Это эквивалентно использованию только цвета, определенного одной координатой (например, верхним левым) по всему патчу.

Простейшее метод был бы позволить Matplotlib сделать интерполяцию и получить facecolors, а затем передавать их на реальный сюжет:

r = ax.plot_surface(X,Y,C, cmap='hot') # first plot the 2nd dataset, i.e. the colors 
fc = r.get_facecolors() 
ax.clear() 
ax.plot_surface(X, Y, Z, facecolors=fc) 

Однако, это не будет работать в версиях < = 1,4. 1 из-за this recently submitted bug.

 Смежные вопросы

  • Нет связанных вопросов^_^