Donc, vous voulez tracer surface of revolution, en faisant tourner la courbe logistique autour de la ligne verticale Dist = 0
. Statistiquement, je ne sais pas pourquoi nous avons besoin de cela, mais purement d'un point de vue mathématique et pour la visualisation 3D, c'est en quelque sorte utile, d'où je décide d'y répondre.
Tout nous avons besoin est une fonction de la courbe 2D initiale f(d)
, où d
est la distance d'un point à centre de rotation et f
est une fonction lisse. Comme nous allons utiliser outer
pour créer une matrice de surface, f
doit être défini pour être fonction vectorisée dans R. Maintenant, la surface de révolution est générée comme f3d(x, y) = f((x^2 + y^2)^0.5)
.
Dans votre paramètre de régression logistique, le f
ci-dessus est la courbe logistique, la réponse prédite d'un GLM. Il peut être obtenu à partir de predict.glm
, qui est une fonction vectorisée. Le code suivant correspond à un modèle et définit cette fonction f
plus son extension 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)
}
En raison de la symétrie, nous appelons seulement f3d
le 1er quadrant pour une matrice de surface X1
, tout en feuilletant X1
pour les matrices de surface sur d'autres quarts de cercle.
## 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]
Enfin, nous combinons des matrices provenant de différents quadrants et réalisons un tracé 3D. Notez que l'ordre de combinaison est le quadrant 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")
Faire une routine de jouet pour tracer la surface de la révolution
Dans cette partie, nous définissons une routine de jouet pour tracer la surface de la révolution.Comme noté ci-dessus, nous avons besoin de cette routine:
- une fonction (vectorisée) de la courbe 2D:
f
;
- grille d'évaluation sur le 1er quadrant
{(x, y) | x >= 0, y >= 0}
(en raison de la symétrie, nous prenons y = x
);
- arguments supplémentaires possibles à
f
, et les paramètres graphiques personnalisés à persp
.
Ce qui suit est une implémentation simple:
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))
}
Supposons maintenant que nous voulons tourner une onde cosinus sur [0, pi]
pour une surface de révolution, nous pouvons faire
surfrev(cos, seq(0, pi, by = 0.1 * pi), col = "lightblue", theta = 35, phi = 40,
xlab = "", ylab = "", zlab = "")
Nous pouvons également utiliser surfrev
pour tracer votre courbe logistique souhaitée:
## `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 = "")
@ZheyuanLi Je suis aussi confus mais j'imagine regarder vers le bas sur une courbe de régression logistique. Juste une ligne droite. Maintenant, tournez cette ligne à 360 degrés autour de l'origine en créant un cercle complet. La surface serait la "pente" de la courbe de régression logistique lorsque Dist était tourné autour de l'origine de cette ligne. – Jdan
Que voulez-vous dire par "courbe de régression logistique?" –
Dans le code ci-dessus, les données ont été modélisées avec une régression logistique. La colonne 'ajustement' est la probabilité prédite de ce modèle au Dist correspondant. Par exemple, à partir de new.data, à Dist = 50, la probabilité est .81 à Dist = 100, le prob est .75 et ainsi de suite. Si vous traciez cette ligne, elle serait sigmoïde et diminuerait de 0 à 650. Donc ce que je veux faire c'est ... Imagine 0 est le centre d'un cercle et 650 est le rayon de ce cercle. En 3 dimensions maintenant .. Maintenant tourner cette courbe sigmoïdale 360 degrés autour de 0. Les probabilités sur l'axe z devraient ressembler à une colline 3D – Jdan