Introduction

This vignette details all the plotting options available in arphit. If you are learning how to use arphit, you should read the getting started guide first.

library(arphit)
set.seed(42)

Data types

tibbles and data.frames

simple_data <- data.frame(date = seq.Date(from = as.Date("2000-03-01"),
                                          length.out = 10,
                                          by = "quarter"),
                          y1 = rnorm(10),
                          y2 = rnorm(10),
                          y3 = rnorm(10),
                          y4 = rnorm(10))
long_data <- data.frame(date = rep(seq.Date(from = as.Date("2000-03-01"),
                                            length.out = 10,
                                            by = "quarter"), 2),
                        y1 = rnorm(20),
                        y2 = rnorm(20),
                        group_var = c(rep("A", 10), rep("B", 10)))
scatter_data <- data.frame(x = rnorm(10), y = rnorm(10))

ts

Here we create a time series starting in 2000Q1 (frequency = 4 means quarterly) with 10 random observations for two variables: x1 and x2.

ts_data <- ts(data.frame(x1 = rnorm(10), x2 = rnorm(10)), frequency = 4, start = c(2000, 1))

Layouts and panels

There are ten supported layouts, with up to 8 panels. Right hand side axes count as separate panels in some layouts. Panels are numbered from left to right, top to bottom.

  1. One-panel "1". This is the default if you do not supply a value for layout. Despite its name this layout has two panels. Panel "1" corresponds to the left axis; panel "2" corresponds to the right axis.
arphitgg(layout = "1")
library(arphit)
agg_draw(arphitgg(layout = "1"), filename = "layout_1.png")
knitr::include_graphics("layout_1.png")
  1. Two-panel vertical "2v". This layout has two panels, divided vertically. Panel "1" is the left panel, panel "2" the right.
arphitgg(layout = "2v")
agg_draw(arphitgg(layout = "2v"), filename = "layout_2v.png")
knitr::include_graphics("layout_2v.png")
  1. Two-panel horizontal "2h". This layout has four panels. Panels "1" and "2" are the left and right axes of the top panel. "3" and "4" for the bottom.
arphitgg(layout = "2h")
agg_draw(arphitgg(layout = "2h"), filename = "layout_2h.png")
knitr::include_graphics("layout_2h.png")
  1. Two-by-two "2b2". This layout is very similar to "2h", except the left and right panels are divided, rather than axes.
arphitgg(layout = "2b2")
agg_draw(arphitgg(layout = "2b2"), filename = "layout_2b2.png")
knitr::include_graphics("layout_2b2.png")
  1. Three panel vertical "3v":
arphitgg(layout = "3v")
agg_draw(arphitgg(layout = "3v"), filename = "layout_3v.png")
knitr::include_graphics("layout_3v.png")
  1. Three panel horizontal "3h" (has left and right axes, like "2h"):
arphitgg(layout = "3h")
agg_draw(arphitgg(layout = "3h"), filename = "layout_3h.png")
knitr::include_graphics("layout_3h.png")
  1. Six panel three-by-two "3b2":
arphitgg(layout = "3b2")
agg_draw(arphitgg(layout = "3b2"), filename = "layout_3b2.png")
knitr::include_graphics("layout_3b2.png")
  1. Four panel horizontal "4h" (has left and right axes like "2h"):
arphitgg(layout = "4h")
agg_draw(arphitgg(layout = "4h"), filename = "layout_4h.png")
knitr::include_graphics("layout_4h.png")
  1. Eight panel four-by-two "4b2":
arphitgg(layout = "4b2")
agg_draw(arphitgg(layout = "4b2"), filename = "layout_4b2.png")
knitr::include_graphics("layout_4b2.png")
  1. One panel horizontal. This layout has only 1 panel - there are not top and bottom y axes.
arphitgg(data.frame(x=1:10), agg_aes(x,x), layout = "1h") + agg_col()
p <- arphitgg(data.frame(x=1:10), agg_aes(x,x), layout = "1h") + agg_col()
agg_draw(p, filename = "layout_1h.png")
knitr::include_graphics("layout_1h.png")

Portrait-size graphs

If you want a larger, portrait size layout, simply pass in portait = TRUE. This works with any of the layouts.

p <- arphitgg(portrait = TRUE)
agg_draw(p, filename = "layout_portrait.png")
knitr::include_graphics("layout_portrait.png")

(Advanced) Custom graph sizes

You can also manually specify the plot size if you want greater control. This size is for the whole graph - i.e. the size of the graph, not the size of a panel. Units are inches (the graphs have been scaled to half original size when included in this document).

p <- arphitgg(plotsize = c(2,10))
agg_draw(p, filename = "plotsize.png")
knitr::include_graphics("plotsize.png")

Aesthetics

An aesthetic is the definition of a layer. It tells arphit how to display the data.

x and y

The x and y variables speak for themselves. They must be variables in your dataset. (x values can be categorical). Aesthetics can also be expressions, rather than single variables - see the section on tidy evaluation below.

p <- arphitgg() + 
  agg_line(data = simple_data, aes = agg_aes(x = date, y = y1))
agg_draw(p, filename = "no-group-aes.png")
knitr::include_graphics("no-group-aes.png")

If your data are a ts, the x aesthetic does not need to specified, it is automatically the dates in the time series.

Inheriting aesthetics

Aesthetics inherit from their parent. That is, if you omit part of an aesthetic in the definition of a layer, it will inherit from the parent (if it exists). If you specify both a parent aesthetic and a layer aesthetic, the layer aesthetic overrides.

In this example, the whole aesthetic is inherited:

p <- arphitgg(data = simple_data, aes = agg_aes(x = date, y = y1)) + 
  agg_line()
agg_draw(p, filename = "inherit-aes-all.png")
knitr::include_graphics("inherit-aes-all.png")

