roadDB: An R package for exploring human prehistory with the ROCEEH Out of Africa Database

Welcome to the R implementation of the ROCEEH Out of Africa Database — or simply ROAD. This tutorial will introduce the core concepts and guide you through your first steps with the roadDB package. In addition, it will offer ideas on how to use roadDB alongside other resources available in the R ecosystem.

But first, let’s start with the installation.

Get started

Install R, RStudio

Please install the current version of the statistical software R and the Integrated Development Environment (IDE) RStudio, both available from https://posit.co/download/rstudio-desktop/.

If you would like to install the development version of roadDB on MS Windows, make sure to install Rtools from https://cran.r-project.org/bin/windows/Rtools/.

Install roadDB

You only need to install the package once on your R setup, so you can skip this step if it’s already installed. The easiest way to install a stable release is through CRAN. Alternatively, you can acquire a development version from Github.

# CRAN installation (stable release)
install.packages("roadDB")

# Github installation (development version)
install.packages("devtools")
devtools::install_github("sommergeo/roadDB")

Load roadDB

After the package has been installed, you can load it every time you run an R session. This will make all the functions available for that session.

# Load the package
library(roadDB)
#> Warning: package 'roadDB' was built under R version 4.5.3
#> 
#>   This package utilizes a regularly updated version of ROAD, 
#>   so results may vary over time.
#>   
#>   An active internet connection is required, and the server may occasionally be
#>   offline. For the current ROAD version and scheduled downtime, please refer 
#>   to https://github.com/sommergeo/roadDB
#> 

First query

Now you are ready to run your first query:

my_query <- road_get_localities(cultural_period='Middle Paleolithic')

Install external packages

If everything worked so far, go ahead and install these additional packages — they’ll be used in the upcoming examples:

# Install packages (needs to be done only once)
install.packages("tidyverse")
install.packages("sf")
install.packages("tmap")
install.packages("rcarbon")

Please ensure that the required packages are installed on your system. If they are not, install them using the instructions provided above

# Load libraries (every time you run this tutorial)
library(roadDB)
library(tidyverse)
library(sf)
library(tmap)
library(rcarbon)

Useful downloads

Basic principles

ROCEEH Out of Africa Database

roadDB is an R package designed to provide simplified access to the ROCEEH Out of Africa Database (ROAD).

Developed over the past 18 years by the ROCEEH (The Role of Culture in Early Expansions of Humans) research center, ROAD integrates a wealth of archaeological, anthropological, paleoenvironmental and geographical data from both Africa and Eurasia, covering a timeframe from 3,000,000 to 20,000 years before present.

The database currently encompasses information on over 29,000 assemblages and 2,700 localities, derived from more than 6,500 publications in over 10 languages. ROAD offers structured data with a high level of both quantity and detail, making it an invaluable resource for quantitative and computational analysis.

However, due to its complexity and expert-level focus, the database can be challenging to navigate and analyse directly. This is why the roadDB package was implemented as a short-cut into the R ecosystem.

R implementation

The package aims to provide a simplified, intuitive, and convenient interface for accessing the ROAD database by following a few core principles:

Background architecture

The roadDB functions are essentially wrappers around complex SQL queries. They interact with a remote copy of the official ROAD database, which is updated four times per year. The current database version number can be found on the Github page.

As a result, query results may change over time and might not always reflect the most recent data available through the browser-based interface of ROAD. Keep in mind that ROAD is continuously expanding.

Because the package relies on a remote server connection, it requires an active internet connection. Occasionally, the server may experience downtime for maintenance or security checks, particularly during the Christmas holidays. The current server status and and planned times of inaccessibility can be accessed using the link above.

How to use roadDB

The use of roadDB can be summarised as follows:

road_get_* functions

The road_get_* functions are used to query data from the ROAD server. They support three Levels of Detail (LOD), which determine the granularity of the returned data frame. Accordingly, each row (or observation) in the output will represent a locality, an assemblage, or a specific object, depending on the selected level of detail (see fig. 1)

