Transformez vos données CSV en RDF

Lynda Temal - Transformez vos données CSV en RDF

Dans cet article, je vais vous présenter un exemple qui permet de passer d’une simple vue tabulaire de données en CSV, interprétable par un humain, vers une vue en RDF interprétable par la machine et interrogeable par SPARQL.

Avant de commencer, rappelons quelques notions de base :

RDF (Resource Description Framework) est un modèle de graphe destiné à décrire de façon formelle les ressources Web et leurs métadonnées, de façon à permettre le traitement automatique de telles descriptions. Développé par le W3C, RDF est le langage de base du Web sémantique. L’une des syntaxes (ou sérialisations) de ce langage est RDF/XML. D’autres sérialisations de RDF sont apparues ensuite, cherchant à rendre la lecture plus compréhensible ; c’est le cas par exemple de Notation3 (ou N3).

Merci Wikipedia.

L’élément de base de RDF est le triplet : Subject Predicat Object.

Grâce à ce formalisme, nous pouvons décrire des données de façon compréhensible par les humains et interprétable par les machines. Comme vu précédemment, RDF est également un modèle de graphe où les sujets et objets représentent les nœuds et les prédicats sont les arcs orientés du graphe.

RDF_PaternFigure1

Un objet peut être sujet dans un autre triplet, ce qui permet de construire le graphe de connaissances lié aux données.

Vous allez me demander : “quel est l’intérêt de passer de CSV à RDF” ?

Il existe plusieurs bénéfices à cette représentation des données en RDF :

  • le lien entre les données dans une ligne CSV n’a pas de sens réel: les données ne sont liées que parce qu’elles sont dans la même ligne. Alors qu’en RDF les données de cette ligne sont reliées explicitement avec des prédicats.
  • les noms de colonnes sont à titre indicatif pour un humain. Elles sont parfois codées ou indiquent uniquement une partie du nom complet, alors qu’en RDF on définit des prédicats qui donnent du sens au lien qui lie le sujet à l’objet.
  • Il est difficile de fusionner deux CSV en gardant la cohérence du document alors qu’il suffit de fusionner deux fichiers RDFs sans altérer la validité du fichier.
  • L’interopérabilité est difficile à assurer avec du CSV alors que RDF (et les ontologies en particulier) représente la brique de base pour assurer l’interopérabilité sémantique.

Pour avoir une introduction complète vous pouvez consulter les slides de la présentation de la soirée « I love my Data »  ici. Ainsi que l’introduction à SPARQL ici.

Exemple :

Dans l’exemple que j’ai pris, nous allons transformer des données sur les musées de France qui se trouvent ici.

Les lignes ci-dessous sont extraites du fichier :

RDF_Tableau

Après transformation, une ligne du CSV aura la forme suivante :

RDF_ontorefineRdfExampleFigure2

Pour passer du CSV au format RDF, il existe plusieurs outils. Dans cet exemple je vais utiliser l’outil ontoRefine de GraphDB.

GraphDB est une base de données de graphe sémantique qui permet aux organisations de stocker, d’organiser et de gérer du contenu sous forme de données intelligentes sémantiquement enrichies.

Pour installer GraphDB, allez ici. Une fois GraphDB lancé il est accessible via le lien http://localhost:7200/.

RDF_graphdb_figure3

  • Créez un nouveau Repository en cliquant sur le lien : Create new Repository.

RDF_graphdb_createRepo_figure4

  • Renseignez le Repository l’ID, le titre et l’URL de base.
  • Cliquez sur le bouton create.
  • Sélectionnez le Repository que vous venez de créer (en haut à droite) .
  • Cliquez sur Import (dans le menu à gauche) puis sur Tabular (OntoRefine).

RDF_graphdb_Ontorefine_figure5

  • Chargez le fichier CSV qui liste les musées de France que vous avez téléchargé précédemment.

RDF_graphdb_Ontorefine_createProject_figure6

  • Cliquez sur next (le fichier va être chargé) (transformer le séparateur de “;” à “,” s’il ne se charge pas correctement. Faites attention à avoir un CSV correct).

RDF_graphdb_Ontorefine_uploadFile_figure7

  • Une fois les données CSV chargées correctement, cliquez sur le bouton Create Project.

RDF_graphdb_Ontorefine_figure8

  • Cliquez sur le bouton SPARQL

RDF_graphdb_Ontorefine_construct_figure10

  • Écrire la requête CONSTRUCT selon vos besoins, puis cliquez sur run :

La requête construct permet de construire un graphe RDF à partir d’autres graphes RDF. Ainsi dans notre exemple, nous passons d’une représentation des données via des noms de colonnes pas toujours évidentes à comprendre et non interprétables par la machine, vers une représentation à l’aide de concept et de prédicats qui explicite le lien entre les données. Les concepts et les relations (prédicats) peuvent provenir de vocabulaires en ligne largement utilisés dans le domaine.

