RDFとは

RDF(Resource Description Framework)は、Web上のリソースに関する情報を記述するためのW3C標準のデータモデルです。Linked Open Dataの基盤技術であり、セマンティックWeb技術スタックの中核を担っています。

RDFの最大の特徴は、すべての情報を「トリプル(三つ組)」という極めてシンプルな構造で表現することです。このシンプルさゆえに、あらゆる種類のデータを統一的に表現でき、異なるデータソース間の統合が容易になります。

筆者はこれまで、さまざまな形式のデータをRDFに変換する実践を行ってきました。ExcelからのRDF作成やVisioファイルからのRDF変換など、実務的なデータ変換の知見を蓄積しています。本章ではRDFの基礎を体系的に解説します。

トリプル(主語・述語・目的語)

RDFにおけるデータの最小単位は「トリプル(Triple)」です。トリプルは以下の3つの要素から構成されます。

SubjectPredicateObject

これは自然言語の「〜は(主語)、〜という関係で(述語)、〜である(目的語)」に対応します。例を見てみましょう。

1867

これらの文をRDFトリプルとして形式化すると、以下のようになります。

<<<hhhttttttppp::://eeexxxaaammmpppllleee...ooorrrggg///pppeeerrrsssooonnn///nnnaaatttsssuuummmeee___sssooossseeekkkiii>>><<<hhhttttttppp::://pddubbrpplee.ddoiiraag..oodrrcgg//toennrttmoosll/oocggryye//abbtiiorrrtt>hhYP<elhaatrct>ep>:"/1</8he6tx7ta"pm^:p^/l</ehd.tbotprpeg:d//ibaw.owokwr/.gww/a3rg.eaoshroagui/r>2c0e0/1T/oXkMyLoS>chema#gYear>

このように、RDFでは世界のあらゆる事実を「何かが(主語)、何らかの関係で(述語)、何かと結びついている(目的語)」という統一的な形式で記述します。

筆者は以前、RDFデータの追加と可視化について備忘録としてまとめています。RDFの基本的な構造を理解した上で実際にデータを追加・操作する手順はRDFデータの追加と可視化に関する備忘録をご参照ください。

URI(Uniform Resource Identifier)

RDFにおいて、リソースの識別にはURI(Uniform Resource Identifier)が用いられます。URIは、Web上のリソースをグローバルに一意に識別するための文字列です。

URIの役割

URIは、RDFトリプルの主語、述語、目的語のそれぞれに使用できます。

UURRUIIR::I:hhhttttttppp:::/eepxxuaarmmlpp.lloeer..gorrdggc/bptoeeorrksm/oswnacgnraaehtaastiuomre_soseki

URIを使うことの重要な利点は、名前の衝突を避けられることです。たとえば、「東京」という名前は曖昧ですが、http://dbpedia.org/resource/Tokyo というURIは世界中で一意に「日本の首都・東京」を指します。

IRI(Internationalized Resource Identifier)

RDF 1.1以降では、URIの国際化版であるIRI(Internationalized Resource Identifier)が使用されます。IRIはURIを拡張し、ASCII以外のUnicode文字(日本語など)をそのまま使用できるようにしたものです。ただし、実際の運用ではASCIIベースのURIが一般的です。

HTTP URIとContent Negotiation

Linked Dataの原則では、HTTP URIを使うことが推奨されています。HTTP URIを使うことで、そのURIにアクセスした際に、リソースに関する情報を返すことができるからです。これを「URIの参照解決(dereferencing)」と呼びます。

たとえば、http://dbpedia.org/resource/Tokyo にアクセスすると、東京に関するRDFデータが返されます。このとき、クライアントのAcceptヘッダに応じてHTMLとRDFを出し分ける仕組みが「Content Negotiation」です。

筆者は、PythonでContent Negotiationを使ってURIからRDFを取得する方法を紹介しています。Wikidataのエンティティに対してプログラムからRDFデータを取得する具体的な実装はContent Negotiationを使って、PythonでURIからRDFを取得するをご覧ください。この技術は、LODの世界で他のデータセットと連携する際の基本テクニックです。

リテラル

RDFトリプルの目的語には、URIの代わりに「リテラル(Literal)」を使うことができます。リテラルは、文字列、数値、日付などの具体的な値を表現します。

プレーンリテラル

最もシンプルなリテラルは、ダブルクォーテーションで囲んだ文字列です。

<http://example.org/person/natsume_soseki> <http://xmlns.com/foaf/0.1/name> "夏目漱石" .

言語タグ付きリテラル

言語タグ(@ja@en など)を付けることで、リテラルの言語を指定できます。

<http://example.org/person/natsume_soseki> <http://www.w3.org/2000/01/rdf-schema#label> "夏目漱石"@ja .
<http://example.org/person/natsume_soseki> <http://www.w3.org/2000/01/rdf-schema#label> "Natsume Soseki"@en .

同じプロパティに対して異なる言語のリテラルを複数持たせることで、多言語対応が実現できます。

型付きリテラル