Figure 1: Three levels of detail determine the granularity of the data frame.

Since ROAD contains extensive information at the assemblage level—and because different types of assemblages may include diverse and sometimes unique sets of columns (or variables)—additional subordinate functions are provided to handle these cases.

A large number of these functions are specifically related to archaeological content. The available functions include:

Arguments

Arguments allow you to refine the queries made through the road_get_* functions. They are optional—if no arguments are provided, the query returns all available information from ROAD.

In practice, however, most research questions require more focused data. You can tailor your query to your needs by filtering, for example, by continent or cultural_period.

Arguments can also be combined, and you may supply a single value or a list of values.

# Single argument
road_get_localities(cultural_period="MSA")

# Multiple arguments
road_get_localities(cultural_period="MSA", country="South Africa")

# Lists of arguments
road_get_localities(cultural_period=c("MSA","LSA"), country=c("South Africa","Namibia"))

The package provides two sets of arguments:

First, the general arguments (tab. 1) which are available for all road_get_* functions. These arguments provide flexible ways to filter and refine your queries.

And second, the function-specific arguments (tab. 2), which are only available for certain road_get_* functions. These arguments refine queries in ways that are unique to the corresponding function. Some of them use exact search terms, whereas others use fuzzy search. Figure 2 gives a compact overview over all possible combinations of functions and arguments:

Figure 2: All possible combinations of functions and arguments. Click here for a PDF version.

Table 1: General arguments are available for all road_get_* functions.

Argument Type Example
continent character “Africa”
subcontinent character “Southern Africa”
country character “South Africa”
locality_type character “rock shelter”
category character “symbolic artifacts, typology”
age_min numeric 20000
age_max numeric 3000000
technocomplex character “ESA/ Early Acheulean”
cultural_period character “Middle Stone Age”

Table 2: Function-specific arguments are available for certain road_get_* functions.

Argument Type Search Type Example(s)
tool_list character contains “bladelet”
raw_material_list character contains “ironstone banded”
transport_distance character exact “regional (6–20 km)”
organic_tool_interpretation character contains “retoucher”
symbolic_artifact_interpretation character contains “anthropomorphic”
feature_interpretation character exact “stone construction”
miscellaneous_find_material character exact “ostrich egg shell”
human_genus character exact “Homo”
human_species character exact “sapiens”
plant_remains character exact “phytoliths”
plant_family character exact “Anarcadiaceae”
plant_genus character exact “Jasione”
plant_species character exact “Potamogeton gramineus L.”
fauna_genus character exact “Lemniscomys”
fauna_species character exact “atapuerquensis”
localities dataframe exact Output from road_get_localities()
assemblages dataframe exact Output from road_get_assemblages()

Helper functions

help()

Each function in ROAD comes with detailed documentation, accessible through the standard help() function in R. The documentation describes what the function does, the arguments it accepts, the columns it returns, and how to interpret them.

# Examples
help(road_get_localities)
help(road_get_lithic_typologies)
help(road_get_dates)

road_list_argument_values()

If you are unsure which values are valid for a given argument, use road_list_argument_values().

For instance, you might not know how specific cultural periods are spelled in ROAD, or which human genera are available. This helper function returns all unique values for the specified argument, allowing you to explore available options before constructing your query.

# Examples
road_list_argument_values("country")
road_list_argument_values("cultural_period")
road_list_argument_values("human_genus")

road_summarize_archaeology()

When working with archaeological data, it can be helpful to summarise content across multiple road_get_* functions. For example, you may want to identify all datasets containing the term “egg shell”.

The summary table shows which road_get_* functions include the term, and in which columns it appears. This allows you to refine and target your queries more effectively.

# Find 'egg shell'
road_summarize_archaeology("egg shell")
#>        term           road_get_ attribute hit_number
#> 1 egg shell miscellaneous_finds  material         96
#> 2 egg shell  symbolic_artifacts  material         92
#> 3 egg shell  symbolic_artifacts  comments          3
#> 4 egg shell miscellaneous_finds  comments          1