In this example, we specify thex aesthetic in the parent, but specify the y aesthetic in the layer. This is helpful if, for instance, you have many y variables you want to plot that all have the same x variable.

p <- arphitgg(data = simple_data, aes = agg_aes(x = date)) + 
  agg_line(aes = agg_aes(y = y1))
agg_draw(p, filename = "inherit-aes-some.png")
knitr::include_graphics("inherit-aes-some.png")

Groups

An aesthetic can also specify a group variable. This is used when your data is in long form and you have multiple observations on each x observation, corresponding to different variables. For instance, x might be the date column, y the column containing observations of the unemployment rate and group the column containing state identifiers.

p <- arphitgg() +
  agg_line(data = long_data, aes = agg_aes(x = date, y = y1, group = group_var))
agg_draw(p, filename = "group-aes.png")
knitr::include_graphics("group-aes.png")
candle <- data.frame(x=rep(letters[1:10],3),y=1:30)
p <- arphitgg() +
  agg_line(data = candle, aes = agg_aes(x = x, y = y, group = x))
agg_draw(p, filename = "group-by-x.png")
knitr::include_graphics("group-by-x.png")

Facets

An aesthetic can also specify a facet variable. facets work like groups, except that facets are split across panels (and so layers ignore if you give them a panel).

p <- arphitgg() +
  agg_line(data = long_data, aes = agg_aes(x = date, y = y1, facet = group_var))
agg_draw(p, filename = "facet.png")
knitr::include_graphics("facet.png")

Data can have both groups and facets.

facet_data <- data.frame(x = rep(c(1,2),4),
                         y = rnorm(8),
                         age = c(rep("A", 4), rep("B", 4)),
                         sex = rep(c("F","F","M","M"), 2))
p <- arphitgg() +
  agg_line(data = facet_data, aes = agg_aes(x = x, y = y, group = sex, facet = age))
agg_draw(p, filename = "facet-group.png")
knitr::include_graphics("facet-group.png")

Ordering of x values in graphs

By default, graphs are ordered by the value of their x-ticks (that is, either numerically or alphabetically, depending on what your x-ticks are).

You can instead specify a variable to order the graph by using the order part of the aesthetic.

Ordering a bar chart by value:

order_data <- data.frame(x=letters[1:10],
                         y=rnorm(10))
p <- arphitgg(order_data, agg_aes(x=x,y=y,order=y))
agg_draw(p, filename = "aes-order-value.png")
knitr::include_graphics("aes-order-value.png")

If you have groups and want to order by value, you need to specify which group's value you want to use as the order. This will apply that order to every group.

order_data <- data.frame(x=letters[1:10],
                         y=rnorm(10),
                         group = c(rep("A",5),rep("B",5)))
p <- arphitgg(order_data, agg_aes(x=x,y=y,group=group,order=A))
agg_draw(p, filename = "aes-order-value-group.png")
knitr::include_graphics("aes-order-value-group.png")

You can order in descending value using the desc function - see the section on tidy evaluation below. E.g.:

order_data <- data.frame(x=letters[1:10],
                         y=rnorm(10))
p <- arphitgg(order_data, agg_aes(x=x,y=y,order=dplyr::desc(y))) + agg_col()
agg_draw(p, filename = "aes-order-value-desc.png")
knitr::include_graphics("aes-order-value-desc.png")

A third alternative way is to use another variable to define the order. In this example we take data and order it by a variable order that is the reverse of the x variable.

order_data <- data.frame(x = rep(letters[1:10], 2),
            y = rep(1:10, 2),
            group = c(rep("A", 10), rep("B", 10)),
            order = rep(letters[10:1], 2),
            stringsAsFactors = FALSE)
p <- arphitgg(order_data, agg_aes(x=x,y=y,group=group,order=order)) + 
  agg_col(stacked = FALSE)
agg_draw(p, filename = "aes-order.png")
knitr::include_graphics("aes-order.png")

You can use a separate order variable with groups, but the ordering variable must uniquely associate with each x value and this ordering must be consistent across all groups. If not, otherwise the ordering of x values is ambiguous.

(Note: Ordering of bars)

You can also control the order of bars within a layer (i.e. which bar appears closest to the axis) using the argument reorder_bars to agg_col. This is covered in detail under the agg_col section of the section 'Layers' below.

Tidy evaluation and aesthetics

Aesthetics support tidy evaluation. This means that your aesthetic can actually be an expression, which is evaluated in the environment of your data. This means you can undertake transformations of your data within how you define the aesthetic. The most common use for this is to order graphs in descending order:

order_data <- data.frame(x=letters[1:10],
                         y=rnorm(10),
                         group = c(rep("A",5),rep("B",5)))
p <- arphitgg(order_data, agg_aes(x=x,y=y,group=group,order=desc(A)))
#this is created above
knitr::include_graphics("aes-order-value-desc.png")

But you can use any expression you like, in any part of the aesthetic. For instance, we can easily create a quadratic:

p <- arphitgg(data.frame(x=-10:10), agg_aes(x=x,y=x^2))+agg_line()
agg_draw(p, filename = "aes-tidy-quadratic.png")
knitr::include_graphics("aes-tidy-quadratic.png")

Or we could group by a combination of two variables:

two_group_data <- data.frame(x=rep(c(1,2),4),
                             y=rnorm(8),
                             g1=c(rep("a",4),rep("b",4)),
                             g2=rep(c(1,1,2,2),2))

Here g1 and g2 together define a unique group, so we set the group aesthetic to the interaction of both variables:

p <- arphitgg(two_group_data, agg_aes(x=x,y=y,group=paste(g1,g2))) + 
  agg_col(stacked = FALSE) + 
  agg_legend()
agg_draw(p, filename = "aes-tidy-double-group.png")
knitr::include_graphics("aes-tidy-double-group.png")

Layers and graph types