リテラルにデータ型を指定することで、文字列以外の値(整数、日付、真偽値など)を表現できます。データ型はXML Schema Datatypes(XSD)のURIで指定します。

# 整数
<http://example.org/person/natsume_soseki> <http://dbpedia.org/ontology/birthYear> "1867"^^<http://www.w3.org/2001/XMLSchema#gYear> .

# 日付
<http://example.org/person/natsume_soseki> <http://schema.org/birthDate> "1867-02-09"^^<http://www.w3.org/2001/XMLSchema#date> .

# 真偽値
<http://example.org/book/wagahai> <http://schema.org/isAccessibleForFree> "true"^^<http://www.w3.org/2001/XMLSchema#boolean> .

# 浮動小数点数
<http://example.org/place/tokyo> <http://www.w3.org/2003/01/geo/wgs84_pos#lat> "35.6762"^^<http://www.w3.org/2001/XMLSchema#double> .

主要なXSDデータ型は以下のとおりです。

データ型URI(短縮形)
文字列xsd:string"Hello"
整数xsd:integer"42"^^xsd:integer
浮動小数点数xsd:double"3.14"^^xsd:double
真偽値xsd:boolean"true"^^xsd:boolean
日付xsd:date"2024-01-15"^^xsd:date
日時xsd:dateTime"2024-01-15T10:30:00"^^xsd:dateTime
xsd:gYear"1867"^^xsd:gYear

RDFグラフ

複数のトリプルが集まると、ノード(主語・目的語)とエッジ(述語)からなる有向グラフが形成されます。これを「RDFグラフ」と呼びます。

以下のトリプル群を考えてみましょう。

<http://example.org/person/natsume_soseki> <http://xmlns.com/foaf/0.1/name> "夏目漱石"@ja .
<http://example.org/person/natsume_soseki> <http://dbpedia.org/ontology/birthPlace> <http://dbpedia.org/resource/Tokyo> .
<http://example.org/person/natsume_soseki> <http://schema.org/author> <http://example.org/book/wagahai> .
<http://example.org/book/wagahai> <http://purl.org/dc/terms/title> "吾輩は猫である"@ja .
<http://example.org/book/wagahai> <http://purl.org/dc/terms/issued> "1905"^^<http://www.w3.org/2001/XMLSchema#gYear> .
<http://dbpedia.org/resource/Tokyo> <http://www.w3.org/2000/01/rdf-schema#label> "東京"@ja .

これをグラフとして可視化すると、以下のようになります。

drbd"pfesd:"il@aaj:baTeolkyo"fodabfo::"nb@aijmraethPlaceex:natsume_sosekischema:au"thord"dc1c"t9t@e0eejr5xram":ms^ws:^a:ixgtssaisdhtu:alegiedYear

RDFグラフの特徴は、あるトリプルの目的語が別のトリプルの主語にもなれることです。これにより、リソース同士がリンクで結ばれたネットワーク構造が自然に形成されます。これこそがLinked Dataの本質です。

RDFグラフの可視化については、筆者が「ARC2によるRDFグラフの視覚化」をPythonで利用するで具体的な方法を紹介しています。

空白ノード(Blank Node)

RDFには、URIを持たない匿名のノードを表現する「空白ノード(Blank Node)」という仕組みがあります。空白ノードは、中間的な構造体を表現する際に使用されます。

たとえば、ある人物の住所を構造的に記述する場合を考えてみましょう。

<http://example.org/person/tanaka> <http://schema.org/address> _:addr1 .
_:addr1 <http://schema.org/postalCode> "100-0001" .
_:addr1 <http://schema.org/addressRegion> "東京都" .
_:addr1 <http://schema.org/addressLocality> "千代田区" .

_:addr1 が空白ノードです。これは「何らかの住所」を表すノードですが、URIによるグローバルな識別子は持ちません。空白ノードは便利ですが、外部からの参照ができないため、Linked Dataの文脈ではURIを付与することが推奨されています。

名前付きグラフ

RDFには、トリプルの集合にURIを付与して管理する「名前付きグラフ(Named Graph)」という仕組みがあります。トリプルにグラフ名を加えた4つ組を「クワッド(Quad)」と呼びます。

<}<>>{<><>

名前付きグラフは、データの出所(provenance)の管理やアクセス制御に役立ちます。筆者がVirtuosoやDydraなどのRDFストアにデータを登録する際にも、名前付きグラフを使ってデータの管理を行っています。

<http://example.org/graph/ndl> {
  <http://example.org/book/wagahai> <http://purl.org/dc/terms/title> "吾輩は猫である" .
  <http://example.org/book/wagahai> <http://purl.org/dc/terms/creator> "夏目漱石" .
}

<http://example.org/graph/wikidata> {
  <http://example.org/book/wagahai> <http://schema.org/datePublished> "1905" .
}

この例では、書誌情報の出所が国立国会図書館(ndl)なのかWikidataなのかをグラフ名で区別しています。

主要な語彙(ボキャブラリ)

