如何获取rdflib中空白节点的所有项目

How to get all items of a blank node in rdflib

我是 RDflib 的新手,我想实现这样的功能: 也就是说,Person hasProperty Weight(kg) , Height(m), BMI (Body Mass Index)=Weight/Height^2,所以如果 Bob 的体重=70,身高=1.75,如何从这个模型中推导出 Bob 的 BMI? 我使用下面的RDF文件来存储以上信息:

@prefix : <http://ex.org/BMI#> .
@prefix owl: <http://www.w3.org/2002/07/owl#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
:Person rdf:type owl:Class;
         :hasProperty :Height, :Weight, :BMI.
:OriginalProperty rdf:type owl:Class .
:DerivedProperty rdf:type owl:Class .
:Weight rdf:type owl:Class ;
        rdfs:subClassOf :OriginalProperty .
:Height rdf:type owl:Class ;
        rdfs:subClassOf :OriginalProperty .
:BMI rdf:type owl:Class ;
     rdfs:subClassOf :DerivedProperty ;
     :equalTo [:divide (:Weight [:power  :Height])] .
:MathOperator rdf:type owl:Class .
:equalTo rdf:type owl:Class ;
         rdfs:subClassOf :MathOperator .
:divide rdf:type owl:Class ;
           rdfs:subClassOf :MathOperator .
:power rdf:type owl:Class ;
       rdfs:subClassOf :MathOperator .
:Bob rdf:type owl:NamedIndividual , :Person ;
     :hasProperty :BMIOfBob ,
                  :HeightOfBob ,
                  :WeightOfBob .
:HeightOfBob rdf:type owl:NamedIndividual , :Height ;
            :hasValue 1.75 .
:WeightOfBob rdf:type owl:NamedIndividual , :Weight ;
            :hasValue 70 .
:BMIOfBob rdf:type owl:NamedIndividual ,:BMI.

我的python代码如下:

from rdflib import Graph
from rdflib.namespace import Namespace
g = Graph()
x = Graph()
g.parse("BMI.ttl")
n = Namespace("http://ex.org/BMI#")
x = g.triples((None,n.equalTo,None))
for s, p, o in x:
    print(s,p,o)

只返回空白节点本身,不包括BNode的其他数据。

http://ex.org/BMI#BMI http://ex.org/BMI#equalTo n2dd6baee104f49189928ce08eb003834b1

如何获取BNode的额外信息?或者有没有更好的方法用RDF来实现这个模型的功能?
感谢您的帮助和建议。

Joylix

  1. 始终将您的 RDF 数据通过转换器进行验证和整理。尝试 http://rdftools.surroundaustralia.com/convert。使用它你会得到:
@prefix : <http://ex.org/BMI#> .
@prefix owl: <http://www.w3.org/2002/07/owl#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .

:Bob a :Person,
        owl:NamedIndividual ;
    :hasProperty :BMIOfBob,
        :HeightOfBob,
        :WeightOfBob .

:divide a owl:Class ;
    rdfs:subClassOf :MathOperator .

:equalTo a owl:Class ;
    rdfs:subClassOf :MathOperator .

:power a owl:Class ;
    rdfs:subClassOf :MathOperator .

:BMIOfBob a :BMI,
        owl:NamedIndividual .

:DerivedProperty a owl:Class .

:HeightOfBob a :Height,
        owl:NamedIndividual ;
    :hasValue 1.75 .

:Person a owl:Class ;
    :hasProperty :BMI,
        :Height,
        :Weight .

:WeightOfBob a :Weight,
        owl:NamedIndividual ;
    :hasValue 70 .

:BMI a owl:Class ;
    :equalTo [ :divide ( :Weight [ :power :Height ] ) ] ;
    rdfs:subClassOf :DerivedProperty .

:OriginalProperty a owl:Class .

:Height a owl:Class ;
    rdfs:subClassOf :OriginalProperty .

:MathOperator a owl:Class .

:Weight a owl:Class ;
    rdfs:subClassOf :OriginalProperty .
  1. 以标准方式重塑您的数值 - 使用已建立的本体。您做事的方式如下:
:WeightOfBob 
    a :Weight, owl:NamedIndividual ;
    :hasValue 70 .

非常好 - 您已经指出了数量类型(测量的事物类型)- 重量 - 和价值 - 70 但您还应该包括单位。尝试 QUDT 建模,看起来像这样:

@prefix qk: <http://qudt.org/vocab/quantitykind/> .
@prefix qudt: <http://qudt.org/schema/qudt/> .
@prefix unit: <http://qudt.org/vocab/unit/> .

:WeightOfBob 
    a qudt:Quantity ;
    qudt:hasQuantityKind qk:Weight ;
    qudt:numericValue 70 ;
    qudt:unit unit:KiloGM ;   # kilogram

有很多定义的度量单位,参见http://www.qudt.org/doc/DOC_VOCAB-UNITS.html

鲍勃现在的身高:

:WeightOfBob 
    a qudt:Quantity ;
    qudt:hasQuantityKind qk:Height ;
    qudt:numericValue 1.75 ;
    qudt:unit unit:M ;   # metre

所以现在,使用常见的 ontology [schema.org](https://schema.org]: for 'Person':

@prefix : <http://ex.org/BMI#> .
@prefix sdo: <https://schema.org/> .

:Bob 
  a sdo:Person ;
  :hasProperty [
    a qudt:Quantity ;
    qudt:hasQuantityKind qk:Weight ;
    qudt:numericValue 70 ;
    qudt:unit unit:KiloGM ;   # kilogram
  ] ,
  [
    a qudt:Quantity ;
    qudt:hasQuantityKind qk:Height ;
    qudt:numericValue 1.75 ;
    qudt:unit unit:M ;   # metre
  ] ;
.

现在,根据更常见的数据模式,让我们回答您的问题。

How can I get additional information of the BNode?

您需要做的是循环遍历图形以获取所需的空白节点,然后从那里遍历图形,将该空白节点作为另一个循环中的主题。

不要像 g.triples((...)) 这样的代码,而是使用更简单的 g.subjects(...)g.subject_objects(...)

还有一个 g.value(..) 函数,您可以通过指定您知道的其他两个三元组值来获取任何主语、谓语或宾语的单个值。

因此,要使用上面建模的新数据获取体重和身高值:

# get the Blank Nodes for Bob for weight & height
height_bn = g.value(predicate=qudt.hasQuantityKind, object=qk.Height)
weight_bn = g.value(predicate=qudt.hasQuantityKind, object=qk.Weight)

# get the numeric values from those Blank Nodes
height_value = g.value(subject=height_bn, predicate=qudt.numericValue)
weight_value = g.value(subject=weight_bn, predicate=qudt.numericValue)

# if you needed to know units, you could do that here...

然后,使用正常 Python,计算 BMI:

import math
bmi_value = float(weight_value) / math.pow(float(height_value), 2)

当然,您的 BMI 算法在这里是用 Python 表示的,而不是 RDF,但您也可以用 SPARQL 表示,或者您可以从 RDF 结构生成算法,这可能是您的最终目标,但这简单的方法至少回答了你的一些问题。

您也可以将 bmi_value 作为另一个 Quantity 写回到您的 RDF 数据中,并使用适当的 quantityKindunit 等值