Ex.4-Reconstructing Intellectual Biographies from Fragmentary Data

📘 Context

You’re part of a research group working on reconstructing the intellectual networks and careers of 17th–18th century scholars using fragmented archival metadata. The data comes from digitized registers of academic appointments, correspondence, travel logs, and publication dates.

The data is partial and irregular: people may appear under different names, records may have missing fields, and events are sometimes only approximated by decade or country.


📂 Dataset Structure (Python list of dicts)

python individuals = [
{
"name": "Gottfried Wilhelm Leibniz",
"activity": "publication",
"location": "Leipzig",
"year": 1666,
"details": "Disputatio Metaphysica de Principio Individui"
},
{
"name": "G. W. Leibniz",
"activity": "correspondence",
"location": "Paris",
"year": 1672,
"details": "Letter to Arnauld"
},
{
"name": "Isaac Newton",
"activity": "appointment",
"location": "Cambridge",
"year": 1669,
"details": "Lucasian Professor of Mathematics"
},
{
"name": "I. Newton",
"activity": "publication",
"location": "London",
"year": 1687,
"details": "Philosophiæ Naturalis Principia Mathematica"
},
...
]

🎯 Assignment Tasks

🧩 1. Name Normalization

Create a function normalize_names(data) that returns a new dataset where names are unified based on a dictionary of aliases:

python aliases = {
"G. W. Leibniz": "Gottfried Wilhelm Leibniz",
"I. Newton": "Isaac Newton"
}

This ensures all records for the same person are aggregated under a single canonical name.


🕰️ 2. Career Timeline Construction

Write a function build_timelines(data) that returns a dictionary like this:

python {
"Isaac Newton": [(1669, "appointment", "Cambridge"), (1687, "publication", "London")],
"Gottfried Wilhelm Leibniz": [(1666, "publication", "Leipzig"), (1672, "correspondence", "Paris")]
}

The list should be sorted by year.


🧭 3. Geographic Mobility Map

Write a function mobility_paths(data) that returns, for each person, a chronologically ordered list of cities they were active in, without repetition:

python {
"Isaac Newton": ["Cambridge", "London"],
"Gottfried Wilhelm Leibniz": ["Leipzig", "Paris"]
}

This allows the study of scholarly migration.


🧮 4. Crossing Paths Detection

Write a function identify_intersections(data) that returns all pairs of individuals who were active in the same city during the same decade, regardless of activity type.

Output format:

python [
("Isaac Newton", "Edmond Halley", "London", "1680s"),
("Leibniz", "Arnauld", "Paris", "1670s")
]

📊 5. Activity Summary Table

Write a function activity_summary(data) that returns a nested dictionary:

python {
"Isaac Newton": {"publication": 1, "appointment": 1},
"Leibniz": {"publication": 1, "correspondence": 1}
}

This shows which scholars were more active in specific types of events.


💡 Optional Bonus Task

🌐 Temporal Network Matrix

Construct a matrix (dictionary of dictionaries) that shows how many times each pair of individuals were active in the same decade, even if not in the same place.

python {
("Leibniz", "Newton"): 2,
("Leibniz", "Arnauld"): 1,
...
}

This can be used to infer indirect intellectual synchronicities.