RDFでデータを記述する際には、述語(プロパティ)として既存の語彙を再利用することが強く推奨されています。語彙のプレフィックスとURIの対応を調べるには、prefix.ccが便利です。筆者はprefix.ccを利用するで詳しく紹介しています。

RDF / RDFS

RDFとRDFS(RDF Schema)は、RDFの基本的な語彙を定義しています。

プロパティ / クラス意味
rdf:typeリソースの型(クラス)を指定する
rdfs:label人間可読なラベルを指定する
rdfs:comment説明文を指定する
rdfs:subClassOfクラスの継承関係を定義する
rdfs:subPropertyOfプロパティの継承関係を定義する
rdfs:domainプロパティの定義域(主語の型)を指定する
rdfs:rangeプロパティの値域(目的語の型)を指定する
<http://example.org/person/natsume_soseki> rdf:type <http://xmlns.com/foaf/0.1/Person> .
<http://example.org/person/natsume_soseki> rdfs:label "夏目漱石"@ja .

RDFSのrangeの仕組みとSHACLのpropertyShapeの関係については、筆者がRDFSとSHACLの使い分け:rangeとpropertyShapeの関係を理解するで詳しく解説しています。

Dublin Core(DC / DCTerms)

Dublin Coreは、メタデータの記述に広く使われる語彙です。図書館情報学の分野で発展し、現在ではISO 15836として標準化されています。筆者はOmeka Sへの語彙登録も行っており、Omeka SにDC-NDL(国立国会図書館ダブリンコアメタデータ記述)を語彙として登録するで具体的な手順を紹介しています。

プロパティ意味
dcterms:titleタイトル
dcterms:creator作成者
dcterms:subject主題
dcterms:description説明
dcterms:publisher出版者
dcterms:date日付
dcterms:typeリソースの種類
dcterms:formatファイル形式
dcterms:identifier識別子
dcterms:language言語
dcterms:rights権利
dcterms:issued発行日
dcterms:spatial空間的範囲
dcterms:temporal時間的範囲

FOAF(Friend of a Friend)

FOAFは、人物とその社会的関係を記述するための語彙です。

@prefix foaf: <http://xmlns.com/foaf/0.1/> .

<http://example.org/person/natsume_soseki> a foaf:Person ;
    foaf:name "夏目漱石"@ja ;
    foaf:familyName "夏目" ;
    foaf:givenName "金之助" ;
    foaf:knows <http://example.org/person/masaoka_shiki> .

Schema.org

Schema.orgは、Google、Microsoft、Yahoo!、Yandexが共同で策定した語彙です。Webページの構造化データ記述に広く使われており、検索エンジンの理解を助けます。RDFの文脈でも利用可能です。

@prefix schema: <http://schema.org/> .

<http://example.org/book/wagahai> a schema:Book ;
    schema:name "吾輩は猫である"@ja ;
    schema:author <http://example.org/person/natsume_soseki> ;
    schema:datePublished "1905" ;
    schema:inLanguage "ja" .

SKOS(Simple Knowledge Organization System)

SKOSは、分類体系やシソーラスなどの知識組織化体系をRDFで表現するための語彙です。筆者がOdeuropa Explorerの語彙階層構造を調査した際にも、SKOS語彙が重要な役割を果たしていました。詳しくはOdeuropa Explorer の語彙階層構造を調査するをご覧ください。

@prefix skos: <http://www.w3.org/2004/02/skos/core#> .

<http://example.org/concept/japanese_literature> a skos:Concept ;
    skos:prefLabel "日本文学"@ja ;
    skos:prefLabel "Japanese Literature"@en ;
    skos:broader <http://example.org/concept/literature> ;
    skos:narrower <http://example.org/concept/meiji_literature> .

RDFデータの作成方法

RDFデータは手書きで作成するだけでなく、既存のデータ形式から変換して作成することも多くあります。筆者は以下のような変換手法を実践してきました。

ExcelからRDFへの変換: 表形式のデータをPythonを使ってRDFに変換する方法についてはExcelからRDFを作成するで紹介しています。

VisioからRDFへの変換: Microsoft Visioの図形データからRDFを生成するアプローチについてはMicrosoft Visioを使ってRDFデータを作成するvsdxファイルからrdfファイルを作成するライブラリで詳しく解説しています。

JSON-LDからの変換: EASY RDFを用いてJSON-LDのデータをRDF/XMLやTurtleに変換する方法はEASY RDFを用いてJSON-LDのデータをRDF/XMLやTurtleに変換してみるで紹介しています。

まとめ

本章では、RDFの基本的なデータモデルを学びました。重要なポイントを振り返ります。

  • RDFはすべての情報を「主語・述語・目的語」のトリプルで表現する
  • リソースの識別にはURIを使い、グローバルに一意な識別を実現する
  • 目的語にはURIまたはリテラル(言語タグ付き、型付き)が使える
  • トリプルの集まりはRDFグラフとして有向グラフを形成する
  • Dublin Core、FOAF、Schema.org、SKOSなど、既存の語彙を再利用することが重要

次章では、RDFデータの具体的な記述形式であるTurtle構文を学びます。

関連記事