Par exemple pour représenter l’adresse nous utilisons schema.org (utilisé également par Google, Yahoo, Bing et bien d’autres). Pour représenter la longitude et la latitude, nous utilisons ce système.

Ci-dessous la requête SPARQL qui permet de générer le RDF à partir des colonnes du fichier CSV.

Les lignes 1–8 représentent les préfixes des vocabulaires ou ontologies utilisés dans la requête. La ligne 9 est le mot clé CONSTRUCT qui permet de construire de nouveaux triplets comme résultat de la requête. Les lignes 10–25 sont les patterns du graphe qu’on veut construire. La ligne 26 est la clause WHERE qui contient les conditions sur la construction du graph.

Les lignes 28–39 représentent l’accès au graphe intermédiaire, mappé à partir du CSV. Les lignes 40–42 permettent de construire l’URI des ressources. Les lignes 43–45 permettent de donner le bon type aux valeurs (XMLSchema).

PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX urn: <http://fliqz.com/>
PREFIX : <http://example.com/ontology/museum>
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX sch: <http://schema.org/>
PREFIX geo: <http://www.w3.org/2003/01/geo/wgs84_pos#>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
CONSTRUCT {
   ?museumURI a :Museum;
    	foaf:name ?nomMusee;
    	:locatedInRegion ?region;
    	:locatedInDepartement ?dep;
        :locatedInCity ?ville;
        sch:address ?adrURI;
       	geo:location ?geolocUri;
    	:annualClosingPeriode ?fermetureAnnuelle;
    	:openingPeriode ?periodeOuverture.
   ?adrURI a sch:PostalAddress;
        sch:streetAddress ?rue;
        sch:postalCode ?codePostalNum;
        sch:addressLocality ?ville.
  ?geolocUri a geo:Point;
        geo:long ?longDouble;
        geo:lat ?lalatDoublet.
} WHERE{
  
  ?sub <urn:col:NOMREG> ?region;
       <urn:rowNumber> ?id;
       <urn:col:NOMDEP> ?dep;
       <urn:col:NOM_DU_MUSEE> ?nomMusee;
       <urn:col:ADR> ?rue;
       <urn:col:CP> ?codePostal;
       <urn:col:VILLE> ?ville;
       <urn:col:SITWEB> ?siteWeb;
       <urn:col:latitude> ?lat;
       <urn:col:longitude> ?long;
       <urn:col:FERMETURE_ANNUELLE> ?fermetureAnnuelle;
       <urn:col:PERIODE_OUVERTURE> ?periodeOuverture.
  BIND(URI(Concat("http://example.com/", ?id)) as ?museumURI)
  BIND(URI(Concat("http://example.com/", ?id, "/adr")) as ?adrURI)
  BIND(URI(Concat("http://example.com/", ?id, "/loc")) as ?geolocUri)
  BIND (xsd:double(?long) as ?longDouble)
  BIND (xsd:double(?lat) as ?latDouble)
  BIND (xsd:integer(?codePostal) as ?codePostalNum)
}

 

RDF_graphdb_Ontorefine_endPoint_figure11

  • Cliquez ensuite sur le lien SPARQL endPoint et copiez le lien. Ce lien permet d’accéder au graphe que nous venons juste de construire avec la requête précédente.
  • Puis cliquez sur SPARQL dans le menu à gauche.

RDF_graphdb_sparql_insert_figure12

  • Écrire la requête INSERT qui va insérer les triplets construits dans le graphe virtuel via la Fonction SERVICE. La ligne 10 représente la clause INSERT qui permet d’insérer les triplets. La ligne 29 est la clause SERVICE qui permet de se connecter à un autre end point. Dans notre cas, on se connecte au endpoint d’ontoRefine.
REFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX urn: <http://fliqz.com/>
PREFIX : <http://example.com/ontology/museum#>
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX sch: <http://schema.org/>
PREFIX geo: <http://www.w3.org/2003/01/geo/wgs84_pos#>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>

