Plotting in Base R

plot(x = iris$Petal.Length, y = iris$Petal.Width, col = iris$Species)

Plotting with ggplot2

library(tidyverse)

Practice with irises

ggplot(iris, aes(x = Petal.Length, y = Petal.Width)) +
  geom_point()

Start with just data and coordinates

ggplot(iris, aes(x = Petal.Length, y = Petal.Width)) 

Add in points to show data, along with color and a linear model

ggplot(iris, aes(x = Petal.Length, y = Petal.Width)) +
  geom_point()

ggplot(iris, aes(x = Petal.Length, y = Petal.Width, color = Species)) +
  geom_point() 

ggplot(iris, aes(x = Petal.Length, y = Petal.Width, color = Species)) +
  geom_point() +
  geom_smooth(method = "lm")

ggplot(iris, aes(x = Petal.Length, y = Petal.Width)) +
  geom_point(aes(color = Species)) +
  geom_smooth(method = "lm")

Looking at a new dataset

diamonds

Start simple, single variable

Histograms

ggplot(diamonds, aes(x = carat)) +
  geom_histogram()
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

Adjust binwidth as necessary

ggplot(diamonds, aes(x = carat)) +
  geom_histogram(bins = 40)

ggplot(diamonds, aes(x = carat)) +
  geom_histogram(bins = 10)

ggplot(diamonds, aes(x = carat)) +
  geom_histogram(bins = 15)

Quick color adjustment

Color is different from Fill

ggplot(diamonds, aes(x = carat)) +
  geom_histogram(bins = 15, color = "black", fill = "steelblue")

Categorical Variables

Bar plots, defaults to stat = “count”

ggplot(diamonds, aes(x = cut)) +
  geom_bar()

ggplot(diamonds, aes(x = cut)) +
  geom_bar(stat = "count")

Using some of the dplyr we learned Monday

diamonds %>%
  group_by(cut) %>%
  summarize(count = n()) %>%
  ggplot(aes(x = cut, y = count)) +
  geom_col() +
  geom_text(aes(label = count))

Boxplots

ggplot(diamonds, aes(x = cut, y = price)) +
  geom_boxplot()

Violin plots

ggplot(diamonds, aes(x = cut, y = price)) +
  geom_violin()

Other features of ggplot2

Starting with a basic scatterplot

ggplot(diamonds, aes(x = carat, y = price)) +
  geom_point()

Plotting in Layers

Points created first, line drawn on top

ggplot(diamonds, aes(x = carat, y = price)) +
  geom_point() +
  geom_smooth()
## `geom_smooth()` using method = 'gam'

Line created first, points drawn on top

ggplot(diamonds, aes(x = carat, y = price)) +
  geom_smooth() + 
  geom_point() 
## `geom_smooth()` using method = 'gam'

Using Color

This applies the color to everything - global ggplot call carries to all geom_*

ggplot(diamonds, aes(x = carat, y = price, color = cut)) +
  geom_point() +
  geom_smooth()
## `geom_smooth()` using method = 'gam'

If we want to color the points based on the cut of the diamond:

This doesn’t work.

ggplot(diamonds, aes(x = carat, y = price)) +
  geom_point(color = cut) +
  geom_smooth()
## `geom_smooth()` using method = 'gam'
## Error in rep(value[[k]], length.out = n): attempt to replicate an object of type 'closure'

This does! Using the data to color the data requires the aes() function

ggplot(diamonds, aes(x = carat, y = price)) +
  geom_point(aes(color = cut)) +
  geom_smooth()
## `geom_smooth()` using method = 'gam'

This changes all of the points to a single color

ggplot(diamonds, aes(x = carat, y = price)) +
  geom_point(color = "orange") +
  geom_smooth()
## `geom_smooth()` using method = 'gam'

This creates a color based on one value, “orange.” It doesn’t involve the color “orange” at all.

ggplot(diamonds, aes(x = carat, y = price)) +
  geom_point(aes(color = "orange")) +
  geom_smooth()
## `geom_smooth()` using method = 'gam'

Colors can be continuous

