2016-11-04 2 views
1

Titre original (vague): Comment faire surface circulaire de x et de la valeur z neProducing 3D terrain pour la surface de révolution (un exemple de courbe logistique GLM)


J'ai des données qui se rapportent à un l'axe x et un axe z similaire à des valeurs de 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") 

Je veux générer une surface/matrice où les valeurs de new.data$fit représentent l'axe z et x et y sont générées à partir de l'axe du rayon étant le new.data$Dist. En d'autres termes, je veux un cercle généré à partir du rayon Dist et des cellules remplies par z valeur de la courbe de probabilité logistique. Je voudrais dire que j'ai essayé certaines solutions mais je ne sais même pas par où commencer.

+0

@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

+0

Que voulez-vous dire par "courbe de régression logistique?" –

+0

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

Répondre

4

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

enter image description here


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:

  1. une fonction (vectorisée) de la courbe 2D: f;
  2. grille d'évaluation sur le 1er quadrant {(x, y) | x >= 0, y >= 0} (en raison de la symétrie, nous prenons y = x);
  3. 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 = "") 

enter image description here

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 = "") 
+0

Merci pour votre aide à ce sujet. La matrice est exactement ce dont j'avais besoin – Jdan