Examples

The following examples demonstrate how to query data from ROAD and seamlessly use the results with external R packages. The tutorial uses the pipe operator |>, which is a native function since R v4.1, allowing to forward the results from one function into the next one (e.g. function1() |> function2()). You can write it by pressing CTRL+SHIFT+M.

Example #1: Localities

1.1 Map the Middle Stone Age

You can retrieve a table of all localities stored in ROAD using the function road_get_localities().

The table shows the first few rows of more than 2,000 localities currently available. Each locality is represented as a row, with attributes stored in the columns.

To explore the complete dataset interactively, you can use the View() function in RStudio.

# Query all localities
localities <- road_get_localities()

head(localities)  # head() shows the first 6 rows of a dataset
#> # A tibble: 6 × 15
#> # Groups:   locality_id, continent, subcontinent, country, locality_type,
#> #   coord_x, coord_y [6]
#>   locality_id       continent subcontinent country locality_type coord_x coord_y
#>   <chr>             <chr>     <chr>        <chr>   <chr>           <dbl>   <dbl>
#> 1 Aar 1             Africa    Southern Af… Namibia rock shelter    16.5    -26.8
#> 2 Aar 2             Africa    Southern Af… Namibia rock shelter    16.5    -26.7
#> 3 Aardjesberg       Europe    Western Eur… Nether… hill slope, …    5.18    52.2
#> 4 Aasvoelkop        Africa    Southern Af… South … open air        28      -26.2
#> 5 Abdur Archaeolog… Africa    East Africa  Eritrea open air        39.9     15.2
#> 6 Abri Blanchard d… Europe    Western Eur… France  rock shelter     1.10    45.0
#> # ℹ 8 more variables: coordinate_source <chr>, category <chr>,
#> #   cultural_period <chr>, technocomplex <chr>, subset_age_min <int>,
#> #   subset_age_max <int>, locality_age_min <int>, locality_age_max <int>

You can narrow down your results by adding optional arguments to road_get_localities(). For example, the query below retrieves only sites from the African continent that are attributed to the Middle Stone Age.

# Query selected localities
african_msa_localities <- road_get_localities(continent = "Africa", cultural_period = "MSA")
head(african_msa_localities)
#> # A tibble: 6 × 15
#> # Groups:   locality_id, continent, subcontinent, country, locality_type,
#> #   coord_x, coord_y [6]
#>   locality_id       continent subcontinent country locality_type coord_x coord_y
#>   <chr>             <chr>     <chr>        <chr>   <chr>           <dbl>   <dbl>
#> 1 Aar 1             Africa    Southern Af… Namibia rock shelter     16.5  -26.8 
#> 2 Aar 2             Africa    Southern Af… Namibia rock shelter     16.5  -26.7 
#> 3 Aasvoelkop        Africa    Southern Af… South … open air         28    -26.2 
#> 4 Abdur Archaeolog… Africa    East Africa  Eritrea open air         39.9   15.2 
#> 5 Airport site      Africa    Southern Af… Malawi  open air         33.9   -9.95
#> 6 Aladi Springs     Africa    East Africa  Ethiop… open air         40.9    9.38
#> # ℹ 8 more variables: coordinate_source <chr>, category <chr>,
#> #   cultural_period <chr>, technocomplex <chr>, subset_age_min <int>,
#> #   subset_age_max <int>, locality_age_min <int>, locality_age_max <int>

Since the dataset contains geographical coordinates in the columns coord_x and coord_y, you can easily convert the results into a spatial object with the sf package and visualise them on an interactive map using the package tmap.

# Load geospatial libraries
library(sf)     # for spatial objects
library(tmap)   # for visualization

# Use coordinate columns to create a spatial dataset
african_msa_sf <- st_as_sf(african_msa_localities, 
                          coords = c("coord_x", "coord_y"), 
                          crs = 4326)  # WGS84 (lat/lon)

# Choose mapping engine
tmap_mode("plot")  # or "view" for interactive map

