我正在努力在python中创建一个非常复杂的3D图形,特别是使用iPython笔记本。我可以将图表的内容分为两部分:
(x,y)平面:这里有一个二维随机游走,我们称之为G()。我想在(x,y)平面上绘制这个轨迹的一部分。比方说,G()的所有数据点的10%。随着G()跳跃,它比其他人更频繁地访问一些(x,y)对。我想使用核估计方法估计G()的密度,并将其绘制为(x,y)平面上的轮廓线。
(z)平面:在这里,我想绘制一个双变量法则信息理论意外的网格或(透明)表面图。惊喜只是-log(p(i))或结果i的负(基数2)对数。给定双变量法线,每个(x,y)对具有一些概率p(x,y),并且其惊人的是-log(p(x,y))。
基本上这两个图是独立的。假设随机游走G()的间隔是[xmin,xmax],[ymin,ymax]和大小为N.应该从相同的区间绘制z平面中的双变量法线,这样每个(x, y)在随机游走中配对,我可以从随机游走的某个子集中绘制一条(虚线)n< N到二元正常。假设G(10)=(5,5)然后我想从(5,5)沿Z轴画一条虚线,直到它达到双变量法线。
到目前为止,我已设法在3维空间中绘制G(),并使用scipy.stats.gaussian_kde估算密度f(X,Y)。在另一个(2d)图中,我有我想要的那种轮廓线。我没有的是使用估计的KDE密度的3d图中的等高线。我也没有二元正态图,或从随机游走的几个随机点的投影到二元法线的表面。我添加了一个手绘的图形,这可能会减轻直觉(忽略z轴上的标签以及没有网格的事实......难以画出来!)
任何输入,甚至只是部分输入,例如如何在3d图的(x,y)平面中绘制轮廓线,或者是双变量法线的网格都将非常受欢迎。
谢谢!
import matplotlib as mpl
import matplotlib.pyplot as plt
import random
import numpy as np
import seaborn as sns
import scipy
from mpl_toolkits.mplot3d import Axes3D
%matplotlib inline
def randomwalk():
mpl.rcParams['legend.fontsize'] = 10
xyz = []
cur = [0, 0]
for _ in range(400):
axis = random.randrange(0, 2)
cur[axis] += random.choice([-1, 1])
xyz.append(cur[:])
x, y = zip(*xyz)
data = np.vstack([x,y])
kde = scipy.stats.gaussian_kde(data)
density = kde(data)
fig1 = plt.figure()
ax = fig1.gca(projection='3d')
ax.plot(x, y, label='Random walk')
sns.kdeplot(data[0,:], data[1,:], 0)
ax.scatter(x[-1], y[-1], c='b', marker='o') # End point
ax.legend()
fig2 = plt.figure()
sns.kdeplot(data[0,:], data[1,:])
调用randomwalk()初始化并绘制:
编辑#1:
取得了一些进展,实际上我唯一需要的是将虚线垂直线的高度限制为双变量。有什么想法吗?
import matplotlib as mpl
import matplotlib.pyplot as plt
import random
import numpy as np
import seaborn as sns
import scipy
from mpl_toolkits.mplot3d import Axes3D
from matplotlib.mlab import bivariate_normal
%matplotlib inline
# Data for random walk
def randomwalk():
mpl.rcParams['legend.fontsize'] = 10
xyz = []
cur = [0, 0]
for _ in range(40):
axis = random.randrange(0, 2)
cur[axis] += random.choice([-1, 1])
xyz.append(cur[:])
# Get density
x, y = zip(*xyz)
data = np.vstack([x,y])
kde = scipy.stats.gaussian_kde(data)
density = kde(data)
# Data for bivariate gaussian
a = np.linspace(-7.5, 7.5, 20)
b = a
X,Y = np.meshgrid(a, b)
Z = bivariate_normal(X, Y)
surprise_Z = -np.log(Z)
# Get random points from walker and plot up z-axis to the gaussian
M = data[:,np.random.choice(20,5)].T
# Plot figure
fig = plt.figure(figsize=(10, 7))
ax = fig.gca(projection='3d')
ax.plot(x, y, 'grey', label='Random walk') # Walker
ax.scatter(x[-1], y[-1], c='k', marker='o') # End point
ax.legend()
surf = ax.plot_surface(X, Y, surprise_Z, rstride=1, cstride=1,
cmap = plt.cm.gist_heat_r, alpha=0.1, linewidth=0.1)
#fig.colorbar(surf, shrink=0.5, aspect=7, cmap=plt.cm.gray_r)
for i in range(5):
ax.plot([M[i,0], M[i,0]],[M[i,1], M[i,1]], [0,10],'k--',alpha=0.8, linewidth=0.5)
ax.set_zlim(0, 50)
ax.set_xlim(-10, 10)
ax.set_ylim(-10, 10)
答案 0 :(得分:0)
最终代码,
import matplotlib as mpl
import matplotlib.pyplot as plt
import random
import numpy as np
import seaborn as sns
import scipy
from mpl_toolkits.mplot3d import Axes3D
from matplotlib.mlab import bivariate_normal
%matplotlib inline
# Data for random walk
def randomwalk():
mpl.rcParams['legend.fontsize'] = 10
xyz = []
cur = [0, 0]
for _ in range(50):
axis = random.randrange(0, 2)
cur[axis] += random.choice([-1, 1])
xyz.append(cur[:])
# Get density
x, y = zip(*xyz)
data = np.vstack([x,y])
kde = scipy.stats.gaussian_kde(data)
density = kde(data)
# Data for bivariate gaussian
a = np.linspace(-7.5, 7.5, 100)
b = a
X,Y = np.meshgrid(a, b)
Z = bivariate_normal(X, Y)
surprise_Z = -np.log(Z)
# Get random points from walker and plot up z-axis to the gaussian
M = data[:,np.random.choice(50,10)].T
# Plot figure
fig = plt.figure(figsize=(10, 7))
ax = fig.gca(projection='3d')
ax.plot(x, y, 'grey', label='Random walk') # Walker
ax.legend()
surf = ax.plot_surface(X, Y, surprise_Z, rstride=1, cstride=1,
cmap = plt.cm.gist_heat_r, alpha=0.1, linewidth=0.1)
#fig.colorbar(surf, shrink=0.5, aspect=7, cmap=plt.cm.gray_r)
for i in range(10):
x = [M[i,0], M[i,0]]
y = [M[i,1], M[i,1]]
z = [0,-np.log(bivariate_normal(M[i,0],M[i,1]))]
ax.plot(x,y,z,'k--',alpha=0.8, linewidth=0.5)
ax.scatter(x, y, z, c='k', marker='o')