ホーム 記事一覧 ブック DH週間トピックス 検索 このサイトについて
English
Odeuropa Explorer の語彙階層構造を調査する

Odeuropa Explorer の語彙階層構造を調査する

はじめに Odeuropa Explorer は、ヨーロッパの嗅覚遺産をデジタル化した興味深いプロジェクトです。EU の Horizon 2020 研究プログラムの助成を受け、歴史的な匂いの体験を横断的に検索・探索できるプラットフォームを提供しています。 このプロジェクトでは、匂いに関連する情報を以下の3つの主要なカテゴリで分類しています: Smell sources : 匂いを発する物体や物質 Fragrant Spaces : 匂いに関連する場所や空間 Gestures and Allegories : 匂いに関する身振りや寓意的表現 本記事では、これらの語彙がどのような階層構造を持っているのか、Odeuropa vocabularies リポジトリで公開されている SKOS(Simple Knowledge Organization System)形式のデータを調査した結果を報告します。 調査方法 SKOS階層の可視化スクリプト 語彙の階層構造を理解するために、Node.js で SKOS Turtle ファイルを解析するスクリプトを作成しました。 import $rdf from 'rdflib'; import fs from 'fs'; const SKOS = $rdf.Namespace('http://www.w3.org/2004/02/skos/core#'); async function visualizeHierarchy(ttlFile) { const store = $rdf.graph(); const data = fs.readFileSync(ttlFile, 'utf8'); $rdf.parse(data, store, 'http://example.org/', 'text/turtle'); // Get all concepts const concepts = store.match(null, $rdf.sym('http://www.w3.org/1999/02/22-rdf-syntax-ns#type'), SKOS('Concept')); // Build maps for broader/narrower relationships const broaderMap = new Map(); const narrowerMap = new Map(); const conceptLabels = new Map(); for (const concept of concepts) { const subject = concept.subject; // Get prefLabel const labels = store.match(subject, SKOS('prefLabel'), null); if (labels.length > 0) { conceptLabels.set(subject.value, labels[0].object.value); } // Get broader concepts const broaders = store.match(subject, SKOS('broader'), null); if (broaders.length > 0) { const broader = broaders[0].object.value; broaderMap.set(subject.value, broader); if (!narrowerMap.has(broader)) { narrowerMap.set(broader, []); } narrowerMap.get(broader).push(subject.value); } } // Print hierarchy recursively function printHierarchy(conceptUri, indent = '', visited = new Set()) { if (visited.has(conceptUri)) return; visited.add(conceptUri); const label = conceptLabels.get(conceptUri); const children = narrowerMap.get(conceptUri) || []; console.log(`${indent}${label}`); children.forEach((child, index) => { const isLast = index === children.length - 1; const prefix = isLast ? '└── ' : '├── '; printHierarchy(child, indent + prefix, new Set(visited)); }); } // Find and display top-level concepts const topLevelConcepts = []; for (const concept of concepts) { if (!broaderMap.has(concept.subject.value)) { topLevelConcepts.push(concept.subject.value); } } topLevelConcepts.forEach(concept => printHierarchy(concept)); } このスクリプトの主要な処理: ...