3 min read

Parábolas con ggplot

Parábola (!)

Una parábola es un conjunto de puntos que equidista de una línea (directriz) y un punto (foco). Estos puntos satisfacen:

\((x-h)^2=4p(y-k), p \neq 0\)

El vértice de la parábola está en \((h,k)\) y la directriz \(y=k-p\). El foco está en \((h, k+p)\) si la parábola es abierta hacia arriba.

Gráfico de un Parábola en ggplot

Si podemos escribir la parábola como una función, podemos graficarla usando stat_fun. Para graficar \(y=f(x)\):

library(latex2exp)

fun.1 <- function(x) { x^2 }
g_1 <- ggplot(data_frame(x=0), aes(x=x)) + 
  stat_function(fun = fun.1) + xlim(-5, 5) + 
  geom_segment(aes(x=-5, xend = 5, y=0, yend=0),
               size = 0.5,
               arrow = arrow(length = unit(0.2, "cm"))) + # Eje X
  geom_segment(aes(x=0, xend=0, y=-1, yend=25),
               size = 0.5,
               lineend = "butt",
               arrow = arrow(length = unit(0.2, "cm"))) + # Eje Y 
  ggtitle(TeX('$y=x^2$')) + 
  theme(
    plot.title = element_text(hjust = 0.5)
  ) 
g_1

Ejemplo

\(x^2=16y\) es una parábola con vértice en \((0,0)\), \(p = 4\) y foco en \((0,4)\).

focus <- list(x=0, y=4, lab = "Foco")
vertex <- list(x=0, y=0, lab = "Vértice")
notable_points <- bind_rows(focus, 
                            vertex)
pt <- data_frame(x=5, y=round(5^2/16, 2))

p <- ggplot(data_frame(x=0), aes(x=x)) +
  geom_segment(aes(x=-9, xend = 9, y=0, yend=0),
               size = 0.5,
               arrow = arrow(length = unit(0.2, "cm"))) + # Eje X
  geom_segment(aes(x=0, xend=0, y=-5, yend=10),
               size = 0.5,
               lineend = "butt",
               arrow = arrow(length = unit(0.2, "cm"))) + # Eje Y
  stat_function(fun = function(x) { x^2 / 16}) + 
  xlim(-9, 9) + 
  ylim(-5, 10)

x <- 5

g_2 <- p +
  geom_point(data = notable_points, aes(x=x, y=y)) + 
  geom_text(data=notable_points, 
            size = 3,
            nudge_y = 1.25,
            nudge_x = 1.25,
            aes(label = paste0(lab, "\n(", x, ",", y, ")"), 
                x = x, y = y)) + 
  geom_hline(yintercept = -4, linetype = "dashed") + 
  annotate("text", x= 3, y= -3.3, label = "Directriz", size = 3) +
  ggtitle(TeX('$y=x^2/16$')) + 
  theme(
    plot.title = element_text(hjust = 0.5)
  ) + geom_point(data = pt, aes(x=x, y=y)) + 
  geom_segment(aes(x= focus$x, y=focus$y, xend=pt$x, yend=pt$y),
               linetype = "dashed") + 
  geom_segment(aes(x=pt$x, y=pt$y, xend=pt$x, yend = -4),
               linetype = "dashed") + 
  annotate("text", 
           label = "phantom(0) == phantom(0)", 
           parse = TRUE,
           angle = 60,
           size = 5,
           x = 2.5, y= 2.85) + 
  annotate("text", 
           label = "phantom(0) == phantom(0)", 
           parse = TRUE,
           size = 5,
           x = 5, y= -2)
g_2

En todos los puntos de la parábola, la distancia del punto al foco es igual que al foco. TODO: una versión interactiva de este gráfico.

Una parábola con eje horziontal

Si completamos el cuadrado, vemos que \(y^2+6y+8x+25 = 0\) es la ecuación de una parábola:

\[\begin{align} y^2+6y+8x+25 &= 0\\ y^2+6y+9+8x+25-9 &= 0\\ (y+3)^2 &= -16-8x\\ (y+3)^2 &= 4(-2)(x+2) \end{align}\]

El vértice es \((-2, -3)\), p es \(-2\), el foco \((-4,-3)\) la directriz es \(x=0\). Pero como la orientación de esta parábola es horizontal, no es una función. Cómo la graficamos con ggplot?

Si despejamos \(y\) en función de \(x\), obtenemos dos funciones: \[\begin{align} (y+3)^2 &= (-8)(x+2)\\ y &= -3 \pm \sqrt{-8(x+2)}\\ y_1 &=-3 + \sqrt{-8(x+2)}\\ y_2 &=-3 - \sqrt{-8(x+2)}\\ \end{align}\]

Podemos graficar \(y1\) y \(y2\):

x <- seq(-5, 0, length.out=1e3)
lbs <- list(bquote(-3 + sqrt(-8*(x+2))), # investigar bquote!
            bquote(-3 - sqrt(-8*(x+2))))

g_3 <- ggplot(data_frame(x=x), 
            aes(x=x, color = color)) + 
  stat_function(data = data_frame(x=x, color = factor(1)),
                fun = function(x) { -3 + sqrt(-8*(x+2)) }) + 
  stat_function(data = data_frame(x=x, color = factor(2)),
                fun = function(x) { -3 - sqrt(-8*(x+2)) }) + 
  scale_color_manual(labels = lbs,
                     name = "",
                     values = c(scales::hue_pal()(2)[1], 
                                scales::hue_pal()(2)[2])) + 
  geom_hline(yintercept = 0) + 
  geom_vline(xintercept = 0)
g_3