
Getting Started with milestoneR
Michael Friendly
2026-01-07
Source:vignettes/getting-started.Rmd
getting-started.RmdIntroduction
The milestoneR package provides R access to the Milestones Project database, a
comprehensive collection of important events in the history of data
visualization. This vignette demonstrates how to:
- Access milestone data
- Search and filter milestones
- Display results in various formats
- Explore relationships between milestones, authors, and references
Accessing data
The package provides accessor functions for all main database tables:
# Get all milestones
ms <- milestone()
cat("Total milestones:", nrow(ms), "\n")
#> Total milestones: 297
# Get all authors
aut <- authors()
cat("Total authors:", nrow(aut), "\n")
#> Total authors: 268
# Get all references
refs <- reference()
cat("Total references:", nrow(refs), "\n")
#> Total references: 352
# Get keywords, subjects, and aspects
kw <- keyword()
subj <- subject()
asp <- aspect()
cat("Keywords:", nrow(kw), "\n")
#> Keywords: 335
cat("Subjects:", nrow(subj), "\n")
#> Subjects: 4
cat("Aspects:", nrow(asp), "\n")
#> Aspects: 4Exploring milestones
Let’s look at the structure of the milestone data:
# View column names
names(ms)
#> [1] "mid" "slug" "date_from_numeric"
#> [4] "date_from" "date_to_numeric" "date_to"
#> [7] "tag" "description" "location"
#> [10] "add_date" "modified_date" "status"
#> [13] "note" "extra"
# Look at a few key fields
ms |>
subset(select = c(mid, date_from, tag, location)) |>
head(10)
#> mid date_from tag location
#> 1 1 -6200 Oldest known map? Museum at Konya, Turkey
#> 2 2 550 BC 1st world map? Turkey
#> 3 3 366 BC 1st route map <NA>
#> 4 4 -240 Diameter of earth measured Libya
#> 5 5 170 BC Invention of parchment Pergamon, Bergama, Turkey
#> 6 6 -134 Star chart Turkey
#> 7 7 105 Invention of paper China
#> 8 8 90 Latitude/longitude <NA>
#> 9 9 950 Diagram: planetary movements Europe
#> 10 10 1280 Diagram: paired comparisons SpainDate range coverage
# Date range of milestones
cat("Earliest milestone:", min(ms$date_from_numeric, na.rm = TRUE), "\n")
#> Earliest milestone: -6200
cat("Most recent milestone:", max(ms$date_from_numeric, na.rm = TRUE), "\n")
#> Most recent milestone: 2009
# Count by century
ms$century <- (ms$date_from_numeric %/% 100) * 100
ms$century |>
table() |>
print()
#>
#> -6200 -600 -400 -300 -200 -100 0 100 900 1200 1300 1400 1500
#> 1 1 1 1 2 1 2 1 1 1 3 2 11
#> 1600 1700 1800 1900 2000
#> 27 34 98 105 5Searching milestones
The package provides three specialized search functions.
Full-text search
Search across milestone fields (description, tag, note):
# Find milestones mentioning "statistical"
stat_ids <- search_milestones("statistical")
cat("Found", length(stat_ids), "milestones mentioning 'statistical'\n")
#> Found 51 milestones mentioning 'statistical'
# Show the first few
head(stat_ids)
#> [1] 36 38 55 76 94 99
# Use regex to find "chart" OR "graph"
chart_ids <- search_milestones("chart|graph", fields = c("description", "tag"))
cat("\nFound", length(chart_ids), "milestones with 'chart' or 'graph'\n")
#>
#> Found 132 milestones with 'chart' or 'graph'
# Search only in tags for items marked as "1st" (first)
first_ids <- search_milestones("^1st", fields = "tag")
cat("\nFound", length(first_ids), "milestone tags starting with '1st'\n")
#>
#> Found 24 milestone tags starting with '1st'Search by keywords
# Find milestones tagged with "contour"
contour_ids <- search_keywords("contour")
cat("Milestones with 'contour' keyword:", paste(contour_ids, collapse = ", "), "\n")
#> Milestones with 'contour' keyword: 65, 117, 145, 83, 53
# Search for statistical keywords
stat_kw_ids <- search_keywords("statistic")
cat("\nMilestones with statistical keywords:", length(stat_kw_ids), "\n")
#>
#> Milestones with statistical keywords: 10Search by author
# Find William Playfair's milestones
playfair_ids <- search_authors("Playfair")
cat("William Playfair's milestones:", paste(playfair_ids, collapse = ", "), "\n")
#> William Playfair's milestones: 80, 89
# Find all authors named John
john_ids <- search_authors("John", name_fields = "givennames")
cat("\nMilestones by authors named John:", length(john_ids), "\n")
#>
#> Milestones by authors named John: 20
# Search only last names
nightingale_ids <- search_authors("Nightingale", name_fields = "lname")
cat("\nMilestones by Nightingale:", paste(nightingale_ids, collapse = ", "), "\n")
#>
#> Milestones by Nightingale: 129Filtering by date and category
Combine direct data frame operations with search functions:
# Milestones from the 1800s
ms_1800s <- ms |>
subset(date_from_numeric >= 1800 & date_from_numeric < 1900)
cat("Milestones from 1800-1899:", nrow(ms_1800s), "\n")
#> Milestones from 1800-1899: 98
# Early milestones (before 1700)
early <- ms |>
subset(date_from_numeric < 1700)
cat("Milestones before 1700:", nrow(early), "\n")
#> Milestones before 1700: 55
# Milestones in France
france <- ms |>
subset(!is.na(location) & grepl("France", location, ignore.case = TRUE))
cat("Milestones in France:", nrow(france), "\n")
#> Milestones in France: 45Filtering by subject and aspect
Using the linking tables:
# Get milestones by subject
m2subj <- milestone2subject()
# Milestones with "Physical" subject
physical_mids <- m2subj |>
subset(subject == "Physical") |>
getElement("mid")
cat("Milestones with 'Physical' subject:", length(physical_mids), "\n")
#> Milestones with 'Physical' subject: 77
# Get milestones by aspect
m2asp <- milestone2aspect()
# Milestones with "Cartography" aspect
carto_mids <- m2asp |>
subset(aspect == "Cartography") |>
getElement("mid")
cat("Milestones with 'Cartography' aspect:", length(carto_mids), "\n")
#> Milestones with 'Cartography' aspect: 44
# Combine: Cartography AND Physical
combined <- intersect(physical_mids, carto_mids)
cat("\nMilestones that are both Physical and Cartography:", length(combined), "\n")
#>
#> Milestones that are both Physical and Cartography: 20Displaying results
The package provides several print functions with various output
formats: "text", "html",
"markdown", "cli" (enhanced console
output).
Printing individual milestones
# Print Halley's 1701 contour map in text format
halley <- ms |>
subset(date_from_numeric == 1701)
print_milestone(halley$mid)
#> [1701] 1st contour map?
#> Authors: Edmond Halley
#>
#> Contour maps showing curves of equal value (an isogonic map, lines of equal magnetic declination for the world, possibly the first contour map of a data-based variable)
#>
#> Keywords: contour map, isogonic
#> Subjects: Physical
#> Aspects: Statistics & Graphics
#>
#> Media:
#> - [link] National maritime museum, Halley magnetic chart
#> - [image] Halley isogonic map
#> - [link] Halley biography
#> - [link] Geomagnetism: early concept of the North Magnetic Pole - The concept of the North Magnetic Pole arose from the desire of early European navigators to explain the directional properties of the compass. Chines used compass at least as early as the 1st century and it was imported to Europe in the 12th century.
#>
#> References:
#> - Halley, Edmund. (1701). "The Description and Uses of a New, and Correct Sea-Chart of the Whole World, Shewing Variations of the Compass"
#> - Abbott, Edwin A. (1884). "Flatland: A Romance of Many Dimensions". Cutchogue, NY: Buccaneer Books. [(1976 reprint of the 1884 edition)]Different output formats
# HTML format (useful for R Markdown documents)
print_milestone(53, result = "html")
# Markdown format
print_milestone(53, result = "md")
# Enhanced CLI format with clickable links (in modern terminals)
print_milestone_cli(53)Printing multiple milestones
# Print Playfair's milestones
print_milestone_cli(playfair_ids)Selective sections
You can control which sections to display:
# Show only authors, media, and references
print_milestone(53, include = c("authors", "media", "references"))Search with formatted output
Combine search with immediate formatted display:
# Find and print Florence Nightingale's work
search_milestones("Florence Nightingale",
fields = "description",
output = "print")
#> [1829] Polar-area charts
#> Authors: André Michel Guerry
#>
#> Polar-area charts (predating those by Florence Nightingale cite{Nightingale:1857}), showing frequency of events for cyclic phenomena
#>
#> Location: France
#> Keywords: chart!polar, coxcomb
#> Subjects: Physical
#> Aspects: Statistics & Graphics
#>
#> Media:
#> - [image] Guerry's polar diagrams
#> - [image] Guerry barcharts and polar diagrams
#>
#> Note: The plate shows six polar diagrams for daily phenomena: direction of the wind in 8 sectors, births and deaths by hour of theday.
#>
#> References:
#> - Balbi, Adriano & Guerry, André-Michel. (1829). "Tableau des Variations météorologique comparées aux phénomènes physiologiques, d'aprés les observations faites à l'Obervatoire royal, et les recherches statistique les plus récentes". _Annales d'Hygiène Publique et de Médecine Légale_. 1. pp. 228-Working with related information
Use helper functions to get related data for milestones.
Getting authors
# Get authors for Halley's milestone
halley_authors <- get_milestone_authors(53)
halley_authors |>
subset(select = c(givennames, lname, birthdate, deathdate)) |>
print()
#> givennames lname birthdate deathdate
#> 1 Edmond Halley 1656-11-08 1742-01-14
# Get authors for multiple milestones
playfair_authors <- get_milestone_authors(playfair_ids)
playfair_authors |>
subset(select = c(givennames, lname, birthdate)) |>
print()
#> givennames lname birthdate
#> 1 William Playfair 1759-09-22
#> 2 William Playfair 1759-09-22Getting references
# Get references for a milestone
halley_refs <- get_milestone_references(53)
halley_refs |>
subset(select = c(rid, author, year, title)) |>
print()
#> rid author year
#> 1 290 Halley, Edmund 1701
#> 2 365 Abbott, Edwin A 1884
#> title
#> 1 The Description and Uses of a New, and Correct Sea-Chart of the Whole World, Shewing Variations of the Compass
#> 2 Flatland: A Romance of Many Dimensions
# Print formatted reference
print_reference(halley_refs[1, ])
#> Halley, Edmund. (1701). "The Description and Uses of a New, and Correct Sea-Chart of the Whole World, Shewing Variations of the Compass"Getting keywords
# Get keywords for a milestone
halley_kw <- get_milestone_keywords(53)
print(halley_kw)
#> mid kid keyword
#> 325 53 38 contour map
#> 324 53 128 isogonic
# Get all keywords for Playfair's work
playfair_kw <- get_milestone_keywords(playfair_ids)
playfair_kw$keyword |>
table() |>
print()
#>
#> bar chart circle graph line graph pie chart
#> 1 1 1 1Getting media items
# Get media items for a milestone
halley_media <- get_milestone_media(53)
halley_media |>
subset(select = c(miid, type, title)) |>
print()
#> miid type title
#> 566 1339 link National maritime museum, Halley magnetic chart
#> 567 1340 image Halley isogonic map
#> 568 1341 link Halley biography
#> 569 1342 link Geomagnetism: early concept of the North Magnetic Pole
# Check how many milestones have media
all_media <- get_milestone_media(ms$mid)
cat("Total media items:", nrow(all_media), "\n")
#> Total media items: 808
cat("Milestones with media:", length(unique(all_media$mid)), "\n")
#> Milestones with media: 256Printing references and authors
References
# Print a reference in text format
print_reference(halley_refs[1, ])
#> Halley, Edmund. (1701). "The Description and Uses of a New, and Correct Sea-Chart of the Whole World, Shewing Variations of the Compass"
# Print as BibTeX
cat("\nAs BibTeX:\n")
#>
#> As BibTeX:
print_reference(halley_refs[1, ], bibtex = TRUE)
#> @article{Halley:1701,
#> author = {Halley, Edmund},
#> title = {The Description and Uses of a New, and Correct Sea-Chart of the Whole World, Shewing Variations of the Compass},
#> year = {1701},
#> publisher = {Author},
#> address = {London}
#> }
# Print multiple references
print_reference(halley_refs)
#> Halley, Edmund. (1701). "The Description and Uses of a New, and Correct Sea-Chart of the Whole World, Shewing Variations of the Compass"
#>
#> Abbott, Edwin A. (1884). "Flatland: A Romance of Many Dimensions". Cutchogue, NY: Buccaneer Books. [(1976 reprint of the 1884 edition)]Authors
# Print author information
print_author(halley_authors[1, ])
#> Edmond Halley; born: Haggerston, Shoreditch, England (1656-11-08); died: Greenwich, England (1742-01-14)
# Get a specific author by name
playfair_aut <- aut |>
subset(grepl("Playfair", lname))
print_author(playfair_aut[1, ])
#> William Playfair; born: Dundee, Scotland (1759-09-22); died: London, England (1823-02-11); [
#> ]Example workflow: Researching a topic
Here’s a complete example of researching “contour maps” in the history of data visualization:
# 1. Search for contour-related milestones
contour_text <- search_milestones("contour", fields = c("description", "tag"))
contour_kw <- search_keywords("contour")
# Combine results (union)
contour_all <- unique(c(contour_text, contour_kw))
cat("Found", length(contour_all), "contour-related milestones\n")
#> Found 6 contour-related milestones
# 2. Get the milestone data
contour_ms <- ms |>
subset(mid %in% contour_all)
# 3. Sort by date
contour_ms <- contour_ms[order(contour_ms$date_from_numeric), ]
# 4. Display summary
cat("\nContour map milestones chronology:\n")
#>
#> Contour map milestones chronology:
for (i in 1:nrow(contour_ms)) {
cat(sprintf("[%s] %s\n",
contour_ms$date_from[i],
contour_ms$tag[i]))
}
#> [1701] 1st contour map?
#> [1752] Contour map
#> [1795] Proto-nomogram
#> [1843] Contour map of 3D table
#> [1874] Statistical contour map
#> [1885] Correlation
# 5. Get all authors involved
contour_authors <- get_milestone_authors(contour_all)
cat("\nAuthors involved in contour mapping:\n")
#>
#> Authors involved in contour mapping:
unique_authors <- unique(contour_authors[, c("givennames", "lname", "birthdate")])
unique_authors[order(unique_authors$birthdate), ] |>
print()
#> givennames lname birthdate
#> 3 Edmond Halley 1656-11-08
#> 1 Phillippe Buache 1700-02-07
#> 4 Léon Lalanne 1811-07-03
#> 6 Louis-Léger Vauthier 1815-04-06
#> 2 Francis Galton 1822-02-16
#> 5 Louis Ézéchiel Pouchet <NA>
# 6. Print detailed information for the earliest one
cat("\n--- Earliest Contour Map Milestone ---\n")
#>
#> --- Earliest Contour Map Milestone ---
print_milestone(contour_ms$mid[1])
#> [1701] 1st contour map?
#> Authors: Edmond Halley
#>
#> Contour maps showing curves of equal value (an isogonic map, lines of equal magnetic declination for the world, possibly the first contour map of a data-based variable)
#>
#> Keywords: contour map, isogonic
#> Subjects: Physical
#> Aspects: Statistics & Graphics
#>
#> Media:
#> - [link] National maritime museum, Halley magnetic chart
#> - [image] Halley isogonic map
#> - [link] Halley biography
#> - [link] Geomagnetism: early concept of the North Magnetic Pole - The concept of the North Magnetic Pole arose from the desire of early European navigators to explain the directional properties of the compass. Chines used compass at least as early as the 1st century and it was imported to Europe in the 12th century.
#>
#> References:
#> - Halley, Edmund. (1701). "The Description and Uses of a New, and Correct Sea-Chart of the Whole World, Shewing Variations of the Compass"
#> - Abbott, Edwin A. (1884). "Flatland: A Romance of Many Dimensions". Cutchogue, NY: Buccaneer Books. [(1976 reprint of the 1884 edition)]Combining filters
Create complex queries by combining multiple search strategies:
# Find statistical graphics in the 1800s
stat_ids <- search_milestones("statistical")
stat_1800s <- ms |>
subset(mid %in% stat_ids) |>
subset(date_from_numeric >= 1800 & date_from_numeric < 1900)
cat("Statistical graphics milestones in the 1800s:", nrow(stat_1800s), "\n")
#> Statistical graphics milestones in the 1800s: 17
# Show them
stat_1800s |>
subset(select = c(mid, date_from, tag)) |>
head(5) |>
print()
#> mid date_from tag
#> 94 94 1819 Choropleth map
#> 99 99 1826 Choropleth map
#> 123 123 1851 Map with diagrams
#> 124 124 1852 Graphics in law
#> 127 127 1857 Standardization of graphsSummary statistics
Get overview statistics about the database:
# Count by subject
m2subj <- milestone2subject()
subj_counts <- table(m2subj$subject)
cat("Milestones by Subject:\n")
#> Milestones by Subject:
print(subj_counts)
#>
#> Human Mathematical Other Physical
#> 59 131 30 77
# Count by aspect
m2asp <- milestone2aspect()
asp_counts <- table(m2asp$aspect)
cat("\nMilestones by Aspect:\n")
#>
#> Milestones by Aspect:
print(asp_counts)
#>
#> Cartography Other Statistics & Graphics
#> 44 11 193
#> Technology
#> 50
# Most common keywords (top 10)
m2kw <- milestone2keyword()
kw_counts <- m2kw$keyword |>
table() |>
sort(decreasing = TRUE)
cat("\nTop 10 Keywords:\n")
#>
#> Top 10 Keywords:
print(head(kw_counts, 10))
#>
#> census line graph interactive graphics
#> 6 6 5
#> longitude mosaic plot chartbook
#> 5 5 4
#> contour map coordinates!polar graphical perception
#> 4 4 4
#> map!choropleth
#> 4
# Milestones per century
century_table <- table(ms$century)
cat("\nMilestones per Century:\n")
#>
#> Milestones per Century:
print(century_table)
#>
#> -6200 -600 -400 -300 -200 -100 0 100 900 1200 1300 1400 1500
#> 1 1 1 1 2 1 2 1 1 1 3 2 11
#> 1600 1700 1800 1900 2000
#> 27 34 98 105 5Next steps
This vignette has covered the basics of accessing, searching, and displaying milestones data. For more advanced usage:
- See
vignette("visualizing-milestones")for creating plots and visualizations - Use
?search_milestonesfor advanced search options - Explore
?print_milestone_clifor enhanced console output with clickable links - Check the package website for updates
References
Friendly, M., Sigal, M. & Harnanansingh, D. (2015). “The Milestones Project: A Database for the History of Data Visualization.” In Kimball, M. & Kostelnick, C. (Eds.) Visible Numbers: The History of Data Visualization, Chapter 10. London, UK: Ashgate Press. preprint