ggplot(diamonds, aes(x = carat, y = price)) +
  geom_point(aes(color = table)) 

Labels, Legends, and Themes

Titles and labels

ggplot(diamonds, aes(x = carat, y = price)) +
  geom_point(aes(color = table)) +
  labs(x = "Carat", y = "Price (USD)", title = "Price vs. Carat", subtitle = "Data from ggplot2", caption = "This is a caption")

Legend label, and color customization

Legend labels have to be defined in their respective scale_* functions

ggplot(diamonds, aes(x = carat, y = price)) +
  geom_point(aes(color = table)) +
  labs(x = "Carat", y = "Price (USD)", title = "Price vs. Carat", subtitle = "Data from ggplot2", caption = "This is a caption") +
  scale_color_continuous(guide = guide_colorbar(title = "Table of Diamond"))

ggplot(diamonds, aes(x = carat, y = price)) +
  geom_point(aes(color = table)) +
  labs(x = "Carat", y = "Price (USD)", title = "Price vs. Carat", subtitle = "Data from ggplot2", caption = "This is a caption") +
  scale_color_continuous(low = "yellow", high = "blue", guide = guide_colorbar(title = "Table of Diamond"))

Using built-in themes

ggplot(diamonds, aes(x = carat, y = price)) +
  geom_point(aes(color = table)) +
  labs(x = "Carat", y = "Price (USD)", title = "Price vs. Carat", subtitle = "Data from ggplot2", caption = "This is a caption") +
  scale_color_continuous(low = "yellow", high = "blue", guide = guide_colorbar(title = "Table of Diamond")) +
  theme_dark()

ggplot(diamonds, aes(x = carat, y = price)) +
  geom_point(aes(color = table)) +
  labs(x = "Carat", y = "Price (USD)", title = "Price vs. Carat", subtitle = "Data from ggplot2", caption = "This is a caption") +
  scale_color_continuous(low = "yellow", high = "blue", guide = guide_colorbar(title = "Table of Diamond")) +
  theme_bw()

Customizing themes further

This moves the legend to the bottom:

ggplot(diamonds, aes(x = carat, y = price)) +
  geom_point(aes(color = table)) +
  labs(x = "Carat", y = "Price (USD)", title = "Price vs. Carat", subtitle = "Data from ggplot2", caption = "This is a caption") +
  scale_color_continuous(low = "yellow", high = "blue", guide = guide_colorbar(title = "Table of Diamond")) +
  theme_bw() +
  theme(legend.position = "bottom")

Changing Font Family

The text element of theme() is inherited by all text in the plot.

ggplot(diamonds, aes(x = carat, y = price)) +
  geom_point(aes(color = table)) +
  labs(x = "Carat", y = "Price (USD)", title = "Price vs. Carat", subtitle = "Data from ggplot2", caption = "This is a caption") +
  scale_color_continuous(low = "yellow", high = "blue", guide = guide_colorbar(title = "Table of Diamond")) +
  theme_bw() +
  theme(legend.position = "bottom", text = element_text(family = "mono"))

It is possible to modify specific elements, such as the plot title:

ggplot(diamonds, aes(x = carat, y = price)) +
  geom_point(aes(color = table)) +
  labs(x = "Carat", y = "Price (USD)", title = "Price vs. Carat", subtitle = "Data from ggplot2", caption = "This is a caption") +
  scale_color_continuous(low = "yellow", high = "blue", guide = guide_colorbar(title = "Table of Diamond")) +
  theme_bw() +
  theme(legend.position = "bottom", text = element_text(family = "mono"), plot.title = element_text(family = "sans"))

Facets / Small Multiples

Facet with one variable using facet_wrap()

ggplot(diamonds, aes(x = carat, y = price)) +
  geom_point(aes(color = table)) +
  labs(x = "Carat", y = "Price (USD)", title = "Price vs. Carat", subtitle = "Data from ggplot2", caption = "This is a caption") +
  scale_color_continuous(low = "yellow", high = "blue", guide = guide_colorbar(title = "Table of Diamond")) +
  theme_bw() +
  theme(legend.position = "bottom", text = element_text(family = "mono"), plot.title = element_text(family = "sans")) +
  facet_wrap(~clarity)