# Create map
tm_shape(african_msa_sf) +
  tm_basemap("OpenStreetMap") +
  tm_dots()

You can extend this map with various functions included in the tmap package.

1.2 Map a technocomplex of your choice

Now you can generate a map for a technocomplex of your choice.

Before selecting one, it’s helpful to get an overview of the available options. This is where the helper function road_list_argument_values() comes in — it allows us to list the unique values that can be used as arguments.

Use it to display all available technocomplexes, and then choose one that interests you.

road_list_argument_values("technocomplex")
#> EP/ Epigravettian, EP/ Epipaleolithic, EP/ Geometric Kebaran, EP/ Harifian, EP/ Iberomaurusian, EP/ Kebaran, EP/ Masraqan, EP/ Mushabian, EP/ Natufian, EP/ Nebekian, EP/ Nizzanian, EP/ Oranian, ESA, ESA/ Acheulean, ESA/ Developed Oldowan, ESA/ Early Acheulean, ESA/ Fauresmith, ESA/ KBS Industry, ESA/ Karari Industry, ESA/ Late Acheulean, ESA/ Late Sangoan, ESA/ Lupemban, ESA/ Middle Acheulean, ESA/ Oldowan, ESA/ Proto-Still Bay, ESA/ Sangoan, ESA/ Victoria West, ESA/MSA, EUP / UP / Lincombian-Ranisian-Jerzmanowician / LRJ, LP/ Acheulean - Europe, LP/ Acheulean - Levant, LP/ Acheulean - S Asia, LP/ Acheulo-Yabrudian, LP/ Amudian, LP/ Clactonian, LP/ Early Acheulean - Levant, LP/ Early Pleistocene - E Asia, LP/ Late Acheulean - E Asia, LP/ Late Acheulean - S Asia, LP/ Late Acheulean - SW Asia, and many more.

Now, adapt the mapping workflow from above to display the technocomplex you selected.

Use your chosen value as argument value in the road_get_localities function to generate a map specific to that culture.

# Query Mousterian sites
mousterian <- road_get_localities(technocomplex = c("MP/ Mousterian - Eurasia", "MP/ Mousterian - Levant"))

# Create spatial dataset
mousterian_sf <- st_as_sf(mousterian, 
                          coords = c("coord_x", "coord_y"), 
                          crs = 4326)  # WGS84 (lat/lon)

# Display map
tmap_mode("plot")  # or "view" for interactive map

tm_shape(mousterian_sf) +
  tm_basemap("OpenStreetMap") +
  tm_dots(
    col = "technocomplex",
    palette = "Set2")+
  tm_layout(legend.outside = TRUE)

As you can see, the map can be customised using the arguments available in tmap::tm_dots().

In this example, we visualise different technocomplex categories by setting the col argument (which determines which variable is used for colouring — here, mousterian$technocomplex) and the palette argument (which specifies the colour scheme to use).

Once you have transferred your dataset to a spatial data type, there are many interesting packages available, that make use of the spatial data in ROAD: - spatstat for spatial point pattern analysis, kernel density, etc. - spatial for interpolation, Kriging and point pattern analysis - gstat for modelling, prediction and simulation

Example #2: Assemblages

Moving to the next level of detail (LOD) of roadDB we will now query assemblages. In the same way as we are able to make a query for all localities in ROAD, we can similarly query for all assemblages that make up those localities.

# We can query all assemblages in ROAD
assemblages <- road_get_assemblages()

# Or we can make more specific queries
lithic_typology <- road_get_lithic_typologies()
lithic_raw_mat <- road_get_lithic_raw_materials()
organic_tools <- road_get_organic_tools()
symbolic <- road_get_symbolic_artifacts()
features <- road_get_features()
mix <- road_get_miscellaneous_finds()
people <- road_get_human_remains()
animals <- road_get_paleofauna()
plants <- road_get_plantremains()

2.1 Lithic Tools

If we stay with our Mousterian people for a bit, we can go into more detail and look at the lithic tools that are present at the localities using the road_get_lithic_typologies() function. But since the Mousterian concept exists in many different classifications, we need to now the exact technocomplexes to query. Using the road_list_argument_values() function once more.

