Добавление 4-й переменной в 3D-график в Python

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

XYZV 1 1 2 10 1 2 3 15 etc... 

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

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

2 Solutions collect form web for “Добавление 4-й переменной в 3D-график в Python”

Matplotlib позволяет пропускать facecolors в качестве аргумента, например, 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*(xy) colors = np.cos(x**2) - np.sin(y)**2 

Теперь у меня есть аналогичный набор данных, как и вы (одномерные массивы для x, y, z и colors ). Заметим, что цвета определены для каждой точки (x, y). Но когда вы хотите построить сюжет с plot_surface , вы 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, CT, 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 

вывод

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

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

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

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

Тем не менее, это не будет работать в версиях <= 1.4.1 из-за этой недавно представленной ошибки .

Это зависит от того, как вы планируете строить эти данные. Мне нравится строить графики с помощью 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.

  • Как нарисовать график, соединяющий точки с двух времен измерения?
  • Как обрабатывать время с часовым поясом в Matplotlib?
  • Графики matplotlib выглядят как R по умолчанию?
  • Библиотека / инструмент для рисования тройных / треугольных графиков
  • Нет графического окна в matplotlib в Linux Shell Windows 10
  • Как построить два столбца кадра данных pandas с помощью точек?
  • Как окрасить поверхность с большей контрастностью
  • как сделать сюжетную легенду о двух столбцах
  • Python - лучший язык программирования в мире.