-
Notifications
You must be signed in to change notification settings - Fork 0
Data provenance modelling example with sub properties
Proposal for modelling data provenance, illustrated for readability in RDF Turtle, but in practice this will be serialized in JSON-LD. The idea is to define an abstract gender property with sub properties that foreground provenance of gender data: f.e. assumedGender, recordedGender, selfIdentifiedGender, livedGender. "Abstract" means instances can never have a gender property, only one of its sub properties. The modelling example also includes sample SPARQL queries that illustrate how gender data and can be queried. The pseudocode script illustrates the proposed logic for provenance-based assignment of the gender property. Other properties such as nationality, country, should be modelled, queried and assigned in the same way.
@prefix : <http://example.org/data/> .
@prefix canon: <http://example.org/ontology/> .
@prefix homosaurus: <https://homosaurus.org/v3/> .
@prefix prov: <http://www.w3.org/ns/prov#> .
@prefix dct: <http://purl.org/dc/terms/> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
# property hierarchy
canon:gender a rdf:Property ;
rdfs:label "gender (abstract)" ;
rdfs:comment "Abstract superproperty for all gender-related properties." .
canon:recordedGender a rdf:Property ;
rdfs:label "recorded gender" ;
rdfs:subPropertyOf canon:gender ;
rdfs:comment "Gender recorded in official sources or references." .
canon:assumedGender a rdf:Property ;
rdfs:label "assumed gender" ;
rdfs:subPropertyOf canon:gender ;
rdfs:comment "Gender inferred from name, title, or other heuristic." .
# instance 1: from Wikidata with external reference
# gender has reference in Wikidata -> recordedGender
:personX canon:recordedGender homosaurus:homoit0001048 ;
prov:wasDerivedFrom :WikidataDump2025-06-01 ;
prov:hadPrimarySource <https://external.source.org/12345> .
:WikidataDump2025-06-01 a prov:Entity ;
dct:title "Wikidata JSON dump from June 1, 2025" ;
dct:source <https://wikidata.org> .
# instance 2: from Wikidata with qualifier P887 "based on heuristic"
# gender based on heuristic in Wikidata -> assumedGender
:personZ canon:assumedGender homosaurus:homoit0001048 ;
prov:wasDerivedFrom :WikidataDump2025-06-01 ;
prov:wasInformedBy <https://en.wikipedia.org/wiki/Some_Person> .
:WikidataDump2025-06-01 a prov:Entity ;
dct:title "Wikidata JSON dump from June 1, 2025" ;
dct:source <https://wikidata.org> .
# instance 3: from authority file with heuristic
# gender is from GND -> assumedGender
:personY canon:assumedGender homosaurus:homoit0001509 ;
prov:wasDerivedFrom :AuthorityFileX .
:AuthorityFileX a prov:Entity ;
dct:title "National Authority File XYZ" ;
dct:source <https://authority.example.org/> ;
rdfs:comment "Gender was assumed based on names and roles." .
# add link to authority file docsExamples for Wikidata based on heuristic qualifier for statements about gender: https://wikis.fu-berlin.de/spaces/phaenodh/pages/1560576942/Kolloquium+%C2%BBPh%C3%A4nomenologie+der+Digital+Humanities%C2%AB+Wintersemester+2024+2025?preview=/1560576942/1595180104/2024-11-15%20Dani%20Metelli%20-%20Wikidata%20Gender%20Diversity%20(Slides).pdf
Simple query for gender of all entities:
PREFIX canon: <http://example.org/ontology/>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
SELECT ?person ?genderProperty ?genderValue WHERE {
?genderProperty rdfs:subPropertyOf canon:gender .
?person ?genderProperty ?genderValue .
}Detailed query for sources for gender values for all entities
PREFIX canon: <http://example.org/ontology/>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX prov: <http://www.w3.org/ns/prov#>
SELECT ?person ?genderProperty ?genderValue ?source WHERE {
?genderProperty rdfs:subPropertyOf canon:gender .
?person ?genderProperty ?genderValue ;
prov:wasDerivedFrom ?source .
}RECORDED_GENDER = "canon:recordedGender"
ASSUMED_GENDER = "canon:assumedGender"
GENERIC_GENDER = "canon:gender"
WIKIDATA = "WikidataDump2025-06-01"
AUTHORITY_FILE = "AuthorityFileX"
for person in dataset:
gender_value = None
gender_property = GENERIC_GENDER
source = None
primary_source = None
# Wikidata
if person.source == "wikidata":
claim = person.get_claim("P21") # sex or gender
if claim is not None:
gender_value = normalize_value(claim.value)
source = WIKIDATA
# has reference
if claim.has_reference("P854"): # external reference URL
gender_property = RECORDED_GENDER
primary_source = claim.get_reference("P854")
# has qualifier (based on heuristic "name")
elif claim.has_qualifier("P887") and is_wikipedia_url(claim.get_qualifier("P887")):
gender_property = ASSUMED_GENDER
primary_source = claim.get_qualifier("P887")
# GND
elif person.source == "authority_file":
gender_value = normalize_value(person.data["gender"])
gender_property = ASSUMED_GENDER
source = AUTHORITY_FILE
if gender_value:
emit_triple(subject=person.uri, predicate=gender_property, object=gender_value)
emit_triple(subject=person.uri, predicate="prov:wasDerivedFrom", object=source)
if primary_source:
emit_triple(subject=person.uri, predicate="prov:hadPrimarySource", object=primary_source)