techno <- road_list_argument_values("technocomplex")

We can then take our new techno data frame and grab all technocomplexes that contain the word Mousterian.

df_mousterian <- techno |> filter(str_detect(technocomplex, regex("mousterian", ignore_case = TRUE)))

And use this new data frame to gather all lithic typology data in ROAD that stems from a Mousterian context.

mous_tools <- road_get_lithic_typologies(technocomplex = df_mousterian$technocomplex)

We can then inspect our result.

This tool list as a bit hard to get an overview of, but if we know what we´re looking for, then we can specify this using the tool_list() function which can be used together with the road_get_lithic_typologies() function. We can first use the road_list_argument_values() function to see what our choices are.

road_list_argument_values("tool_list")
#> NA, abrader, adze, anvil, axe polished, bec, bec , bec burin, biface, biface , blade, blade , blade aurignacian, blade crested, blade levallois, blade micro, bladelet, bladelet , bladelet burin spall, bladelet dufour, block, block battered, boulder, burin, burin , burin noailles, chisel, chopper, chopping tool, cleaver, cobble, cobble battered, cobble worked, core, core , core biconical, core bipolar, core blade, core blade , core bladelet, and many more.

This gives us an alphabetical list of all tool types. Let us look for all instances of Levallois technology, a defining element of the Mousterian tradition. The term Levallois occurs in many different cases and in combination with many different words/categories. Luckily, we do not need the entire entry as the tool_list() function conducts a fuzzy search and we can therefore just enter levallois.

mous_levallois <- road_get_lithic_typologies(technocomplex = df_mousterian$technocomplex,
                                           tool_list = "levallois")

Now we have all assemblages with levallois technology present. Let us see how many Mousterian assemblages there are in comparison to assemblages with levallois technology. And let us see how they are distributed across different countries. For that we can use ggplot. But first we need to combine the two dataframes. In order for us to know which rows come from which dataframe once it is merged, we need to give them a new column each with to identify them later for the plot.

# Add a new column called 'source' to each dataset
mous_levallois$source <- "Levallois" # label all rows in this dataframe
mous_tools$source     <- "Mousterian" # label all rows in this dataframe

# Combine the two dataframes into one
combined <- rbind(mous_levallois, mous_tools)

Now we have our combined dataset and we are ready for plotting.

# Plot the combined data in a bar plot
ggplot(combined, aes(x = fct_infreq(country), # x-axis = countries ordered by how often they appear
                     fill = source)) + # colour of the bars is determined on the source columns
  geom_bar(position = "dodge") + # draw side-by-side bars for each 'source'
  coord_flip() + # flip coordinates to make horizontal bars
  labs(
    title = "Levallois vs. Mousterian", # Plot title
    x = NULL, # remove x-axis label as countries are self explanatory
    y = "Assemblages (n=)", # label the y-axis
    fill = "Key" # legend title
  ) +
  scale_y_continuous(breaks = scales::pretty_breaks(n = 10)) + # clean axis ticks
  theme_minimal(base_size = 12) # simple theme and larger font for readability

2.2 Ostrich egg shells

Ostrich egg shells are an interesting material with a variety of uses. In this exercise, we’ll create a quick graph to visualise their appearance across different cultural periods.

First, we can use road_summarize_archaeology() to get an overview of the tables in which these items can be found. The search term ostrich egg shell appears in two tables: miscellaneous finds and symbolic artifacts. In these tables, the term is found in the attributes material and comments, and the hit count indicates how many rows contain these items.

