Skip to content

x ticks and x tick labels

cathmmitchell edited this page Apr 1, 2021 · 5 revisions

x-tick and x-tick label positions

Sometimes we want to manually set the positions of the x-ticks and the x-tick labels of a figure, rather than use the default values selected by ggplot.

Let’s take a look at an example from the tutorial: plotting the surface chlorophyll fluorescence data for 2016 by cruise and station (for a full explanation of the data manipulation steps in this example check out this part of the tutorial).

There are a few different ways to do this depending on the x-axis data type. We’re going to look at a couple of those. But first we need to initialize our session by loading the relevant libraries and importing our data.

Initialize session

Let’s import the tidyverse and lubridate:

library(tidyverse)
## -- Attaching packages ------------------- tidyverse 1.3.0 --

## v ggplot2 3.3.2     v purrr   0.3.4
## v tibble  3.0.3     v dplyr   1.0.2
## v tidyr   1.1.2     v stringr 1.4.0
## v readr   1.3.1     v forcats 0.5.0

## -- Conflicts ---------------------- tidyverse_conflicts() --
## x dplyr::filter() masks stats::filter()
## x dplyr::lag()    masks stats::lag()
library(lubridate)
## 
## Attaching package: 'lubridate'

## The following objects are masked from 'package:base':
## 
##     date, intersect, setdiff, union

and read the data into a data frame:

fieldData <- read_csv('DamariscottaRiverData.csv')
## Parsed with column specification:
## cols(
##   date = col_double(),
##   station = col_double(),
##   depthbin = col_double(),
##   year = col_double(),
##   month = col_double(),
##   day = col_double(),
##   depth_m = col_double(),
##   temperature_degC = col_double(),
##   salinity_psu = col_double(),
##   density_kg_m3 = col_double(),
##   PAR = col_double(),
##   fluorescence_mg_m3 = col_double(),
##   oxygenConc_umol_kg = col_double(),
##   oxygenSaturation_percent = col_double(),
##   latitude = col_double()
## )

Now we are ready to set our x-ticks for different data types on the x-axis.

If your axis data are dates: scale_x_date()

Data Manipulation

Creating a data frame which contains latitudes, date (as date objects) and surface chlorophyll fluorescence data:

chldata2016 <- fieldData %>% mutate(rdate = ymd(date)) %>% filter(year == 2016, depth_m < 2) %>% group_by(station,rdate) %>% summarize(surf_chl = mean(fluorescence_mg_m3))
## `summarise()` regrouping output by 'station' (override with `.groups` argument)
structure(chldata2016)
## # A tibble: 20 x 3
## # Groups:   station [4]
##    station rdate      surf_chl
##      <dbl> <date>        <dbl>
##  1       1 2016-09-08    4.46 
##  2       1 2016-09-20    1.18 
##  3       1 2016-10-04    1.34 
##  4       1 2016-10-19    0.911
##  5       1 2016-11-01    1.06 
##  6       2 2016-09-08    4.15 
##  7       2 2016-09-20    1.56 
##  8       2 2016-10-04    1.17 
##  9       2 2016-10-19    1.03 
## 10       2 2016-11-01    0.696
## 11       3 2016-09-08    4.23 
## 12       3 2016-09-20    3.50 
## 13       3 2016-10-04    1.04 
## 14       3 2016-10-19    3.25 
## 15       3 2016-11-01    0.690
## 16       4 2016-09-08    5.33 
## 17       4 2016-09-20    5.38 
## 18       4 2016-10-04    1.04 
## 19       4 2016-10-19    2.89 
## 20       4 2016-11-01    0.511

Visualizing data using a contour plot

We can visualize this using a contour plot (geom_contour_filled()):

ggplot(chldata2016,aes(x=rdate,y=station)) +
  geom_contour_filled(aes(z=surf_chl)) +
  geom_point() 

But, in this case, the x-ticks and x-tick labels don’t align with where our cruise dates are. Can we fix this?

Set the x-ticks and labels

If we know what x-tick positions we want, we could specify them in a call to scale_x_date(). Recall to get a list of the cruise dates we can use unique:

unique(chldata2016$rdate)
## [1] "2016-09-08" "2016-09-20" "2016-10-04" "2016-10-19" "2016-11-01"

So we can use this in our call to scale_x_date():

ggplot(chldata2016,aes(x=rdate,y=station)) +
  geom_contour_filled(aes(z=surf_chl)) +
  geom_point() +
  scale_x_date(breaks=unique(chldata2016$rdate))

Great - our xticks and labels now align with our data points. We could have specified our labels separately, but R does a good job in this case of automatically naming based on where we want our ticks to be.

If your axis data are continuous numbers: scale_x_continuous

In this case, we are going to keep the dates in their raw format as numeric objects of the form yyyymmdd. Note, this means the spacing of the data points along the x-axis will be weird (as was pointed out in the main tutorial), but for now, what we care about is aligning the ticks with those points.

Data Manipulation

