When working with a massive dataset with hundreds or thousands of records or data points, it is quite easy to create an overloaded plot where the number of dots, lines, or symbols is so high that the plot become unreadable. Individual dots are displayed on top of each other, and patterns are hardly visible without any further work. This is called overplotting. An example of overplotting is the following scatter plot displaying 3000 data points:

library(ggplot2) library(viridis) #dataframe ID <- 1:3000 groups <- c(rep("A", 500), rep("B", 500), rep("C", 500), rep("D", 500), rep("E", 500), rep("F", 500)) values_x <- c(rnorm(500, mean=80, sd=10), rnorm(500, mean=100, sd=15), rnorm(500, mean=120, sd=10), rnorm(500, mean=75, sd=20), rnorm(500, mean=95, sd=10), rnorm(500, mean=115, sd=15)) values_y <- c(rnorm(500, mean=115, sd=10), rnorm(500, mean=125, sd=5), rnorm(500, mean=105, sd=10), rnorm(500, mean=85, sd=20), rnorm(500, mean=95, sd=10), rnorm(500, mean=90, sd=15)) categories <- as.factor(floor(runif(3000, min=1, max=4))) df <- data.frame(ID, groups, categories, values_x, values_y) #scatter plot baseplot <- ggplot(df, aes(values_x, values_y)) + geom_point() baseplot

If the dataset is well organized in categories/groups, several options exist to help you make things clearer and easier to analyse. In the example above, each of the records in the dataframe contains an ID, two independent variables (`categories`

and `group`

) and two dependent variables (`values_x`

and `values_y`

).

We can ask ggplot to help discriminate between the independent variables by grouping the data (with colors, shapes and/or size) or by creating faceted plots which split the data in smaller panels based on these independent variables.

Here are 3 examples where the `groups`

from our example are highlighted with colors (left), shapes (center) and size (right):

#color baseplot + geom_point(aes(color = groups)) + scale_color_viridis(discrete = TRUE) #shapes baseplot + geom_point(aes(shape = groups)) #size baseplot + geom_point(aes(size = groups))

As you may realize from these 3 examples, not all forms of grouping are suitable. Sometimes, colors are good enough for visually separating groups. However, when the density is high, and the colors not well chosen, these might not turn that helpful. Shapes and size are also good helpers when the number of data points is not too high… but in our case, they make things actually even more confusing or less readable.

In such situations, it may be helpful to split the plot into a bunch of smaller plots, each containing one group (or combination of independent variables). In that way, you might easily spot clusters or patterns defined by one of a few specific groups or observe differences in distribution. To create such multifaceted plots, we will use `facet_wrap()`

or `facet_grid()`

. These functions are further introduced in the present chapter, and we will see how to tune some of the parameters and arguments.

Here is an example using `facet_wrap()`

to discriminate among the `groups`

:

baseplot + facet_wrap(~groups)

The distribution pattern of those 6 groups becomes now obvious, possibly even more obvious than when represented with colors.

Using `facet_grid()`

, you can actually use combinations of two independent variables to divide your plot into a matrix of mini-plots. Here is our example where `categories`

and `groups`

are used to split the data:

baseplot + facet_grid(categories~groups)

In the following pages of this chapter, you will see how to make use of these functions, how to modify their look, the labels and so on. Keep in mind that their is no universal solution for all data sets and that you may have to try several plots or designs before you find what fits best your data set and represents best your results.

]]>`facet_wrap`

is a function that allows you to split an overloaded plot into several smaller, lighter plots (panels). All these panels will of course display the same variables along the same axes, but one category at a time.

Let’s illustrate this with an overloaded histogram of distribution. The dataframe for drawing this histogram is described below. It contains 3000 values dispatched into 6 groups (A, B, C, D, E and F):

ID <- 1:3000 groups <- c(rep("A", 500), rep("B", 500), rep("C", 500), rep("D", 500), rep("E", 500), rep("F", 500)) values <- c(rnorm(500, mean=50, sd=10), rnorm(500, mean=30, sd=5), rnorm(500, mean=40, sd=10), rnorm(500, mean=60, sd=20), rnorm(500, mean=70, sd=10), rnorm(500, mean=55, sd=15)) df <- data.frame(ID, groups, values)

and the histogram looks like this:

ggplot(df, aes(values)) + geom_histogram(bins=50)