INSERT {
  ?museumURI a :Museum;
        foaf:name ?nomMusee;
        foaf:homePage ?siteWeb;
        :locatedInRegion ?region;
        :locatedInDepartement ?dep;
        :locatedInCity ?ville;
        sch:address ?adrURI;
        geo:location ?geolocUri;
        :annualClosingPeriode ?fermetureAnnuelle;
        :openingPeriode ?periodeOuverture.
  ?adrURI a sch:PostalAddress;
        sch:streetAddress ?rue;
        sch:postalCode ?codePostalNum;
        sch:addressLocality ?ville.
  ?geolocUri a geo:Point;
        geo:long ?longDouble;
        geo:lat ?lalatDoublet.
} where{
  service <http://localhost:7200/rdf-bridge/1956163084749>{
  select * where{
  ?sub <urn:col:NOMREG> ?region;
       <urn:rowNumber> ?id;
       <urn:col:NOMDEP> ?dep;
       <urn:col:NOM_DU_MUSEE> ?nomMusee;
       <urn:col:ADR> ?rue;
       <urn:col:CP> ?codePostal;
       <urn:col:VILLE> ?ville;
       <urn:col:SITWEB> ?siteWeb;
       <urn:col:latitude> ?lat;
       <urn:col:longitude> ?long;
       <urn:col:FERMETURE_ANNUELLE> ?fermetureAnnuelle;
       <urn:col:PERIODE_OUVERTURE> ?periodeOuverture.
  BIND(URI(Concat("http://example.com/museum/", ?id)) as ?museumURI)
  BIND(URI(Concat("http://example.com/museum/", ?id, "/adr")) as ?adrURI)
  BIND(URI(Concat("http://example.com/museum", ?id, "/loc")) as ?geolocUri)
  BIND (xsd:double(?long) as ?longDouble)
  BIND (xsd:double(?lat) as ?latDouble)
  BIND (xsd:integer(?codePostal) as ?codePostalNum)
  }
 }
} 

Maintenant que nous avons les données dans le repository, nous pouvons faire des requêtes SPARQL intéressantes. Par exemple, la requête suivante donne les distances entre deux musées à Paris.

RDF_graphdb_museumDistance_figure15

Mais avant cela, il est nécessaire d’activer les requêtes géospatiales ainsi que l’indexation des données géospatiales. Pour cela, il suffit d’exécuter les requêtes suivantes dans GraphDB.

RDF_graphdb_enableGeosparqlIndex_figure14

# requête pour créer l’index
PREFIX ontogeo: <http://www.ontotext.com/owlim/geo#>
INSERT DATA { _:b1 ontogeo:createIndex _:b2. }

RDF_graphdb_enableGeosparql_figure13

#requête pour permettre les requêtes geosparql
PREFIX  geosparql: <http://www.ontotext.com/plugins/geosparql#>
INSERT DATA {
    _:s geosparql:enabled "true".
 }

Ci-dessous, la requête qui permet de calculer les distances entre les musées de Paris.

RDF_graphdb_museumDistanceQuery_figure16

Les lignes 1–6 sont les préfixes. La ligne 8 est la clause SELECT qui liste les variables résultats de la requête. Les lignes 10–23 représentent les patterns du graphe recherché. Les lignes 24–25 sont des filtres pour restreindre le résultat à la ville de Paris et comparer des musées différents. La ligne 26 est la fonction qui permet de calculer la distance à partir de la latitude et de la longitude de deux points.

PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX : <http://example.com/ontology/museum#>
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX geo: <http://www.w3.org/2003/01/geo/wgs84_pos#>
PREFIX omgeo:   <http://www.ontotext.com/owlim/geo#>

SELECT ?nameA ?nameB ?city ?distance 
WHERE { 
     ?museumA a :Museum;
         :locatedInCity ?city;
         foaf:name ?nameA;
         geo:location ?locationA.
     ?museumB a :Museum;
     	 foaf:name ?nameB;
         :locatedInCity ?city;
         geo:location ?locationB.
    ?locationA a geo:Point;
         geo:lat ?latA;
         geo:long ?longA.
    ?locationB a geo:Point;
         geo:lat ?latB;
         geo:long ?longB.
    FILTER(?museumA != ?museumB)
    FILTER (regex(?city, 'Paris', 'i'))
    BIND( omgeo:distance(?latA, ?longA, ?latB, ?longB) as ?distance)

Ci-dessous, le résultat de la requête :

RDF_graphdb_museumDistanceResult_figure17

Conclusion

Nous avons vu comment il est possible de passer d’une vue tabulaire plate sans aucune sémantique vers une vue en RDF qui permet de représenter les données en graphe, avec des liens sémantiques explicites. Ces données sont ensuite exploitées via SPARQL, qui est à la fois un langage de requêtes, un langage de résultats et un protocole de communication.

Notez que ce que je vous ai montré est juste l’un des usages des technologies du Web sémantique. L’interopérabilité, l’enrichissement, l’inférence et la connexion à d’autres données liées sont quelques autres des bénéfices de la sémantique.

Dans un prochain billet, je vais vous montrer comment mapper une base de données relationnelle à un graphe virtuel, pour mieux exploiter les données et les inférences.

Vous aimerez aussi...