About 2 years ago, I wrote a post about plotting parabolas and quadratic equations, because I was learning quadratics that year in my math work. Now that I’m almost done with my sophomore year of high school, I’ve moved on to more complicated things.
Conic Sections
There are 3 types of conic sections. An ellipse, a parabola, and a hyperbola .
You get a conic section by intersecting 2 cones and a plane in various ways.
Parabolas
I covered parabolas in a previous post, but I’ll do a quick review in this post as well. Parabolas are the curve formed when the plane is at the same angle as the side of the cone. It is #3 in the Figure 1
The simplest equation for a parabola is a quadratic equation:
This will be very easy to plot. When making this a function, we can’t include the
A Function
We will be using the following equation for this example:
Code
<- function(x) {
q ^2 - 4*x + 2
x }
It only has one variable, so it is a function with
Plotting
Now, we need a familiar library, tidyverse.
Code
library(tidyverse)
We can start plotting with ggplot()
, and add geom_function()
as layer. Within geom_function()
, we need to set the function equal to
Code
ggplot() +
geom_function(fun = q)
This makes a really zoomed in plot. I want to see the whole parabola though. We can set different limits using xlim()
and ylim()
. We will also add some vertical and horizontal lines to make the different quadrants of the Cartesian plane more apparent, and change the color of the parabola to make it more visible. I’m also going to switch the order so the parabola shows up on top.
Code
ggplot() +
geom_hline(yintercept = 0) +
geom_vline(xintercept = 0) +
geom_function(fun = q, color = "red") +
xlim(-10, 10) +
ylim(-10, 10)
Hmm… I don’t love where the breaks are, and I don’t like how the Cartesian plane is made of rectangles.
Code
ggplot() +
geom_hline(yintercept = 0) +
geom_vline(xintercept = 0) +
geom_function(fun = q, color = "red") +
coord_fixed(xlim = c(-10, 10), ylim= c(-10, 10)) +
scale_x_continuous(breaks = -10:10, limits = c(-10, 10))+
scale_y_continuous(breaks = -10:10, limits = c(-10, 10))
We can fix that with coord_fixed
and scale_x/y_continuous
. We also no longer need the x/ylim
layers after the geom
Let’s add labels and a theme to finish up.
Code
ggplot() +
geom_hline(yintercept = 0) +
geom_vline(xintercept = 0) +
geom_function(fun = q, color = "red") +
coord_fixed(xlim = c(-10, 10), ylim= c(-10, 10)) +
scale_x_continuous(breaks = -10:10, limits = c(-10, 10))+
scale_y_continuous(breaks = -10:10, limits = c(-10, 10))+
labs(x = "X",
y = "Y")+
theme_linedraw()+
theme(
panel.grid.minor = element_blank(),
axis.title.y = element_text(angle = 0, vjust = 0.5)
)
That was pretty easy, because we only had one variable to contend with. From now on, things will get a little bit trickier.
Circles and Ellipses
In Figure 1, the circle is #1 and the ellipse is #2
Circles centered at the origin
Circle equations centered at the origin (
In functions, we can’t have an equals sign, so we’ll need to move the
If we assign this equation with any y
to the argument, like this:
Code
<- function(x, y) {
h ^2 + y^2 - 4
x }
But we still can’t plug this function in to ggplot. Something that’s more complicated with multiple variables (that I’ve found, if there are easier ways please let me know) is that you have to make your own data for any extra variables.
Making a Y
Thankfully, making a tibble
, but I found that expand_grid
works best. We don’t need very many numbers, so
The way we make our
Code
<- expand_grid(
circle_data x = seq(-7, 7, length.out = 100),
y = seq(-7, 7, length.out = 100))
Make sure you save it to an object, otherwise all the numbers won’t be easily viewable, and will get lost. We are technically making a dataset (though we are really just reminding R to list a bunch of numbers), so we need an x
and a y
. We also need a z
, which will be the product of the x
and y
in the function mutate
Code
<- expand_grid(
circle_data x = seq(-7, 7, length.out = 100),
y = seq(-7, 7, length.out = 100)) |>
mutate(z = h(x, y))
Plot at the origin
We can finally plot this circle! We can start like we normally do, with ggplot
and a geom
.
Code
ggplot(circle_data, aes(x = x, y = y)) +
geom_contour(aes(z = z), breaks = 0, color = "purple")
Wait a minute. That’s… not a circle? Don’t worry, it is actually a circle, we just need to add a few more things to the graph to make it be extra circle-y. We will also fix what the limits are and make it look just a little bit nicer.
Inside geom_contour
there is something called breaks
. What exactly is that for? There are 10,000 observations in circle_data
and we don’t use all of them for this graph. We actually only use the observations where z
is closest to 0. If the breaks
was set to 1, for example, it would take all observations where z
is close to/equal to 1. That’s kind of like adding a number to the radius. It’s a similar equation, but won’t produce the circle we are looking for.
Code
ggplot(circle_data, aes(x = x, y = y)) +
geom_contour(aes(z = z), breaks = 0, color = "purple") +
coord_fixed(xlim = c(-10, 10), ylim= c(-10, 10)) +
scale_x_continuous(breaks = -10:10, limits = c(-10, 10))+
scale_y_continuous(breaks = -10:10, limits = c(-10, 10))+
geom_hline(yintercept = 0)+
geom_vline(xintercept = 0)+
labs(x = "X",
y = "Y") +
theme_linedraw() +
theme(panel.grid.minor = element_blank(),
axis.title.y = element_text(angle = 0, vjust = 0.5))
Awesome!!! We made a circle with radius 4, centered around the origin, which is what our original equation was!
Circles not centered at the origin
So, the standard equation for a circle is:
When a circle, ellipse, or hyperbola is not centered around the origin, we simply shift the
The new circle equation is
For some
Let’s take the same equation from the last graph, and change some things about it.
I want this new circle to be 4 over and 3 down from the original circle.
We can turn this into a function
Code
<- function(x, y) {
t - 4)^2 + (y + 3)^2 - 4
(x }
We need to make our
Code
<- expand_grid(
circle_data2 x = seq(-7, 7, length.out = 100),
y = seq(-7, 7, length.out = 100)) |>
mutate(z = t(x, y))
Now we can plot it the same exact way as before. It should be the same size, but in a different place.
Code
ggplot(circle_data2, aes(x = x, y = y)) +
geom_contour(aes(z = z), breaks = 0, color = "blue") +
coord_fixed(xlim = c(-10, 10), ylim= c(-10, 10)) +
scale_x_continuous(breaks = -10:10, limits = c(-10, 10))+
scale_y_continuous(breaks = -10:10, limits = c(-10, 10))+
geom_hline(yintercept = 0)+
geom_vline(xintercept = 0)+
labs(x = "X",
y = "Y") +
theme_linedraw() +
theme(panel.grid.minor = element_blank(),
axis.title.y = element_text(angle = 0, vjust = 0.5))
Now that we’ve done 2 circles, we should be getting into a bit of a rhythm. All we really need to change is what the function is!
Ellipses
The standard form equation for an Ellipse is:
This should look really similar to the circle equation:
Vertical Ellipse
We will be using the equation
Code
<- function(x, y) {
p 2*x - 2)^2/4^2 + (3*y + 3)^2/8^2 - 1
( }
Now, we go through the same process of making our
Code
<- expand_grid(
ellipse_data x = seq(-7, 7, length.out = 100),
y = seq(-7, 7, length.out = 100)) |>
mutate(z = p(x, y))
And we graph the same way:
Code
ggplot(ellipse_data, aes(x = x, y = y)) +
geom_contour(aes(z = z), breaks = 0, color = "violetred2") +
coord_fixed(xlim = c(-10, 10), ylim= c(-10, 10)) +
scale_x_continuous(breaks = -10:10, limits = c(-10, 10))+
scale_y_continuous(breaks = -10:10, limits = c(-10, 10))+
geom_hline(yintercept = 0)+
geom_vline(xintercept = 0)+
labs(x = "X",
y = "Y") +
theme_linedraw() +
theme(panel.grid.minor = element_blank(),
axis.title.y = element_text(angle = 0, vjust = 0.5))
Horizontal Ellipse
See if you can graph this equation:
Hyperbolas
This is the last kind of conic section. It is #4 in Figure 1, a plane that cuts through 2 cones.
Standard Equation
A hyperbola is kind of like an opposite ellipse. The standard equation is:
Horizontal Hyperbola
Here’s the equation:
Code
<- function(x, y) {
m + 4)^2/1^2 - y^2/2^2 - 1
(x
}
<- expand_grid(
hyperbola1 x = seq(-7, 7, length.out = 100),
y = seq(-7, 7, length.out = 100)) |>
mutate(z = m(x, y))
And we can even use the same template for the plot!
Code
ggplot(hyperbola1, aes(x = x, y = y)) +
geom_contour(aes(z = z), breaks = 0, color = "orange1") +
coord_fixed(xlim = c(-10, 10), ylim= c(-10, 10)) +
scale_x_continuous(breaks = -10:10, limits = c(-10, 10))+
scale_y_continuous(breaks = -10:10, limits = c(-10, 10))+
geom_hline(yintercept = 0)+
geom_vline(xintercept = 0)+
theme_linedraw()+
labs(x = "X",
y = "Y") +
theme(
panel.grid.minor = element_blank(),
axis.title.y = element_text(angle = 0, vjust = 0.5)
)
Uh-oh…
Why are we running out of lines? They’re supposed to go on infinitely!
Making the
Code
<- function(x, y) {
m + 4)^2/1^2 - y^2/2^2 - 1
(x
}
<- expand_grid(
hyperbola2 x = seq(-10, 10, length.out = 100),
y = seq(-10, 10, length.out = 100)) |>
mutate(z = m(x, y))
I only moved it to
Code
ggplot(hyperbola2, aes(x = x, y = y)) +
geom_hline(yintercept = 0)+
geom_vline(xintercept = 0)+
geom_contour(aes(z = z), breaks = 0, color = "orange1") +
coord_fixed(xlim = c(-10, 10), ylim= c(-10, 10)) +
scale_x_continuous(breaks = -10:10, limits = c(-10, 10))+
scale_y_continuous(breaks = -10:10, limits = c(-10, 10))+
theme_linedraw()+
labs(x = "X",
y = "Y") +
theme(
panel.grid.minor = element_blank(),
axis.title.y = element_text(angle = 0, vjust = 0.5)
)
That’s much better! You can make an up and down opening hyperbola pretty much the same way.
Vertical Hyperbola
Same process as last time, we need to start out with an equation. The
Code
<- function(y, x) {
b ^2/2^2 - (x-4)^2/1^2 - 1
y
}
<- expand_grid(
hyperbola3 y = seq(-10, 10, length.out = 100),
x = seq(-10, 10, length.out = 100)) |>
mutate(z = b(y, x))
And we follow the same procedure as last time for the graph as well.
Code
ggplot(hyperbola3, aes(x = x, y = y)) +
geom_hline(yintercept = 0)+
geom_vline(xintercept = 0)+
geom_contour(aes(z = z), breaks = 0, color = "deeppink") +
coord_fixed(xlim = c(-10, 10), ylim= c(-10, 10)) +
scale_x_continuous(breaks = -10:10, limits = c(-10, 10))+
scale_y_continuous(breaks = -10:10, limits = c(-10, 10))+
theme_linedraw()+
labs(x = "X",
y = "Y") +
theme(
panel.grid.minor = element_blank(),
axis.title.y = element_text(angle = 0, vjust = 0.5)
)
Review
The process is quite similar for all of the conic sections (except for parabola, which is easier). Take your equation with some
Circle
Code
<- function(x, y) {
a -2)^2 + (y-1)^2 - 9
(x
}
<- expand_grid(
example_circle x = seq(-7, 7, length.out = 100),
y = seq(-7, 7, length.out = 100)) |>
mutate(z = a(x, y))
ggplot(example_circle, aes(x = x, y = y)) +
geom_contour(aes(z = z), breaks = 0, color = "blue") +
coord_fixed(xlim = c(-10, 10), ylim= c(-10, 10)) +
scale_x_continuous(breaks = -10:10, limits = c(-10, 10))+
scale_y_continuous(breaks = -10:10, limits = c(-10, 10))+
geom_hline(yintercept = 0)+
geom_vline(xintercept = 0)+
labs(x = "X",
y = "Y") +
theme_linedraw() +
theme(panel.grid.minor = element_blank(),
axis.title.y = element_text(angle = 0, vjust = 0.5))
Ellipse
Code
<- function(x, y) {
j -3)^2/6^2 + (y+3)^2/4^2 - 1
(x
}
<- expand_grid(
example_ellipse x = seq(-15, 15, length.out = 100),
y = seq(-15, 15, length.out = 100)) |>
mutate(z = j(x, y))
ggplot(example_ellipse, aes(x = x, y = y)) +
geom_contour(aes(z = z), breaks = 0, color = "springgreen3") +
coord_fixed(xlim = c(-10, 10), ylim= c(-10, 10)) +
scale_x_continuous(breaks = -10:10, limits = c(-10, 10))+
scale_y_continuous(breaks = -10:10, limits = c(-10, 10))+
geom_hline(yintercept = 0)+
geom_vline(xintercept = 0)+
theme_linedraw()+
labs(x = "X",
y = "Y") +
theme(
panel.grid.minor = element_blank(),
axis.title.y = element_text(angle = 0, vjust = 0.5)
)
Parabola
Code
<- function(x, y) {
k ^2+5*x + 3
x
}
ggplot() +
geom_hline(yintercept = 0) +
geom_vline(xintercept = 0) +
geom_function(fun = k, color = "red") +
coord_fixed(xlim = c(-10, 10), ylim= c(-10, 10)) +
scale_x_continuous(breaks = -10:10, limits = c(-10, 10))+
scale_y_continuous(breaks = -10:10, limits = c(-10, 10))+
labs(x = "X",
y = "Y")+
theme_linedraw()+
theme(
panel.grid.minor = element_blank(),
axis.title.y = element_text(angle = 0, vjust = 0.5)
)
Hyperbola
Code
<- function(x, y) {
l 3*y^2/4^2-(2*x-7)^2/3^2-1
}
<- expand_grid(
example_hyperbola x = seq(-15, 15, length.out = 100),
y = seq(-15, 15, length.out = 100)) |>
mutate(z = l(x, y))
ggplot(example_hyperbola, aes(x = x, y = y)) +
geom_hline(yintercept = 0)+
geom_vline(xintercept = 0)+
geom_contour(aes(z = z), breaks = 0, color = "deeppink") +
coord_fixed(xlim = c(-10, 10), ylim= c(-10, 10)) +
scale_x_continuous(breaks = -10:10, limits = c(-10, 10))+
scale_y_continuous(breaks = -10:10, limits = c(-10, 10))+
theme_linedraw()+
labs(x = "X",
y = "Y") +
theme(
panel.grid.minor = element_blank(),
axis.title.y = element_text(angle = 0, vjust = 0.5)
)
Figure 1: Jens Vyff, Types Of Conic Sections , via Wikimedia Commons, February 2021