Skip to contents

Bar and pie charts are the categorical family: one navigable term per bar, wedge or word, moved through with the Left and Right arrow keys, with the value of each announced and mapped to pitch when sonification is on. Bar and pie charts are stable plot types in both ggplot2 and Base R (see “Supported plot types” in the README); the word cloud is an experimental Base R type whose reading may change without a deprecation period. The examples hub lists every other plot family.

Bar Plots

Simple Bar Chart

A simple bar chart compares values across categories. Each bar represents one category with its height proportional to its value.

ggplot2

bar_data <- data.frame(
  Product = c("Laptop", "Tablet", "Phone", "Monitor"),
  Sales = c(150, 230, 180, 290)
)

p <- ggplot(bar_data, aes(x = Product, y = Sales)) +
  geom_bar(stat = "identity", fill = "steelblue") +
  labs(
    title = "Product Sales by Category",
    x = "Product",
    y = "Sales (units)"
  ) +
  theme_minimal()

p
0100200300LaptopMonitorPhoneTabletProductSales (units)Product Sales by Category

Base R

products <- c("Laptop", "Tablet", "Phone", "Monitor")
sales <- c(150, 230, 180, 290)

barplot(sales,
  names.arg = products,
  col = "steelblue",
  main = "Product Sales by Category",
  xlab = "Product",
  ylab = "Sales (units)"
)
LaptopMonitorPhoneTabletProduct Sales by CategoryProductSales (units)050100150200250

Dodged / Grouped Bar Chart

A dodged bar chart places bars for each sub-group side by side, making it easy to compare values within and across categories.

ggplot2

dodged_data <- data.frame(
  Region = rep(c("North", "South", "East"), each = 2),
  Quarter = rep(c("Q1", "Q2"), 3),
  Revenue = c(120, 150, 200, 180, 160, 210)
)

p <- ggplot(dodged_data, aes(x = Region, y = Revenue, fill = Quarter)) +
  geom_bar(stat = "identity", position = position_dodge(width = 0.8)) +
  labs(title = "Quarterly Revenue by Region") +
  scale_fill_manual(values = c("steelblue", "coral")) +
  theme_minimal()

p
050100150200EastNorthSouthRegionRevenueQuarterQ1Q2Quarterly Revenue by Region

Base R

revenue_matrix <- matrix(c(120, 150, 200, 180, 160, 210), nrow = 2)
rownames(revenue_matrix) <- c("Q1", "Q2")
barplot(revenue_matrix,
  beside = TRUE,
  names.arg = c("North", "South", "East"),
  col = c("steelblue", "coral"),
  legend.text = rownames(revenue_matrix),
  main = "Quarterly Revenue by Region",
  xlab = "Region",
  ylab = "Revenue"
)
NorthSouthEastQ1Q2Quarterly Revenue by RegionRegionRevenue050100150200

Stacked Bar Chart

A stacked bar chart layers sub-groups on top of each other within each category, showing both individual contributions and the total.

ggplot2

stacked_data <- data.frame(
  Year = rep(c("2022", "2023", "2024"), each = 3),
  Source = rep(c("Solar", "Wind", "Hydro"), 3),
  Output = c(40, 30, 50, 55, 45, 48, 70, 60, 52)
)

p <- ggplot(stacked_data, aes(x = Year, y = Output, fill = Source)) +
  geom_bar(stat = "identity", position = position_stack()) +
  labs(
    title = "Renewable Energy Output by Source",
    y = "Output (GWh)"
  ) +
  scale_fill_manual(values = c("#2ecc71", "#3498db", "#9b59b6")) +
  theme_minimal()

p
050100150202220232024YearOutput (GWh)SourceHydroSolarWindRenewable Energy Output by Source

Base R

energy_matrix <- matrix(
  c(40, 30, 50, 55, 45, 48, 70, 60, 52),
  nrow = 3
)
rownames(energy_matrix) <- c("Solar", "Wind", "Hydro")
barplot(energy_matrix,
  beside = FALSE,
  names.arg = c("2022", "2023", "2024"),
  col = c("#2ecc71", "#3498db", "#9b59b6"),
  legend.text = rownames(energy_matrix),
  main = "Renewable Energy Output by Source",
  xlab = "Year",
  ylab = "Output (GWh)"
)
202220232024HydroWindSolarRenewable Energy Output by SourceYearOutput (GWh)050100150

