<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>About on Bas Ernst</title><link>https://my-site-12f6cf.gitlab.io/</link><description>Recent content in About on Bas Ernst</description><generator>Hugo</generator><language>en-uk</language><copyright>© 2026 Bas Ernst</copyright><lastBuildDate>Thu, 01 Oct 2026 21:32:33 +0200</lastBuildDate><atom:link href="https://my-site-12f6cf.gitlab.io/rss.xml" rel="self" type="application/rss+xml"/><item><title>4 - More SPARQL queries</title><link>https://my-site-12f6cf.gitlab.io/posts/4---more-sparql-queries/</link><pubDate>Thu, 01 Oct 2026 21:32:33 +0200</pubDate><guid>https://my-site-12f6cf.gitlab.io/posts/4---more-sparql-queries/</guid><description>&lt;p&gt;This week I continue studying the basic concepts of RDF. According to my ChatGpt course, I will study other types of queries that allow to filter or aggregate results. Let’s see what that will mean.&lt;/p&gt;
&lt;p&gt;I will again reference mainly this website for studying the concepts: &lt;a href="https://sparql.dev/article/SPARQL_Query_Language_Basic_Concepts_and_Features.html"&gt;https://sparql.dev/article/SPARQL_Query_Language_Basic_Concepts_and_Features.html&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;OPTIONAL&lt;/p&gt;
&lt;p&gt;A user sometimes cannot be certain that the data they are looking for is present in the database. The Optional patterns allow to specify patterns that may or may not be present in the data. This is used to retrieve data that may be missing or incomplete, as it does not require the pattern to match. The syntax for an optional pattern is as follows:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;OPTIONAL {
 query pattern
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;For example, if we wanted to retrieve all organisations in our dataset that have a name defined by schema:name and that may or may not have a ex:presents relation with a project , we would use the following query:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;PREFIX ex: &amp;lt;https://example.org/kg/&amp;gt;
PREFIX schema: &amp;lt;https://schema.org/&amp;gt; 

SELECT ?organisation ?organisationName ?project
WHERE {
 ?organisation schema:name ?organisationName .
 OPTIONAL {
 ?organisation ex:presents ?project .
 }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;can return something like:&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;organisation&lt;/th&gt;
 &lt;th&gt;organisationName&lt;/th&gt;
 &lt;th&gt;project&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;organisation1&lt;/td&gt;
 &lt;td&gt;Organisation One&lt;/td&gt;
 &lt;td&gt;project1&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;organisation2&lt;/td&gt;
 &lt;td&gt;Organisation Two&lt;/td&gt;
 &lt;td&gt;—&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;GROUP BY&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We now look at some of the aggregation clauses when working with SPARQL. The ORDER BY clause is used to create groups of solutions, normally with the intention to perform an aggregation on each group. In the example we return the number of projects per organisation.&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;PREFIX ex: &amp;lt;https://example.org/kg/&amp;gt;

SELECT ?organisation (COUNT(?project) AS ?numberOfProjects)
WHERE {
 ?organisation ex:presents ?project .
}
GROUP BY ?organisation
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This can result in something like:&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;organisation&lt;/th&gt;
 &lt;th style="text-align: right"&gt;numberOfProjects&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;organisation1&lt;/td&gt;
 &lt;td style="text-align: right"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;organisation2&lt;/td&gt;
 &lt;td style="text-align: right"&gt;2&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;organisation3&lt;/td&gt;
 &lt;td style="text-align: right"&gt;7&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;ul&gt;
&lt;li&gt;COUNT&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;COUNT&lt;/code&gt; is another aggregation functions, that allows the user to count the number of occurrences or values of the specified variable. The COUNT funtion is used in the SELECT clause.&lt;/p&gt;
&lt;p&gt;If the user intends to count the number of projects per organisation in the database, they can use the following query:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;PREFIX ex: &amp;lt;https://example.org/kg/&amp;gt;

SELECT ?organisation (COUNT(?project) AS ?numProjects)
WHERE {
 ?organisation ex:presents ?project .
}
GROUP BY ?organisation
&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt;
&lt;li&gt;HAVING&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Having is a related function to GROUP BY. The HAVING clause is used to filter the results produced by GROUP BY based on a specified condition. In the example that follows, the query returns organisations that have presented at least three projects.&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;PREFIX ex: &amp;lt;https://example.org/kg/&amp;gt;

SELECT ?organisation (COUNT(?project) AS ?numberOfProjects)
WHERE {
 ?organisation ex:presents ?project .
}
GROUP BY ?organisation
HAVING (COUNT(?project) &amp;gt;= 3)
&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt;
&lt;li&gt;FILTER&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Filters allows the user to specify additional criteria for the data they want to retrieve. A filter is used to restrict the results of the query based on certain conditions. The syntax for a filter is as follows:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;FILTER(condition)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;For example, if we wanted to retrieve all the people in our dataset who have a foaf:name starting with the letter &amp;ldquo;J&amp;rdquo;, we would use the following query:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;PREFIX foaf: &amp;lt;http://xmlns.com/foaf/0.1/&amp;gt;

SELECT ?name
WHERE {
 ?person foaf:name ?name
 FILTER(STRSTARTS(?name, &amp;#34;J&amp;#34;))
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;It seems that &lt;code&gt;HAVING&lt;/code&gt; and &lt;code&gt;FILTER&lt;/code&gt; are fairly similar.&lt;/p&gt;
&lt;p&gt;The W3C specification describes &lt;code&gt;HAVING&lt;/code&gt; as analogous to &lt;code&gt;FILTER&lt;/code&gt;, but operating over groups rather than individual solutions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;FILTER filters &lt;em&gt;individual&lt;/em&gt; solutions/rows.&lt;/li&gt;
&lt;li&gt;HAVING filters &lt;em&gt;groups&lt;/em&gt; of solutions, usually after GROUP BY and aggregation such as COUNT, SUM, or AVG.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And finally we can combine the previous concepts (GROUP BY, HAVING, COUNT and ORDER BY) together:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;SELECT ?organisation (COUNT(?project) AS ?numProjects)
WHERE {
?organisation ex:presents ?project .
}
GROUP BY ?organisation
HAVING (COUNT(?project) &amp;gt;= 3)
ORDER BY DESC(?numProjects)
&lt;/code&gt;&lt;/pre&gt;</description></item><item><title>3 - SPARQL queries</title><link>https://my-site-12f6cf.gitlab.io/posts/3---sparql-queries/</link><pubDate>Thu, 24 Sep 2026 21:32:33 +0200</pubDate><guid>https://my-site-12f6cf.gitlab.io/posts/3---sparql-queries/</guid><description>&lt;h1 id="learn-to-query-rdf"&gt;Learn to query RDF.&lt;/h1&gt;
&lt;p&gt;SPARQL (a recursive acronym for SPARQL Protocol and RDF Query Language) is the query language to retrieve and manipulate data in an RDF database. SPARQL combines elements from SQL queries with the RDF triple patterns. A SPARQL query applies triple patterns (subject, predicate, object) that can be used to match against the RDF data. SPARQL allows to read and to write to the database. It is primarily a query language, but it also supports operations for modifying RDF data through specific query forms and protocols.&lt;/p&gt;
&lt;p&gt;In this article I try to discuss some of the basic search functions. I am using as a source SPARQL Query Language: Basic Concepts and Features &lt;a href="https://sparql.dev/article/SPARQL_Query_Language_Basic_Concepts_and_Features.html"&gt;sparql.dev&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Essential elements for queries are SELECT, WHERE, and FILTER clauses.&lt;/p&gt;
&lt;p&gt;SELECT&lt;/p&gt;
&lt;p&gt;The SELECT clause specifies which variables will returned by the query as results. The following query retrieves all the predicates and objects associated with the subject “Maria”:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;SELECT ?predicate ?object
WHERE {
 &amp;lt;http://example.org/Maria&amp;gt; ?predicate ?object
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Query elements that start with a question mark are the variables. So, in this case we have the variables ?predicate and ?object.&lt;/p&gt;
&lt;p&gt;WHERE&lt;/p&gt;
&lt;p&gt;The Where clause allows to add constraints to the query in order to return data the meets certain criteria. SPARQL uses a SELECT &amp;hellip; WHERE { &amp;hellip; } structure. Variables start with ?.&lt;/p&gt;
&lt;p&gt;The WHERE clause is used to specify the triple patterns to match against the RDF data. For example, the following query retrieves all triples where the subject is &amp;ldquo;Maria&amp;rdquo; and the object is &amp;ldquo;project3&amp;rdquo;:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;SELECT ?predicate
WHERE {
 &amp;lt;http://example.org/Maria&amp;gt; ?predicate &amp;lt;http://example.org/project3&amp;gt;
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;In this query, the triple pattern &lt;a href="http://example.org/Maria"&gt;http://example.org/Maria&lt;/a&gt; ?predicate &amp;lt;http://example.org/project3 &amp;gt; matches against all triples where the subject is “Maria” and the object is &amp;ldquo;project3&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;FILTER&lt;/p&gt;
&lt;p&gt;The Filter clause ensures that only data is returned that meets the filter criteria. It works as a filter on the amount data to be returned. The FILTER clause is used to apply additional constraints to the query results. For example, the following query retrieves all predicates where the subject is &amp;ldquo;Maria&amp;rdquo; and the object is a string that contains the word &amp;ldquo;Community Voices&amp;rdquo;:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;SELECT ?predicate
WHERE {
 &amp;lt;http://example.org/Maria&amp;gt; ?predicate ?object
 FILTER (CONTAINS(str(?object), &amp;#34;Community Voices&amp;#34;))
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;In this query, the FILTER clause applies a constraint to the ?object variable, ensuring that it contains the words &amp;ldquo;Community Voices&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;ORDER BY&lt;/p&gt;
&lt;p&gt;The ORDER BY clause is used to sort the query results based on a specific variable. For example, the following query retrieves all predicates where the subject is &amp;ldquo;Maria&amp;rdquo; and orders the results by the predicate:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;SELECT ?predicate
WHERE {
 &amp;lt;http://example.org/Maria&amp;gt; ?predicate ?object
}
ORDER BY ?predicate
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;In this query, the ORDER BY clause sorts the results by the ?predicate variable in ascending order.&lt;/p&gt;
&lt;h1 id="run-sparql"&gt;Run SPARQL&lt;/h1&gt;
&lt;p&gt;To run SPARQL queries I use Apache Fuseki. This runs as a server on my local machine while accessing the database I am workng on.&lt;/p&gt;
&lt;p&gt;First step is to install Fuseki. I run a Debian based Linux distribution, and I downloaded the latest Fuseki distribution from Apache.&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;wget https://downloads.apache.org/jena/binaries/apache-jena-fuseki-6.2.0.tar.gz
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Then:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;tar -xzf apache-jena-fuseki-*.tar.gz
cd apache-jena-fuseki-*
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Suppose my Turtle file is:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;~/Development/rdf-course/cultural-graph.ttl
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;You can start Fuseki with a dataset called cultural:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;./fuseki-server --file ~/Development/rdf-course/cultural-graph.ttl /cultural
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now Fuseki is running locally.&lt;/p&gt;
&lt;h2 id="practical-work"&gt;Practical work&lt;/h2&gt;
&lt;p&gt;I use an RDF/SPARQL environment to query the graph I made during previous lessons. Here are some examples of basic queries:&lt;/p&gt;
&lt;h4 id="which-organisations-exist"&gt;Which organisations exist?&lt;/h4&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;PREFIX ex: &amp;lt;https://example.org/kg/&amp;gt;
PREFIX schema: &amp;lt;https://schema.org/&amp;gt; 

SELECT ?organisation 
WHERE { ?organisation a schema:Organisation .}
&lt;/code&gt;&lt;/pre&gt;&lt;h4 id="which-projects-exist"&gt;Which projects exist?&lt;/h4&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;PREFIX ex: &amp;lt;https://example.org/kg/&amp;gt;
PREFIX schema: &amp;lt;https://schema.org/&amp;gt; 

SELECT ?project 
WHERE { ?project a ex:Project .}
&lt;/code&gt;&lt;/pre&gt;&lt;h4 id="which-organisations-participate-in-which-projects"&gt;Which organisations participate in which projects?&lt;/h4&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;PREFIX ex: &amp;lt;https://example.org/kg/&amp;gt;
PREFIX schema: &amp;lt;https://schema.org/&amp;gt; 

SELECT ?organisation ?project 
WHERE { ?project ex:hasPartner ?organisation .}
&lt;/code&gt;&lt;/pre&gt;&lt;h4 id="which-people-work-for-which-organisations"&gt;Which people work for which organisations?&lt;/h4&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;PREFIX ex: &amp;lt;https://example.org/kg/&amp;gt;
PREFIX schema: &amp;lt;https://schema.org/&amp;gt; 

SELECT ?person ?name ?organisation 
WHERE { ?person ex:worksAt ?organisation ;
 schema:name ?name .}
&lt;/code&gt;&lt;/pre&gt;&lt;h4 id="which-projects-belong-to-which-organisation---just-return-the-names"&gt;Which projects belong to which organisation - just return the names?&lt;/h4&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;PREFIX ex: &amp;lt;https://example.org/kg/&amp;gt;
PREFIX schema: &amp;lt;https://schema.org/&amp;gt; 
PREFIX dcterms: &amp;lt;http://purl.org/dc/terms/&amp;gt; 

SELECT ?projectName ?organisationName 
WHERE { ?project ex:hasPartner ?organisation ;
 dcterms:title ?projectName.
		 ?organisation schema:name ?organisationName .}
&lt;/code&gt;&lt;/pre&gt;&lt;h4 id="which-projects-started-after-a-particular-date"&gt;Which projects started after a particular date?&lt;/h4&gt;
&lt;p&gt;Example:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;PREFIX ex: &amp;lt;https://example.org/kg/&amp;gt;

SELECT ?project ?organisation
WHERE { ?project ex:hasPartner ?organisation .}
&lt;/code&gt;&lt;/pre&gt;</description></item><item><title>2 - RDF Modelling and Vocabulary Reuse</title><link>https://my-site-12f6cf.gitlab.io/posts/2---rdf-modelling/</link><pubDate>Mon, 07 Sep 2026 06:32:33 +0200</pubDate><guid>https://my-site-12f6cf.gitlab.io/posts/2---rdf-modelling/</guid><description>&lt;p&gt;&lt;img src="https://my-site-12f6cf.gitlab.io/rdf_logo.png" alt="RDF Logo"&gt;&lt;/p&gt;
&lt;h2 id="objectives"&gt;Objectives&lt;/h2&gt;
&lt;p&gt;This week I continue to improve my understanding of RDF. I use the previous mentioned sources, as well as 3WC and online material.&lt;/p&gt;
&lt;p&gt;Learn about:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Vocabulary reuse&lt;/li&gt;
&lt;li&gt;Namespaces&lt;/li&gt;
&lt;li&gt;Interoperability&lt;/li&gt;
&lt;li&gt;Domain vocabularies&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;RDF is a W3C standard for representing and exchanging structured, machine-readable data on the web, using a graph-based model to describe resources and their relationships.&lt;/p&gt;
&lt;p&gt;What is RDF modelling:&lt;/p&gt;
&lt;p&gt;A way to represent and organise data in a structured manner. As we discussed last week, RDF uses statements consisting of triples. RDF modelling is the process of representing entities, their properties, and relationships as RDF triples, thereby creating a graph describing some domain of interest.&lt;/p&gt;
&lt;p&gt;It can also consist of meta data that describes how data is organised in the RDF model. The purpose is to organise and encode data in such a way that computers can understand them. There are several standards in use to ensure a that rdf data is handled and modelled in a consistent way.&lt;/p&gt;
&lt;p&gt;Vocabularies and ontologies provide terms and semantics.&lt;/p&gt;
&lt;p&gt;For example:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;ex:maria a foaf:Person ;
 foaf:name &amp;#34;Maria Rossi&amp;#34; ;
 ex:worksAt ex:organisation3 .
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="vocabulary-reuse"&gt;Vocabulary reuse&lt;/h3&gt;
&lt;p&gt;Let’s first try to understand what vocabularies are in the context of RDF. A vocabulary describes the use of properties and classes in RDF data (3WC). This collection of terms can be used to describe resources in an RDF graph.&lt;/p&gt;
&lt;p&gt;The reason for reusing existing vocabularies is that developers, data scientists, or others who have worked with RDF before are more likely to understand and work with the data. The terms already have a shared meaning, which makes it easier to exchange and combine data. The disadvantage is that popular shared vocabularies are often quite generic by design and may not cover the specific needs of a particular domain. Therefore, it makes sense to reuse existing terms when they accurately describe what you mean, and extend them when necessary instead of creating everything from scratch.
(&lt;a href="https://medium.com/the-national-archives-digital/reusing-standard-rdf-vocabularies-part-1-5a9bbfa58b85"&gt;https://medium.com/the-national-archives-digital/reusing-standard-rdf-vocabularies-part-1-5a9bbfa58b85&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;Imagine two cultural organisations:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;museum1 ex:hasName &amp;#34;Louvre&amp;#34; .
museum2 ex:hasName &amp;#34;Rijksmuseum&amp;#34; .
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;versus:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;museum1 schema:name &amp;#34;Louvre&amp;#34; .
museum2 schema:name &amp;#34;Rijksmuseum&amp;#34; .
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;If both use schema:name, another dataset can much more easily understand and query both datasets.&lt;/p&gt;
&lt;p&gt;FOAF, Schema.org, Dublin Core and SKOS are all RDF vocabularies used to describe things on the web, but they focus on different domains and overlap in complementary ways.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Schema.org: Used across the web to describe everyday things like products, events, and organisations.&lt;/li&gt;
&lt;li&gt;FOAF (Friend of a Friend): Used to describe people, their profiles, and how they relate to other people.&lt;/li&gt;
&lt;li&gt;Dublin Core: Used to describe digital and physical documents, books, and media files.&lt;/li&gt;
&lt;li&gt;SKOS: Provides terms for describing concepts and knowledge organisation systems such as thesauri, taxonomies and controlled vocabularies.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="namespaces"&gt;Namespaces&lt;/h3&gt;
&lt;p&gt;The IRIs in an RDF vocabulary often begin with a common substring known as a namespace IRI. Some namespace IRIs are associated by convention with a short name known as a namespace prefix.&lt;/p&gt;
&lt;p&gt;A namespace IRI is commonly used as the base for the IRIs of terms belonging to a vocabulary. A namespace prefix is a convenient abbreviation for that IRI in RDF serialisations such as Turtle.&lt;/p&gt;
&lt;p&gt;Some examples:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;@prefix schema: &amp;lt;https://schema.org/&amp;gt; .
@prefix dct: &amp;lt;http://purl.org/dc/terms/&amp;gt; .
@prefix ex: &amp;lt;https://example.org/&amp;gt; .
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="interoperability"&gt;Interoperability&lt;/h3&gt;
&lt;p&gt;Interoperability is a characteristic of a product or system to work with other products or systems.&lt;/p&gt;
&lt;p&gt;In the case of RDF Interoperability is the ability of different systems and datasets to exchange and interpret data consistently. RDF supports interoperability by providing a common data model and allowing datasets to use shared, globally identifiable vocabulary terms.&lt;/p&gt;
&lt;p&gt;As RDF has developed over time, variations in syntax, processing assumptions, and supported features have the potential to create inconsistencies between implementations. W3C aims to mitigate these risks by outlining shared practices for maintaining consistent behaviour.&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;RDF
↓
common graph/data model
↓
shared vocabularies
↓
shared terms and meanings
↓
interoperability
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="domain-vocabularies"&gt;Domain vocabularies&lt;/h3&gt;
&lt;p&gt;Domain vocabularies in RDF (Resource Description Framework) are specialised sets of predefined classes and properties used to describe data and relationships for a specific subject area or industry. The important idea is specialisation.&lt;/p&gt;
&lt;p&gt;Domain vocabulary describes a vocabulary whose terms are specifically concerned with a particular subject/domain. A domain vocabulary can also be a shared vocabulary.&lt;/p&gt;
&lt;p&gt;A general vocabulary like Schema.org won&amp;rsquo;t necessarily capture all the semantics you need. A domain vocabulary such as CIDOC CRM provides much richer concepts for cultural heritage.&lt;/p&gt;
&lt;p&gt;And you can combine them:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;ex:exhibition1 a crm:E7_Activity ;
 schema:name &amp;#34;Italian Renaissance&amp;#34; ;
 dcterms:description &amp;#34;...&amp;#34; .
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Here you&amp;rsquo;re reusing multiple shared vocabularies, including a domain-specific shared vocabulary.&lt;/p&gt;
&lt;p&gt;Let’s have a closer look at four shared vocabularies:&lt;/p&gt;
&lt;h4 id="skos"&gt;SKOS&lt;/h4&gt;
&lt;p&gt;Simple Knowledge Organization System (SKOS) provides a standard way to represent knowledge organisation systems using the Resource Description Framework (RDF). Encoding this information in RDF allows it to be passed between computer applications in an interoperable way.&lt;/p&gt;
&lt;p&gt;SKOS is a data model for representation of thesauri, classification schemes, taxonomies, subject-heading systems, or any other type of structured controlled vocabulary. SKOS is part of the Semantic Web family of standards built upon RDF and RDFS, and its main objective is to enable easy publication and use of such vocabularies as linked data.&lt;/p&gt;
&lt;h4 id="dublin-core-terms"&gt;Dublin Core Terms&lt;/h4&gt;
&lt;p&gt;Dublin Core is an RDFS Schema (RDFS) ontology for metadata management for electronic resources. It is commonly used in the digital and printed publication domain for creative works. It contains concepts like BibliographicResource and Dataset and properties like author, license, language, audience. (Serles)&lt;/p&gt;
&lt;p&gt;DCT is a vocabulary that has been around since 2008 and its use is ubiquitous. Even if somehow the user was not aware of Dublin Core, the naming of the terms is straight-forward. One can likely infer the meaning of &lt;code&gt;dct:identifier&lt;/code&gt; as holding an identifier for the resource, and &lt;code&gt;dct:description&lt;/code&gt; as holding a description of the resource.&lt;/p&gt;
&lt;h4 id="schemaorg"&gt;Schema.org&lt;/h4&gt;
&lt;p&gt;Schema.org is a reference website that publishes documentation and guidelines for using structured data mark-up on web-pages (in the form of microdata, RDFa or JSON-LD). Its main objective is to standardise HTML tags to be used by webmasters for creating rich results (displayed as visual data or infographic tables on search engine results) about a certain topic of interest. It is a part of the semantic web project, which aims to make document mark-up codes more readable and meaningful to both humans and machines.&lt;/p&gt;
&lt;p&gt;Schema.org is a collaborative, community activity with a mission to create, maintain, and promote schemas for structured data on the Internet, on web pages, in email messages, and beyond.&lt;/p&gt;
&lt;h4 id="foaf"&gt;FOAF&lt;/h4&gt;
&lt;p&gt;The FOAF (&amp;ldquo;Friend of a Friend&amp;rdquo;) project is a community driven effort to define an RDF vocabulary for expressing metadata about people, and their interests, relationships and activities.&lt;/p&gt;
&lt;p&gt;FOAF is a machine-readable ontology describing persons, their activities and their relations to other people and objects. Anyone can use FOAF to describe themselves. FOAF allows groups of people to describe social networks without the need for a centralised database.&lt;/p&gt;
&lt;p&gt;FOAF is a descriptive vocabulary expressed using the Resource Description Framework (RDF) and the Web Ontology Language (OWL).&lt;/p&gt;
&lt;h3 id="reflection-using-chatgpt"&gt;Reflection using ChatGpt&lt;/h3&gt;
&lt;p&gt;During my final project at the Open University, I worked with RDF before, although my experience is still quite limited. I came across some of the four vocabularies that I have now studied. The additional context provided in this lesson is definitely helpful. However, I still do not have a clear understanding of which concepts are best handled by one of these vocabularies, or perhaps by other vocabularies. I suppose I will have to find that out by working more with RDF and building up my experience.&lt;/p&gt;</description></item><item><title>1 - Understanding RDF</title><link>https://my-site-12f6cf.gitlab.io/posts/1----studying-towards-knowledge-graphs-rdf/</link><pubDate>Sat, 29 Aug 2026 06:32:33 +0200</pubDate><guid>https://my-site-12f6cf.gitlab.io/posts/1----studying-towards-knowledge-graphs-rdf/</guid><description>&lt;p&gt;&lt;img src="https://my-site-12f6cf.gitlab.io/knowledge_graph.png" alt="Knowledge graph"&gt;
Image taken from: &lt;a href="https://deeppavlov.ai/research/tpost/bn15u1y4v1-improving-knowledge-graph-completion-wit"&gt;Deeppavlov.ai&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;When studying towards my undergraduate in IT I got interested in graph databases. In the graph data model, things are related to other things. These things and relationships can be further detailed by adding properties. In the background, the data of the graph data is abstracted away from the user and stored in appropriated data structures. Graph databases depend on graph theory stemming from mathematics, where the things are called vertices or nodes and connected with edges. The mathematical concepts from graph theory can be used for working with graphs in computer science, for instance for calculating shortest distances between nodes via edges.&lt;/p&gt;
&lt;p&gt;I am learning RDF, Resource Description Framework, as a model for expressing statements. This will become useful as I aim studying knowlegde graphs that can use RDF. I am currently using these two resources:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Hogan, Aidan, Claudio Gutierrez, Michael Cochez, et al. Knowledge Graphs. Synthesis Lectures on Data, Semantics, and Knowledge. Springer International Publishing, 2022. &lt;a href="https://doi.org/10.1007/978-3-031-01918-0"&gt;https://doi.org/10.1007/978-3-031-01918-0&lt;/a&gt;.&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;Serles, Umutcan, and Dieter Fensel. An Introduction to Knowledge Graphs. Springer Nature Switzerland, 2024. &lt;a href="https://doi.org/10.1007/978-3-031-45256-7"&gt;https://doi.org/10.1007/978-3-031-45256-7&lt;/a&gt;.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;RDF is used as a data model for an RDF graph database. RDF is the framework to organise and represent data as triples.&lt;/p&gt;
&lt;p&gt;More formally, the things I mentioned earlier can be represented as triples consisting of subjects and objects connected by predicates. A subject is related to something else, an object, through a predicate (the relationship). The reasoning goes from subject via the predicate to the object: an RDF triple is directed.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://my-site-12f6cf.gitlab.io/rdf_basics.jpg" alt="Simple RDF model showing subject, predicate and object"&gt;&lt;/p&gt;
&lt;p&gt;One of the fundamental ideas of using RDF, is that a subject is represented by some unique identifier, related to something else represented by a unique identifier or a literal value (something with a datatype, such as strings, integers, dates), or a blank node (a node without an IRI or literal value).&lt;/p&gt;
&lt;p&gt;The unique nodes are identified with an IRI (Internationalised Resource Identifier) which denotes a resource. This is key in RDF, which is based on working with resources. IRIs are similar to URIs. An IRI is essentially an internationalised form of a URI, allowing a much broader range of Unicode characters. Nodes and edges can have human readable labels.&lt;/p&gt;
&lt;p&gt;Namespaces are used to avoid naming collisions and to provide a way of grouping and identifying terms. A prefix provides a short name for an IRI namespace, allowing long IRIs to be written in a more compact form. They make RDF more readable and manageable. In short In RDF, a namespace is a base IRI (like &lt;a href="http://xmlns.com/foaf/0.1/)"&gt;http://xmlns.com/foaf/0.1/)&lt;/a&gt;, and a prefix is a short label (like foaf) used to make long IRIs short and easy to read.&lt;/p&gt;
&lt;p&gt;Blank nodes are different from IRIs and literals. They are typically used for unnamed objects or describing complex constructs.&lt;/p&gt;
&lt;p&gt;In synthesis (Serles)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The subject of a triple can be an IRI or a blank node.&lt;/li&gt;
&lt;li&gt;The predicate of a triple must be an IRI.&lt;/li&gt;
&lt;li&gt;The object of a triple can be any of the three types of terms.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To wrap it all up as: A set of RDF triples comprise an RDF graph. Therefore, they are often presented as graphs. An RDF graph is a labelled, directed graph where nodes represent resources (IRI or literal) and blank nodes and edges represent predicates that connect two resources denoted by the subjects and objects of triples. (Serles)&lt;/p&gt;</description></item><item><title>Asking Chatgpt to come up with a RDF course</title><link>https://my-site-12f6cf.gitlab.io/posts/rdf-course-developed-with-chatgpt/</link><pubDate>Sat, 15 Aug 2026 06:32:33 +0200</pubDate><guid>https://my-site-12f6cf.gitlab.io/posts/rdf-course-developed-with-chatgpt/</guid><description>&lt;p&gt;&lt;img src="https://my-site-12f6cf.gitlab.io/learning_rdf_chatgpt.png" alt="Chatgpt generated image for this course"&gt;&lt;/p&gt;
&lt;h2 id="learning-rdf-a-hands-on-approach"&gt;Learning RDF: a hands-on approach&lt;/h2&gt;
&lt;p&gt;While writing my BSc thesis, I learned the basics of labelled property graphs, working mainly with Neo4j, and I also experimented a little with RDF-based graph querying using Wikidata.&lt;/p&gt;
&lt;p&gt;I decided that, at some point, I wanted to spend more time understanding RDF properly. The reason is that I want to learn more about Knowledge Graphs and, in particular, explore the RDF world in more depth.&lt;/p&gt;
&lt;p&gt;One of the things I want to find out is whether RDF and its related technologies allow me to describe a specific domain of my research in a richer and more precise way than I could with a labelled graph. I have some ideas about this, but I want to test them through practical examples rather than simply assuming that RDF is the better approach.&lt;/p&gt;
&lt;p&gt;I have been reading two textbooks on the subject. However, I have found myself feeling a little like I am reading dictionaries: they describe a huge number of possibilities, but often without giving me a clear path through the concepts or enough hands-on examples to build up a proper understanding.&lt;/p&gt;
&lt;p&gt;That is why I decided to ask ChatGPT to develop a tailor-made course for me. The idea is to learn RDF and related technologies step by step, apply them to examples from the cultural and NGO sectors, and gradually build something more substantial.&lt;/p&gt;
&lt;p&gt;So I asked ChatGPT to design a 14-week course. This is what it came up with:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Week 1 – RDF fundamentals&lt;/strong&gt;
Understanding triples, IRIs, literals, blank nodes, Turtle and the RDF data model.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Week 2 – Reusing vocabularies&lt;/strong&gt;
Working with existing vocabularies such as Schema.org and understanding when and why to reuse them.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Week 3 – SPARQL fundamentals&lt;/strong&gt;
Querying RDF graphs and learning the basic structure of SPARQL queries.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Week 4 – Advanced SPARQL&lt;/strong&gt;
Exploring more complex queries, filtering, aggregation, optional patterns and federated queries.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Week 5 – Setting up a local triplestore&lt;/strong&gt;
Moving beyond examples and working with a local RDF database, using Apache Jena/Fuseki.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Week 6 – RDFS and inference&lt;/strong&gt;
Understanding classes, subclasses, properties and how RDF Schema can be used to derive new information.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Week 7 – Introduction to OWL&lt;/strong&gt;
Moving from basic RDF/RDFS towards ontologies and understanding what OWL adds.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Week 8 – OWL restrictions and modelling&lt;/strong&gt;
Working with restrictions, classes, properties and more expressive ways of describing a domain.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Week 9 – The Open World Assumption&lt;/strong&gt;
Understanding one of the important differences between RDF/OWL reasoning and the assumptions we often make when working with conventional databases.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Week 10 – OWL, SPARQL, SHACL and application logic&lt;/strong&gt;
Exploring what each technology is good at and, importantly, what it is &lt;em&gt;not&lt;/em&gt; designed to do.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Week 11 – SKOS&lt;/strong&gt;
Learning how controlled vocabularies, thesauri and classification schemes can be represented as RDF.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Week 12 – SHACL validation&lt;/strong&gt;
Using shapes to define constraints and validate RDF data.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Week 13 – Working with RDF programmatically&lt;/strong&gt;
Using Python and Java to create, query and manipulate RDF data.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Week 14 – A cultural/NGO Knowledge Graph&lt;/strong&gt;
Bringing everything together in a small practical project based on a realistic cultural or NGO domain.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The course itself is only the starting point. For each topic, I study the subject using books, academic articles, documentation and discussions in relevant online forums. I then bring what I have found back to ChatGPT, discuss and challenge the results, and use that process to clarify my understanding and identify gaps or inconsistencies. Finally, I write my own version of the material. In this way, ChatGPT is not simply providing the course content; it acts more as a tutor and discussion partner while I use other sources to build and verify my understanding. Let&amp;rsquo;s see if this aproacj will work out well.&lt;/p&gt;</description></item><item><title>Graduation Open University - BSc in Computing and IT</title><link>https://my-site-12f6cf.gitlab.io/posts/graduation/</link><pubDate>Sun, 29 Mar 2026 11:32:33 +0200</pubDate><guid>https://my-site-12f6cf.gitlab.io/posts/graduation/</guid><description>&lt;p&gt;&lt;img src="https://my-site-12f6cf.gitlab.io/graduation_ceremony_square.jpeg" alt="Me crossing the stage at the Barbican in London during the Open University graduation ceremony"&gt;&lt;/p&gt;
&lt;p&gt;On Saturday 28 March 2026 I attended the graduation ceremony of the Open University at the Barbican Centre in London, an absolutely brilliant event and a memorable way to celebrate with my biggest supporters the conclusion of an eight-year journey studying part-time towards a BSc in Computing and IT.
I have always enjoyed learning, ever since I was a child, and that curiosity helped me through the many assignments, deadlines, and eventually a thesis on data analysis in diplomacy and gender.
What I learned during these years is already proving useful in my work. And who knows, perhaps &lt;em&gt;computational cultural diplomacy&lt;/em&gt; might one day become a discipline in its own right.
For now, I am simply grateful for the journey… and already thinking about the next study objective for the coming years.&lt;/p&gt;</description></item><item><title>Evaluating Cultural Diplomacy projects with Neo4j</title><link>https://my-site-12f6cf.gitlab.io/posts/evalutating_cultural_diplomacy_neo4j/</link><pubDate>Sat, 21 Mar 2026 11:32:33 +0200</pubDate><guid>https://my-site-12f6cf.gitlab.io/posts/evalutating_cultural_diplomacy_neo4j/</guid><description>&lt;p&gt;I will once again work with the small dataset I used for my previous post. However, this time I will not use Calc or Excel, but a graph database. Of course, for this tiny dataset, using this tool could be considered overkill. However, as I plan to add more projects and countries to the analysis in future iterations, the advantages of a graph-based database will become clearer. Since it is well suited for analysing networks, it will allow us, in future versions of this project, to analyse cultural relations by examining them as a network.&lt;/p&gt;
&lt;p&gt;For now, I will partially repeat the same analysis as in my previous post, but I will also add some new analyses that are not easily possible with a tabular spreadsheet. For more info on the data, see &lt;a href="https://my-site-12f6cf.gitlab.io/posts/evaluating_cultural_diplomacy_made_easy/"&gt;evaluating_cultural_diplomacy_made_easy&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Beyond that, I find graph databases more intuitive than relational databases. In cultural diplomacy, missions and their teams either manage cultural projects directly (engaging artists directly) or collaborate with external partners. This is far easier to visualise as a network than as a table of columns and rows.&lt;/p&gt;
&lt;p&gt;Graph databases are built on the idea that things in real life are connected to each other. These things are called &lt;strong&gt;nodes&lt;/strong&gt;, and they can have relationships. Graph databases are highly flexible and easy to work with, supporting a wide range of data types. For example, Wikipedia is based on a graph database.
For my project, I’ll be using &lt;strong&gt;Neo4j&lt;/strong&gt;, one of the market leaders in this space. Its query language is called &lt;strong&gt;Cypher&lt;/strong&gt;, and Neo4j offers excellent learning resources on its website, making it quick to pick up. I use both their &lt;strong&gt;Community Server Edition&lt;/strong&gt;, which runs locally on my system, and their cloud solution, &lt;strong&gt;Aura&lt;/strong&gt;, which adds useful tools like &lt;strong&gt;Bloom&lt;/strong&gt; for exploration and dashboards.
Of course, if you’re working with sensitive data, it’s worth while considering other solutions than corporate clouds. Since I’m using fake data for this project, there’s no issue.&lt;/p&gt;
&lt;p&gt;Let’s start by considering how to manage our data and constructing a simple data model. Conceptually, I find the &lt;strong&gt;Theory of Change&lt;/strong&gt; useful (it has of course it limits, not in the last place it implies presumes causality between inputs and outputs which is not easy to demonstrate). It analyses how policy implementation can achieve meaningful impact. Using this framework, we can:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Identify a challenge to address,&lt;/li&gt;
&lt;li&gt;Deploy specific instruments,&lt;/li&gt;
&lt;li&gt;Generate results,&lt;/li&gt;
&lt;li&gt;Analyse the outcomes, and&lt;/li&gt;
&lt;li&gt;Measure how these contribute to broader policy goals.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The Theory of Change helps structure the thought process into a model that supports cultural diplomacy, focusing on instruments most likely to generate positive outcomes. You can read more about it on Wikipedia &lt;a href="https://en.wikipedia.org/wiki/Theory_of_change"&gt;Theory of Change&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;For this use case, I opted for the following data model. In Cypher a datamodel can be called with the following query:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code class="language-cypher" data-lang="cypher"&gt;CALL db.schema.visualization()
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;img src="https://my-site-12f6cf.gitlab.io/dataModel.png" alt="Image of the datamodel. On the lefthand side the team member, who is connected to a organisation they follow. Each organisation organises one or more projects. The projects contribute to goals, but also relate to &amp;ldquo;date&amp;rdquo;, &amp;ldquo;region&amp;rdquo; and &amp;ldquo;discipline&amp;rdquo;."&gt;&lt;/p&gt;
&lt;p&gt;Starting on the left, each team member is linked to one or more organizations they follow. Each organization manages one or more projects, which in turn contribute to specific goals. Additionally, each project is associated with a date, a region, and a discipline.&lt;/p&gt;
&lt;p&gt;One feature I particularly appreciate is the ability to generate a &lt;strong&gt;graph visualisation&lt;/strong&gt; of team members and their partners. While this is a small example, it effectively illustrates the team’s dynamics: who is working on what, and what the team is collectively focused on. For this example, I’ve included two team members, Eve and Mike, along with their local cultural partners. To visuelise their relations, I used the following query:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code class="language-cypher" data-lang="cypher"&gt;(t:TeamMember)-[f:FOLLOWS]-&amp;gt;(p:Partner) RETURN t,f,p;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Which returns:&lt;/p&gt;
&lt;p&gt;&lt;img src="https://my-site-12f6cf.gitlab.io/graphTeam.png" alt="Graps visualisation of a team working with cultural organisations."&gt;&lt;/p&gt;
&lt;p&gt;As in my previous post, Neo4j allows you to calculate aggregations such as the average, maximum, and minimum grant amounts. Using its built-in dashboard functionality, you can easily generate visualisations, such as a bar graph showing the total and average grants awarded to different cultural disciplines.&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code class="language-cypher" data-lang="cypher"&gt;MATCH (p:Project)-[:HAS_DISCIPLINE]-&amp;gt;(d:Discipline)
RETURN d.name AS discipline, COUNT(p.naam) AS projects, SUM(p.grant) AS totalGrants, SUM(p.grant)/COUNT(p.naam) AS `average grant`
ORDER BY projects DESC;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Neo4j Aura generates an interactive graph that allows the user to indicate what variables to include. The user can switch between properties. In this case, the totals and averages are displayed.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://my-site-12f6cf.gitlab.io/barPlotDisciplines.png" alt="A bar plot indicating the total and average amounts of grants given to projects in five artistic disciplines"&gt;&lt;/p&gt;
&lt;p&gt;Finally, Cypher queries can be integrated into a &lt;strong&gt;Jupyter notebook&lt;/strong&gt;. This combination is very powerful, merging the flexibility of a graph database with the robust data analysis and visualisation tools offered by Pandas. In a future update, I’ll share examples of how this approach can enhance the analysis of cultural diplomacy projects. Before that, I will write a post in which I will illustrate setting up the graph database combining this small dateset and Neo4j.&lt;/p&gt;</description></item><item><title>Setting up a graph database</title><link>https://my-site-12f6cf.gitlab.io/posts/setting_up_graph_database_evaluation_cultural_diplomacy/</link><pubDate>Fri, 06 Mar 2026 11:32:33 +0200</pubDate><guid>https://my-site-12f6cf.gitlab.io/posts/setting_up_graph_database_evaluation_cultural_diplomacy/</guid><description>&lt;p&gt;In my previous post I mentioned using a graph database to store data from a small cultural diplomacy database. This would be most useful considering partners and projects as a network. The example data that I am using here is rather small, but eventually I can add more data and this type of database will become more usefull. Intuitively a graph database is easier to visualise mentally than a traditional relational database. Basically it boils down to &amp;rsquo;things&amp;rsquo; that are related to other &amp;rsquo;things'.&lt;/p&gt;
&lt;p&gt;In this post I will show how to set up the nodes and relationships that model the reality of my simple cultural diplomacy dataset. I will start with the datamodel that visualises how the data elements relate to each other. Using the data in my previous post, it consist of the nodes and relationships that I will build now.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://my-site-12f6cf.gitlab.io/dataModel.png" alt="Image of the datamodel. On the lefthand side the team member, who is connected to a organisation they follow. Each organisation organises one or more projects. The projects contribute to goals, but also relate to &amp;ldquo;date&amp;rdquo;, &amp;ldquo;region&amp;rdquo; and &amp;ldquo;region&amp;rdquo;."&gt;&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s start working from left to righ. I will first create the nodes of the two team members. Cypher can read &lt;code&gt;csv&lt;/code&gt; files. In this case fields are separated by a semi-colon, which we should indicate. Cypher reads the csv file form row to row.&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code class="language-cypher" data-lang="cypher"&gt;LOAD CSV WITH HEADERS
FROM &amp;#39;file:///randomProjectList2.csv&amp;#39; AS row
FIELDTERMINATOR &amp;#39;;&amp;#39;
WITH row
MERGE (p:`TeamMember` {naam: row.`TeamMember`})
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;When I run this code, Neo4j will return a graphical representation of the team member nodes. As some of the projects are followed by more then one team member, we get three nodes of which one with the list containing both member. We can limit the representation to the only two staff members by separating the names that are present in a list of names.&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code class="language-cypher" data-lang="cypher"&gt;LOAD CSV WITH HEADERS
FROM &amp;#39;file:///randomProjectList2.csv&amp;#39; AS row
FIELDTERMINATOR &amp;#39;;&amp;#39;
WITH row,
 split(row.TeamMember, &amp;#39;,&amp;#39;) AS members
UNWIND members AS staff
WITH row, trim(staff) AS TeamMember

MERGE (p:`TeamMember` {naam: row.`TeamMember`})
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The creation of the other nodes is pretty much following a similar pattern. Except for projects, where I have added a various properties that describe projects.&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code class="language-cypher" data-lang="cypher"&gt;FROM &amp;#39;file:///randomProjectList.csv&amp;#39; AS row
FIELDTERMINATOR &amp;#39;;&amp;#39;
WITH row,

MERGE (p:Project {name: row.`Project Name`})
SET p.id = row.`Project ID`
SET p.grant = toFloat(row.Grant)
SET p.budget = toFloat(row.`Project budget`)
SET p.disciplines = row.Discipline
SET p.regios = row.Region
SET p.months = row.Month
SET p.participants = toInteger(row.`Number national participants`)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The nodes are related with each other through relationships. The relationships express how and in what way the nodes are connected. Team members &lt;em&gt;follow&lt;/em&gt; cultural partner organisations. Cultural organisations &lt;em&gt;organise&lt;/em&gt; cultural projects. In Cypher this can be define with the following expression. In this example the two nodes &lt;code&gt;TeamMember&lt;/code&gt; and &lt;code&gt;Partner&lt;/code&gt; are connected with the relationship &lt;code&gt;FOLLOWS&lt;/code&gt;. The same procedure can be followd for a &lt;code&gt;Partner&lt;/code&gt; that &lt;code&gt;ORGANISES&lt;/code&gt; a &lt;code&gt;Project&lt;/code&gt; In cypher these triplets are formed as follows.&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code class="language-cypher" data-lang="cypher"&gt;(t:TeamMember)-[f:FOLLOWS]-&amp;gt;(p:Partner)
(p:Partner)-[o:ORGANISES]-&amp;gt;(a:Project)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;And just as an example, this is how you can create a relationship:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code class="language-cypher" data-lang="cypher"&gt;LOAD CSV WITH HEADERS
FROM &amp;#39;file:///randomProjectList.csv&amp;#39; AS row
FIELDTERMINATOR &amp;#39;;&amp;#39;
WITH row,
 split(row.Discipline, &amp;#39;,&amp;#39;) AS disciplines
UNWIND disciplines AS sector
WITH row, trim(sector) AS discipline

MERGE (d:Discipline {name: discipline})
MERGE (p:Project {naam: row.`Project Name`})

MERGE (p)-[:HAS_DISCIPLINE]-&amp;gt;(d)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;These were some examples and code snippets how to set up the graph database. Neo4j&amp;rsquo;s website contains some great documentation as well as online course that will teach you effectively how to create cypher queries to set up up your database and return data from it. &lt;a href="https://neo4j.com/docs/"&gt;Neo4j Docs&lt;/a&gt;.&lt;/p&gt;</description></item><item><title>Why Evaluation and Monitoring Matter in Cultural Diplomacy</title><link>https://my-site-12f6cf.gitlab.io/posts/why_evaluating_cultural_diplomacy_matters/</link><pubDate>Sun, 22 Feb 2026 11:32:33 +0200</pubDate><guid>https://my-site-12f6cf.gitlab.io/posts/why_evaluating_cultural_diplomacy_matters/</guid><description>&lt;p&gt;&lt;img src="https://my-site-12f6cf.gitlab.io/chart-data.jpg" alt="A hand with a pen and a paper with charts on it, photo by Lukas https://www.pexels.com/@goumbik"&gt;&lt;/p&gt;
&lt;p&gt;There are many definitions about cultural diplomacy. I profer to consider my work as a pracitce through which states and/or international organisations pursue foreign policy objectives. There exists many approaches how to implement cultural diplomacy.
In this field measuring results and impacts is often considered problematic. There is still a common perception that cultural projects cannot be measured. Some argue that quantitative analysis fails to capture the complexity and nuance of artistic work. Others point out a more practical challenge: in cultural diplomacy there is often limited time, and evaluation activities are the first to be postponed or neglected.
I understand the difficulties of measuring impact of artistic work, but in this field of work we are not merely artistic directors. Cultural diplomats collaborate with organisations and practitioners who create and deliver artistic content. Therefore, cultural diplomacy is less about making artistic choices and more about building networks, facilitating partnerships, and identifying strategic opportunities. Our role is often one of connection, coordination and positioning rather than curation.
So, despite the difficulties, why is it important to try to measure results in cultural diplomacy?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Without data, it becomes difficult to tell the story of what has been achieved. Careful analysis can reveal patterns and insights that would otherwise remain hidden. Numbers do not replace narratives, but they support them.&lt;/li&gt;
&lt;li&gt;Cultural teams in diplomatic missions should also see themselves as learning teams. Reflection requires input. Structured monitoring helps teams understand what worked well, what did not, and why. This is not about control; it is about continuous improvement.&lt;/li&gt;
&lt;li&gt;There is also an important dimension of accountability. In diplomacy, we work with taxpayers’ money. The public has a right to know how cultural budgets are used and what impact they generate.&lt;/li&gt;
&lt;li&gt;Finally, from an internal perspective, having reliable data strengthens a team’s position. Evidence-based reporting allows you to defend your work and demonstrate performance using your own data.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Another common obstacle is the perceived lack of technical knowledge. How should projects be tracked? How should data be structured? In reality, one can start very simply. Tools such as LibreOffice Calc, Excel, or Google Sheets are entirely sufficient to build a basic monitoring system.
If you are interested, you can find the tutorial here: &lt;a href="https://my-site-12f6cf.gitlab.io/posts/evaluating_cultural_diplomacy_made_easy/"&gt;evaluating_cultural_diplomacy_made_easy&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Evaluation of cultural projects made easy</title><link>https://my-site-12f6cf.gitlab.io/posts/evaluating_cultural_diplomacy_made_easy/</link><pubDate>Sun, 15 Feb 2026 11:32:33 +0200</pubDate><guid>https://my-site-12f6cf.gitlab.io/posts/evaluating_cultural_diplomacy_made_easy/</guid><description>&lt;p&gt;&lt;img src="https://my-site-12f6cf.gitlab.io/excel_evaluation_sheet.png" alt="image of excel sheet containing data discussed in this article"&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Making evaluations of cultural projects easy&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;In general, those working in cultural diplomacy tend to focus on making projects happen. Collecting and analysing data for monitoring and evaluation purposes is often seen as a challenge. A lack of time, limited expertise, or simply a lack of priority can all stand in the way. However, with relatively little effort, it is possible to gather basic project data, carry out straightforward analysis, calculate key indicators and produce meaningful visualisations. Even setting up a simple document in Excel, Calc, or any other readily available spreadsheet programme can be an effective first step towards visualising the results of your work.&lt;/p&gt;
&lt;p&gt;This tutorial provides some easy steps to evaluate projects. For this purpose I made a simple Excel sheet that can be a starting point. Click &lt;a href="https://my-site-12f6cf.gitlab.io/randomProjectList2.xlsx"&gt;here&lt;/a&gt; to download.&lt;/p&gt;
&lt;p&gt;This will enable us to answer questions such as:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;How many projects did we support?&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;In which regions did we support projects?&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;How many projects took place per month?&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;How many projects were there per discipline?&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;What is the average, minimum and maximum grant amount?&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;How many euros did our partners invest for each euro from our side?&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Which projects scored best against our policy goals?&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;What do you need?&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;A list of projects&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Grants per project&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Project budget (Dutch part of the budget)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Starting date&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Month (enter the month as a number; Excel will convert this to the correct month).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Number of our national participants (artists, makers, …) per project&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Disciplines per project&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A score per policy goal, depending on how you measure a project&amp;rsquo;s contribution to policy goals.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Step 1: Define the column names. For example&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Project ID&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Project Name&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Subsidy&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Project budget&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Partner organisation&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Region&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Start date&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Month&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Number of national participant&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Goal 1&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Goal 2&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Goal 3&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Weighted average&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Discipline&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Then comes the more tedious part: populating your Excel spreadsheet with data. Ensure that numbers are recognised as numbers and dates as dates. You can do this by selecting the relevant cells and checking &amp;lsquo;Format cells&amp;rsquo;. Numbers should not be treated as text; otherwise, calculations will not be possible.&lt;/p&gt;
&lt;p&gt;All the data in this example has been generated randomly. The scores for the three imaginary policy goals could be the scores that you and your team gave to projects, or the results of a questionnaire. It depends on what is available.&lt;/p&gt;
&lt;p&gt;The weighted average of the scores for the policy goals is calculated so that a final score between 0 and 1 is returned.&lt;/p&gt;
&lt;p&gt;Goal 1 contains scores from 1 to 5; therefore, the results are divided by 5.&lt;/p&gt;
&lt;p&gt;Goal 2 contains scores from 0 to 2; therefore, the results are divided by 3.&lt;/p&gt;
&lt;p&gt;Since there are three policy goals in this example, the sum of the three scores is divided by 3.&lt;/p&gt;
&lt;p&gt;The whole table is ordered so that the weighted average column goes from highest to lowest score. This will be needed for a visualisation later.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Step 2 Aggregate results&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;In order to create visualisations, we need to prepare the data by grouping the required variables. Excel wants us to calculate totals by discipline, month, and so on before we can use the data for charts.&lt;/p&gt;
&lt;p&gt;We are going to count how many times a project takes place in a certain region. I created a new list of regions in column T and used Excel&amp;rsquo;s built-in &lt;code&gt;COUNTIF&lt;/code&gt; function to count how many times a region appears in that column. If you click on one of the cells, you can see the formula: &lt;code&gt;=COUNTIF($G6:$G23;T6)&lt;/code&gt;. This counts how many times the word in cell T6 (which refers to &amp;lsquo;Region 1&amp;rsquo;) is present in the column from G6 to G23. You can use this format for other aggregations, of course.&lt;/p&gt;
&lt;p&gt;For disciplines, I changed the formula slightly to ensure that cells containing multiple disciplines separated by commas are counted individually. This formula is similar to that used to count the number of regions, except that it separates words divided by commas: &lt;code&gt;=COUNTIF($P$6:$P$23;&amp;quot;\*&amp;quot; &amp;amp; W6 &amp;amp; &amp;quot;\*&amp;quot;)&lt;/code&gt;. Here, &amp;ldquo;W6&amp;rdquo; refers to &amp;ldquo;Design&amp;rdquo;, and Excel looks in the P6–P23 column. Enclosing the W6 cell between stars and ampersands lets us count occurrences in cells with multiple results.&lt;/p&gt;
&lt;p&gt;The procedure for the months is the same as for the regions. Again, make sure that the months in column I are stored as dates (you can do this by changing the cells&amp;rsquo; format).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Step 3: Perform some basic calculations&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Excel has all the basic functionality required to calculate averages, minimums and maximums. We will use this for grants. For example, the average grant is calculated using the formula &lt;code&gt;=AVERAGE(D6:D23)&lt;/code&gt; in the “Subsidy” column.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Step 4: Visualise the results&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Visualisations such as bar and pie charts are powerful tools for revealing the stories hidden in data. The Insert pane in Excel offers plenty of charting solutions. I have included some examples. The procedure is essentially the same for all of them.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;First, select the data you want to use; for example, the disciplines and their scores.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Then click on the type of chart that you want in the &amp;lsquo;Insert&amp;rsquo; pane, for example &amp;lsquo;bar chart&amp;rsquo;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Excel will then generate the visualisation.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;There are many options for fine-tuning the presentation of a chart. You can change colours, headings, and so on, depending on your use case. Excel also has a built-in feature “Recommended Charts” that assists the user selecting the most suitable chart.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Step 5: Conclusions&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Even this short data sheet demonstrates that meaningful visualisations can be generated to show the results of the work carried out. By examining the responses gathered through the sheet, we were able to address all of the questions.&lt;/p&gt;
&lt;p&gt;How many projects did we support?&lt;/p&gt;
&lt;p&gt;18 Projects&lt;/p&gt;
&lt;p&gt;In which regions did we support projects?&lt;/p&gt;
&lt;p&gt;&lt;img src="https://my-site-12f6cf.gitlab.io/projects-per-region.png" alt="graph with projects per region"&gt;&lt;/p&gt;
&lt;p&gt;How many projects took place per month?&lt;/p&gt;
&lt;p&gt;&lt;img src="https://my-site-12f6cf.gitlab.io/projects-per-month.png" alt="graph with projects per month"&gt;&lt;/p&gt;
&lt;p&gt;How many projects per discipline?&lt;/p&gt;
&lt;p&gt;&lt;img src="https://my-site-12f6cf.gitlab.io/projects-per-discipline.png" alt="graph with projects per discpline"&gt;&lt;/p&gt;
&lt;p&gt;What is the average grant amount, the minimum, and maximum&lt;/p&gt;
&lt;p&gt;Average grant per project		 € 5.650,00&lt;br&gt;
Min grant				 € 1.400,00&lt;br&gt;
Max grant				 € 9.200,00&lt;/p&gt;
&lt;p&gt;How many euros did our partners invest for each euro from our side?&lt;/p&gt;
&lt;p&gt;€ 6.11&lt;/p&gt;
&lt;p&gt;Which projects scored best against our policy goals?&lt;/p&gt;
&lt;p&gt;&lt;img src="https://my-site-12f6cf.gitlab.io/ranking_porojects.png" alt="graph with ranking of projects"&gt;&lt;/p&gt;
&lt;p&gt;I hope this worksheet has served as a helpful example of how, with minimal effort and only a basic understanding of data analysis, you can begin collecting meaningful information about a cultural diplomacy programme. The data itself is not an end in its own right; rather, it provides a starting point from which you can tell the story of your work and demonstrate how your particular programme of projects has contributed to your wider objectives.&lt;/p&gt;</description></item><item><title>Gender and Diplomacy</title><link>https://my-site-12f6cf.gitlab.io/posts/gender-diplomacy/</link><pubDate>Tue, 30 Dec 2025 21:32:33 +0200</pubDate><guid>https://my-site-12f6cf.gitlab.io/posts/gender-diplomacy/</guid><description>&lt;p&gt;&lt;img src="https://my-site-12f6cf.gitlab.io/map_diplo_gender.png" alt="Map visualising part of female diplomatic network 2021"&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Analysing Gender and Diplomacy using Neo4j and Pandas&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;In December 2025, I completed my BSc in Computing and IT at the Open University in the UK. For my final project, I deliberately chose a topic that connects my interest in data analysis with my professional field, diplomacy.&lt;/p&gt;
&lt;p&gt;My final research project focused on gender and diplomacy. In summer 2024, I discovered the &lt;em&gt;GenDip&lt;/em&gt; dataset developed by the University of Gothenburg. This dataset maps all diplomatic relations by gender for the period 1968–2021 and was published with an explicit invitation for scholars to analyse the data and enrich it with additional sources. One of the central questions posed by the project was whether states use the appointment of female ambassadors as an instrument of diplomacy in its own right.&lt;/p&gt;
&lt;p&gt;I used a range of data analysis tools to address this and related questions, with particular attention to how the structure of international relations networks influences the behaviour of the diplomatic network. My research is based on graph analysis and offers alternative perspectives on explaining the persistent under-representation of women in diplomacy.&lt;/p&gt;
&lt;p&gt;This report is an elaboration of the final research project. It presents the data analysis on gender and diplomacy and documents both the research process and its results. Much of the required reflections by the Open University on the learning process, references to previous OU modules and explanations of how the research builds upon them have been omitted here.&lt;/p&gt;
&lt;p&gt;Despite some statistical limitations, my research confirms the GenDip findings on the systematic under-representation of women in diplomacy. By integrating additional datasets, I also propose alternative explanations. Here are some of the &lt;strong&gt;main findings&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The project demonstrates the potential of graph data science for research on diplomacy and international relations.&lt;/li&gt;
&lt;li&gt;Women are under-represented in senior diplomatic positions, and states appear to make strategic decisions about where to post female ambassadors.&lt;/li&gt;
&lt;li&gt;Countries with women holding influential positions in key foreign policy areas tend to attract a relatively higher share of female ambassadors.&lt;/li&gt;
&lt;li&gt;Living conditions and levels of gender inequality in host countries are significant indicators: women are more frequently posted to countries with better overall conditions.&lt;/li&gt;
&lt;li&gt;Despite its limitations, the additional religion dataset suggests that Buddhist and Muslim countries send a higher proportion of their female ambassadors to countries that promote gender equality, indicating that religion may be a factor worthy of further investigation.&lt;/li&gt;
&lt;li&gt;The project started with the question of whether countries use female ambassadorial appointments as a political signal. By combining relevant variables with network centrality measures, I identified countries, beyond the frequently cited case of Saudi Arabia, that deviate from the dominant patterns within the diplomatic network. In this way, the analysis aims to provide useful input for future research.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To read the study, click &lt;a href="https://my-site-12f6cf.gitlab.io/gender_diplomacy.pdf"&gt;Open PDF&lt;/a&gt;&lt;/p&gt;</description></item></channel></rss>