As you may see, this histogram represents all the 3000 values without splitting them by groups. Let’s use colors (from the Viridis color palette) to represent these groups:

ggplot(df, aes(values, fill=groups)) + geom_histogram(bins=50) + scale_fill_viridis(discrete=TRUE)

baseplot <- ggplot(df, aes(values, fill=groups)) + geom_histogram(bins=50) + scale_fill_viridis(discrete=TRUE)

Displaying the groups by color help make thing a bit clearer indeed. But things would be even clearer if we could isolate the groups from each other. And this is exactly what `facet_wrap()`

offers to do. The only thing that you must supply is the name of the variable that contains the groups (in our dataframe, it is `groups`

) and put a `~`

in front of it:

baseplot + facet_wrap(~groups)

From here, you can define whether you want these “mini-plots” to be separated in a grid with n columns (use `ncol= n`

) or with n rows (use `nrow= n`

). Here are two examples, one with 2 columns and one with only 1 column:

baseplot + facet_wrap(~groups, ncol = 2) baseplot + facet_wrap(~groups, ncol = 1)

The advantage with one row for all plots is that you can compare the distribution of each group on the same X-axis.

Another useful option is `dir =`

which allow to reorder the display of the categories or groups. On the examples above, group A is displayed first in the top left corner of the grid, then comes group B directly to the right, and so one until the row is complete (then starts a new row…). Use `dir = v`

, groups will be dispatched vertically first. In the example below, group B comes under group A:

baseplot + facet_wrap(~groups, dir = "v")

By default in `facet_wrap()`

, the scales of the X- and Y-axes are fixed. This means that all the mini-plots will have the same scales, making them easy to compare. You may override that setting with `scales =`

. This argument has 4 options: `free`

where all the plots will have different scales on both axes based on the data content of the individual plots, `free_x`

where only the scale of the Y-axis will be common to all plots, `free_y`

where only the scale of the X-axis will be common to all plots, and `fixed`

where both the X- and Y-axis are common to all plots. Here are two examples, `free_y`

to the left and `free`

to the right:

#free scale on on Y-axis, fixed scale on X-axis baseplot + facet_wrap(~groups, scales = "free_y") #free scale on both axes baseplot + facet_wrap(~groups, scales = "free")

`facet_grid`

is a function that allows you to split an overloaded plot into several smaller, lighter plots (panels). All these panels will of course display the same variables along the same axes, but one category (or one combination of categories) at a time. The resulting plot is thus a matrix of “mini-plots”.

Let’s illustrate this with an overloaded histogram of distribution. The dataframe for drawing this histogram is described below. It contains 3000 values dispatched into 6 groups (A, B, C, D, E and F), and with a second attribute (category) in the form of a number randomly picked between 1 and 3.

ID <- 1:3000 groups <- c(rep("A", 500), rep("B", 500), rep("C", 500), rep("D", 500), rep("E", 500), rep("F", 500)) categories <- as.factor(floor(runif(3000, min=1, max=4))) values <- c(rnorm(500, mean=50, sd=10), rnorm(500, mean=30, sd=5), rnorm(500, mean=40, sd=10), rnorm(500, mean=60, sd=20), rnorm(500, mean=70, sd=10), rnorm(500, mean=55, sd=15)) df <- data.frame(ID, groups, categories, values)

and the histogram looks like this:

ggplot(df, aes(values)) + geom_histogram(bins=50)

For making thing easier, we will store the code for the plot in the object `baseplot`

:

baseplot <- ggplot(df, aes(values)) + geom_histogram(bins=50)

For having a quick overview about the dataset and the different groups and categories before going any further with `facet_grid`

, we can make 2 colored histograms, the first one where groups are colored, and the other where categories are colored:

#histogram with colored "groups" ggplot(df, aes(values, fill=groups)) + geom_histogram(bins=50) + scale_fill_viridis(discrete=TRUE) #histogram with colored "categories" ggplot(df, aes(values, fill=categories)) + geom_histogram(bins=50) + scale_fill_viridis(discrete=TRUE)

Using `facet_grid()`

, you can immediately get an overview over all the groups and categories in the form of a 6 by 3 matrix. you just need to indicate `groups`

and `categories`

between the parentheses, and separated by `~`

:

baseplot + facet_grid(categories~groups)

Note that the order of the elements between the parentheses in `facet_grid()`

