1. Key findings (h2)
This section includes the key points of your publication (in an unordered list). The logos used in the banner are intentionally placed in order. NISRA logo on left and department on right, if an Accredited Official Statistics publication then this logo will be in the middle. Logo placement is automated in the code depending on which logos are required.
There are some key accessibility features to highlight here:
- the language element is set to English, which is done in the YAML section of the code
- there is a named accessibility contact at the end of the doc
- you will see from the code that the main sections of the html are enclosed in div elements
It can help automation of reports to include sections of text that contain numerical values calculated by code. These will then update automatically when the data changes. This has been implemented below. For key points with accompanying charts or graphics, a two column structure can be used.
Population change
# create a bullet point in unicode called 'b'
b <- "\U2022"
point_1 <- paste0(
b, " The Northern Ireland population grew from ",
round_half_up(ni_earliest_total, 2), " million in ",
earliest_year, " to ", round_half_up(ni_latest_total, 2),
" million in ", latest_year, ", an increase of ",
round_half_up(ni_earliest_latest_change, 0), " percent."
)
point_2 <- paste0(
b, " Under 25s make up the largest age group in the ",
"population."
)
point_3 <- paste0(
b, " Derry City and Strabane has seen the largest increase ",
"of all the LGDs (Local Government Districts)."
)
change_chart <- here(
"code/demo/demo_data/images/mini_population.png"
)
div(
class = "row",
div(
class = "col-sm-6", style = "margin-top: 10px; font-size:120%;",
point_1, p(), point_2, p(), point_3
),
div(
class = "col-sm-6",
img(
src = change_chart,
alt = "Column chart showing relative increase in population"
)
)
)
2. Introduction (h2)
This is a section with some basic paragraphs of text like you would use for an introduction or commentary. The data used in Demo Report are from the NISRA - 2022 Mid Year Population Estimates for Northern Ireland. It includes LGD2014, single year of age and sex mid-year estimates for years 2001 to 2022. We are using it to outline some accessibility features. If a report uses a number of different data sources, they should be provided along with their respective figures or tables. For example:
Source: NISRA - 2022 Mid Year Population Estimates for Northern Ireland
The source can be specified in the ‘fig.cap’ option of R Markdown blocks to be included underneath figures.
3. Infographics and images (h2)
An image should not replace a clear text description so ensure any information presented in an infographic is presented elsewhere. Add descriptive alt text for anyone using a screen reader - even images with no substantive content should have empty alt text added to indicate that they are decorative.
Do not use images that only contain text - images can contain explanatory text but should never exclusively be of text. Use real text and style appropriately instead.
The reading order of an infographic should always be left-to-right.
For more specific guidance about accessible infographics refer to Dissemination Branch document ‘Creating an accessible infographic’. For more general guidance you can also refer to Government Statistical Service (GSS) guidance on infographics but note that as of the 20th of August 2021 it does not include accessibility requirements.
Important note: If SVG images are used for images these should be marked up properly. It is important that all text is clear on these images and are properly tested for accessibility. If there are still issues with the screen reader reading text within an SVG image, it is recommended to use a PNG image format instead.
Type the title of infographic here (h3)
# file is in image folder
knitr::include_graphics("../demo/demo_data/images/PopInfographic.png")
Source: 2019 Mid-year population estimates
4. Tables (h2)
This section has a number of basic tables. The UK Analysis function guidance recommends that only small demonstration tables should be included in the publication itself. Demonstration tables are small tables which highlight one or two messages clearly and are supported by commentary.
When it comes to accessibility, a good rule of thumb is to use a simple structure. Use a simple table matrix with a single row of column headers describing what is in each column. Other considerations are as follows:
- don’t merge cells
- don’t have blank rows or columns
- every column should have a heading
- make sure all headings and labels are visible
- use consistent rounding
- left align text, or row labels, right align numbers
- use thousand comma separator
- avoid abbreviations or make sure they are explained fully when first used
- use caption for table titles
- put any data labels in the headings such as % or millions or STG rather than in all column cells
- don’t use symbols such as * or superscripts to create notes or explanations
Basic table (h3)
Table 1: Mid ulster had the highest proportion of under 25s (h4)
Select the tab to view population of young or elderly people.
1a Population of young people by LGD
# kable code needs to be created as a string to allow correct rendering of
# source code on second tab
kable(df_mye_latest_year_youthrate,
# left align text, right align numbers
align = ("lrrr"),
# full and descriptive headings
col.names = c(
"Local Government District (LGD)",
"Young people in LGD",
"Total population of LGD",
"Young people as percentage"
),
# use caption to keep text associated with table
caption = paste0("Population of young people by Local Government District in
NI, ", latest_year),
# add thousand separator
format.args = list(big.mark = ","),
label = NA
) %>%
kable_styling()
| Local Government District (LGD) | Young people in LGD | Total population of LGD | Young people as percentage |
|---|---|---|---|
| Antrim and Newtownabbey | 43,399 | 146,148 | 29.7 |
| Ards and North Down | 43,686 | 164,223 | 26.6 |
| Armagh City, Banbridge and Craigavon | 69,994 | 220,271 | 31.8 |
| Belfast | 113,076 | 348,005 | 32.5 |
| Causeway Coast and Glens | 41,392 | 141,316 | 29.3 |
| Derry City and Strabane | 47,552 | 150,836 | 31.5 |
| Fermanagh and Omagh | 36,180 | 116,994 | 30.9 |
| Lisburn and Castlereagh | 43,265 | 149,915 | 28.9 |
| Mid Ulster | 50,409 | 151,001 | 33.4 |
| Mid and East Antrim | 39,019 | 139,200 | 28.0 |
| Newry, Mourne and Down | 58,475 | 182,634 | 32.0 |
Commentary describing the key messages you want readers to take from the table could go here.
1b Population of elderly people by LGD
# kable code needs to be created as a string to allow correct rendering of
# source code on fourth tab
kable(df_mye_latest_year_elderlyrate,
# left align text, right align numbers
align = ("lrrr"),
# full and descriptive headings
col.names = c(
"Local Government District (LGD)",
"Elderly people in LGD",
"Total population of LGD",
"Elderly people as percentage"
),
# use caption to keep text associated with table
caption = paste0("Population of elderly people by Local Government District
in NI, ", latest_year),
# add thousand separator
format.args = list(big.mark = ","),
label = NA
) %>%
kable_styling()
| Local Government District (LGD) | Elderly people in LGD | Total population of LGD | Elderly people as percentage |
|---|---|---|---|
| Antrim and Newtownabbey | 25,751 | 146,148 | 17.6 |
| Ards and North Down | 37,193 | 164,223 | 22.6 |
| Armagh City, Banbridge and Craigavon | 36,034 | 220,271 | 16.4 |
| Belfast | 51,989 | 348,005 | 14.9 |
| Causeway Coast and Glens | 28,091 | 141,316 | 19.9 |
| Derry City and Strabane | 24,759 | 150,836 | 16.4 |
| Fermanagh and Omagh | 22,148 | 116,994 | 18.9 |
| Lisburn and Castlereagh | 26,910 | 149,915 | 18.0 |
| Mid Ulster | 23,137 | 151,001 | 15.3 |
| Mid and East Antrim | 27,964 | 139,200 | 20.1 |
| Newry, Mourne and Down | 31,473 | 182,634 | 17.2 |
Commentary describing the key messages you want readers to take from the table could go here.
Pagination (h3)
Table 2: Northern Ireland population is growing year on year (h4)
datatable(df_mye_year_gender_t,
# DT creates row numbers by default. Suppress to ensure all cols have a header
rownames = FALSE,
# Rename column headers to make them descriptive
colnames = c(
"Mid Year Ending",
"Females",
"Males",
"NI Population Total"
),
caption = paste0("Number of males and females making up the total NI
population from ", earliest_year, -latest_year),
# left align first column and add thousand separator to numbers
options = list(columnDefs = list(list(className = "dt-left", targets = 0)))
) %>%
formatRound(c("Females", "Males", "All persons"),
digits = 0, interval = 3,
mark = ","
)
Descriptive commentary to highlight key point from this table. Females outnumber males year on year and population growth is driven by both sexes
Cross-tabulation (h3)
Table 3: Under 25s were the largest age group in Northern Ireland
cross_tab_data <- df_mye_latest_year_agegrp_gend %>%
pivot_wider(names_from = gender, values_from = pop_total) %>%
mutate(persons = Males + Females)
cross_tab_data["Female_Male_ratio_100"] <-
round_half_up(cross_tab_data$Females / cross_tab_data$Males * 100, 0)
# Adding thousand separator
cross_tab_data$Females <- prettyNum(cross_tab_data$Females, big.mark = ",")
cross_tab_data$Males <- prettyNum(cross_tab_data$Males, big.mark = ",")
cross_tab_data$persons <- prettyNum(cross_tab_data$persons, big.mark = ",")
kable(cross_tab_data,
# left row labels, right align numbers
align = "lrrrr",
# make column headings clear and descriptive
col.names = c(
"Age group",
"Females",
"Males",
"Total persons",
"Number of females to every 100 males"
),
# use caption for descriptive title
caption = paste0("Northern Ireland population by broad age band and sex ", latest_year),
) %>%
kable_styling()
| Age group | Females | Males | Total persons | Number of females to every 100 males |
|---|---|---|---|---|
| 0-24 | 285,014 | 301,433 | 586,447 | 95 |
| 25-44 | 252,835 | 241,141 | 493,976 | 105 |
| 45-64 | 252,234 | 242,437 | 494,671 | 104 |
| 65plus | 180,513 | 154,936 | 335,449 | 117 |
If we group the population into broad age bands we can compare the proportion of males to females. Males outnumber females in the under 25 age group only. As age increases, the ratio of females to males increases.
Table with colour scales
Table 4: Belfast saw greatest increase in population from 2021 to 2022
# function to add thousand separator
mycomma <- function(digits = 0) {
require(formattable)
formatter("span", x ~ comma(x, digits = digits))
}
# up and down arrows added to column four
# colour tiles added to column five. Colour selected is a lighter shade of
# nisra_blue (which failed accessibility check). Seems that colour specified in
# code is the mid point of the tiles generated so needs to be pale to ensure
# contrast for higher levels is sufficient.
t4 <- formattable(df_t4_html,
align = c("lrrrr"),
list(
area(col = 2:3) ~ mycomma(digits = 0), # apply mycomma fn
area(col = 5) ~ color_tile("transparent", "#7ca6da"),
`Change` = formatter("span",
style = ~ style(
color = ifelse(
`Change` > 0, "black", "#e60000"
)
),
~ icontext(ifelse(
`Change` > 0, "arrow-up",
"arrow-down"
), format(`Change`, big.mark = ","))
)
)
)
t4
| LGD | 2022 population | 2021 population | Change | Change (%) |
|---|---|---|---|---|
| Antrim and Newtownabbey | 146,148 | 145,852 | 296 | 0.2 |
| Ards and North Down | 164,223 | 163,827 | 396 | 0.2 |
| Armagh City, Banbridge and Craigavon | 220,271 | 219,127 | 1,144 | 0.5 |
| Belfast | 348,005 | 344,992 | 3,013 | 0.9 |
| Causeway Coast and Glens | 141,316 | 141,664 | -348 | -0.2 |
| Derry City and Strabane | 150,836 | 150,834 | 2 | 0.0 |
| Fermanagh and Omagh | 116,994 | 116,926 | 68 | 0.1 |
| Lisburn and Castlereagh | 149,915 | 149,272 | 643 | 0.4 |
| Mid Ulster | 151,001 | 150,598 | 403 | 0.3 |
| Mid and East Antrim | 139,200 | 139,127 | 73 | 0.1 |
| Newry, Mourne and Down | 182,634 | 182,345 | 289 | 0.2 |
Ensure sufficient contrast between background colours and the text when using colour scales.
5. Charts (h2)
This section includes a line chart with a single line, a line chart with multiple lines, a bar chart, a column chart, a pie chart, tree maps and a donut chart.
Considerations when creating charts:
Accessibility
- Do not rely on colour alone to convey information; include data labels and be mindful of legends
- Ensure colour contrast ratios between adjacent chart elements and against background is min 3:1. There is an accessible colour palette developed by Dissemination Branch available on the Dissemination Tab of the NISRA Teams channel
- ONS recommend that you link to the raw data in csv or xls format or provide a way for users to request it
- Chart titles should be descriptive. A main title and statistical subtitle should be used (e.g. main title ‘Figure 1: The sex pay gap fell to 8.6% among full-time employees in 2018’) and statistical subtitle should include statistical measure, geographic coverage and time period (e.g. ‘Sex pay gap for median gross hourly earnings (excluding overtime), UK, April 1997 to 2019’)
- Charts should include a line of alt text (to include chart type, type of data used and summary of main trend); all detail should be in main text
- All text on a chart should be presented horizontally (including axis labels)
- Axis labels should be displayed in full (i.e. not abbreviated)
- Where abbreviations are included they should be in full, or explained in footnotes
- Try to avoid a legend (especially if they rely on colour alone to convey meaning), but if legend is needed place above the chart
- Where possible, charts should be created in HTML (i.e. interactive), and where not possible, in SVG image format (this exemplar contains examples of both)
- Main message(s) of charts should be clearly explained in text above or below the chart ( i.e. provide a clear text alternative)
- Avoid using dual axis charts
- Consider punctuation on labels of interactive charts and how a screen reader will vocalise them
- Consider how charts will resize for different display sizes e.g. mobile, laptop or desktop; a message has been added for mobile users to suggest rotating phone to landscape for viewing charts
- If using Plotly package to create charts users must keep plotly logo and icons switched off. This is to avoid multiple links going to same destination (poor accessibility) and the icons create visual clutter. Instructions on how to do this are provided in the code.
For further information, please refer to the UK Government Analysis Function (UKAF) guidance on best practice for designing charts.
Single line chart (h3)
This section includes a static and reactive version of a line chart.
The line has to meet colour contrast standards for adjacent colours (3:1). In this case it applies to the line against the background.
The value labels have to meet the colour contrast requirements for normal sized text which is 4.5:1. Here, the labels are placed at the ends of the line to make them easier to read and to avoid any problems with overlap if the chart is resized when viewed on different devices or browsers.
To add the broken axis symbol in a ‘plot_ly’ chart pipe the function “fn_break_axis” with “linecolor” matching the colour given in the “y-axis” attributes in the layout section. This function is a NISRA created function that can be found in the functions folder. This function is for use only with a ‘plot_ly’ chart.
To add the broken axis symbol to a ‘ggplot’ chart, it must be added as an annotation to give the illusion of a broken axis as the ‘ggplot’ package does not provide a built-in axis-break feature.
The code below shows examples of how a broken axis symbol can be added to both ‘plot_ly’ and ‘ggplot’ charts.
Include descriptive text before or after the chart.
Figure 1: Mid year population estimates continue to increase
Northern Ireland mid year population estimate (total) between 2001 and 2022
Figure 1 tabs
Figure 1 plotly
year1_lab <- list(
x = ~ mid_year_ending[1],
y = ~ ni_pop_total[1], # sets position of label
xanchor = "right",
yanchor = "middle", # alignment of label
text = ~ paste0(
earliest_year, ": \n",
round_half_up(ni_pop_total[1] / 1e6, 2), "m"
),
# punctuated and formatted label text
showarrow = FALSE, # turn off otherwise get line between label and chart
font = list(size = 14, color = nisra_blue)
)
year2_lab <- list(
x = ~ tail(mid_year_ending, n = 1), # position at last value of x variable
y = ~ tail(ni_pop_total, n = 1), # position at last value of y variable
xanchor = "left",
yanchor = "middle", # alignment
# punctuated and formatted label text
text = ~ paste0(
latest_year, ": \n",
round_half_up(tail(ni_pop_total, 1) / 1e6, 2), "m"
),
showarrow = FALSE,
font = list(size = 14, color = nisra_blue)
)
# create annotations
# annotation on vertical line
note_1 <- list(
x = 0.41, y = 1, # position of annotation
text = "2009",
showarrow = FALSE, xref = "paper", yref = "paper",
xanchor = "left", align = "left",
font = list(size = 14, color = nisra_navy, family = "Arial black")
)
# use annotation rather than y axis title variable for horizontal text
yaxistitle <- list(
x = 0.02, y = 1.06,
text = paste0("Population (Millions)"),
showarrow = FALSE,
xref = "paper", yref = "paper",
xanchor = "center", yanchor = "centre",
xshift = 0, yshift = 0,
font = list(size = 14, color = "black")
)
# Create the caption - Note the non-zero axis
note_2 <- list(
x = 0.75, y = -0.13, # position of annotation
text = "Note the non-zero axis",
showarrow = FALSE, xref = "paper", yref = "paper",
xanchor = "left", align = "left",
font = list(size = 14, color = nisra_navy)
)
# aesthetic definitions for vertical line used in fig1
vline <- function(x = 0, color = nisra_navy) {
list(
type = "line",
y0 = 0,
y1 = 1,
yref = "paper",
x0 = x,
x1 = x,
line = list(color = color, dash = "dot")
)
}
# create line chart (type = scatter and mode = line)
plot_ly(df_annual_pop_tot,
x = ~mid_year_ending,
y = ~ni_pop_total,
name = "Northern Ireland population",
line = list(color = nisra_blue),
type = "scatter",
mode = "line",
hoverinfo = "text",
# formatting hover text to millions(m) to 2dp
text = ~ paste0(
mid_year_ending, ": ",
format(round_half_up(ni_pop_total / 1e6, 2), nsmall = 2), "m"
)
) %>%
layout(
showlegend = FALSE,
font = list(family = "Arial", size = 14),
xaxis = list(
title = "Year",
showline = TRUE,
linecolor = "#000000",
showgrid = FALSE,
showticklabels = TRUE,
range = c(1999, 2024),
ticks = "outside",
tickwidth = 2
),
yaxis = list(
title = "",
showline = TRUE,
linecolor = "#000000",
showgrid = FALSE
),
annotations = list(
year1_lab,
year2_lab,
note_1,
yaxistitle,
note_2
)
) %>%
# To add the broken axis symbol pipe the function "fn_break_axis" with
# "linecolor" matching the colour given above. This function is a NISRA
# created function that can be found in the functions folder.
fn_break_axis(
linecolor = "#000000",
ref_line = vline(2009)
) %>%
# modebar is series of icons and plotly logo linked to plotly site. Turned off
# throughout to avoid multiple links going to same destination (poor
# accessibility) and icons can create visual clutter.
config(displayModeBar = FALSE)
Figure 1 plotly zero axis
year1_lab <- list(
x = ~ mid_year_ending[1],
y = ~ ni_pop_total[1], # sets position of label
xanchor = "right",
yanchor = "middle", # alignment of label
text = ~ paste0(
earliest_year, ": \n",
round_half_up(ni_pop_total[1] / 1e6, 2), "m"
),
# punctuated and formatted label text
showarrow = FALSE, # turn off otherwise get line between label and chart
font = list(size = 14, color = nisra_blue)
)
year2_lab <- list(
x = ~ tail(mid_year_ending, n = 1), # position at last value of x variable
y = ~ tail(ni_pop_total, n = 1), # position at last value of y variable
xanchor = "left",
yanchor = "middle", # alignment
# punctuated and formatted label text
text = ~ paste0(
latest_year, ": \n",
round_half_up(tail(ni_pop_total, 1) / 1e6, 2), "m"
),
showarrow = FALSE,
font = list(size = 14, color = nisra_blue)
)
# create annotations
# annotation on vertical line
note_1 <- list(
x = 0.41, y = 1, # position of annotation
text = "2009",
showarrow = FALSE, xref = "paper", yref = "paper",
xanchor = "left", align = "left",
font = list(size = 14, color = nisra_navy, family = "Arial black")
)
# use annotation rather than y axis title variable for horizontal text
yaxistitle <- list(
x = 0.02, y = 1.06, text = paste0("Population (Millions)"),
showarrow = FALSE, xref = "paper", yref = "paper",
xanchor = "center", yanchor = "centre", xshift = 0, yshift = 0,
font = list(size = 14, color = "black")
)
# aesthetic definitions for vertical line used in fig1
vline <- function(x = 0, color = nisra_navy) {
list(
type = "line",
y0 = 0,
y1 = 1,
yref = "paper",
x0 = x,
x1 = x,
line = list(color = color, dash = "dot")
)
}
# create line chart (type = scatter and mode = line)
plot_ly(df_annual_pop_tot,
x = ~mid_year_ending,
y = ~ni_pop_total,
name = "Northern Ireland population",
line = list(color = nisra_blue),
type = "scatter",
mode = "line",
hoverinfo = "text",
# formatting hover text to millions(m) to 2dp
text = ~ paste0(
mid_year_ending, ": ",
format(round_half_up(ni_pop_total / 1e6, 2), nsmall = 2), "m"
)
) %>%
layout(
showlegend = FALSE,
font = list(family = "Arial", size = 14),
xaxis = list(
title = "Year",
showline = TRUE,
linecolor = "#000000",
showgrid = FALSE,
showticklabels = TRUE,
range = c(1999, 2024),
ticks = "outside",
tickwidth = 2
),
yaxis = list(
title = "",
showline = TRUE,
range = c(0, 2100000),
linecolor = "#000000",
showgrid = FALSE
),
annotations = list(
year1_lab,
year2_lab,
note_1,
yaxistitle
)
) %>%
layout(shapes = list(vline(2009))) %>%
# modebar is series of icons and plotly logo linked to plotly site. Turned off
# throughout to avoid multiple links going to same destination (poor
# accessibility) and icons can create visual clutter.
config(displayModeBar = FALSE)
Figure 1 static
ggline(df_annual_pop_tot,
x = "mid_year_ending",
y = "ni_pop_total",
plot_type = "l",
color = nisra_blue,
linetype = "solid",
size = 1,
caption = "Note the non-zero axis",
xlim = c(2000, 2026),
xlab = "Mid year ending",
ylab = "Population"
) +
font("ylab", angle = 0, vjust = 1.02) +
scale_y_continuous(
limits = c(1650000, 2000000),
labels = scales::label_number(suffix = "m", scale = 1e-6, big.mark = ",")
) +
theme(text = element_text(family = "Arial")) +
theme(
axis.title = element_text(size = 11),
axis.text = element_text(size = 10),
# give a bit of room at the left for the slashes if needed
plot.margin = margin(5.5, 20, 5.5, 20)
) +
geom_text(
data = df_annual_pop_tot %>% dplyr::filter(mid_year_ending == latest_year),
aes(
label = paste0(latest_year, ": \n", format(ni_pop_total,
big.mark = ","
)),
x = mid_year_ending + 1.5, y = ni_pop_total
)
) +
geom_text(
data = df_annual_pop_tot %>% dplyr::filter(
mid_year_ending == earliest_year
),
aes(
label = paste0(earliest_year, ": ", format(ni_pop_total, big.mark = ",")),
x = mid_year_ending + 2.5,
y = ni_pop_total - 7000
)
) +
geom_vline(xintercept = 2009, linetype = "dashed", color = nisra_blue) +
annotate("text",
x = 2009.5, y = 1880000, hjust = 0,
label = paste(strwrap("2009: Growth rate starts to slow", width = 18),
collapse = "\n"
)
) +
# --- Add a “fake” axis-break mark (two slashes) near the left axis ---
coord_cartesian(clip = "off") +
annotate("text",
x = min(df_annual_pop_tot$mid_year_ending),
y = 1.67e6,
label = "//",
hjust = 2.55, # nudges further left
vjust = 0.5, size = 5
)
End tabs
Further information on the chart download buttons can be found in section 7. Download data of the demo report.
Multiple lines chart (h3)
This section includes a line chart with more than one series which are not overlapping.
The navy and mid-blues meet the 3:1 contrast and the text for both of these colours meets the 4.5:1 contrast for text against the background. It is difficult to ensure sufficient contrast for more than 2 lines especially when they overlap or cross because the order in which they appear will change.
A static chart is used here so it views well on mobile as well as desktop. Annotations easily get crowded and overlap when resized and the chart resizes the x axis which alters how the trend is perceived.
Include descriptive text before or after the chart.
Figure 2: Females outnumber males in total population
Northern Ireland mid year population estimate (sex) 2001 to 2022
# Create separate dataframe for selected datapoints from main dataframe
df_mye_selected_years_gender <- df_mye_year_gender %>%
filter(mid_year_ending %in% c(2001, 2012, 2022)) %>%
# format numbers
mutate(label = paste0(
mid_year_ending, ": ",
round_half_up(mye_pop / 1e6, 2), "m"
))
# code to create interpolated points with blank labels along the line of the
# line plot to cause repulsion of labels from line and avoid overlap - the
# final df, df_fig2_labs_inter is used in the geom_text_repel statement
df_mye_interp_male <- (filter(df_mye_year_gender, gender == "Males"))
df_mye_interp_male <- as.data.frame(do.call(
cbind, approx(df_mye_interp_male$mid_year_ending,
df_mye_interp_male$mye_pop,
n = 30
)
))
df_mye_interp_female <- (filter(df_mye_year_gender, gender == "Females"))
df_mye_interp_female <- as.data.frame(do.call(
cbind, approx(df_mye_interp_female$mid_year_ending,
df_mye_interp_female$mye_pop,
n = 30
)
))
df_mye_interp_male$label <- ""
df_mye_interp_male$Gender <- "Males"
df_mye_interp_male <- df_mye_interp_male %>% select(x, Gender, y, label)
colnames(df_mye_interp_male) <- colnames(df_mye_selected_years_gender)
df_mye_lab_select_male <- (filter(
df_mye_selected_years_gender,
gender == "Males"
))
df_mye_interp_male <- rbind(df_mye_lab_select_male, df_mye_interp_male)
df_mye_interp_female$label <- ""
df_mye_interp_female$Gender <- "Females"
df_mye_interp_female <- df_mye_interp_female %>% select(x, Gender, y, label)
colnames(df_mye_interp_female) <- colnames(df_mye_selected_years_gender)
df_mye_lab_select_female <- (filter(
df_mye_selected_years_gender,
gender == "Females"
))
df_mye_interp_female <- rbind(df_mye_lab_select_female, df_mye_interp_female)
df_fig2_labs_inter <- rbind(df_mye_interp_male, df_mye_interp_female)
df_fig2_labs_inter <- arrange(df_fig2_labs_inter, mid_year_ending, gender)
fig2 <- ggplot(
df_mye_year_gender,
aes(
x = mid_year_ending,
y = mye_pop,
color = gender
)
) +
geom_line(linewidth = 1) +
# ACC: Change to line colours with sufficient contrast
scale_color_manual(values = c(nisra_blue, nisra_navy)) +
# Using NITotals_lab_select_multiple from above to pick the years that will
# have "points", specifying the size of the dots
geom_point(
data = df_mye_selected_years_gender,
aes(x = mid_year_ending, y = mye_pop), size = 3
) +
labs(
x = "Year",
y = "Population",
caption = "Note the non-zero axis"
) +
theme_bw() +
theme( # removes grid lines from chart
panel.grid = element_blank(),
# removes chart border top and right
panel.border = element_blank(),
axis.line.x = element_line(colour = "#000000"),
axis.line.y = element_line(colour = "#000000"),
# ACC: make y axis title horizontal and position it further from y axis line
axis.title.y = element_text(
angle = 0, vjust = 1, hjust = 0,
margin = margin(t = 0, r = 5, b = 0, l = 0)
),
# align title and subtitle to left
plot.title.position = "plot",
# align caption to left
plot.caption = element_text(hjust = 0),
# ACC: change all fonts to 12
text = element_text(size = 12, family = "Arial"),
# bolds title and subtitle + adds margin below subtitle and plot
plot.title = element_text(face = "bold"),
plot.subtitle = element_text(face = "bold", margin = margin(0, 0, 15, 0)),
# ACC: Legend to top and tidy up
legend.position = "top",
legend.title = element_blank(),
legend.text = element_text(size = 12)
) +
geom_text_repel( # ACC: show value label for specified years
data = df_fig2_labs_inter,
aes(
x = mid_year_ending,
y = mye_pop,
label = label
), force = 10
) +
# ACC: make x axis labels easier to read by removing every other year
scale_x_continuous(breaks = seq(earliest_year, latest_year, by = 2)) +
# add comma to y labels
scale_y_continuous(labels = label_number(scale = 1e0, big.mark = ",")) +
# indicate non zero axis
labs(tag = "//") +
theme(plot.tag.position = c(0.203, 0.2))
fig2
Multiple single line charts (h3)
This section changes from multiple lines on one chart to include a small chart for each grouping specified (i.e. LGD2014 as below).
In situations where you have a larger number of lines, consider using small multiples to either highlight trends against noisy backgrounds or present trends side by side. You could highlight a single line in colour and have the other lines in grey or just show individual lines as demonstrated below.
This is a static chart as it is more mobile friendly.
Include descriptive text before or after the chart.
Figure 3: In 2022, Belfast Local Government District (LGD) has more younger people than other areas
Northern Ireland mid year population estimate by LGD in 2022
ggplot(
df_mye_latest_5yr_age_lgd,
aes(
x = age_group_5,
y = population_latest
)
) +
geom_line(linewidth = 1, group = 1, color = nisra_blue) +
# ACC: Specify line colour with sufficient contrast
facet_wrap(vars(str_wrap(lgd2014name, 30)), ncol = 3) +
# ACC: Use clear and descriptive labels
labs(
x = "Age",
y = "Population"
) +
theme_bw() +
theme( # removes grid lines from chart
panel.grid = element_blank(),
# panel margin
panel.spacing.x = unit(0.7, "lines"),
axis.line.x = element_line(colour = "#000000"),
axis.line.y = element_line(colour = "#000000"),
# ACC: make y axis title horizontal and position it further from y axis line
axis.title.y = element_text(
angle = 1, vjust = 1, hjust = 0,
margin = margin(t = 0, r = 5, b = 0, l = 0)
),
# ACC: change all fonts to 12
text = element_text(size = 12, family = "Arial"),
# facet only legend hide bg
legend.title = element_blank(),
legend.position = "none",
strip.background = element_blank()
) +
scale_x_discrete(breaks = c("0-4", "45-49", "90-94"), labels = c(
"0-4",
"45-49",
"90+"
)) +
# ACC: add comma to y labels
scale_y_continuous(labels = label_number(scale = 1e0, big.mark = ","))
Bar chart (a-z) (h3)
This section includes a bar chart sorted in alphabetical Local Government District (LGD) order. A bar chart was chosen so that the LGD names could be displayed in full horizontally.
Include descriptive text before or after the chart.
Figure 4: Young people by LGD
Data from 2022 mid-year estimates (MYEs) showing the percentage of each LGD population that is under 25
# create amended df for chart. Reorder factors for plotting (need lgd names in
# reverse alphabetical order as coord flip reverses order).
# Remove unnecessary columns
fig4_data <- df_mye_latest_year_youthrate %>%
mutate(lgd2014name = fct_reorder(lgd2014name, desc(lgd2014name))) %>%
select(-under25_pop, -lgd_pop_total)
ggplot(fig4_data, aes(x = lgd2014name, y = youthrate)) +
geom_bar(fill = nisra_blue, stat = "identity") +
geom_text(aes(label = youthrate),
hjust = 1.5,
colour = "white", fontface = "bold"
) +
# adds value labels to the bars, sets text to colour and weight that meet
# contrast standards.
theme_bw() +
# axis labels
labs(
x = paste(strwrap("LGD", width = 0.2 * getOption("width")),
collapse = "\n"
),
y = "Percentage of population under 25"
) +
# makes y axis title horizontal
theme(
axis.title.y = element_text(
angle = 0,
vjust = 1,
hjust = 1
),
# removes grids from chart
panel.grid = element_blank(),
# added vertical grid at major ticks
panel.grid.major.x = element_line(color = "#BEBEBE", linewidth = 0.1),
# removes chart border top and right
panel.border = element_blank(),
# xaxis line black
axis.line.x = element_line(colour = "#000000"),
# yaxis line black
axis.line.y = element_line(colour = "#000000"),
) +
coord_flip()
The chart shows that LGD with the greatest percentage of population less than 25 is Mid Ulster. Ards and North down is the LGD with the smallest percentage.
Interactive bar chart (h3)
This bar chart is created using the same data but using plotly to create an interactive html chart. Title is used for statistical title and h4 for descriptive title.
When resized for mobile the bars shorten but the labels remain a more readable size. Keep the x axis title short so it won’t get cut off on a smaller display.
Include descriptive text before or after the chart highlighting the key message.
Figure 5: Proportion of under 25s was higher in 2001.
Percentage of population aged under 25 by LGD, 2001 MYEs
Dashed line represents Northern Ireland mean.
# create annotation for y axis title so it can be horizontal.
yaxistitle <- list(
x = -0.3, y = 1.06, # position of y axis title
text = "LGD", # title
showarrow = FALSE, xref = "paper", yref = "paper",
xanchor = "center", yanchor = "centre", # alignment
xshift = 0, yshift = 0,
font = list(family = "Arial Black", size = 14, color = "black")
)
fig5 <- plot_ly(df_mye_earliest_youthrate,
x = ~earliest_youthrate,
y = ~lgd2014name,
type = "bar",
orientation = "h", # horizontal bars. Default is vertical
hoverinfo = "text",
# adds value labels to the bars and sets hover text
text = ~earliest_youthrate, textposition = "auto",
# sets colour of bars to navy
marker = list(color = nisra_navy)
) %>%
layout( # add annotation
font = list(family = "Arial", size = 14),
annotations = list(yaxistitle),
shapes = list(vline(~ mean(earliest_youthrate), color = nisra_blue)),
xaxis = list(title = "Under 25s (%)"),
yaxis = list(
title = "",
ticks = "outside",
tickcolor = "#ffffff",
ticklen = 10,
categoryorder = "category descending"
)
)
# displays lgds in alphabetic order
# modebar is series of icons and plotly logo linked to plotly site. Turned off
# throughout to avoid multiple links going to same destination (poor
# accessibility) and icons can create visual clutter.
config(fig5, displayModeBar = FALSE) # hide the modebar
The chart shows that LGD with the greatest percentage of population under 25 in 2001 was Derry City and Strabane. Ards and North down was the LGD with the smallest percentage.
Column chart (h3)
This section includes two versions of a column chart (one static, one interactive) and two stacked bar charts. To ensure colour is not the only means of conveying information, contrast is used to differentiate between male and female columns and data labels have been added.
In this instance, the plotly grouped bar chart resizes well because the x axis labels are short and don’t overlap when resized. The data labels will change to vertical on mobile which is not ideal (should be horizontal) but the hover labels will be horizontal and legible.
The stacked bars have been created in plotly. They resize well for small screens because the age group labels are short and don’t overlap. The horizontal stacked bar also resizes well because there are only two groups. If there were many more a static chart would likely be more appropriate.
Include descriptive text before or after the chart.
Figure 6: Females outnumber males in all age groups except the under 25s
Northern Ireland population in 2022 by age group
Figure 6 tabs
ggplot static
fig6 <- ggplot(
df_mye_latest_year_agegrp_gend,
aes(
x = age_group,
y = pop_total,
fill = gender
)
) +
geom_col(position = position_dodge()) +
# colour bars that meet contrast for adjacent colours
scale_fill_manual(values = c(nisra_navy, nisra_blue)) +
# add value labels, and add thousand separator
geom_text(aes(label = prettyNum(pop_total, big.mark = ",")),
position = position_dodge(width = 1), vjust = 1.1,
colour = "white", size = 3.2
) +
theme_bw() +
# axis labels
labs(
x = "Age group",
y = "Population",
fill = "Gender"
) +
theme(
axis.title.y = element_text( # makes y axis title horizontal
angle = 0,
vjust = 1.05,
hjust = 1
),
# removes grids from chart
panel.grid = element_blank(),
# added horizontal grid at major ticks
panel.grid.major.y = element_line(color = "#BEBEBE", linewidth = 0.1),
# removes chart border top and right
panel.border = element_blank(),
# xaxis line black
axis.line.x = element_line(colour = "#000000"),
# yaxis line black
axis.line.y = element_line(colour = "#000000"),
legend.position = "top"
) +
# add thousand separator to y axis labels
scale_y_continuous(labels = label_number(scale = 1e0, big.mark = ","))
fig6
plotly
df_fig6 <- pivot_wider(df_mye_latest_year_agegrp_gend,
names_from = gender,
values_from = pop_total
)
df_fig6 <- as.data.frame(df_fig6)
df_fig6 <- gather(df_fig6, key = "variable", value = "value", 2:3)
nisra_blue <- "#3878c5"
nisra_navy <- "#00205b"
colormap <- setNames(
object = c("#00205b", "#3878c5"),
nm = unique(df_fig6$variable)
)
df_fig6 <- df_fig6 %>%
mutate(variable = factor(variable, levels = c("Females", "Males"))) %>%
plotly::plot_ly(
x = ~age_group, y = ~value, color = ~variable, colors = colormap,
type = "bar",
text = format(df_fig6$value, big.mark = ","),
textposition = "inside",
textangle = "horizontal", # for accessibility
insidetextfont = list(size = 12), # to fit
hovertemplate = "%{text}", # hover text = text
textfont = list(color = "white")
) %>%
layout( # makes it a clustered bar
barmode = "group",
font = list(family = "Arial", size = 14),
xaxis = list(title = "Age group"),
yaxis = list(
title = "",
tickformat = ",d",
showgrid = FALSE
),
legend = list(
orientation = "h",
xanchor = "center",
x = 0.5,
y = 1.1,
# so order is same as legend
traceorder = "normal"
),
annotations = list(list(
text = "Population",
x = -0.03,
xref = "paper",
xanchor = "center",
y = 1.02,
yref = "paper",
yanchor = "bottom",
showarrow = FALSE,
font = list(size = 16)
))
) %>%
# modebar is series of icons and plotly logo linked to plotly site. Turned off
# throughout to avoid multiple links going to same destination (poor
# accessibility) and icons can create visual clutter.
config(displayModeBar = FALSE)
df_fig6
Stacked bar
df_fig6 <- pivot_wider(df_mye_latest_year_agegrp_gend,
names_from = gender,
values_from = pop_total
)
df_fig6 <- as.data.frame(df_fig6)
df_fig6 <- gather(df_fig6, key = "variable", value = "value", 2:3)
fig6c <- df_fig6 %>%
mutate(variable = factor(variable, levels = c("Females", "Males"))) %>%
plotly::plot_ly(
x = ~age_group, y = ~value, color = ~variable, colors = colormap,
type = "bar",
text = format(df_fig6$value, big.mark = ","),
textposition = "inside",
textangle = "horizontal", # for accessibility
insidetextfont = list(size = 12), # to fit
hovertemplate = "%{text}", # hover text = text
textfont = list(color = "white")
) %>%
layout(
# stacked rather than clustered/grouped
barmode = "stack",
font = list(family = "Arial"),
xaxis = list(title = "Age group"),
yaxis = list(
title = "",
tickformat = ",d",
showgrid = FALSE
),
legend = list(
orientation = "h",
xanchor = "center",
x = 0.5,
y = 1.1,
font = list(family = "Arial", size = 14),
traceorder = "normal"
),
font = list(family = "Arial", size = 14),
annotations = list(list(
text = "Population",
x = -0.03,
xref = "paper",
xanchor = "center",
y = 1.02,
yref = "paper",
yanchor = "bottom",
showarrow = FALSE,
font = list(size = 16)
))
)
# modebar is series of icons and plotly logo linked to plotly site. Turned off
# throughout to avoid multiple links going to same destination (poor
# accessibility) and icons can create visual clutter.
config(fig6c, displayModeBar = FALSE)
Stacked horizontal bar (%)
# for stacked horizontal bar set orientation to "h" (horizontal)
# and barmode to stack
fig6d <- plot_ly(df_latest_year_agegrp_gend_pct,
x = ~Females,
y = ~age_group,
marker = list(color = nisra_navy),
type = "bar",
orientation = "h",
name = "Females",
text = ~ paste0(format(round_half_up(Females, 1), nsmall = 1), "%"),
# use excel rounding function, display to 1dp
insidetextanchor = "middle",
hoverinfo = "y+text"
) %>%
add_trace(
x = ~Males,
marker = list(color = nisra_blue),
name = "Males",
text = ~ paste0(format(round_half_up(Males, 1), nsmall = 1), "%")
) %>%
layout(
barmode = "stack",
font = list(family = "Arial", size = 14),
yaxis = list(
title = "",
ticks = "outside",
tickcolor = "#ffffff",
ticklen = 5,
# default was 65+ at top
autorange = "reversed"
),
xaxis = list(title = "Percentage (%)"),
legend = list(
orientation = "h",
xanchor = "center",
x = 0.42,
y = 1.1,
traceorder = "normal"
),
annotations = list(list(
text = "Age Group",
x = 0,
xref = "paper",
xanchor = "center",
y = 1.02,
yref = "paper",
yanchor = "bottom",
showarrow = FALSE,
font = list(size = 16)
))
)
# ensure legend is same order as stacks
# modebar is series of icons and plotly logo linked to plotly site. Turned off
# throughout to avoid multiple links going to same destination (poor
# accessibility) and icons can create visual clutter.
config(fig6d, displayModeBar = FALSE)
End tabs
Column chart 5 categories
This chart has been included to show how the 5 colour palette can be used for categorical data. The order in which the colours are used is important as are the colours of the data labels on each and should be preserved. These can be used for fewer categories as long as the order is retained.
Figure 7: Over 85s remain the smallest age group
Northern Ireland population in 2022 in 5 age bands
yaxistitle <- list(
text = "Population",
x = 0.01, y = 1.05,
xref = "paper", yref = "paper",
xanchor = "right", yanchor = "top",
showarrow = FALSE,
font = list(size = 14)
)
fig7 <- plot_ly(df_mye_latest_5_agegroups,
x = ~age_grp_5,
y = ~agegroup_total,
type = "bar",
marker = list(color = c(
nisra_blue, nisra_navy,
nisra_col3_green, nisra_col4_purple, nisra_col5_lilac
)),
# order of colours is important: need medium and
# dark colours beside one another
text = ~ format(agegroup_total, big.mark = ","),
textfont = list(color = c(
"white", "white",
"black", "white", "black"
)),
# need to specify black or white labels. plotly default
# is grey and fails contrast required
textangle = "horizontal",
hovertemplate = ~ paste0(
age_group, ": ", format(agegroup_total, big.mark = ","),
"<extra></extra>"
),
hoverlabel = list(font = list(color = c(
"white", "white",
"black", "white", "black"
)))
) %>%
layout(
yaxis = list(
title = "",
tickformat = ",d"
), # adds thousand separator
xaxis = list(title = "Age Group"),
annotations = list(yaxistitle)
)
# modebar is series of icons and plotly logo linked to plotly site. Turned off
# throughout to avoid multiple links going to same destination (poor
# accessibility) and icons can create visual clutter.
config(fig7, displayModeBar = FALSE)
Pie chart (h3)
Ensure that colour is not the only means of conveying meaning. Here value labels are added for alternative source of information.
These pie charts have been placed in two columns so that when resized for mobile they will wrap one under the other and remain legible.
Please note, pie charts should only have 5 or fewer categories.
Include descriptive text before or after the chart.
Figure 8: Higher percentage of females than males in the over 65 age group in NI
Percentage of Northern Ireland population aged 65 plus by sex, 2022
fig8a <- plot_ly(df_mye_latest_over_under_65,
labels = ~age_65split,
values = ~Females,
type = "pie",
# create better punctuated labels for screen readers,
# default value failed accessibility audit
text = ~ paste0(
age_65split, " \n (",
round_half_up(Females / sum(Females) * 100, 1), "%)"
),
# increase label size
insidetextfont = list(size = 16),
insidetextorientation = "horizontal",
textinfo = "text",
hoverinfo = "text",
# hover font colour for contrast
hoverlabel = list(font = list(color = c(
"black",
"white"
))),
marker = list(
colors = c(nisra_col3_green, nisra_navy)
),
textfont = list(color = c("black", "white")),
showlegend = FALSE
) %>%
# modebar is series of icons and plotly logo linked to plotly site. Turned off
# throughout to avoid multiple links going to same destination (poor
# accessibility) and icons can create visual clutter.
config(displayModeBar = FALSE) %>%
layout(
annotations = list(
x = 0.5, y = 1.08, xanchor = "center",
text = ~ paste("<b> Females </b>"),
showarrow = FALSE,
font = list(family = "Arial", size = 16)
),
font = list(family = "Arial", size = 14)
)
fig8b <- plot_ly(df_mye_latest_over_under_65,
labels = ~age_65split,
values = ~Males,
type = "pie",
text = ~ paste0(
age_65split, " \n (",
round_half_up(Males / sum(Males) * 100, 1), "%)"
),
textinfo = "text",
hoverinfo = "text",
# increase label size
insidetextfont = list(size = 16),
insidetextorientation = "horizontal",
marker = list(
colors = c(nisra_col3_green, nisra_navy)
),
# plotly default is grey which is insufficient contrast
textfont = list(color = c(
"black",
"white"
)),
showlegend = FALSE
) %>%
# modebar is series of icons and plotly logo linked to plotly site. Turned off
# throughout to avoid multiple links going to same destination (poor
# accessibility) and icons can create visual clutter.
config(displayModeBar = FALSE) %>%
layout(
annotations = list(
x = 0.5, y = 1.08,
xanchor = "center",
text = ~ paste("<b> Males </b>"),
showarrow = FALSE,
font = list(family = "Arial", size = 16)
),
font = list(family = "Arial", size = 14)
)
# creates a two column div placing a chart in each. Usual plotly method of
# creating a row with 2 columns did not resize well. This way, the pies display
# one below the other when viewed on mobile.
div(
class = "row",
div(
class = "col-sm-6", style = "margin-top: 10px;",
fig8a
),
div(class = "col-sm-6", fig8b)
)
Treemap - basic (h3)
Tile size and value labels are sources of meaning in addition to colour in the treemap. Again, text must meet 4.5:1 contrast and adjacent colours 3:1.
Borders are used around the tiles to ensure the contrast requirements are met. All of these colours can be used against a white background for chart elements but because the tiles are adjacent to multiple colours, not all the contrasts are OK (green against NISRA mid-blue for example). In this instance, a white border is used around the tiles.
Include descriptive text before or after the chart.
Figure 9: Females aged 0-24 make up the largest age group in NI.
Female population of Northern Ireland by age group, 2022
fig9 <- plot_ly(df_fig9,
type = "treemap",
labels = ~age_grp_5,
parents = ~gender,
values = ~pop_total,
# punctuated labels so that readers do not rely solely on colour
# or shape to understand the chart and screen readers vocalise ok
text = ~ paste0(
"Age ", age_grp_5, ":",
"\n", format(pop_total, big.mark = ",")
),
textinfo = "text",
hoverinfo = "text",
hoverlabel = list(font = list(color = c(
"white", "white",
"black", "white", "black"
))),
branchvalues = "total",
# set tile colours, border and label colours to meet accessibility standards
marker = list(
colors = c(
nisra_blue, nisra_navy,
nisra_col3_green, nisra_col4_purple, nisra_col5_lilac
),
line = list(color = "black", width = 1)
),
textfont = list(family = "Arial", size = 16, color = c(
"white", "white",
"black", "white",
"black"
))
)
# modebar is series of icons and plotly logo linked to plotly site. Turned off
# throughout to avoid multiple links going to same destination (poor
# accessibility) and icons can create visual clutter.
config(fig9, displayModeBar = FALSE)
Treemap - nested (3 levels) (h3)
To demonstrate a more complex tree map with three levels of nesting and multiple tiles, a tree map (Figure 3) from the Economic and Labour Market Statistics report Structure and Performance of the Northern Ireland Economy 2018 and 2019 is shown below. These colours have not been checked for accessibility.
Figure 10: Split of Northern Ireland GVA by industry, 2019
Agriculture accounted for the largest share of GVA
To view the sub-industries in more detail by industry, click on the industry header at the top of each box. To reset the chart, click on the industry header again to get back to the original view.
2019
tmap_textcolours[1] <- "black"
fig10 <- plot_ly(
type = "treemap",
labels = ~tmap_labels_9,
parents = ~tmap_parents_9,
values = ~tmap_values_9,
textinfo = "label",
text = ~ paste0(tmap_labels_9, "\n", round_half_up(tmap_values_9_lab, 1), "%"),
hoverinfo = "text",
# ⬇️ put per-tile hover colours HERE (trace-level)
hoverlabel = list(font = list(color = tmap_textcolours)),
marker = list(colors = c(
"white", nisra_green_decoration, nisra_navy, nisra_col9_pink,
nisra_col3_green, nisra_col4_purple, nisra_col5_lilac,
nisra_col6_olive, nisra_col8_slate, nisra_blue,
nista_col10_burgandy
)),
textfont = list(color = tmap_textcolours)
) %>%
layout(
# leave layout.hoverlabel without color (size/bg ok if you want)
hoverlabel = list(font = list(size = 20)),
font = list(family = "Arial", size = 14),
margin = list(l = 0, r = 0, b = 12, t = 0)
) %>%
config(displayModeBar = FALSE)
fig10
2018
fig10prev <- plot_ly(
type = "treemap",
labels = ~tmap_labels_9prev,
parents = ~tmap_parents_9prev,
values = ~tmap_values_9prev,
textinfo = "label",
text = ~ paste0(
tmap_labels_9prev,
"\n", round_half_up(tmap_values_9prev_lab, 1), "%"
),
hoverinfo = "text",
# ⬇️ put per-tile hover colours HERE (trace-level)
hoverlabel = list(font = list(color = tmap_textcolours)),
marker = list(colors = c(
"white", nisra_green_decoration, nisra_navy, nisra_col9_pink,
nisra_col3_green, nisra_col4_purple, nisra_col5_lilac,
nisra_col6_olive, nisra_col8_slate, nisra_blue,
nista_col10_burgandy
)),
textfont = list(
color = tmap_textcolours
)
) %>%
layout(
hoverlabel = list(
font = list(size = 20)),
font = list(family = "Arial", size = 14),
margin = list(
l = 0,
r = 0,
b = 12,
t = 0
)
) %>%
# modebar is series of icons and plotly logo linked to plotly site. Turned off
# throughout to avoid multiple links going to same destination (poor
# accessibility) and icons can create visual clutter.
config(displayModeBar = FALSE)
fig10prev
Donut chart (h3)
This donut chart has 4 sections. Please note, donut charts should only have 5 or fewer categories. It’s important that these colours appear in order to retain required contrast and the correct colour is used for the labels. The plotly default label colour is grey or white so these are set manually to ensure sufficient contrast. The default grey is too pale against the green.
Keep labels short and concise when using plotly for donut so that labels remain visible on mobile.
Figure 11: Under 25s largest age group in Northern Ireland
Northern Ireland population by age group 2022
fig11 <- plot_ly(df_mye_latest_year_agegroup,
type = "pie",
labels = ~age_group,
values = ~agegroup_total,
# default orders segments by size
sort = FALSE,
# accompanies sort argument
direction = "clockwise",
# turns pie into donut
hole = 0.5,
# create labels with age group and percentage values in brackets
text = ~ paste0(
age_group, ": \n (",
round_half_up(agegroup_total / sum(agegroup_total) * 100, 1), "%)"
),
hoverinfo = "text",
textinfo = "text",
# keeps labels horizontal
insidetextorientation = "horizontal",
# specify colours in correct order.
marker = list(
colors = c(
nisra_blue, nisra_navy, nisra_col3_green, nisra_col4_purple
),
# border required to ensure contrast between nisra blue and lilac
line = list(color = "black", width = 1)
),
# specify label colours to meet contrast standards
textfont = list(
family = "Arial",
color = c("white", "white", "black", "white"),
size = 14
)
) %>%
layout(
# legend removed for accessibility (relies on colour to be able to
# understand it. Labels added to segments instead)
showlegend = FALSE,
font = list(family = "Arial", size = 12)
)
# modebar is series of icons and plotly logo linked to plotly site. Turned off
# throughout to avoid multiple links going to same destination (poor
# accessibility) and icons can create visual clutter.
# modebar is series of icons and plotly logo linked to plotly site. Turned off
# throughout to avoid multiple links going to same destination (poor
# accessibility) and icons can create visual clutter.
config(fig11, displayModeBar = FALSE)
Population pyramid (h3)
This population pyramid shows populations by age for two sexes, in two years a decade apart, with the most recent represented by the shaded area and the comparison year represented by the lines. The colours of both the shaded areas and the lines have been chosen to ensure sufficient contrast, and the text manually set to white to ensure visibility. A unified hovermode has been applied to show all data for the relevant age in the hover label at once.
Figure 12: The population of Northern Ireland is aging
Norhern Ireland population by age and sex (2012 and 2022)
plot_ly(fig_12_data,
y = ~Age,
orientation = "h",
type = "bar",
showlegend = FALSE,
hoverinfo = "none"
) %>%
add_trace(
x = as.formula(paste0("~`Males ", latest_year, "`")),
name = paste("Males", latest_year),
marker = list(color = nisra_navy),
hoverinfo = "text+y",
hovertext = paste0(
"Males ", latest_year, ": ",
prettyNum(fig_12_data[[paste("Males", latest_year)]],
big.mark = ","
)
)
) %>%
add_trace(
x = as.formula(paste0("~`Females ", latest_year, "`")),
name = paste("Females", latest_year),
marker = list(color = nisra_col3_green),
hoverinfo = "text+y",
hovertext = paste0(
"Females ", latest_year, ": ",
prettyNum(
abs(fig_12_data[[paste(
"Females",
latest_year
)]]),
big.mark = ","
)
)
) %>%
add_trace(
x = as.formula(paste0("~`Males ", latest_year - 10, "`")),
type = "scatter",
mode = "lines",
name = paste("Males", latest_year - 10),
line = list(
color = "#00b0f0",
width = 4
),
showlegend = TRUE,
hoverinfo = "text+y",
hovertext = paste0(
"Males", latest_year - 10, ": ",
prettyNum(
fig_12_data[[paste(
"Males",
latest_year - 10
)]],
big.mark = ","
)
)
) %>%
add_trace(
x = as.formula(paste0("~`Females ", latest_year - 10, "`")),
type = "scatter",
mode = "lines",
name = paste("Females", latest_year - 10),
line = list(
color = "#2c523b",
width = 4
),
showlegend = TRUE,
hoverinfo = "text+y",
hovertext = paste0(
"Females",
latest_year - 10, ": ",
prettyNum(
abs(fig_12_data[[paste(
"Females",
latest_year - 10
)]]),
big.mark = ","
)
)
) %>%
layout(
barmode = "overlay",
bargap = 0,
font = list(family = "Arial", size = 14),
xaxis = list(
title = "Persons (Thousands)",
tickformat = ",",
tickmode = "array",
tickvals = seq(-15000, 15000, by = 5000),
ticktext = as.character(abs(seq(-15, 15, by = 5))),
range = c(-15000, 15000),
showgrid = FALSE,
zeroline = FALSE, # Remove the internal vertical zero line
showline = TRUE, # Draw the solid x-axis line
linecolor = "black",
linewidth = 1,
ticks = "outside", # Tick marks on the axis
ticklen = 8,
tickwidth = 1,
tickcolor = "black",
mirror = FALSE, # Axis line only on the bottom
anchor = "y", # Tie axis to y-axis (removes gap)
fixedrange = TRUE,
domain = c(0, 1), # Ensures the plot spans full width
constrain = "domain" # Keeps data flush to axes (no extra padding)
),
yaxis = list(
title = "",
categoryorder = "category ascending",
tickvals = seq(0, 90, by = 10),
ticktext = c(as.character(seq(0, 80, by = 10)), "90+"),
showgrid = FALSE,
zeroline = FALSE, # Avoid extra horizontal line
showline = TRUE, # Draw solid y-axis line
linecolor = "black",
linewidth = 1,
ticks = "outside",
ticklen = 6,
tickwidth = 1,
tickcolor = "black",
range = c(-0.5, 90.5)
),
legend = list(
x = 1,
y = 1,
xanchor = "right"
),
annotations = list(
list(
text = paste0("<b>Females\n", latest_year, "</b>"),
x = -5000,
xref = "x",
xanchor = "center",
y = 30,
yref = "y",
yanchor = "middle",
showarrow = FALSE,
font = list(color = "#fff", size = 16)
),
list(
text = paste0("<b>Males\n", latest_year, "</b>"),
x = 5000,
xref = "x",
xanchor = "center",
y = 30,
yref = "y",
yanchor = "middle",
showarrow = FALSE,
font = list(color = "#fff", size = 16)
)
),
hovermode = "y unified"
) %>%
# modebar is series of icons and plotly logo linked to plotly site. Turned off
# throughout to avoid multiple links going to same destination (poor
# accessibility) and icons can create visual clutter.
config(displayModeBar = FALSE)
f_make_tables(fig_12_xl,
title = paste0(
"Figure 12: Population by age and sex (",
latest_year - 10, " and ", latest_year, ")"
),
data_dir = here("code/demo/demo_outputs/figdata")
)
Flow chart (h3)
This flow chart shows components of change to the population in Northern Ireland from 2021 to 2022. The chart has been constructed directly in the Markdown document, using shapes that are defined in the CSS document.
Black text has been used against light colours with a darker border line, as using light backgrounds with dark text has been shown to reduce eyestrain. If the colours are changed, it is important to ensure that contrast continues to meet accessibility requirements.
Figure 13: Natural change is the main driver of population growth
Components of population change in Northern Ireland (2021 and 2022)
cat(sprintf('
::::::::: div-row
::: {.navy-box style="font-weight: bold"}
%s\\
Population\\
(%s)
:::
::: arrow
:::
::: green-circle
Natural\\
Change\\
%s
:::
::: blue-circle
Net\\
Migration\\
%s
:::
::: green-circle
Other\\
Changes\\
%s
:::
::: arrow
:::
::: {.navy-box style="font-weight: bold"}
%s\\
Population\\
(%s)
:::
:::::::::
',
prev_year, pop_ni_last_rounded,
natural_change_sign,
net_migration_sign,
other_changes_sign,
latest_year, pop_ni_current_rounded))
Natural
Change
+3,800
Net
Migration
+2,300
Other
Changes
-100
Filled multiple line chart (h3)
This chart shows population change in Northern Ireland over the course of five years by five broad age bands. Labels are placed at the start and end of each time series to avoid visual clutter.
Figure 14: Over 65s see largest population growth
Northern Ireland population change by age group (2018 to 2022)
fig_14_plot <- plot_ly(
data = fig_14_data,
x = ~index,
y = ~pct,
fill = "tozeroy",
type = "scatter",
mode = "none",
color = ~age_grp_5,
fillcolor = nisra_blue,
hoverinfo = "text",
text = ~ paste(mid_year_ending,
age_grp_5, paste0(round_half_up(pct, 1), "%"),
sep = "\n"
)
) %>%
layout(
font = list(family = "Arial", size = 12),
title = "",
xaxis = list(
title = "",
showticklabels = FALSE,
showgrid = FALSE
),
yaxis = list(
title = "",
range = c(0, 35),
showgrid = FALSE, # No vertical gridlines
zeroline = TRUE, # Keep the main x-axis line
showline = TRUE, # Ensure axis line is drawn
linecolor = "black", # Axis line color
linewidth = 1
),
showlegend = FALSE,
margin = list(b = 100),
hovermode = "x unified"
)
fig_14_data$age_grp_5 <- as.factor(fig_14_data$age_grp_5)
age_groups <- c("Under 24", "25 to 44", "45 to 64", "65 to 84", "85 and over")
x_positions <- seq(1 / (length(age_groups) * 2),
(length(age_groups) * 2 - 1) / (length(age_groups) * 2),
length.out = length(age_groups)
)
annotations <- lapply(seq_along(age_groups), function(i) {
list(
text = age_groups[i],
x = x_positions[i],
xref = "paper",
xanchor = "center",
y = -0.1,
yref = "paper",
yanchor = "top",
showarrow = FALSE
)
})
annotations_left <- list()
annotations_right <- list()
for (i in seq_len(nrow(fig_14_data))) {
if (fig_14_data$index[i] %% 5 == 1) {
annotations_left[[i]] <- list(
x = fig_14_data$index[i],
y = 0,
text = fig_14_data$label[i],
xanchor = "left",
yanchor = "top",
xref = "x",
yref = "paper",
showarrow = FALSE
)
} else if (fig_14_data$index[i] %% 5 == 0) {
annotations_right[[i]] <- list(
x = fig_14_data$index[i],
y = 0,
text = fig_14_data$label[i],
xanchor = "right",
yanchor = "top",
xref = "x",
yref = "paper",
showarrow = FALSE
)
}
}
fig_14_plot <- fig_14_plot %>%
layout(annotations = c(annotations, annotations_left, annotations_right)) %>%
# modebar is series of icons and plotly logo linked to plotly site. Turned off
# throughout to avoid multiple links going to same destination (poor
# accessibility) and icons can create visual clutter.
config(displayModeBar = FALSE)
for (i in seq_len(nrow(fig_14_data))) {
if ((fig_14_data$mid_year_ending[i]) == year_minus_four) {
fig_14_plot <- fig_14_plot %>%
add_annotations(
text = paste0(sprintf("%0.1f", fig_14_data$pct[i]), "%"),
x = fig_14_data$index[i],
y = fig_14_data$pct[i] + 1.4,
xanchor = "left",
yanchor = "bottom",
showarrow = FALSE
)
}
if ((fig_14_data$mid_year_ending[i]) == latest_year) {
fig_14_plot <- fig_14_plot %>%
add_annotations(
text = paste0(sprintf("%0.1f", fig_14_data$pct[i]), "%"),
x = fig_14_data$index[i],
y = fig_14_data$pct[i] + 1.4,
xanchor = "right",
yanchor = "bottom",
showarrow = FALSE
)
}
}
fig_14_plot
f_make_tables(fig_14_data_xl,
title = paste0(
"Figure 14: Northern Ireland population change by age group (",
latest_year - 4, " to ", latest_year, ")"
),
data_dir = here("code/demo/demo_outputs/figdata")
)
Diverging stacked bar
This chart has been included to show how to display a dataset with positive and negative change.
Figure 15: Hawaii had the largest positive population change
Population change in selected US States in 2022
plot_ly(fig_15_data_filtered,
x = ~`Net Migration & Other Changes`,
y = ~`Local Government District`,
type = "bar",
orientation = "h",
marker = list(color = nisra_col3_green),
name = "Net Migration and Other Changes",
hoverinfo = "text+x",
hovertext = ~paste("Net Migration:", `Net Migration & Other Changes`)) %>%
add_trace(x = ~`Natural Change (births minus deaths)`,
y = ~`Local Government District`,
type = "bar",
orientation = "h",
marker = list(color = nisra_navy),
name = "Natural Change (births minus deaths)",
hovertext = ~paste("Natural Change:", `Natural Change (births minus deaths)`)) %>%
add_trace(x = ~`Total Percentage Change`,
y = ~`Local Government District`,
type = "scatter",
mode = "markers",
marker = list(color = nisra_blue,
size = 9,
symbol = "diamond",
line = list(color = "#fff", width = 2)),
name = "Total Percentage Change",
hovertext = ~paste("Total Change:", `Total Percentage Change`)) %>%
layout(
font = list(family = "Arial", size = 14),
barmode = "relative",
xaxis = list(
title = "Percentage change",
range = c(-50, 50),
tickmode = "array", # manually define ticks
tickvals = c(-50, -25, 0, 25, 50), # exact tick positions
ticktext = c("-50%", "-25%", "0%", "25%", "50%"), # custom labels (optional)
automargin = TRUE,
tickfont = list(size = 10)
),
yaxis = list(title = "", automargin = TRUE),
legend = list(orientation = "h", y = 1.35, xanchor = "center"),
hovermode = "y unified",
margin = list(l = 10, r = 10, t = 10, b = 60)
) %>%
config(displayModeBar = FALSE, responsive = TRUE)
f_make_tables(fig_15_data_filtered,
title = paste0(
"Figure 15: Population change in selected US States in 2022"),
data_dir = here("code/demo/demo_outputs/figdata")
)
Other chart types (h3)
There are many other potential charts, maps and data visualisations that can be coded in R and included in html reports. More information and examples can be explored in the following links:
Plotly R Open Source Graphing Library
Plotly R Library Statistical Charts
The R Graph Gallery - Interactive Charts
Data visualization with ggplot2
6. Maps (h2)
This section includes a static map and an interactive map. If you create a map in another package and import as an image, ensure it meets accessibility requirements for an infographic.
Static map (h3)
This section includes a map generated in R. General principles to consider are:
- ensure contrast between text labels and background colour is at least 4.5:1
- ensure contrast between adjacent colours is at least 3:1, if they don’t use borders that do
- verify using online tools like WebAIM contrast checker
- ensure colour is not the only way of conveying meaning
- use clear and descriptive labels
Here the data labels are displayed on the map, alt text is included and the shapefile has been simplified to reduce the file size.
We have used three colours. More than three colours increases the difficulty of creating sufficient contrast.
Ensure the data underlying the maps is accessible to users who cannot perceive images. In this case, the data is in a table in a previous section. You could also make it available as a download.
Include descriptive text before or after the map.
Map 1: Proportion of people aged under 25 in Northern Ireland by LGD
df_map_data$xmod <- c(0.8, 0, 0, 0.5, 0, 1.1, 0.5, 0.5, 0, 1, -1)
df_map_data$ymod <- c(-0.5, 0, 0.2, 0.3, 0, 0, 1.4, -0.55, 0.3, 0, -1)
map1_static_map <- tm_shape(df_map_data,
# Default is km
unit = "imperial"
) +
tm_polygons( # Colours the map sections based on these values
col = "lgd_young_perc",
# Legend title
title = "Percentage of under 25s",
# Number of different colours to use
n = 3,
# Quantiles gives even sized groupings
style = "quantile",
# Colour palette. Execute the command tmaptools::palette_explorer() in R
# console to see range of options
palette = "Blues",
# Add transparency to polygons improving contrast with text
alpha = 0.5,
legend.show = FALSE,
border.col = "black"
) +
tm_text( # add labels to polygons, change text colour to black and move
# labels to fit within shapes
"map_label",
size = 0.8,
col = "#000000",
auto.placement = FALSE,
xmod = "xmod",
ymod = "ymod"
) +
tm_add_legend("fill",
fill = RColorBrewer::brewer.pal(3, "Blues"),
border.col = "#454A58",
labels = c("26.6 to 29.5", "29.6 to 31.5", "31.6 to 33.5"),
title = "Percentage of under 25s"
) +
tm_add_legend( # add manual legend as a key
"symbol",
fill = "#00205b",
title = "Key",
labels = c(
"AN = Antrim and Newtownabbey",
"AND = Ards and North Dow",
"B = Belfast"
)
) +
tm_format( # setting format to worldwide creates a wider rectangle shape that
# fits width of page
"World_wide"
) +
tm_layout(legend.position = c("left", "top"))
# Plotting map:
tmap_mode("plot") # Set to "view" for interactive map or "plot" for static
map1_static_map
Interactive maps (h3)
This section shows the same map produced as an interactive plot. The figures are displayed on the map, council names show on hover and the council name and figures display on click. The shapefile has been simplified to reduce file size and not slow page load speed.
Ensure the data underlying the maps is accessible to users who cannot perceive images. In this case, the data is in a table in a previous section. You could also make it available as a download.
The default rendering tabs through the LGDs but the focus area is not visible for keyboard users. This is an accessibility fail. Additional code has been added to remove the map from the tab order and to add alt text to the LGDs for screen reader users. See sections of code in the final code chunk (download buttons) which creates alt text and in the script section at the very end of the code to create an array of alt texts for the map and remove tabs from the LGDs.
Include descriptive text before or after the map.
Map 2: Interactive shapefile map with hover text
# Reduce the size of the shapefile using the simplify command in rmaptools.
#### interactive map ####
# df_map_data$xmod <- c(3, 1, 0, 1.5, 0, 1.5, 0, 0, 0, 1, 1)
# df_map_data$ymod <- c(0, 3, 0, 0, 0, 0, 1, 0, 0, 0, -3)
df_map_data$xmod <- c(0, -1.5, 0, -1.1, 0, 0, 0, -1, 0, 0, -1)
df_map_data$ymod <- c(0, 1, 0, 0, 0, 0, 1, 0, 0, 0, -1)
map2_interactive_map <- tm_shape(
df_map_data %>%
select(lgd2014name, lgd_young_perc, map_label_value_only, ymod, xmod),
name = "Show data",
# Default is km
unit = "imperial"
) +
tm_basemap( # Adds background map.
"Esri.WorldGrayCanvas"
) +
tm_polygons( # Colours the map sections based on these values
col = "lgd_young_perc",
# Number of different colours to use
n = 3,
# Quantiles gives even sized groupings
style = "quantile",
# Colour palette
palette = "Blues",
# Add transparency to polygons improving contrast with text
alpha = 0.5,
border.alpha = 1,
legend.show = FALSE,
popup.vars = c("Percentage of under 25s: " = "lgd_young_perc")
) +
tm_add_legend("fill",
fill = RColorBrewer::brewer.pal(3, "Blues"),
border.col = "#454A58",
labels = c("26.6 to 29.5", "29.6 to 31.5", "31.6 to 33.5"),
title = "Percentage of under 25s"
) +
tm_view( # Re-positioning legend
view.legend.position = c("left", "top"),
# Re-positioning layer controls
control.position = c("left", "bottom"),
leaflet.options = c(
zoomControl = FALSE,
# Removes zoom and drag options
dragging = FALSE,
keyboard = FALSE,
boxZoom = FALSE,
doubleClickZoom = FALSE,
scrollWheelZoom = FALSE,
tap = FALSE,
touchZoom = FALSE,
zoom = 8,
minZoom = 8,
maxZoom = 8,
attributionControl = FALSE
)
) +
tm_text( # Label polygons, increase font size, set colour to black (better
# contrast) and adjust positioning so they are contained as much as
# possible within the polygons
"map_label_value_only",
size = 1.2,
col = "#000000",
auto.placement = FALSE,
xmod = "xmod",
ymod = "ymod"
) +
tm_scale_bar(width = 250) +
tmap_mode( # Set to "view" for interactive map or "plot" for static
"view"
)
map2_interactive_map
# please also refer to the "alt text for maps" chunk in the source code of this
# section for additional configurations
Map 3: Interactive point map with zoom and hover text
Map 3 shows another example of an interactive map that plots specific points instead of using a shapefile. This map uses a data-set containing information on the location of benefits offices (JBO) and the number of available vacancies.
The location points are displayed on the map and JBO names as well as available vacancies show on hover or click. This interactive map also includes zoom functionality and a view reset button. Points on the map can be resized according to the data or also grouped together.
The data underlying the map is available to view and download in a tab for users who cannot perceive images.
Map (interactive) output
#### interactive map ####
map3_interactive_map <- leaflet(options = leafletOptions(
minZoom = 8,
maxZoom = 12
)) %>%
setView(lng = -6.5, lat = 54.6, zoom = 8.15, ) %>%
addProviderTiles("Esri.WorldGrayCanvas")
map3_interactive_map <- addCircleMarkers(
map = map3_interactive_map, data = df_jbo, lng = ~Longitude, lat = ~Latitude,
color = "blue",
radius = 10,
label = lapply(paste0(
df_jbo$JBO, ": ", df_jbo$Vacancies,
" vacancies"
), HTML),
labelOptions = labelOptions(style = list("font-size" = "14px"))
) %>%
addEasyButton(easyButton(
icon = "fa-globe",
title = "Reset Zoom",
onClick = JS("function(btn, map){ map.setView([54.6,lng = -6.5],8.15); }")
))
map3_interactive_map
df_jbo <- df_jbo[1:2]
Map (interactive) data
kable(df_jbo)
| JBO | Vacancies |
|---|---|
| Shaftesbury Square | 6,431 |
| Holywood Road | 4,411 |
| Antrim | 4,325 |
| Foyle/Lisnagelvin | 4,174 |
| Belfast North | 3,664 |
| Lisburn | 3,410 |
| Bangor | 2,921 |
| Portadown | 2,912 |
| Ballymena | 2,736 |
| Knockbreda | 2,258 |
| Newry | 2,041 |
| Newtownards | 1,992 |
| Coleraine | 1,872 |
| Magherafelt | 1,619 |
| Armagh | 1,612 |
| Enniskillen | 1,567 |
| Omagh | 1,255 |
| Dungannon | 1,198 |
| Lurgan | 1,098 |
| Banbridge | 863 |
| Falls Road | 850 |
| Newtownabbey | 834 |
| Cookstown | 804 |
| Downpatrick | 759 |
| Ballymoney | 754 |
| Limavady | 739 |
| Carrickfergus | 701 |
| Strabane | 670 |
| Andersonstown | 573 |
| Ballynahinch | 569 |
| Larne | 538 |
| Newcastle | 462 |
| Kilkeel | 426 |
| Shankill | 410 |
7. Download data (h2)
Embed spreadsheet into report (h3)
Another option to include downloadable data in a html report is to embed a spreadsheet into the report by adding a download data button as below. For this option edit and run the demo_excel_tables.R script first to create the required spreadsheet in the demo output folder or add the already prepared spreadsheet to the folder. Using the code below (click on show code) parameters can be set in the embed_file function to set the file path, file name and text to appear on the download button. Run this code to create the download data button with the embedded spreadsheet.
It is not recommended to use this option unless necessary. This is due to the large file sizes of the embedded files. This has the potential to slow the processing and knitting time of the report and generate a html page that is very large and slow to load. Due to the large file sizes of the HTML, it is not possible to attain metrics for the embedded files within the report. It is recommended to host spreadsheets elsewhere and link to them in your HTML. This keeps the HTML file size down for quicker loading and allows metrics to be gathered on the associated spreadsheets.
# embeds the spreadsheets
embexcel <- embed_file(
here("code/demo/demo_outputs/RAP_demo_tables.xlsx"),
text = "Publication tables: 15KB"
)
div(
div(
class = "row", style = "display: flex;",
div(class = "row-indent"),
div(class = "download", "Download data: ", style = "font-size: 12pt"),
div(class = "row-indent"),
div(class = "xl-button2", HTML(embexcel)), # <-- wrap with HTML()
div(class = "download", style = "padding-top: 7px; padding-left: 5px;
padding-right: 5px;")
)
)
8. Notes for readers (h2)
This section has been separated from the main section of the document to aid navigation. Normally a publication should contain a separate section of this nature and can be named ‘Notes for Readers’, ‘Background Notes’ or ‘Supporting Information’. It should include:
- definitions (or a link to definitions) of all relevant concepts and terms. Whether the definition is included in the text, the Notes section or a link provided depends on the importance of the reader knowing the correct definition
- key quality information (including any limitations or key caveats) and a link to the Background Quality Report (or the equivalent). Where appropriate, limitations or caveats should also be flagged in the text alongside the data, as not all users will read the Notes section
- links to the equivalent statistics in England, Scotland and Wales (and if appropriate RoI) or indicate that equivalent statistics are not available (with an explanation or guidance on comparison if appropriate) - assuming this information is not included elsewhere in the publication
It may include (if relevant):
- a series of methodology notes (or a link to the methodology used to produce the statistics). This may include details of the data sources used to produce the statistics.
- information on how the statistics are used, for example if they are used to measure key performance targets; and advice on the appropriate use of the statistics
- links to related statistics, including where appropriate guidance on the coherence and comparability of the statistics
- links to social media accounts X (Twitter) and Facebook
- information on supplementary statistical services
- date of the next release
- links to previous publications
- email addresses should all be lowercase jo.bloggs@nisra.gov.uk and it is good practice to include a named individual (some exemptions apply)
- links to downloads should have file type and size in the link text 2022 Mid-year population estimates statistical bulletin pdf 545KB
With regards to adding ‘Contact Details’, they may be included in
this section. However the RAP skeleton has a contact details function
called f_contact in the html_formatting R
script within the functions folder. This function is called at the
bottom of a report (Section 13) above the footer and is the recommended
way to add contact details to a report as it ensures consistency for
users. Information for specific contact details can be added and edited
in the config file
Requests for PDF
It is not encouraged to produced NISRA publications in PDF format however if users request a HTML publication in PDF format it can be created by printing to HTML to PDF using the browser print. Please note - any PDF files created in this way will not be accessible.
9. Text presentation (h2)
This section includes a quote, more subheading levels, unordered lists, ordered lists and links.
Quote box (h3)
Mid Year Estimates:
In June each year NISRA prepares data on the size of the Northern
Ireland population and includes statistics on a range of administrative
and statistical geographies. A style like this could be used for
definitions or for emphasis.
Administrative geographies (h3)
Local government districts (h4)
- Antrim and Newtownabbey (no ampersand).
- Ards and North Down.
- Armagh City, Banbridge and Craigavon.
- Belfast.
- Causeway Coast and Glens.
- Derry and Strabane.
- Fermanagh and Omagh.
- Lisburn and Castlereagh.
- Mid and East Antrim.
- Mid Ulster.
- Newry, Mourne and Down.
Statistical geographies (h3)
- NUTS III areas.
- Super Output Areas.
- Census Small Areas.
Former administrative and statistical geographies (h3)
- Parliamentary Constituencies (Assembly Areas).
- Health and Social Care Trusts.
- The former Education and Library Boards.
- The former Health and Social Services Boards.
- The former NUTS-III areas.
- The former 582 Electoral Wards.
Bullets following a heading start with a capital letter, finish with a full stop and are short (no more than one sentence)
Bullets as a list within the text should always have a lead-in line, start in lowercase (unless it starts with a proper noun), don’t have full stops within bullets or at the end. For more guidance see the ONS punctuation guide.
Accordions
Notes can be stored in accordions, as shown below. This can be useful to reduce clutter in your HTML and allow users to access notes when needed.
htmltools::HTML("
<div class='accordion'>
<button class='accordion-toggle' aria-expanded='false'
aria-controls='panel1' id='accordion1'>
Local Government Districts
<span class='accordion-arrow'>▶</span>
</button>
<div class='accordion-panel' id='panel1' role='region'
aria-labelledby='accordion1' hidden>
<ul>
<li>Antrim and Newtownabbey (no ampersand).</li>
<li>Ards and North Down.</li>
<li>Armagh City, Banbridge and Craigavon.</li>
<li>Belfast.</li>
<li>Causeway Coast and Glens.</li>
<li>Derry and Strabane.</li>
<li>Fermanagh and Omagh.</li>
<li>Lisburn and Castlereagh.</li>
<li>Mid and East Antrim.</li>
<li>Mid Ulster.</li>
<li>Newry, Mourne and Down.</li>
</ul>
</div>
</div>
<script>
document.getElementById('accordion1').addEventListener('click', function() {
var expanded = this.getAttribute('aria-expanded') === 'true';
this.setAttribute('aria-expanded', !expanded);
var panel = document.getElementById(this.getAttribute('aria-controls'));
panel.hidden = expanded;
});
</script>
")
- Antrim and Newtownabbey (no ampersand).
- Ards and North Down.
- Armagh City, Banbridge and Craigavon.
- Belfast.
- Causeway Coast and Glens.
- Derry and Strabane.
- Fermanagh and Omagh.
- Lisburn and Castlereagh.
- Mid and East Antrim.
- Mid Ulster.
- Newry, Mourne and Down.
Hyperlinks (h3)
When creating a hyperlink, do not use the url. Instead, create link text that describes the link destination and if appropriate a file type and size. If linking to a data download, we are advising against linking directly to the actual file, instead link to the publication page. If linking directly to the file you have to include the file type and size in the link text and tell users if it opens in a new window. The colour of hyperlinks in this demo report were changed in the cascading style sheets (CSS) because the default colour was too low contrast to meet accessibility standards.
Examples of adding links (h4)
For a link that opens in the same window, in the R code simply give the link a relevant name in square brackets and add the link url in brackets immediately after. For accessibility it is recommended that links open in the same window in so far as possible.
NISRA - 2022 Mid Year Population Estimates for Northern Ireland
[NISRA - 2022 Mid Year Population Estimates for Northern Ireland](https://www.nisra.gov.uk/publications/2022-mid-year-population-estimates-northern-ireland)
Where a link will open in a new window the “(opens in a new window)” text should be added to the end of the link name. In addition an icon to show the user it opens in a new window can be added with the r inline code (fa(“arrow-up-right-from-square”)). When target = “_blank” is set the link opens in a new window or tab.
NISRA - 2022 Mid Year Population Estimates for Northern Ireland (opens in a new window)
[NISRA - 2022 Mid Year Population Estimates for Northern Ireland (opens in a new window) `r fa("arrow-up-right-from-square")`](https://www.nisra.gov.uk/publications/2022-mid-year-population-estimates-northern-ireland){target="_blank"}
Where a link takes the user directly to a download or file the link text should have file type and size included as below.
2022 Mid-year population estimates statistical bulletin pdf 545KB
[2022 Mid-year population estimates statistical bulletin pdf 545KB](https://www.nisra.gov.uk/system/files/statistics/Statistical%20Bulletin%20-%202022%20Mid-year%20Population%20Estimates%20for%20Northern%20Ireland.pdf)
10. Useful acessibility links (h2)
Some features may not work or be accessible in older browsers.
The NISRA Accessibility Statement is now included as a link in the footer of the RAP Skeleton.
New Analysis Function website - General guidance
New Guidance Hub - Guidance hub including some specific accessibility guides and references (see below)
Government Analysis Function - Accessibility support for statistical and analytical publications - provides information on all the help that is available from the Government Analysis Function, including details on their online tool (basecamp for statistics) that has a message board and other functions where you can ask questions about accessibility as well as information on the available drop in clinics
Government Analysis Function - Making analytical publications accessible - Guide on making analytical publications accessible
Government Analysis Function - Releasing statistics in spreadsheets - General guide including specific section on accessibility with links to Web Content Accessibility Guidelines (WCAG) 2.1
Government Analysis Function - Making spreadsheets accessible: a checklist of the basics - Specific guide on making accessible spreadsheets
Government Analysis Function - Data visualisation: tables - guidance on how to present tables
Government Analysis Function - Data visualisation: charts - guidance on how to create accessible charts
Government Analysis Function - Data visualisation: colours - guidance on using colours in data visualisations s
Government Analysis Function - Data visualisation: examples - Specific examples of using the datavisualisation guidance with real-life charts and tables
Government Analysis Function - Data visualisation: examples - guidance providing a consistent shorthand to be used in statistical and analytical publicaitons produced by the public sector
Government Analysis Function - infographics - guidance on infographics
Office for National Statistics (ONS) - Style.ONS - A guide to writing about statistics - General style guide for writing about statistics. ‘Web accessibility’ section under ‘Writing for the web’ offers specifics around accessibility.
NISRA Dissemination Branch guidance on creating an accessible infographic - Guidance shared by NISRA Dissemination Branch on how to create an accessible infographic.
11. Accredited official statistics and official statistics (h2)
Outputs should include a chapter detailing regulatory information regarding the Statistic type of the report. Example text for each of Accredited Official Statistics, Official Statistics and Official Statistics in Development can be found on the NISRA Teams Code Of Practice page.
It is recommended to use these templates and update them with your respective information accordingly.
12.Contact details (h2)
Published by: Dissemination Branch, Northern Ireland Statistics and Research Agency
Lead Statistician: John Smith
Telephone: 028 XX XXXXXX
Email: contact@nisra.gov.uk
Accessibility contact (h3)
Please contact Dissemination Branch for assistance with accessibility requirements or alternative formats. Contact details are:
Email: info@nisra.gov.uk
Telephone: +44 (0)300 200 7836
Dissemination Branch
NISRA
Colby House
Stranmillis Court
BELFAST
BT9 5RR