Pie Chart

A pie chart splits a whole into wedges, one per category, each wedge’s angle proportional to its share. maidr announces every slice by name and value, and derives its percentage of the total for you.

ggplot2

ggplot2 has no pie geom: a pie is a single stacked column bent around by coord_polar("y"), so x is the literal "" and the categories go on fill. coord_radial(theta = "y") works the same way. Note that coord_polar("x") draws a coxcomb instead, which maidr still describes as a bar chart.

market_share <- data.frame(
  Browser = c("Chrome", "Safari", "Edge", "Firefox"),
  Share = c(64, 19, 5, 3)
)

p <- ggplot(market_share, aes(x = "", y = Share, fill = Browser)) +
  geom_col(width = 1) +
  coord_polar("y") +
  labs(
    title = "Browser Market Share",
    fill = "Browser",
    y = "Share (%)"
  ) +
  theme_void()

p
BrowserChromeEdgeFirefoxSafariBrowser Market Share

Base R

shares <- c(Chrome = 64, Safari = 19, Edge = 5, Firefox = 3)
pie(shares,
  col = c("#3498db", "#2ecc71", "#9b59b6", "#e67e22"),
  main = "Browser Market Share",
  xlab = "Browser",
  ylab = "Share (%)"
)
ChromeSafariEdgeFirefoxBrowser Market ShareBrowserShare (%)

Word Cloud [experimental]

A word cloud is the extreme case of a chart that carries real data while being readable only by eye: each term’s weight is drawn as glyph size and written down nowhere on the page. Structurally it is a categorical label and a magnitude, so maidr reads it as a term and its number.

Experimental. word_cloud is one of the experimental layer types. It has not been through a user study, and it may change without a deprecation period. See the experimental table in the README.

Note: Word clouds are a Base R feature. ggplot2 has no word cloud geom, and the packages that add one draw through their own devices rather than through a layer maidr can read.

Requires the {wordcloud} package. Install with install.packages("wordcloud").

Base R

The counts you pass survive into the reading, so the weight axis honestly says Occurrences. (The Python binding cannot: wordcloud.WordCloud divides every frequency by the largest and keeps only the ratio, so py-maidr announces a relative frequency. Same chart, two different honest readings.)

mentions <- c(
  accessibility = 412, sonification = 300, braille = 250,
  screenreader = 190, keyboard = 155, contrast = 120
)

maidr::wordcloud(
  words = names(mentions),
  freq = mentions,
  min.freq = 1,
  random.order = FALSE,
  colors = c(
    "#3498db", "#2ecc71", "#9b59b6",
    "#e67e22", "#e74c3c", "#16a085"
  )
)
accessibilitysonificationbraillescreenreaderkeyboardcontrast

Attach order matters. library(wordcloud) after library(maidr) puts package:wordcloud ahead of package:maidr on the search path, so a bare wordcloud() call reaches the wordcloud package directly and maidr never records it — the chart draws, but show() and save_html() then report that no Base R plot was found. Measured on a three-term cloud:

How it is called Recorded?
library(maidr) then library(wordcloud), bare wordcloud() no
library(wordcloud) then library(maidr), bare wordcloud() yes
maidr::wordcloud() yes

Either attach wordcloud before maidr, or call maidr::wordcloud() explicitly as above, which works in either order.

The word being read is highlighted. wordcloud() draws each term with its own text() call, so each word is its own element on the page, and moving with the arrow keys recolors the word being announced in your highlight color. A term wordcloud() could not fit on the page (it warns “could not be fit on page”) has no word to point at; then the cloud is read without a highlight rather than with highlights on the wrong words.

Two of wordcloud()’s arguments decide which terms are drawn, and the reading replicates both so it never announces a term the chart left out: min.freq (default 3) drops anything rarer, and max.words keeps only the heaviest. wordcloud() also lowers min.freq to 0 when it exceeds every frequency, which is what stops a cloud of rare terms coming out empty; that rule is copied rather than approximated.