A layer is a series (or group of series) built from the same aesthetic. In arphit, layers must be assigned to a panel. You can have more than one layer per panel.

All layer types have four common arguments, and some layers have extra options to define their look:

  1. Data
  2. Aesthetic
  3. Panel (defaults to "1" if not supplied)
  4. Colour (optional)

NB: Layers will inherit data and aesthetic from their parent if omitted. This is helpful if you want to define multiple layers from the one dataset. (Example below)

You can assign the same layer to multiple panels in one call by specifying a vector of panel names. E.g. panel = c("1","2").

There are three types of basic layers, agg_line, agg_col, and agg_point. These are used nearly identically to produce line, column, and scatter graphs respectively. There are also two types of specialised layers, discussed below.

p <- arphitgg(layout = "2h") + 
  agg_line(data = long_data, aes = agg_aes(x = date, y = y1, group = group_var), panel = "1") + 
  agg_col(data = long_data, aes = agg_aes(x = date, y = y2, group = group_var), panel = "3")
agg_draw(p, filename = "layers.png")
knitr::include_graphics("layers.png")
p <- arphitgg(layout = "1") + 
  agg_point(data = data.frame(x = rnorm(10), y = rnorm(10)), aes = agg_aes(x = x, y = y), panel = "1")
agg_draw(p, filename = "scatter.png")
knitr::include_graphics("scatter.png")

Layers will inherit data and aesthetic (or parts of the aesthetic) if these are left null in the layer specification. This is handy to save you from having to repeat yourself:

p <- arphitgg(long_data, aes = agg_aes(x = date, group = group_var), layout = "2h") + 
  agg_line(aes = agg_aes(y = y1), panel = "1") + 
  agg_col(aes = agg_aes(y = y2), panel = "3")
agg_draw(p, filename = "inherit.png")
knitr::include_graphics("inherit.png")

Line layers

agg_line layers convert data and an aesthetic into line series in the chosen panel (or, panels if you set a facet variable in the aesthetic).

There are 7 options for line layers. What the options do is covered in more detail below.

Column/bar layers

agg_col layers plot data as a vertical column graph. They have 6 options. What the options do is covered in more detail below.

(Advanced) Horizontal bar graphs

You can use the layout option layout = "1h" to create horizontal bar graphs - where the x axis on the left side. This type of graph has only one panel. (NB: You can make any layer type a horizontal graph, but it is most useful for column graphs.) See the section "Layouts and panels" above.

(Advanced) Order of bar layers

Bars are ordered left-to-right (if not stacked) or closest to axis (if stacked) based on the order they are added to the graph. For layers with group aesthetics, the bars within a layer are ordered alphabetically;^[Series without a name (i.e. value of grouping variable equal to NA) appear last.] but later layers always appear after earlier layers:

p <- arphitgg() + 
  agg_col(data = simple_data, aes = agg_aes(x = date, y = y1), stacked = FALSE) + # appears left-most
  agg_col(data = long_data, aes = agg_aes(x = date, y = y2, group = group_var), stacked = FALSE) + # appears to the right the first layer, with the groups in alphabetical order
  agg_legend()
agg_draw(p, filename = "bar-order.png")
knitr::include_graphics("bar-order.png")

You can manually control the order of bars using the argument reorder_bars. All bar series added to a panel up to that point can be reordered within that layer. As such, you should always reorder in the last layer you add to a panel:

p <- arphitgg() + 
  agg_col(data = simple_data, aes = agg_aes(x = date, y = y1), stacked = FALSE) + # appears left-most
  agg_col(data = long_data, aes = agg_aes(x = date, y = y2, group = group_var), stacked = FALSE,
          reorder_bars = c("B","y1", "A")) + # reorder the series so that B appears left-most then y1 (added in a previous layer) and then A
  agg_legend()
agg_draw(p, filename = "bar-reorder.png")
knitr::include_graphics("bar-reorder.png")

You do not have to specify a full order. If you leave out series, these are ordered after those you manually order (in alphabetical order). You will get a warning telling you this (in case it was a mistake).

Point/scatter layers

agg_point layers are just a wrapper around agg_line that set the line to NA, and the point marker (pch) to 19 for solid dots. Naturally, this layer type is best for scatter graphs, as they quicker and easier than constructing your own agg_line layer.

agg_point has only 5 options: Data (data), aesthetic (aes), panel (panel), colour for the markers (colour) and a size for the points (pointsize). As with other layer types, data and aesthetic (including parts of an aesthetic) will be inherited from the parent if omitted.

Specialised layer types

Step layers

agg_step layers are a special type of line layer that 'step' to each point rather than connecting the two with a straight line. What this means is that the line is held constant from the previous observation and then 'steps' up to the next observation. The final observation has only the vertical part of the step.

step_data <- data.frame(x=1:10,y=1:10)
p <- arphitgg(step_data, aes = agg_aes(x = x, y = y)) + 
  agg_step()
agg_draw(p, filename = "step.png")
knitr::include_graphics("step.png")

Otherwise, agg_step layers are identical to line layers. They have same arguments and attributes (such as colour, line type etc).

Waterfall layers

agg_waterfall creates waterfall graphs. These are a specialised bar graph where the bars (except for the last one) step from where the previous one ends. These work largely identically to agg_col layers. The first and last bars (determined by the order aesthetic) are always anchored to zero; but every other colubarmn is anchored to where the previous bar ended. X-ticks can have multiple observations, using groups. In this case, the net of the bar is where the next bar(s) start.

waterfall_data <- data.frame(x = letters[1:6],
                             y = c(1,0.5,-0.2,0.3,-0.5,1.1))
p <- arphitgg(waterfall_data, agg_aes(x,y)) + agg_waterfall()
agg_draw(p, filename = "waterfall.png")
knitr::include_graphics("waterfall.png")

