Python/Matplotlib: 在3D图中绘制带有KDE联合密度轮廓线的2D随机漫步。

3
我正在尝试使用Python创建一个相当复杂的三维图形,具体来说是在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)向上绘制一条虚线,直到它碰到双变量正态分布。
到目前为止,我已经成功在三维空间中绘制了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)

enter image description here

1个回答

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')

enter image description here


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接