determines the order of the matrix:

baseplot + facet_grid(groups~categories)

If you are not interested in combinations of grousp/categories, you may choose do display a matrix based only on one element. Here you may choose to display only the `groups`

, and in rows. Use `rows = vars()`

in the following way:

baseplot + facet_grid(rows = vars(groups))

Same request, but this time displayed in columns with `cols = vars()`

:

baseplot + facet_grid(cols = vars(groups))

By default in `facet_grid()`

, the scales of the X- and Y-axes are fixed. This means that all the mini-plots will have the same scales, making them easy to compare. You may override that setting with `scales =`

. This argument has 4 options: `free`

where all the plots will have different scales on both axes based on the data content of the individual plots, `free_x`

where only the scale of the Y-axis will be common to all plots, `free_y`

where only the scale of the X-axis will be common to all plots, and `fixed`

where both the X- and Y-axis are common to all plots. Here are two examples, `free_y`

to the left and `free`

to the right:

#free scale on on Y-axis, fixed scale on X-axis baseplot + facet_grid(categories~groups, scales = "free_y") #free scale on both axes baseplot + facet_grid(categories~groups, scales = "free")

`facet_grid`

and `facet_wrap`

both produce faceted plots where the labels of the groups/variables used to split the data are displayed on top or to the right, while the axes are at the bottom and to the left, as usual, along with the axtis titles. This is illustrated with the two examples below.

While axis titles, ticks, scales, etc are editable in the same way as a normal plot (see here), the labels showing the names of the categories and groups may be edited via a series of specific arguments in the function `theme()`

. These arguments and options are described below.

Use `theme(strip.background = element_rect())`

to edit the box of the labels. This includes background color and frame:

baseplot + theme(strip.background = element_rect(fill="lightblue", size=1, color="darkblue"))

Here you will find the color names and a tool to provide you with hex codes.

Use `theme(strip.text = element_text())`

to change the *look* of the text in ALL the labels. Alternatively use `strip.text.x =`

or `strip.text.y =`

to only affect the horizontal or the vertical labels:

ALL labels baseplot + theme(strip.text = element_text(size=12, face="bold", color="darkblue")) Horizontal or vertical labels baseplot + theme(strip.text.x = element_text(size=12, face="italic", color="darkblue")) + theme(strip.text.y = element_text(size=13, face="bold", color="red"))

Note that the *names* of the labels are directly taken from the dataframe and automatically displayed in the plot. If you wish to modify these names without changing the dataframe, build a vector with the new names and use the function `labeller = labeller()`

in `facet_grid()`

or `facet_wrap()`

. Indicate the name of the element to modify (here `groups=`

) and add the new vector. For example, we wish to replace the group names “A”, “B”, etc. by “group A”, “group B”, and so on. First we build the vector `new_labels`

:

new_labels <- c("A" = "group A", "B" = "group B", "C" = "group C", "D" = "group D", "E" = "group E", "F" = "group F")

Then we use that vector in the plot code in the following way:

ggplot(df, aes(values_x, values_y)) + geom_point() + facet_grid(categories~groups, labeller = labeller(groups = new_labels))

Use `theme(panel.spacing = unit(1, "cm"))`

to change the spacing between ALL the labels (and thus the panels). Alternatively use `panel.spacing.x =`

or `panel.spacing.y =`

to only affect spacing between the horizontal or the vertical labels (and panels):

#ALL margins baseplot + theme(panel.spacing = unit(1, "cm")) #X and Y margins baseplot + theme(panel.spacing.x = unit(.25, "cm")) + theme(panel.spacing.y = unit(1, "cm"))]]>

A good graph is always introduced by a title that tells the reader what your figure is about. It does not need to be long or detailed. Often it only states which variables are represented, or it may summarize the meaning of the graph.

- A few examples:
- temperature vs. time,
- effect of various salt concentration on the growth of
*Saccharomyces cerevisiae* - goose population in Longyearbyen, 1990-2010

Here we will see a simple way to set up a title above the graph. The Rscript for the present tutorial is available here. Let’s see that with the following example, a scatter plot brought by the following code (note that the code for the plot is stored in the object `baseplot`

so that we can reuse it throughout the whole tutorial) :

