Problem 1 - Choropleth map

library(plotly)
## Loading required package: ggplot2
## 
## Attaching package: 'plotly'
## The following object is masked from 'package:ggplot2':
## 
##     last_plot
## The following object is masked from 'package:stats':
## 
##     filter
## The following object is masked from 'package:graphics':
## 
##     layout
library(dplyr)
## 
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
library(readr)
library(rworldmap) # For country boundaries
## Loading required package: sp
## ### Welcome to rworldmap ###
## For a short introduction type :   vignette('rworldmap')
data <- read_csv("C:/Users/ipasq/OneDrive/Desktop/Masters Work - Robert Morris University/Data Visualization/Week 2/Evolution_DataSets.csv")
## Rows: 12000 Columns: 28
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (25): Genus_&_Specie, Location, Zone, Current_Country, Habitat, Incisor_...
## dbl  (3): Time, Cranial_Capacity, Height
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
# Preprocess the data: calculate the average Cranial Capacity for each Current Country
country_data <- data %>%
  group_by(Current_Country) %>%
  summarise(Avg_Cranial_Capacity = mean(Cranial_Capacity, na.rm = TRUE))

# Join with the country boundaries data
countries <- rworldmap::getMap(resolution = "low")
country_data <- merge(countries@data, country_data, by.x = "NAME", by.y = "Current_Country")

# Create the choropleth map
p <- plot_ly(type = 'choropleth', locationmode = 'country names',
             locations = country_data$NAME, z = country_data$Avg_Cranial_Capacity,
             text = country_data$NAME, colors = 'Purples')

# Add layout details
p <- p %>% layout(title = 'Average Cranial Capacity by Country',
                  geo = list(projection = list(type = 'natural earth')))

# Display the map
p

Analysis

For this visualization I figured I would try something different. I decided to build an interactive choropleth map that depicts average cranial capacity of early hominids grouped by location. What I did to build this was find a data set in R that has country boundaries, and then I matched it to the locations that are provided to me in the Evolution_dataset that I use for my work.

Using the ‘rWorldMap’ library allowed me to map countries to their geographical boundaries. Once this was accomplished I was able to work with ‘plotly’ to use the variable ‘Current_Country’ as the location identifier and ‘Cranial_Capacity’ as the value to be visualized. The biggest obstacle that I ran into with this project was handling some missing country names, and a few mismatched country names. It was also a challenge to find ‘rWorldMap’ and learn how to use it in conjunction with my existing data.

For the analysis we can see that in accordance with established theory. The early hominids that historically had the highest cranial capacity were the neanderthal or ‘Homo Neanderthalensis’. These hominids had a wide span of territory, but in the data set that I am working with has the majority of the population living in what is now modern day Germany. This is important, because many central Europeans including Germans, French, and Scandinavian peoples can trace their genetic heritage to Neanderthal DNA. This is often a contentious point, claiming that instead of being out competed by rival hominid species, or going extinct from natural disaster; Perhaps Neanderthal’s were genetically assimilated into what is now Modern Homo Sapien.

There are other takeaways such as the presence of Homo Erectus (Widely considered the first man-like hominid) living in modern day Indonesia. Considering a 2 million year fossil record, Erectus had a high cranial capacity compared to other hominids of its time, possibly leading to how they were able to colonize and populate island territories. Possibly using tools that were believed to not have been used until hundred’s of thousand years later.

Problem 2 - Animated Choropleth Map of Cranial Capacity over Time.

library(plotly)
library(dplyr)
library(readr)

# Load the dataset
data <- read_csv("C:/Users/ipasq/OneDrive/Desktop/Masters Work - Robert Morris University/Data Visualization/Week 2/Evolution_DataSets.csv")
## Rows: 12000 Columns: 28
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (25): Genus_&_Specie, Location, Zone, Current_Country, Habitat, Incisor_...
## dbl  (3): Time, Cranial_Capacity, Height
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
# Filter the data to include only the last 1 million years
data <- data %>%
  filter(Time <= 1) # Time is in million years

# Create a human-readable time label (this won't be the x-axis label anymore to avoid redundancy)
data$Time_Label <- paste(round(data$Time * 1000), "thousand years ago")

# Find the range for the x-axis based on the Time data to ensure all points are visible
time_range <- range(data$Time, na.rm = TRUE)

# Create the animated line graph focusing only on Cranial Capacity
p <- plot_ly(data, x = ~Time, y = ~Cranial_Capacity, text = ~Time_Label, type = 'scatter',
             mode = 'lines+markers', frame = ~Time_Label, line = list(color = 'red')) %>%
  layout(
    title = 'Cranial Capacity Over the Last 1 Million Years',
    xaxis = list(title = 'Time (in million years)', range = time_range), # Set x-axis range
    yaxis = list(title = 'Cranial Capacity (cc)'),
    showlegend = FALSE
  ) %>%
  animation_opts(frame = 100, redraw = TRUE) %>%
  animation_slider(currentvalue = list(prefix = "Time: ", font = list(color = "blue", size = 20)))

# Display the plot
p

Analysis

This animated line graph illustrates the variations in cranial capacity over the last million years, serving as a visual proxy for the evolutionary trends among hominid species. Each point on the graph represents average cranial capacity measurement at a specific time slice, capturing the essence of evolutionary changes across the epochs within the dataset’s scope. As the animation progresses through time, note we are viewing from present day to 1 million years ago, we observe a trend of increasing cranial capacity. This suggests a possible correlation with cognitive development and environmental adaptation, or periods of stasis and decline, indicating other evolutionary pressures or events.

This animation posed significant challenges. Initially, the inclusion of the full dataset led to a heavy computational load, causing the R environment to run slowly and freeze. This issue was mitigated by filtering the dataset to concentrate on the most recent million years, significantly reducing the number of frames and thereby easing the computational burden. Additionally to enhance readability, the time variable was reformatted from raw numerical representations to a more interpretable label indicating “thousand years ago,” improving the audience’s ability to track evolutionary progress across a comprehensible temporal scale.

Another issue was the redundancy in displaying time and ensuring that all data points were visible and within the graph’s boundaries. I still had this issue, but I kind of resolved it by adjusting the time labels and setting the x-axis range to encapsulate the entire data spread. As a result, the final animated graph provides a somewhat clear, concise narrative of cranial evolution, showcasing the intricate dance of hominid development over a significant expanse of time.