Facet in specific directions with facet_grid()

ggplot(diamonds, aes(x = carat, y = price)) +
  geom_point(aes(color = table)) +
  labs(x = "Carat", y = "Price (USD)", title = "Price vs. Carat", subtitle = "Data from ggplot2", caption = "This is a caption") +
  scale_color_continuous(low = "yellow", high = "blue", guide = guide_colorbar(title = "Table of Diamond")) +
  theme_bw() +
  theme(legend.position = "bottom", text = element_text(family = "mono"), plot.title = element_text(family = "sans")) +
  facet_grid(cut~.)

ggplot(diamonds, aes(x = carat, y = price)) +
  geom_point(aes(color = table)) +
  labs(x = "Carat", y = "Price (USD)", title = "Price vs. Carat", subtitle = "Data from ggplot2", caption = "This is a caption") +
  scale_color_continuous(low = "yellow", high = "blue", guide = guide_colorbar(title = "Table of Diamond")) +
  theme_bw() +
  theme(legend.position = "bottom", text = element_text(family = "mono"), plot.title = element_text(family = "sans")) +
  facet_grid(.~cut)

Facet in both directions across different variables

ggplot(diamonds, aes(x = carat, y = price)) +
  geom_point(aes(color = table)) +
  labs(x = "Carat", y = "Price (USD)", title = "Price vs. Carat", subtitle = "Data from ggplot2", caption = "This is a caption") +
  scale_color_continuous(low = "yellow", high = "blue", guide = guide_colorbar(title = "Table of Diamond")) +
  theme_bw() +
  theme(legend.position = "bottom", text = element_text(family = "mono"), plot.title = element_text(family = "sans")) +
  facet_grid(color~cut)

Saving

It’s easy to save a plot, especially once you’ve stored it in a variable (like p).

p <- ggplot(diamonds, aes(x = carat, y = price)) +
  geom_point(aes(color = table)) +
  labs(x = "Carat", y = "Price (USD)", title = "Price vs. Carat", subtitle = "Data from ggplot2", caption = "This is a caption") +
  scale_color_continuous(low = "yellow", high = "blue", guide = guide_colorbar(title = "Table of Diamond")) +
  theme_bw() +
  theme(legend.position = "bottom", text = element_text(family = "mono"), plot.title = element_text(family = "sans")) +
  facet_grid(color~cut)

ggplot2 can save in many file formats without difficulty. Here are three:

ggsave(plot = p, filename = "./images/diamonds.png")
ggsave(plot = p, filename = "./images/diamonds.svg")
ggsave(plot = p, filename = "./images/diamonds.eps")

We can define further options, like dpi, within the ggsave() command. Remember that width and height are defined in inches by default.

ggsave(plot = p, filename = "./images/diamonds.png", dpi = 1200, width = 8, height = 6)

Shiny

# Load required packages
library(shiny)
library(tidyverse)

# User Interface
ui <- fluidPage(
   
   titlePanel("Iris Data"),

   mainPanel(
     
     # "irisPlot" matches output$irisPlot from server
     plotOutput("irisPlot")
   ),
   
   sliderInput(inputId = "pl", label = "Petal Length", min = 0, max = 10, value = c(0, 10), step = 0.5)
   
   
)

# Server
server <- function(input, output) {

  # Anything that responds to input from the UI needs to be put in a reactive context
  df <- reactive({
    
    # input$pl matches the sliderInput with inputId = "pl" from the UI
    data <- iris %>%
      filter(Petal.Length >= input$pl[1] & Petal.Length <= input$pl[2])
    
    return(data)
  })
    
  # This will be sent to the matching plotOutput in the UI
  output$irisPlot <- renderPlot({
    ggplot(df(), aes(x = Petal.Length, y = Petal.Width)) +
      geom_point(aes(color = Species))
  })
}

# This command actually creates the app
shinyApp(ui = ui, server = server)