road_summarize_archaeology("ostrich egg shell")
#>                 term           road_get_            attribute hit_number
#> 1  ostrich egg shell miscellaneous_finds             material         96
#> 2  ostrich egg shell  symbolic_artifacts             material         92
#> 3  ostrich egg shell  symbolic_artifacts             comments          3
#> 4  ostrich egg shell miscellaneous_finds             comments          1
#> 5  ostrich egg shell             feature             comments       <NA>
#> 6  ostrich egg shell             feature       interpretation       <NA>
#> 7  ostrich egg shell            function             comments       <NA>
#> 8  ostrich egg shell            function        function_list       <NA>
#> 9  ostrich egg shell            function    functional_traces       <NA>
#> 10 ostrich egg shell miscellaneous_finds  raw_material_source       <NA>
#> 11 ostrich egg shell       organic_tools             comments       <NA>
#> 12 ostrich egg shell       organic_tools       interpretation       <NA>
#> 13 ostrich egg shell       organic_tools organic_raw_material       <NA>
#> 14 ostrich egg shell       organic_tools           technology       <NA>
#> 15 ostrich egg shell        raw_material             comments       <NA>
#> 16 ostrich egg shell        raw_material    raw_material_list       <NA>
#> 17 ostrich egg shell  symbolic_artifacts             category       <NA>
#> 18 ostrich egg shell  symbolic_artifacts       interpretation       <NA>
#> 19 ostrich egg shell  symbolic_artifacts  raw_material_source       <NA>
#> 20 ostrich egg shell  symbolic_artifacts           technology       <NA>
#> 21 ostrich egg shell          technology             comments       <NA>
#> 22 ostrich egg shell          technology         product_list       <NA>
#> 23 ostrich egg shell          technology           technology       <NA>
#> 24 ostrich egg shell          technology      technology_type       <NA>
#> 25 ostrich egg shell            typology             comments       <NA>
#> 26 ostrich egg shell            typology            tool_list       <NA>
#> 27 ostrich egg shell            typology             typology       <NA>

In the next step, we can use this information to run the appropriate query functions: road_get_miscellaneous_finds() and road_get_symbolic_artifacts().

We then combine the two data frames using the merge function.

# Query from miscellaneous finds
eggshell_misc <- road_get_miscellaneous_finds() %>%
  filter(str_detect(miscellaneous_find_material,
                    regex("ostrich egg shell", ignore_case = TRUE))) # filter rows for search pattern

# Query from symbolic artifacts
eggshell_symbolic <- road_get_symbolic_artifacts() %>%
  filter(str_detect(symbolic_artifact_material,
                    regex("ostrich egg shell", ignore_case = TRUE))) # filter rows for search pattern

# Combine dataframes
eggshell_combined <- merge(
  eggshell_misc,
  eggshell_symbolic,
  by = c("locality_id", "assemblage_id", "continent", "subcontinent", "country",
         "locality_type", "coord_x", "coord_y", "assemblage_name", "category",
         "age_min", "age_max", "cultural_period", "technocomplex"),
  all = TRUE
)

Finally, we can visualise the results in a simple bar chart.

# Plot the ostrich egg shell distribution over cultural periods
ggplot(eggshell_combined, aes(y = cultural_period)) +
  geom_bar() +
  labs(
    title = "Ostrich egg shells",
    x = "Number of assemblages",
    y = "Cultural period")

Example #3: Dates

Throughout this tutorial, you may have noticed the columns age_min and age_max, ROAD’s own age estimates based on a combination of all available temporal information, including cultural and radiometric dates — essentially a best guess.

However, if the temporal aspect is crucial for your research, for example a time series analysis, it is important to look at the actual data rather than aggregates.

This is especially true for radiocarbon ages, which are stored as uncalibrated dates in ROAD, and which require you to perform and customise your own age modelling.

For this reason, we implemented road_get_dates().

3.1 Getting chronological dates

Let’s have a look at Hohle Fels, a well-known Palaeolithic cave site in the Swabian Jura with plenty of dates.

Figure 3: Inside the UNESCO site “Hohle Fels” | CC BY-SA Thilo Parg

Hohle Fels is known for a number of fascinating finds, including one nearly complete bone flute and fragments of three ivory flutes that were excavated from archaeological layer Vb (Conard et al. 2009). The radiocarbon ages for this layer were derived from bone and charcoal and were analysed at the Oxford Radiocarbon Accelerator Unit and the Leibniz Laboratory in Kiel.

