生成旋转表面的 3D 图(GLM 逻辑曲线示例)

Jda*_*dan 1 3d plot r surface glm

原标题(含糊):如何仅根据 x 和 z 值制作圆形表面


我有与 x 轴和 z 轴相关的数据,类似于以下值new.data

mydata <- structure(list(Dist = c(82, 82, 85, 85, 126, 126, 126, 126, 178, 
178, 178, 178, 178, 236, 236, 236, 236, 236, 312, 368, 368, 368, 
368, 368, 425, 425, 425, 425, 425, 425, 560, 560, 560, 560, 560, 
612, 612, 612, 612), pDet = c(1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 
1, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 
0, 0, 0, 0, 1, 0, 0)), .Names = c("Dist", "pDet"), row.names = c(NA, 
-39L), class = "data.frame")

model <- glm(pDet ~ Dist, data = mydata, family = binomial(link = "logit"))
new.data <- data.frame(Dist = seq(0, 650, 50))
new.data$fit <- predict(model, newdata = new.data, type="response")
Run Code Online (Sandbox Code Playgroud)

我想生成一个表面/矩阵,其中new.data$fit代表 z 轴、x 轴和 y 轴的值是根据半径生成的new.data$Dist

换句话说,我想要一个由半径生成的圆Dist和由z逻辑概率曲线值填充的单元格。我想说我已经尝试了一些解决方案,但甚至不知道从哪里开始。

李哲源*_*李哲源 5

因此,您想要通过围绕垂直线旋转逻辑曲线来绘制旋转曲面Dist = 0从统计角度来看,我不知道为什么我们需要这个,但纯粹从数学方面来看,为了 3D 可视化,这有点有用,因此我决定回答这个问题。

我们所需要的只是初始二维曲线 的函数f(d),其中d是从一点到旋转中心的距离,并且f是一些平滑函数。正如我们将用来outer制作表面矩阵一样,f必须将其定义为 R 中的矢量化函数。现在旋转表面生成为f3d(x, y) = f((x ^ 2 + y ^ 2) ^ 0.5)

在逻辑回归设置中,上面f是逻辑曲线,即 GLM 的预测响应。它可以从 获得predict.glm,它是一个向量化函数。以下代码适合模型,并定义此类函数f及其 3D 扩展。

mydata <- structure(list(Dist = c(82, 82, 85, 85, 126, 126, 126, 126, 178, 
178, 178, 178, 178, 236, 236, 236, 236, 236, 312, 368, 368, 368, 
368, 368, 425, 425, 425, 425, 425, 425, 560, 560, 560, 560, 560, 
612, 612, 612, 612), pDet = c(1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 
1, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 
0, 0, 0, 0, 1, 0, 0)), .Names = c("Dist", "pDet"), row.names = c(NA, 
-39L), class = "data.frame")

model <- glm(pDet ~ Dist, data = mydata, family = binomial(link = "logit"))

## original 2D curve
f <- function (d, glmObject) 
  unname(predict.glm(glmObject, newdata = list(Dist = d), type = "response"))

## 3d surface function on `(x, y)`
f3d <- function (x, y, glmObject) {
  d <- sqrt(x ^ 2 + y ^ 2)
  f(d, glmObject)
  }
Run Code Online (Sandbox Code Playgroud)

由于对称性,我们只调用f3d第一象限的表面矩阵X1,而翻转X1其他象限的表面矩阵。

## prediction on the 1st quadrant
x1 <- seq(0, 650, by = 50)
X1 <- outer(x1, x1, FUN = f3d, glmObject = model)

## prediction on the 2nd quadrant
X2 <- X1[nrow(X1):2, ]

## prediction on the 3rd quadrant
X3 <- X2[, ncol(X2):2]

## prediction on the 4th quadrant
X4 <- X1[, ncol(X1):2]
Run Code Online (Sandbox Code Playgroud)

最后,我们组合来自不同象限的矩阵并绘制 3D 图。请注意,组合顺序为象限 3-4-2-1。

## combined grid
x <- c(-rev(x1), x1[-1])
# [1] -650 -600 -550 -500 -450 -400 -350 -300 -250 -200 -150 -100  -50    0   50
#[16]  100  150  200  250  300  350  400  450  500  550  600  650

## combined matrix
X <- cbind(rbind(X3, X4), rbind(X2, X1))

## make 3D surface plot
persp(x, x, X, col = "lightblue", theta = 35, phi = 40,
      xlab = "", ylab = "", zlab = "pDet")
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述


制作一个绘制旋转曲面的玩具例程

在这一部分中,我们定义了一个绘制旋转曲面的玩具例程。如上所述,我们需要这个例程:

  1. 2D 曲线的(矢量化)函数:f
  2. 第一象限的评估网格{(x, y) | x >= 0, y >= 0}(由于我们采用 的对称性y = x);
  3. 可能的附加参数f,以及自定义的图形参数persp

下面是一个简单的实现:

surfrev <- function (f, x, args.f = list(), ...) {
  ## extend `f` to 3D
  .f3d <- function (x, y) do.call(f, c(list(sqrt(x ^ 2 + y ^ 2)), args.f))
  ## surface evaluation
  X1 <- outer(x, x, FUN = .f3d)
  X2 <- X1[nrow(X1):2, ]
  X3 <- X2[, ncol(X2):2]
  X4 <- X1[, ncol(X1):2]
  xbind <- c(-rev(x), x[-1])
  X <- cbind(rbind(X3, X4), rbind(X2, X1))
  ## surface plot
  persp(xbind, xbind, X, ...)
  ## invisible return
  invisible(list(grid = xbind, z = X))
  }
Run Code Online (Sandbox Code Playgroud)

现在假设我们想要在[0, pi]旋转表面上旋转余弦波,我们可以这样做

surfrev(cos, seq(0, pi, by = 0.1 * pi), col = "lightblue", theta = 35, phi = 40,
        xlab = "", ylab = "", zlab = "")
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

我们还可以用来surfrev绘制您想要的逻辑曲线:

## `f` and `model` defined at the beginning
surfrev(f, seq(0, 650, by = 50), args.f = list(glmObject = quote(model)),
        col = "lightblue", theta = 35, phi = 40, xlab = "", ylab = "", zlab = "")
Run Code Online (Sandbox Code Playgroud)