chldata2016 <- fieldData %>% filter(year == 2016, depth_m < 2) %>% group_by(station,date) %>% summarize(surf_chl = mean(fluorescence_mg_m3))
## `summarise()` regrouping output by 'station' (override with `.groups` argument)
structure(chldata2016)
## # A tibble: 20 x 3
## # Groups:   station [4]
##    station     date surf_chl
##      <dbl>    <dbl>    <dbl>
##  1       1 20160908    4.46 
##  2       1 20160920    1.18 
##  3       1 20161004    1.34 
##  4       1 20161019    0.911
##  5       1 20161101    1.06 
##  6       2 20160908    4.15 
##  7       2 20160920    1.56 
##  8       2 20161004    1.17 
##  9       2 20161019    1.03 
## 10       2 20161101    0.696
## 11       3 20160908    4.23 
## 12       3 20160920    3.50 
## 13       3 20161004    1.04 
## 14       3 20161019    3.25 
## 15       3 20161101    0.690
## 16       4 20160908    5.33 
## 17       4 20160920    5.38 
## 18       4 20161004    1.04 
## 19       4 20161019    2.89 
## 20       4 20161101    0.511

We can see our dates are <dbl> or “doubles” - which are just numbers.

Visualizing data using a contour plot

We can visualize this using a contour plot (geom_contour_filled()):

ggplot(chldata2016,aes(x=date,y=station)) +
  geom_contour_filled(aes(z=surf_chl)) +
  geom_point() 

As mentioned earlier, the x-spacing is all wrong, but let’s ignore that for now.

Set the x-ticks and labels

For this plot, our x-axis is numeric i.e. it is a continuous number scale. So here we have to use scale_x_continuous() to set our x-tick positions and labels.

ggplot(chldata2016,aes(x=date,y=station)) +
  geom_contour_filled(aes(z=surf_chl)) +
  geom_point() +
  scale_x_continuous(breaks=unique(chldata2016$date))

Great. Our ticks have come out in the correct place, but now the labels overlap because they are so close. Can we do something about that? Yes!

ggplot(chldata2016,aes(x=date,y=station)) +
  geom_contour_filled(aes(z=surf_chl)) +
  geom_point() +
  scale_x_continuous(breaks=unique(chldata2016$date)) +
  theme(axis.text.x = element_text(angle = 90))

If your axis data are discrete numbers: scale_x_discrete

In this case, we are going to set our x-axis to be factors i.e. discrete values that could be anything. We’re still going to plot date on the x-axis, but we’ll convert it to a factor, so even though it might look like a number - it is not.

Data Manipulation

Note we are converting the date column to factors in the below (compared to the earlier data manipulation steps):

chldata2016 <- fieldData %>% filter(year == 2016, depth_m < 2) %>% group_by(station,date) %>% summarize(surf_chl = mean(fluorescence_mg_m3))
## `summarise()` regrouping output by 'station' (override with `.groups` argument)
chldata2016$date <- factor(chldata2016$date)

structure(chldata2016)
## # A tibble: 20 x 3
## # Groups:   station [4]
##    station date     surf_chl
##      <dbl> <fct>       <dbl>
##  1       1 20160908    4.46 
##  2       1 20160920    1.18 
##  3       1 20161004    1.34 
##  4       1 20161019    0.911
##  5       1 20161101    1.06 
##  6       2 20160908    4.15 
##  7       2 20160920    1.56 
##  8       2 20161004    1.17 
##  9       2 20161019    1.03 
## 10       2 20161101    0.696
## 11       3 20160908    4.23 
## 12       3 20160920    3.50 
## 13       3 20161004    1.04 
## 14       3 20161019    3.25 
## 15       3 20161101    0.690
## 16       4 20160908    5.33 
## 17       4 20160920    5.38 
## 18       4 20161004    1.04 
## 19       4 20161019    2.89 
## 20       4 20161101    0.511

Here we can see the dates are saved as factors.

Visualizing data using a scatter plot

Because our dates are now factors, we can’t interpolate between the dates, so geom_contour_filled won’t work (because it’s interpolating data behind the scenes).

In this case, we’ll just plot the data points:

ggplot(chldata2016,aes(x=date,y=station)) +
  geom_point() 

Here we’ve already got our x-ticks in the right place! Wooo! But maybe we want to only have some of the ticks. How would we do that?

Set the x-ticks and labels

Because our dates are now factors, we have to use scale_x_discrete() to set our x-tick positions and labels. Let’s just show the 1st, 3rd and 5th x-ticks - here we’re going to type them out manually.

ggplot(chldata2016,aes(x=date,y=station)) +
  geom_point() +
  scale_x_discrete(breaks=c(20160908, 20161004, 20161101))

We could even change how these labels are shown if we wanted:

ggplot(chldata2016,aes(x=date,y=station)) +
  geom_point() +
  scale_x_discrete(breaks=c(20160908, 20161004, 20161101),
                   labels = c('09-08-2016', '10-04-2016', '11-01-2016'))