Постройте контуры распределения по всем трем осям на трехмерном графике

У меня есть облако точек в трехмерном пространстве, и я оценил некоторое распределение по этим точкам (также в трехмерном пространстве; используя оценка плотности ядра, хотя это не имеет отношения к этому вопросу). Я хотел бы построить проекцию этого распределения в виде контурного графика на все три оси (x, y и z). Это просто сделать для оси z (т.е. проецировать на плоскость с одинаковой координатой z везде):

import numpy as np
import scipy as sp
import scipy.stats
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import axes3d

# generate some points of a 3D Gaussian
points = np.random.normal(size=(3, 50))

# do kernel density estimation to get smooth estimate of distribution
# make grid of points
x, y, z = np.mgrid[-4:4:100j, -4:4:100j, -4:4:100j]
kernel = sp.stats.gaussian_kde(points)
positions = np.vstack((x.ravel(), y.ravel(), z.ravel()))
density = np.reshape(kernel(positions).T, x.shape)

# now density is 100x100x100 ndarray

# plot points
ax = plt.subplot(projection='3d')
ax.plot(points[0,:], points[1,:], points[2,:], 'o')

# plot projection of density onto z-axis
plotdat = np.sum(density, axis=2)
plotdat = plotdat / np.max(plotdat)
plotx, ploty = np.mgrid[-4:4:100j, -4:4:100j]
ax.contour(plotx, ploty, plotdat, offset=-4)

ax.set_xlim((-4, 4))
ax.set_ylim((-4, 4))
ax.set_zlim((-4, 4))

Проекция контуров на ось Z

Однако выполнение этого для других осей, похоже, не реализовано в Matplotlib. Если я использую метод, описанный в этом примере, и укажу аргумент ключевого слова zdir:

# plot projection of density onto x-axis
plotdat = np.sum(density, axis=0)
plotdat = plotdat / np.max(plotdat)
ploty, plotz = np.mgrid[-4:4:100j, -4:4:100j]
ax.contour(ploty, plotz, plotdat, offset=-4, zdir='x')

генерация контура выполняется «по другому срезу», так сказать:

введите описание изображения здесь

В то время как я хочу что-то вроде этого (плохие навыки рисования; надеюсь, идея ясна):

введите описание изображения здесь

Один из вариантов, который я имел в виду, заключался в том, чтобы создать контур по умолчанию zdir='z', а затем повернуть полученные кривые в трехмерном пространстве, но я понятия не имею, как к этому подойти. Буду очень признателен за любые наводки!


person EelkeSpaak    schedule 18.04.2016    source источник


Ответы (1)


Я попытался изменить контурные графики, смешав данные, рассчитанные как сумма по оси, с сеткой, созданной np.mgrid. Я вычислил сумму плотности по оси, на которой я хочу иметь контур. Это выглядит следующим образом:

# plot projection of density onto z-axis
plotdat = np.sum(density, axis=2)
plotdat = plotdat / np.max(plotdat)
plotx, ploty = np.mgrid[-4:4:100j, -4:4:100j]
ax.contour(plotx, ploty, plotdat, offset=-4, zdir='z')

#This is new
#plot projection of density onto y-axis
plotdat = np.sum(density, axis=1) #summing up density along y-axis
plotdat = plotdat / np.max(plotdat)
plotx, plotz = np.mgrid[-4:4:100j, -4:4:100j]
ax.contour(plotx, plotdat, plotz, offset=4, zdir='y')

#plot projection of density onto x-axis
plotdat = np.sum(density, axis=0) #summing up density along z-axis
plotdat = plotdat / np.max(plotdat)
ploty, plotz = np.mgrid[-4:4:100j, -4:4:100j]
ax.contour(plotdat, ploty, plotz, offset=-4, zdir='x')
#continue with your code

К сожалению, я не очень хорошо знаком с оценкой плотности ядра, поэтому надеюсь, что не понял что-то совершенно неправильное, но результат, сгенерированный, если вы добавите несколько строк кода выше, выглядит чем-то похожим на вашу причудливую картинку :) введите описание изображения  здесь

person jammartin    schedule 18.04.2016
comment
Так просто, я чувствую себя глупо, потому что сам об этом не подумал :) Отличный ответ; большое спасибо! - person EelkeSpaak; 19.04.2016
comment
Пожалуйста! Эти сетки, необходимые для трехмерного построения matplotlib, тоже часто меня смущают. Рад слышать, что смог вам помочь! :) - person jammartin; 19.04.2016