ID <- 1:400 values1 <- rnorm(200, mean=50, sd=10) values2 <- c(rnorm(100, mean=20, sd=10), rnorm(100, mean=40, sd=10)) df <- data.frame(ID, values1, values2) baseplot <- ggplot(df, aes(values1, values2)) + geom_point(size=2) baseplot

A simple way to add a title to the plot is to use the function `labs()`

:

baseplot + labs(title="values2 vs. values1")

As you may see above, the title appears by default at the top left corner, just above the plot. This is not directly modifiable with the function `labs()`

. In fact, `labs()`

does not allow you to do much more than displaying a title (with `title=""`

), a subtitle just under the title (with `subtitle=""`

) and a tag in the top left corner of the whole figure (with `tag=""`

):

baseplot + labs(title="values2 vs. values1", subtitle="presented in the form of a scatterplot", tag="Fig.1A")

In order to modify the look of the title that has been created by `labs()`

, you will have to modify the *theme*. To do so, you will have to add an additional line to the code and use the function `theme(plot.title = element_text())`

. Using this line and a few additional arguments, you will be able to set the position (with `hjust=`

and `vjust=`

), color (with `color=`

), size (with `size=`

), font (with `family=`

), etc of this title:

baseplot + labs(title="values2 vs. values1") + theme(plot.title = element_text(family = "serif", face = "bold", color = "blue", size = 18, hjust = .5, vjust = 2))]]>

Axis titles are important for the clarity of a graph as they give the reader information about the variables which are represented and their unit (if any). A common mistake is to omit the unit, thus leading to misinterpretation of the data and aberrant conclusions. Axis titles should be clear, short but descriptive enough to leave no doubt about the variables.

In ggplot, there are several ways to assign a title to an axis, and to change its look. Here we will see a couple of them using a simple example. The Rscript for the present tutorial is available here.

Two randomly generated variables are represented in the following scatter plot via the following code (note that the code for the plot is stored in the object `baseplot`

so that we can reuse it throughout the whole tutorial):

ID <- 1:400 values1 <- rnorm(200, mean=50, sd=10) values2 <- c(rnorm(100, mean=20, sd=10), rnorm(100, mean=40, sd=10)) df <- data.frame(ID, values1, values2) baseplot <- ggplot(df, aes(values1, values2)) + geom_point(size=2) baseplot

As you may see here, ggplot has already taken care of placing the vector/variable names (i.e. `values1`

and `values2`

) as axis titles. The whole point here is to override this action by default, and replace `values1`

by `variable1 (unit)`

, and `values2`

by `variable2 (unit)`

.

Here we use the function `xlab()`

and `ylab()`

to indicate the new titles for the axes:

baseplot + xlab("variable1 (unit)") + ylab("variable2 (unit)")

The functions `scale_x_continuous()`

and `scale_y_continuous()`

(alternatively `scale_x_discrete()`

and `scale_y_discrete()`

if your variables are discrete instead of continuous) may be use instead of `xlab()`

and `ylab()`

:

baseplot + scale_x_continuous("variable3 (unit)") + scale_y_continuous("variable4 (unit)")

If you wish to change the size and/or color of the axis titles, you won’t be able to do it using the previous functions, but will have to modify the *theme* of the plot itself. To do so, you will have to add an additional line to the code and use the function `theme(axis.title = element_text())`

:

baseplot + xlab("variable1 (unit)") + ylab("variable2 (unit)") + theme(axis.title = element_text(color = "blue", size = 12))

You can alternatively modify only one of the axis titles, or both in a different manner, by replacing `axis.title`

with `axis.title.x`

and/or `axis.title.y`

:

baseplot + xlab("variable1 (unit)") + ylab("variable2 (unit)") + theme(axis.title.x = element_text(color = "blue", face ="bold", size = 12)) + theme(axis.title.y = element_text(color = "red", size = 14))

]]>

For better clarity of your chart, it is important to correctly set the limits of the axes, i.e. the minimum and maximum values on the axes. If the limits are too low, part of your data might not be visible; if the limits are to broad, your plot might look small, empty and less readable.

In ggplot, the default arguments in the functions take care of setting appropriate dimensions to your plot. However, there are simple ways to modify the axis limits. Here we will see how to do this using a simple example. The Rscript for the present tutorial is available here.

Two randomly generated variables are represented in the following scatter plot via the following code (note that the code for the plot is stored in the object `baseplot`

so that we can reuse it throughout the whole tutorial):

