-
Notifications
You must be signed in to change notification settings - Fork 0
x ticks and x tick labels
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.
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.
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
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?
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.
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.
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.
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.
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))
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.
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.
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?
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'))