Waterfall layers work with groups. This can be helpful for highlighting positive and negative changes, but can also be used when you have multiple observations per x-tick:

library(dplyr)
waterfall_data <- data.frame(x = letters[1:6],
                             y = c(1,0.5,-0.2,0.3,-0.5,1.1))
p <- arphitgg(waterfall_data,
              agg_aes(x = x,
                      y = y,
                      group = case_when(x == "a" ~ "start",
                                        x == "f" ~ "end",
                                        y > 0 ~ "plus",
                                        y <=0 ~ "minus"))) + 
  agg_waterfall(colour = c("grey","red","blue","black"))
agg_draw(p, filename = "waterfall-plusminus.png")
knitr::include_graphics("waterfall-plusminus.png")
data <- data.frame(x = c('start','a','a','b','b','end'),
                   y = c(1, 0.5, -0.4, 0.2, 0.1, 1.4),
                   group = c(1, 2, 3, 2, 3, 4),
                   order = c(1,2,2,3,3,4))
p <- arphitgg(data) +
    agg_waterfall(agg_aes(x=x,y=y,group=group,order=order))
agg_draw(p, filename = "waterfall-group.png")
knitr::include_graphics("waterfall-group.png")

Series colours and other attributes

Colours

Specifying line, bar or point (depending on layer type) colours for series is done when creating a layer. For instance:

p <- arphitgg() + 
  agg_line(data = simple_data, aes = agg_aes(x = date, y = y1), colour = RBA["Red1"])
agg_draw(p, filename = "simplecolour.png")
knitr::include_graphics("simplecolour.png")

This colour is applied to all series in the layer. This is less helpful when you have a group variable, since they will all show up as the same colour (which is unlikely to be what you want). E.g. this is not helpful:

p <- arphitgg() +
  agg_line(data = long_data,
           aes = agg_aes(x = date, y = y1, group = group_var),
           colour = RBA["Red1"])
agg_draw(p, filename = "group-single-colour.png")
knitr::include_graphics("group-single-colour.png")

To specify for different colours for different series in a grouped layer, you can instead specify a vector of colours:

p <- arphitgg() +
  agg_line(data = long_data,
           aes = agg_aes(x = date, y = y1, group = group_var),
           colour = c(RBA["Red1"], RBA["Blue4"]))
agg_draw(p, filename = "group-multi-colour.png")
knitr::include_graphics("group-multi-colour.png")