ID <- 1:400 values1 <- rnorm(200, mean=50, sd=10) values2 <- c(rnorm(100, mean=20, sd=10), rnorm(100, mean=40, sd=10)) df <- data.frame(ID, values1, values2) baseplot <- ggplot(df, aes(values1, values2)) + geom_point(size=2) baseplot

Here we use `xlim()`

and `ylim()`

to tune the X- and Y-axis, respectively, to set the range of the axis to 0-90:

baseplot + xlim(0, 90) + ylim(0, 90)

Note that, by doing this, the negative values have been removed from the plot.

Using the same function, you can actually reverse the axes by inverting the limits:

baseplot + xlim(90, 0) + ylim(90, 0)

You can also let ggplot do half of the job, by setting one limit manually and asking ggplot to set the other limit based on the data set. In this case, use `NA`

instead of one of the limits:

baseplot + xlim(0, NA) + ylim(0, NA)

Note that these examples applied to *continuous* variables. If your variables are *discrete *(categorical), you may use the same functions. to illustrate this, we use the following example:

ID <- 1:600 values <- c(rnorm(150, mean=25, sd=5), rnorm(150, mean=30, sd=4), rnorm(150, mean=15, 3), rnorm(150, mean=40, sd=5)) category <- c(rep("A", 150), rep("B", 150), rep("C", 150), rep("D", 150)) df <- data.frame(ID, category, values) baseplot2 <- ggplot(df, aes(category, values)) + geom_boxplot() baseplot2

Here, we want to display fewer groups on the X-axis, and a different scale on the Y-axis:

baseplot2 + xlim("A", "C", "D") + ylim(0, 90)

It is also possible to use `scale_x_continuous()`

, `scale_y_continuous()`

, `scale_x_discrete()`

and `scale_y_discrete()`

to achieve the same results. Of course, if your data are continuous, use `scale_x_continuous()`

and/or `scale_y_continuous()`

, and if your data are discrete, use `scale_x_discrete()`

and/or `scale_y_discrete()`

. See this example:

baseplot + scale_x_continuous(limits=c(0, 90)) + scale_y_continuous(limits=c(0, 90))

… and that example:

baseplot2 + scale_x_discrete(limits=c("A", "C", "D")) + scale_y_continuous(limits=c(0, 90))

Note that these functions are the same that where used to define the axis titles here. It is thus possible to adjust the titles and limits simultaneously:

baseplot2 + scale_x_discrete("variable1 (unit)", limits=c("A", "C", "D")) + scale_y_continuous("variable2 (unit)", limits=c(0, 90))

`scale_x_discrete()`

and `scale_y_discrete()`

allow for reordering of the display of categories. To reorder categories along an axis, simply indicate this order in `limits=`

:

baseplot2 + scale_x_discrete("variable1 (unit)", limits=c("A", "C", "B", "D")) + scale_y_continuous("variable2 (unit)", limits=c(0, 90))]]>

The clarity of your plot might sometimes rely on the proper scaling of the axes. Often, the scale is linear, and ggplot displays that by default. But your dataset and resulting plot might be better represented if the Y-axis is logarithmic, for example. In such a case, not resetting the scale of the axis may result in a plot where the pattern appears inconclusive.

In ggplot, the scale can be set to log10, log2, sqrt(square root), and reverse (to invert the axis) among others. Here we will see how to do this using a simple example. The Rscript for the present tutorial is available here.

The scatter plot represented further below via the following code will serve as an example (note that the code for the plot is stored in the object `baseplot`

so that we can reuse it throughout the whole tutorial):

ID <- 1:100 values1 <- 1:100 values2 <- values1*(rnorm(100, mean=1, sd=.1)) df <- data.frame(ID, values1, values2) baseplot <- ggplot(df, aes(values1, values2)) + geom_point(size=2) baseplot

Here, we use `scale_y_continuous()`

with the argument `trans=`

to transform the Y-axis, and with `"log10"`

to set the log10 Y-axis scale:

baseplot + scale_y_continuous(trans = "log10")

Now, we use `"log2"`

to set the log2 axis scale:

baseplot + scale_y_continuous(trans = "log2")

Now, we use `"sqrt"`

to set the square root axis scale:

baseplot + scale_y_continuous(trans = "sqrt")

Now, we use `"reverse"`

