我必须承认,我将其视为一个挑战,因为我一直在寻找不同的方式来展示其他数据集。我通常会scatterhist
按照其他答案中显示的 2D 图表的方式做一些事情,但我想尝试一下rgl
。
我用你的函数来生成数据
gibbs<-function (n, rho) {
mat <- matrix(ncol = 2, nrow = n)
x <- 0
y <- 0
mat[1, ] <- c(x, y)
for (i in 2:n) {
x <- rnorm(1, rho * y, (1 - rho^2))
y <- rnorm(1, rho * x, (1 - rho^2))
mat[i, ] <- c(x, y)
}
mat
}
bvn <- gibbs(10000, 0.98)
设置
我rgl
用于硬举,但我不知道如何在不去的情况下获得置信椭圆car
。我猜还有其他方法可以攻击这个。
library(rgl) # plot3d, quads3d, lines3d, grid3d, par3d, axes3d, box3d, mtext3d
library(car) # dataEllipse
处理数据
获取直方图数据而不绘制它,然后我提取密度并将它们归一化为概率。这些*max
变量是为了简化未来的绘图。
hx <- hist(bvn[,2], plot=FALSE)
hxs <- hx$density / sum(hx$density)
hy <- hist(bvn[,1], plot=FALSE)
hys <- hy$density / sum(hy$density)
## [xy]max: so that there's no overlap in the adjoining corner
xmax <- tail(hx$breaks, n=1) + diff(tail(hx$breaks, n=2))
ymax <- tail(hy$breaks, n=1) + diff(tail(hy$breaks, n=2))
zmax <- max(hxs, hys)
地板上的基本散点图
应根据分布将比例设置为适当的值。诚然,X 和 Y 标签的放置并不漂亮,但根据数据重新定位应该不会太难。
## the base scatterplot
plot3d(bvn[,2], bvn[,1], 0, zlim=c(0, zmax), pch='.',
xlab='X', ylab='Y', zlab='', axes=FALSE)
par3d(scale=c(1,1,3))
后墙上的直方图
我不知道如何让它们在整个 3D 渲染的平面上自动绘制,所以我不得不手动制作每个矩形。
## manually create each histogram
for (ii in seq_along(hx$counts)) {
quads3d(hx$breaks[ii]*c(.9,.9,.1,.1) + hx$breaks[ii+1]*c(.1,.1,.9,.9),
rep(ymax, 4),
hxs[ii]*c(0,1,1,0), color='gray80')
}
for (ii in seq_along(hy$counts)) {
quads3d(rep(xmax, 4),
hy$breaks[ii]*c(.9,.9,.1,.1) + hy$breaks[ii+1]*c(.1,.1,.9,.9),
hys[ii]*c(0,1,1,0), color='gray80')
}
汇总行
## I use these to ensure the lines are plotted "in front of" the
## respective dot/hist
bb <- par3d('bbox')
inset <- 0.02 # percent off of the floor/wall for lines
x1 <- bb[1] + (1-inset)*diff(bb[1:2])
y1 <- bb[3] + (1-inset)*diff(bb[3:4])
z1 <- bb[5] + inset*diff(bb[5:6])
## even with draw=FALSE, dataEllipse still pops up a dev, so I create
## a dummy dev and destroy it ... better way to do this?
dev.new()
de <- dataEllipse(bvn[,1], bvn[,2], draw=FALSE, levels=0.95)
dev.off()
## the ellipse
lines3d(de[,2], de[,1], z1, color='green', lwd=3)
## the two density curves, probability-style
denx <- density(bvn[,2])
lines3d(denx$x, rep(y1, length(denx$x)), denx$y / sum(hx$density), col='red', lwd=3)
deny <- density(bvn[,1])
lines3d(rep(x1, length(deny$x)), deny$x, deny$y / sum(hy$density), col='blue', lwd=3)
美化
grid3d(c('x+', 'y+', 'z-'), n=10)
box3d()
axes3d(edges=c('x-', 'y-', 'z+'))
outset <- 1.2 # place text outside of bbox *this* percentage
mtext3d('P(X)', edge='x+', pos=c(0, ymax, outset * zmax))
mtext3d('P(Y)', edge='y+', pos=c(xmax, 0, outset * zmax))
完成品
使用的一个好处rgl
是您可以用鼠标旋转它并找到最佳视角。由于没有为这个 SO 页面制作动画,执行上述所有操作应该可以让您有播放时间。(如果你旋转它,你将能够看到这些线略在直方图前面,略高于散点图;否则我会发现交叉点,所以它在某些地方看起来是不连续的。)

最后,我发现这有点让人分心(二维变体就足够了):显示 z 轴意味着数据存在第三维;Tufte 特别反对这种行为(Tufte,“Envisioning Information”,1990)。然而,随着更高的维度,这种使用 RGL 的技术将允许对模式进行重要的透视。
(记录在案,Win7 x64,在 32 位和 64 位中使用 R-3.0.3 测试,rgl v0.93.996,汽车 v2.0-19。)