(NB: arphit will cycle through the supplied vector colours if there aren't enough in the vector to cover the number of series in the layer.)

To see the full list of availble colours type vignette("rba-colours", package = "arphit").

Alternatively, you can use any colour that R recognises.

If you don't specify colours, arphit cycles through a set of default colours. Should you need to (e.g. for labels) you can access the default colours using the alias RBA["Default1"] etc.

(Advanced) Defining your own default colours

If you want to define your own set of default colours to be used set the option arphit.user_colours with a vector of colours. Putting this into your .Rprofile is sensible.

options(arphit.user_colours = c(RBA["Red1"],RBA["Blue10"],RBA["Olive1"]))

Line markers

pch allows you to add markers to your series. These directly follow the R options. These are specified like colours (setting one will apply it to all series in the layer, a vector will be cycled through).

p <- arphitgg(simple_data) + 
  agg_line(agg_aes(x = date, y = y1), pch = 19)
agg_draw(p, filename = "pch.png")
knitr::include_graphics("pch.png")

Line type

lty allows you to control the line type - e.g. add dashing. These directly follow the R options. These are specified like colours (setting one will apply it to all series in the layer, a vector will be cycled through).

p <- arphitgg(simple_data) + 
  agg_line(agg_aes(x = date, y = y1), lty = 2)
agg_draw(p, filename = "lty.png")
knitr::include_graphics("lty.png")

Line width

lwd controls the width of the line. 1 corresponds to default. 2 to twice default, 0.5 half it, etc. These are specified like colours (setting one will apply it to all series in the layer, a vector will be cycled through).

p <- arphitgg(simple_data) + 
  agg_line(agg_aes(x = date, y = y1), lwd = 3)
agg_draw(p, filename = "lwd.png")
knitr::include_graphics("lwd.png")

Bar outline

barcol lets you set the colour of the bar outline for agg_col layers. By default, this is NA, meaning no outline. These are specified like colours (setting one will apply it to all series in the layer, a vector will be cycled through).

p <- arphitgg(simple_data) + 
  agg_col(agg_aes(x = date, y = y1), barcol = "black")
agg_draw(p, filename = "barcol.png")
knitr::include_graphics("barcol.png")

Point size

pointsize lets change the size of plot markers on agg_line or agg_point layers. By default, this is 1, meaning the default size. These are specified like colours (setting one will apply it to all series in the layer, a vector will be cycled through).

p <- arphitgg(data.frame(x=rnorm(15),y=rnorm(15))) + 
  agg_point(agg_aes(x = x, y = y), pointsize = 2) + 
  agg_point(agg_aes(x = x, y = y))
agg_draw(p, filename = "pointsize.png")
knitr::include_graphics("pointsize.png")

Titles and subtitles

Titles and subtitles are added using agg_title and agg_subtitle respectively. The only required argument is the text for the title/subtitle:

p <- arphitgg() + 
  agg_title("Graph Title Goes Here") + 
  agg_subtitle("Or a subtitle, if you like")
agg_draw(p, filename = "title.png")
knitr::include_graphics("title.png")

arphit will automatically place linebreaks in long titles but may not be smart enough in all cases. You can insert linebreaks yourself as necessary by using "\n".

p <- arphitgg() + 
  agg_title("Here is a very very very long title that arphit will automatically put a break in") +
  agg_subtitle("And a subtitle\nwith a manual break too")
agg_draw(p, filename = "longtitle.png")
knitr::include_graphics("longtitle.png")

Panel titles and subtitles

You can add titles and subtitles to panels in much the same way as titles and subtitles. Allyou do is specify panel as an argument:

p <- arphitgg() + 
  agg_title("Panel title for panel 1", panel = "1") +
  agg_subtitle("And a subtitle", panel = "1")
agg_draw(p, filename = "paneltitles.png")
knitr::include_graphics("paneltitles.png")

You can also apply the same title to multiple panels at once using a vector of panel names panel = c("1","3").

Units

You can specify the units for your graph using the agg_units function. This can be used either with or without a panel specifier. If called without a panel specifier, the units are applied to all panels, otherwise the units are added only to specified panel:

p <- arphitgg() + agg_units("index")
agg_draw(p, filename = "units-all.png")
knitr::include_graphics("units-all.png")
p <- arphitgg() +
  agg_units("index", panel = "1") +
  agg_units("ppt", panel = "2")
agg_draw(p, filename = "units-specific.png")
knitr::include_graphics("units-specific.png")

You can also apply the same units to multiple panels at once using a vector of panel names panel = c("1","3").

x-axis units

You can also add units for the x-axis in much the same way. These are ignored for anything other than scatter graphs.

p <- arphitgg(scatter_data, agg_aes(x=x,y=y)) + 
  agg_point() + agg_xunits("ppt")
agg_draw(p, filename = "x-units.png")
knitr::include_graphics("x-units.png")

You can also apply the same units to multiple panels at once using a vector of panel names panel = c("1","3").

Sources and footnotes

Adding sources and footnotes is done using agg_source and agg_footnote. You can pass in a single text string, or a vector of multiple strings. You can add as many agg_source/agg_footnote as you like:

p <- arphitgg() + 
  agg_source("Source 1") + 
  agg_source(c("Source 2 (as a vector)", "Source 3 (vectors are easy!")) + 
  agg_footnote("This is my first footnoote") + 
  agg_footnote("This is a second footnote")
agg_draw(p, filename = "sources.png")
knitr::include_graphics("sources.png")

Axis limits

Y axis

arphit will automatically guess axes for each panel. However, it is not smart enough to sensibly line up axes across panels (e.g. if you have left and right axes). And stacked bar graphs will confuse it.

Y-limits can be controlled with agg_ylim. This function takes three required arguments: a minimum, a maximum, and the number of steps to include. You can optionally include a panel identifier; if omitted, the limits will be applied to all panels. You can alternatively apply the same limits to a set of panels at once using a vector of panel names panel = c("1","3").

Example 1: Manually setting left and right axes

p <- arphitgg(simple_data) + 
  agg_line(agg_aes(x=date,y=y1),panel="1") + 
  agg_line(agg_aes(x=date,y=y1),panel="2") + 
  agg_ylim(-1,1,5,panel="1") +
  agg_ylim(-4,4,5,panel="2")
agg_draw(p, filename = "ylim-left-right-axes.png")
knitr::include_graphics("ylim-left-right-axes.png")

Example 2: Applying the same y axis to all panels

p <- arphitgg(simple_data) + 
  agg_line(agg_aes(x=date,y=y1),panel="1") + 
  agg_line(agg_aes(x=date,y=y1),panel="2") + 
  agg_ylim(-1,1,5)
agg_draw(p, filename = "ylim-all-axes.png")
knitr::include_graphics("ylim-all-axes.png")

X axis

X-limits are controlled using agg_xlim. This is similar to y-limits, but only a minimum and maximum is required. For time series graphs, you can use part years if desired by adding decimal places (e.g. 2000.5).

As with the y-axis you can specify a panel identifier to apply the limits to a specific panel; if you omit the panel identifier, the limits will be applied to all panels. You can alternatively apply the same limits to a set of panels at once using a vector of panel names panel = c("1","3").

Very fine-grained control of x-ticks is not possible; x-ticks are determined by your x-variables.

p <- arphitgg(simple_data, agg_aes(x=date, y=y1)) + 
  agg_line() + 
  agg_xlim(1998, 2008)
agg_draw(p, filename = "x-axis-lim.png")
knitr::include_graphics("x-axis-lim.png")

You can specify only an upper or lower bound by setting the other the NA. For instance, to start the above graph at 2001 but let the data determine where to end it:

p <- arphitgg(simple_data, agg_aes(x=date, y=y1)) + 
  agg_line() + 
  agg_xlim(2001, NA)
agg_draw(p, filename = "x-axis-lim-single-arg.png")
knitr::include_graphics("x-axis-lim-single-arg.png")

Time series graphs with data that gets close to the right hand axis will automatically add a small margin of spacing to the right hand side. You can stop this by setting a manual x-limit for the right hand side. Vertically divided time series graphs always add a margin.

close_data <- data.frame(date = seq.Date(as.Date("2000-03-01"),by="quarter",length.out=20),
                         y1 = rnorm(10))
p <- arphitgg(close_data, agg_aes(x=date, y=y1)) + 
  agg_line()
agg_draw(p, filename = "x-axis-padding.png")
knitr::include_graphics("x-axis-padding.png")

For layouts with vertical division (e.g. "2v", "2b2" etc), you can drop the the first tick of the right hand panel by setting dropxlabel = TRUE in arphitgg. This prevents the last label of the left hand panel overlapping the first of the right hand panel.

p <- arphitgg(simple_data, agg_aes(x=date, y=y1), layout = "2v", dropxlabel = TRUE) + 
  agg_line(panel = c("1","2"))
agg_draw(p, filename = "drop-x-label.png")
knitr::include_graphics("drop-x-label.png")

By default categorical graphs have all their x ticks displayed. You can change this behaviour (if your x-ticks are overlapping) to only display an automatically determined limited set of x-ticks by setting showallxlabels = FALSE in the call to arphitgg:

foo <- data.frame(x=paste("label",1:9),y=1:9)
p <- arphitgg(foo, agg_aes(x=x,y=y), showallxlabels = FALSE) + agg_col()
agg_draw(p, filename = "showallxlabel.png")
knitr::include_graphics("showallxlabel.png")

Frequency of x axis

For time series graphs, arphit will automatically choose the frequency of the ticks on the x axis. Any graph covering less than a year will use months, less than 3 years quarters and greater than 50 years decades. (Note that vertically divided graphs will swap to decades sooner, due to the compression of the x-axis).

decades_data <- data.frame(date = seq.Date(from=as.Date("1950-06-01"),by="year",length=50),
                                   y1 = rnorm(50))
p <- arphitgg(decades_data, agg_aes(x=date, y=y1)) + 
  agg_line()
agg_draw(p, filename = "decades.png")
knitr::include_graphics("decades.png")

Automatic x-limits respect the frequency. If your axis is in quarters or months, arphit will set the limits to the first and last quarter/month of data:

partial_quarter_data <- data.frame(date = seq.Date(from=as.Date("2000-03-01"),by="quarter",length=9),
                                   y1 = rnorm(9))
p <- arphitgg(partial_quarter_data, agg_aes(x=date, y=y1)) + 
  agg_line()
agg_draw(p, filename = "quarter-partial-year.png")
knitr::include_graphics("quarter-partial-year.png")

If you want override the automatically chosen frequency, you can use agg_xaxisfreq. Valid options are decade, year, quarter and month. You can specify panels too if desired.

partial_quarter_data <- data.frame(date = seq.Date(from=as.Date("2000-03-01"),by="quarter",length=9),
                                   y1 = rnorm(9))
p <- arphitgg(partial_quarter_data, agg_aes(x=date, y=y1)) + 
  agg_line() + 
  agg_xaxisfreq("year")
agg_draw(p, filename = "manual-year.png")
knitr::include_graphics("manual-year.png")

Log axes

You can make either or both of the y and x axes log scales (x only makes sense for scatter graphs.) Use the log_scale option to arphitgg and specify one of "x", "y" or "xy", which behave as you'd expect.

log_scale_data <- data.frame(x = 1:10, y = c(11, 20, 40, 90, 11, 14, 90, 15, 15, 16))
p <- arphitgg(log_scale_data, agg_aes(x = x, y = y), log_scale = "y") + 
  agg_line() + 
  agg_ylim(10, 90, 5)
agg_draw(p, filename = "logscale.png")
knitr::include_graphics("logscale.png")

Shading between series

You can shade the area between series by adding agg_shading.

Shading is drawn in the order you add it; the first shading added is on the bottom and subsequently added shading is drawn on top of this. Series are always drawn on top of shading.

p <- arphitgg(simple_data, agg_aes(x=date)) +
  agg_line(agg_aes(y=y1)) +
  agg_line(agg_aes(y=y2)) +
  agg_shading(from = y1, to = y2, colour = RBA["Blue1"])
agg_draw(p, filename = "shading-single.png")
knitr::include_graphics("shading-single.png")

Multiple shading:

p <- arphitgg(simple_data, agg_aes(x=date)) +
  agg_line(agg_aes(y=y1)) +
  agg_line(agg_aes(y=y2)) +
  agg_line(agg_aes(y=y3)) +
  agg_line(agg_aes(y=y4)) +
  agg_shading(from = y1, to = y2, colour = RBA["Blue1"]) + 
  agg_shading(from = y3, to = y4, colour = "lightgrey")
agg_draw(p, filename = "shading-multiple.png")
knitr::include_graphics("shading-multiple.png")

Plot annotations (labels, arrows and lines)

Adding labels and arrows

You can add series labels, and arrows to aid those labels, using agg_label and agg_arrow arguments.

agg_label takes 6 arguments - some are optional.

p <- arphitgg() +
  agg_label("A label", x = 2002, y = 0.5, colour = RBA["Blue2"], panel = "1")
agg_draw(p, filename = "labels.png")
knitr::include_graphics("labels.png")

Arrows are specified with agg_arrow.

p <- arphitgg() +
  agg_arrow(tail.x = 2000, tail.y = 0, head.x = 2001, head.y = 0.5, colour = RBA["Blue1"], panel = "1")
agg_draw(p, filename = "arrow.png")
knitr::include_graphics("arrow.png")

(Experimental) Automatic labels

arphit has (experimental) functionality to automatically add series labels for you. If enabled, the auto labeller will run on panels with more than one series, and which do not already have text labels. If you manually set text labels for a panel, the auto labeller will skip that panel. By default, it will also add arrows from the label to the series if necessary for line series, but not for bar series. You can stop the autolabeller from adding arrows to line series (or have it add arrows to bars using the arguments arrow_lines and arrow_bars to agg_autolabel).

Series names

The auto labeller will use whatever your series are called in the data. For long data, this will be the value of the group variable. This is identical to how legends are determined. Series that appear in multiple panels are only labelled once. Series that have NA as their name are ignored by the autolabeller.

You can rename series using the function agg_rename_series. See the section on adding legends for more details.

Enabling the auto labeller

Enable the auto labeller by adding agg_autolabel():

p <- arphitgg(long_data, agg_aes(x = date, y = y1, group = group_var)) +
  agg_line() + 
  agg_autolabel()
agg_draw(p, filename = "autolabel.png")
knitr::include_graphics("autolabel.png")

If you put text labels on a panel, that disables the auto labeller for that panel, unless you set ignore_existing_labels = TRUE as an argument to agg_autolabel:

p <- arphitgg(long_data, agg_aes(x = date, y = y1, group = group_var), layout = "2v") +
  agg_line(panel = "1") + 
  agg_line(panel = "2") + 
  agg_label("Manual\nlabel disables\nautolabels", x = 2001, y = 1.5, colour = "black", panel = "2") + 
  agg_autolabel()
agg_draw(p, filename = "autolabel2.png")
knitr::include_graphics("autolabel2.png")

The autolabeller correctly handles left and right hand series:

p <- arphitgg(simple_data, agg_aes(x = date), layout = "1") +
  agg_line(agg_aes(y = y1), panel = "1") + 
  agg_line(agg_aes(y = y2), colour = RBA["Orange5"], panel = "2") + 
  agg_autolabel()
agg_draw(p, filename = "autolabel_rhs.png")
knitr::include_graphics("autolabel_rhs.png")

Adding lines (vertical, horizontal, etc)

Horizontal and vertical lines are added using agg_hline and agg_vline respectively. Horizontal lines are drawn by specifying the y co-ordinate to draw the line at agg_hline(y = 1); vertical lines are similar, but the x variable only. You can also control the colour and line type. These are optional and default to a solid black line. You must also tell arphit which panel to put the line on.

The following example draws a vertical line at 2001 using the default colour and solid line. It also draws a horizontal line at -1 coloured darkred and dashed (lty = 2).

p <- arphitgg() + 
  agg_vline(x = 2001, panel = "1") + 
  agg_hline(y = -1, colour = "darkred", lty = 2, panel = "1")
agg_draw(p, filename = "lines.png")
knitr::include_graphics("lines.png")

If you need more control over the line, you can use agg_abline to specify the coordinates of the line segment instead of using x or y. To do so use x1, x2, y1 and y2. All other options are the same. For example:

p <- arphitgg() + 
  agg_abline(x1 = 2003, y1 = -0.1, x2 = 2005, y2 = 0.5, panel = "1")
agg_draw(p, filename = "specificlines.png")
knitr::include_graphics("specificlines.png")

Entering NA (or omitting the argument) for any of x1, y1, x2, or y2 will set that coordinate to the axis limit (with x1 and y1 going to the left and bottom axes and x2 and y2 to the right and top).

Adding background shading

Background shading can be added using agg_bgshading. This draws a rectangle with bottom left corner at x1, y1 and top right corner at x2,y2. Passing NA for any of the four coordinates will set that coordinate to the axis limit - this is useful for creating shading that stretches across a whole panel. colour and panel are self-explanatory (colour is optional and defaults to light grey).

This example creates horizontal shading across the whole panel between -1 and 3 on the y axis.

p <- arphitgg() + 
  agg_bgshading(x1 = NA, y1 = -0.5, x2 = NA, y2 = 0.5, panel = "1")
agg_draw(p, filename = "bgshading.png")
knitr::include_graphics("bgshading.png")

And this two panel example repeats the above example for panel 1, but puts light green shading between two dates on the bottom panel.

p <- arphitgg(layout = "2h") + 
  agg_bgshading(x1 = NA, y1 = -0.5, x2 = NA, y2 = 0.5, panel = "1") + 
  agg_bgshading(x1 = 2000.5, y1 = NA, x2 = 2001.5, y2 = NA, panel = "3", colour = "lightgreen")
agg_draw(p, filename = "bgshading2.png")
knitr::include_graphics("bgshading2.png")

Adding axis labels

You can add y and x axis labels to plots using agg_yaxislabel and agg_xaxislabel. These take the text for the axis label, plus an optional panel identifier. If omitted, the label is applied to all panels.

p <- arphitgg(layout = "2b2") + 
  agg_yaxislabel("A y axis label") + 
  agg_xaxislabel("An x label")
agg_draw(p, filename = "oneaxislabel.png")
knitr::include_graphics("oneaxislabel.png")
p <- arphitgg(layout = "2b2") + 
  agg_yaxislabel("Foo", panel = "1") + 
  agg_yaxislabel("Bar", panel = "3") + 
  agg_xaxislabel("An x label", panel = "3") + 
  agg_xaxislabel("Another x label", panel = "4")
agg_draw(p, filename = "differentaxislabel.png")
knitr::include_graphics("differentaxislabel.png")

Rotating x ticks

You can rotate x ticks using the srt option in arphitgg. It represents the rotation (in degrees):

p <- arphitgg(simple_data, agg_aes(x=date,y=y1), srt = 45) + agg_line()
agg_draw(p, filename =  "xlabel-rotation.png")
knitr::include_graphics("xlabel-rotation.png")

Joining and missing values

The joined argument inarphitgg controls how your graph behaves with missing values. When joined = TRUE (which is the default) the series will ignore the missing value and connect to the next non-missing value. When joined = FALSE the series will break.

For instance, let's use this series, with the middle observation missing:

joining_data <- ts(data.frame(y = c(1,2,NA,3,4)), start = 2000, frequency = 1)

With joined = TRUE, the series continues straight across the missing value for 2002.

p <- arphitgg(joining_data, agg_aes(y = y), joined = TRUE) +
  agg_line()
agg_draw(p, filename = "joined.png")
knitr::include_graphics("joined.png")

But when we set joined = FALSE, the series does not connect over the missing observation:

p <- arphitgg(joining_data, agg_aes(y = y), joined = FALSE) +
  agg_line()
agg_draw(p, filename = "unjoined.png")
knitr::include_graphics("unjoined.png")

Adding a legend

You can add a legend to your graph by adding agg_legend(). This can also take one optional argument to specify how many columns to have with ncol; arphit will automatically guess if you leave it blank.

p <- arphitgg(long_data, agg_aes(x = date, y = y1, group = group_var)) +
  agg_line() +
  agg_legend()
agg_draw(p, filename = "legend.png")
knitr::include_graphics("legend.png")

arphit will ignore duplicate series in multiple panels (i.e. it will only put in one legend entry).

If a series has NA as it's name, it will not get a legend entry.

On-panel legend

You can also add the legend on the panel, instead of beneath the graph. This is done by specifying a location for the legend. There are two ways. The easiest is to choose one of "bottomright", "bottom", "bottomleft", "left", "topleft", "top", "topright", "right" and "center". Pass this to the optoinal x argument to agg_legend and the legend will be automatically placed in the appropriate location.

p <- arphitgg(long_data, agg_aes(x = date, y = y1, group = group_var)) +
  agg_line() +
  agg_legend(x="topright")
agg_draw(p, filename = "onpanel-legend.png")
knitr::include_graphics("onpanel-legend.png")

Multipanels are ignored for the purposes of on-panel legends - graphs are treated as a whole and panels are ignored. E.g. in a "2b2" graph, "topright" is the top right of the graph, meaning top right in panel "2".

If you want fine-grained control, you can supply a value between 0 and 1 for x and a supply a y coordinate. This will place a legend in a specific place on the graph. (0,0) corresponds to the bottom left corner, (1,1) top right.

p <- arphitgg(long_data, agg_aes(x = date, y = y1, group = group_var)) +
  agg_line() +
  agg_legend(x=0.6,y=0.9)
agg_draw(p, filename = "onpanel-legend-specific-place.png")
knitr::include_graphics("onpanel-legend-specific-place.png")

(Advanced) Renaming series for legends

By default, series names in legends are the name of the y aesthetic (if the aesthetic has no group) or the value of the grouping variable. Often these are variable names and so are not particularly meaningful on a graph. The function agg_rename_series exists to allow you to easily rename series for legends (or for the autolabeller).

This function takes a named list. The values in the list are the current name and the names in the list are what the series are to be renamed to. (This is the same structure as dplyr's rename function.) You can optional restrict the mapping to only a specific panel; if no panel ID is supplied, the mapping will be applied to all panels:

p <- arphitgg(simple_data, agg_aes(x = date, y = y1)) +
  agg_line() +
  agg_rename_series(list("Nicer name" = "y1")) + 
  agg_legend()
agg_draw(p, filename = "rename-series-simple.png")
knitr::include_graphics("rename-series-simple.png")
p <- arphitgg(long_data, agg_aes(x = date, y = y1, group = group_var)) +
  agg_line() +
  agg_rename_series(list("Series A" = "A", "Series B" = "B")) + 
  agg_legend()
agg_draw(p, filename = "rename-series-group.png")
knitr::include_graphics("rename-series-group.png")

As before, you can stop a series from being displayed in a legend by settings its name to NA. This is a little complicated in agg_rename_series because R does not accept NA as a name in a list. Instead use the string "" as the series name to indicate that a series should not be displayed in a legend:

p <- arphitgg(long_data, agg_aes(x = date, y = y1, group = group_var)) +
  agg_line() +
  agg_rename_series(list("Series A" = "A", "<NA>" = "B")) + 
  agg_legend()
agg_draw(p, filename = "rename-series-na.png")
knitr::include_graphics("rename-series-na.png")

Saving to a file

To save your graph to a file instead of displaying it, use agg_draw with the optional filename command. arphit will determine what file to save as, based on the extension of your filename. png, emf, emf+, svg and pdf are supported. xlsx is as well, which exports the data (see below).

p <- arphitgg(simple_data, aes = agg_aes(x = date, y = y1)) +
  agg_line()
agg_draw(p, filename = "my-graph.png")
agg_draw(p, filename = "my-graph.emf")
agg_draw(p, filename = "my-graph.svg")
agg_draw(p, filename = "my-graph.pdf")

You can also use the newer EMFplus format by using extention .emf+. This will still write an emf file, but it is encoded as the newer EMF+ format.

agg_qplot(data, filename = "my_filename.emf+")

You can also export to an XLSX, which will save your graph data in a nicely formatted spreadsheet. This can be convenient for archiving, or talking with other programs.

agg_draw(p, filename = "my-graph.xlsx")

A note about EMF files

EMF files are problematic:

Additionally, only EMF+ files support partial transparency; EMF files do not.

If you can, you should prefer SVG over EMF. SVG is a much better supported vector image format. And much less problematic in how it is rendered by R.

Creating GIF animations

You can create a GIF animation by creating a list of arphitgg objects and using agg_slides. You can specify how many seconds each 'slide' should be shown for, and how many times the animation should loop (0 if infinitely). If you don't supply a filename, it will open it externally.

Here we create a dataframe of four series over the same time period.

gif_data <- data.frame( 
  series = rep(1:4, each = 10), 
  x = rep(seq.Date(from = as.Date("2000-03-01"), by = "quarter", 
                   length.out = 10)), 
  y = rnorm(4*10))

We then split this into a list of four dataframes, one for each series and construct a graph for each series

gif_data_list <- split(gif_data, gif_data$series)
gg_list <- lapply(gif_data_list, function(data) {
  arphitgg(data, agg_aes(x = x, y = y)) + agg_line()
})

To create the GIF animation, just pass gg_list to agg_slides

agg_slides(gg_list, filename = "agg.gif")
knitr::include_graphics("agg.gif")

You do need to be careful. The different scales can cause the graphs to be out of alignment. This could be solved by setting the same agg_ylim for each graph.

The graphs don't need to be the same time series, that was just a convenient example. Here's a gif going through the different possible layouts, but only 3 times.

gg_list <- list(
  arphitgg(layout = "1"), arphitgg(layout = "2v"), arphitgg(layout = "2h"),
  arphitgg(layout = "2b2"), arphitgg(layout = "3v"), arphitgg(layout = "3h"),
  arphitgg(layout = "3b2"), arphitgg(layout = "4h"), arphitgg(layout = "4b2")
)
agg_slides(gg_list, filename = "agg_layouts.gif", loop = 3)
knitr::include_graphics("agg_layouts.gif")


angusmoore/arphit documentation built on Feb. 15, 2021, 9:40 a.m.