to invert the Y-axis scale:

baseplot + scale_y_continuous(trans = "reverse")]]>

Not that essential to be honest, but something that can improve the readability of your plot: the axis ticks. Again, ggplot does quite an good job setting up the scale and thus the ticks along the X- and Y-axes. But you can still have a different opinion about where these ticks have to be, or how many should be there…

The scatter plot represented further below via the following code will serve again as an example (note that the code for the plot is stored in the object `baseplot`

so that we can reuse it throughout the whole tutorial). The Rscript for the present tutorial is available here.

Axis ticks on the Y-axis are easily defined by the argument `breaks=`

in `scale_y_continuous()`

(note that it is of course possible to do the same on the X-axis using `scale_x_continuous()`

). The syntax is `breaks=c(a, b, ...)`

where `a`

and `b`

are the ticks that you want to set on the axis. You can put as many as you want, not just 2. Here for example, we want to put 12, 30 and 55 (and only these values) on the Y-axis:

baseplot + scale_y_continuous(breaks=c(12, 30, 55))

To define the ticks in a more regular/organized manner, you may use `break=seq(a, b, c)`

where `a`

is the start of the interval where the ticks are displayed, `b`

is the end of the interval where the ticks are displayed, and `c`

defines the frequency of the ticks in the interval. Here, in this example, we will start the ticks at 10 and stop at 90 on both the X-axis and Y-axis, and the ticks will be placed every 10:

baseplot + scale_x_continuous(breaks=seq(10, 90, 10)) + scale_y_continuous(breaks=seq(10, 90, 10))

Here you notice that the Y-axis stops around 75. ggplot knows that all values (data points) are well below 90, thus ignores your request, and resets automatically the top limit of the axis. To override ggplot, use `limits=c(NA, 90)`

as described here:

baseplot + scale_x_continuous(breaks=seq(10, 90, 10)) + scale_y_continuous(limits=c(NA,90), breaks=seq(10, 90, 10))

It is also possible to make things a bit more complicated, for example by setting two or more intervals with specific ticks. In the example below, we set on the X-axis a series of ticks every 5 between 10 and 50, and every 10 between 50 and 90. On the Y-axis, we set a series of ticks every 2.5 between 20 and 60, and every 10 between 10 and 90:

baseplot + scale_x_continuous(breaks=c(seq(10, 50, 5), seq(50, 90, 10))) + scale_y_continuous(breaks=c(seq(20, 60, 2.5), seq(10, 90, 10)))

If one or both of the axes have a logarithmic scale, then it is also possible to set ticks in another way than the one imposed by default by ggplot. Use `annotation_logticks()`

to display the ticks. Then use `sides=`

to define which side of the plot (which axis) will be affected by the modifications. Write `l`

for left, `r`

for right, `b`

for bottom and `t`

for top. Combinations such as `lr`

or `lb`

are possible.

baseplot + scale_y_continuous(trans = "log10") + annotation_logticks(sides="l")

]]>

If you feel that you are desperately missing axis lines (since they are not part of the standard plot drawn by ggplot), then this article is for you. Adding X- and Y-axis lines to your plot implies that you modify the theme of the plot itself. Nothing very complicated about it, as you will see further below.

The scatter plot represented here via the following code will serve as an example (note that the code for the plot is stored in the object `baseplot`

so that we can reuse it throughout the whole tutorial). The Rscript for the present tutorial is available here.

ID <- 1:100 values1 <- 1:100 values2 <- values1*(rnorm(100, mean=1, sd=.1)) df <- data.frame(ID, values1, values2) baseplot <- ggplot(df, aes(values1, values2)) + geom_point(size=2) baseplot

To add both X- and Y-axis lines to your plot, add an extra line of code and use `theme(axis.line = element_line())`

. In the parentheses, you may add additional arguments for modifying the size/thickness (`size=`

), the color (`color=`

) and the pattern of the line (`linetype=`

):

baseplot + theme(axis.line = element_line(linetype = "solid", size = 1, colour = "darkblue"))

If you wish to use different parameters for each axis, use axis.line.x and axis.line.y to operate on the X- and Y-axis separately:

baseplot + theme(axis.line.y = element_line(size = 1, colour = "darkblue", linetype = "solid"), axis.line.x = element_line(size = 1.25, colour = "red", linetype = "dotted"))]]>