Figure 4: Flute from the Aurignacian layers of Hohle Fels | H. Jensen/Universität Tübingen

First, we’ll get an overview of all the available assemblages from this site using road_get_assemblages(), and then filter() to narrow down our results to rows, where the column locality_id contains the site name.

In the next step, we download the dates for these assemblages with road_get_dates(). It is a handy feature, that the argument assemblages accepts data frames, like the one we created one step ahead, for filtering the chronological dates.

# Download a data frame of all assemblages and filter for the site
hohle_fels_assemblages <- road_get_assemblages() |> 
  filter(locality_id=="Hohle Fels")

# Use the dataframe to query specific dates
hohle_fels_dates <- road_get_dates(assemblages = hohle_fels_assemblages)

Try to answer the following questions:

  • How many assemblages are there in Hohle Fels

  • How many dates are there?

  • How many of the dates used radiocarbon dating?

  • Which technocomplexes are present at the site?

3.2 Radiocarbon calibration

In this example we will calibrate the radiocarbon dates from the ivory flute layer “AH Vb” from Hohle Fels. To do so, we adapt the code from above, so that it filters for the right locality_id and additionally for the needed archlayer.

flute_dates <- road_get_assemblages() |> 
  filter(locality_id=="Hohle Fels", archlayer=="AH Vb") |> 
  road_get_dates()

We can calibrate the layer Vb ages using the R package rcarbon. Since the site is located in the Northern Hemisphere, we’ll use the “IntCal20” calibration curve (Reimer et al. 2020).

# Load radiocarbon library
library(rcarbon)

# Calibrate
flute_dates_cal <- calibrate(x=flute_dates$age,
                             errors=flute_dates$positive_standard_deviation,
                             calCurves="intcal20")
#> [1] "Calibrating radiocarbon ages..."
#>   |                                                                              |                                                                      |   0%  |                                                                              |=========                                                             |  12%  |                                                                              |==================                                                    |  25%  |                                                                              |==========================                                            |  38%  |                                                                              |===================================                                   |  50%  |                                                                              |============================================                          |  62%  |                                                                              |====================================================                  |  75%  |                                                                              |=============================================================         |  88%  |                                                                              |======================================================================| 100%
#> [1] "Done."

Now the calibrated ages can be displayed using summary().

# Display calibrated ages
summary(flute_dates_cal)
#>   DateID MedianBP  OneSigma_BP_1  OneSigma_BP_2  TwoSigma_BP_1
#> 1      1    43264 43830 to 43597 43447 to 42801 44167 to 42636
#> 2      2    40822 41174 to 40532       NA to NA 41407 to 40011
#> 3      3    39878 40179 to 39524       NA to NA 40512 to 39335
#> 4      4    35758 35998 to 35538       NA to NA 36147 to 35358
#> 5      5    39334 39803 to 39000       NA to NA 40157 to 38042
#> 6      6    35682 35907 to 35441       NA to NA 36102 to 35301
#> 7      7    36493 36808 to 36191       NA to NA 37171 to 35820
#> 8      8    38063 38612 to 37481       NA to NA 39076 to 37157

You can also visualise the results with plot() and multiplot().

# Visualise the first date
plot(flute_dates_cal,1)

# Visualise all dates, with numbers indicating row number
multiplot(flute_dates_cal,
          decreasing=TRUE,
          rescale=TRUE,
          HPD=TRUE,
          label.pos=0.9,
          label.offset=-200) 

The radiocarbon analyses were based on an introduction into the [rcarbon] software. Using this, you can extend your roadDB workflow to create Summed Probability Distributions (SPD), temporal composite kernel density estimates (CKDE) or spatio-temporal analyses, for example.

A dedicated tutorial is available for analyzing chronological data from roadDB in conjunction with the Chronomodel software: https://github.com/ameliechallier/roadDB_chrono_tutorial.

Further Reading

Open-Archaeo: A list of open source archaeological software and resources