3

私の仕事は推薦システムの図書館の本です。入力として、分類オントロジーの本が必要です。私のオントロジーでは、図書館の本を分類します。この分類には、兄弟クラスの Author、book、Isbn の他に、14 のカテゴリがあります。book クラスの個人は本の主題 (約 600 科目) であり、author クラスの個人は name の著者であり、isbn クラスでもあります。このオントロジーを protege 4.1 で設計します。

また、私は手動でカテゴリに属する​​本の一部を収集して取得しました。オブジェクトのプロパティは、「hasSubject」という名前で、カテゴリを持つ個々の書籍クラスに関連付けられています。例 本「A」にはサブジェクト カテゴリ「S」と「F」と... 結果として、本のカテゴリに属する​​マトリックスを取得したいと考えています。これは、書籍がカテゴリに属している場合は 1 を取得し、それ以外の場合は値 0 を取得する方法です。次のように:

     cat1   cat2   cat3   
book1   1      0      0   
book2   1      0      1   
book3   1      1      0  

この例では、book1 がカテゴリ 1 に属し、カテゴリ 2 および 3 に属していないことを表しています。

4

1 に答える 1

6

一定数のカテゴリを処理する

次のようなデータが与えられた場合

@prefix : <http://example.org/books/> .

:book1 a :Book, :Cat1 .
:book2 a :Book, :Cat1, :Cat3 .
:book3 a :Book, :Cat1, :Cat2 .

次のようなクエリを使用できます

prefix : <http://example.org/books/>

select ?individual
       (if(bound(?cat1),1,0) as ?Cat1)
       (if(bound(?cat2),1,0) as ?Cat2)
       (if(bound(?cat3),1,0) as ?Cat3)
where {
  ?individual a :Book .
  OPTIONAL { ?individual a :Cat1 . bind( ?individual as ?cat1 ) } 
  OPTIONAL { ?individual a :Cat2 . bind( ?individual as ?cat2 ) }
  OPTIONAL { ?individual a :Cat3 . bind( ?individual as ?cat3 ) }
}
order by ?book

これらのような結果を得るために特定のトリプルが存在するかどうかに基づいて、特定の変数がバインドされている (それらがバインドされている特定の値は実際には重要ではありません)。

$ arq --data data.n3 --query matrix.sparql
-----------------------------------
| individual | Cat1 | Cat2 | Cat3 |
===================================
| :book1     | 1    | 0    | 0    |
| :book2     | 1    | 0    | 1    |
| :book3     | 1    | 1    | 0    |
-----------------------------------

任意の数のカテゴリを処理する

特定の結果が保証されているかどうかはわかりませんが、Jena で動作するように見えるソリューションを次に示します。(更新:このanswer.semanticweb.com の質問と回答に基づくと、この動作はSPARQL 仕様によって保証されていないようです。) もう少しデータがある場合、たとえば、どのものがカテゴリで、どれが本であるかについて、例えば、

@prefix : <http://example.org/books/> .

:book1 a :Book, :Cat1 .
:book2 a :Book, :Cat1, :Cat3 .
:book3 a :Book, :Cat1, :Cat2 .

:Cat1 a :Category .
:Cat2 a :Category .
:Cat3 a :Category .

次に、すべてのカテゴリを順番に選択するサブクエリを実行し、書籍ごとに、その書籍が各カテゴリに含まれているかどうかを示す文字列を計算します。

prefix : <http://example.org/books/>

select ?book (group_concat(?isCat) as ?matrix) where { 
  { 
    select ?category where { 
      ?category a :Category 
    }
    order by ?category 
  }
  ?book a :Book .
  OPTIONAL { bind( 1 as ?isCat )              ?book a ?category . }
  OPTIONAL { bind( 0 as ?isCat ) NOT EXISTS { ?book a ?category } }
}
group by ?book
order by ?book

これにより、次の出力が得られます。

$ arq --data data.n3 --query matrix2.query
--------------------
| book   | matrix  |
====================
| :book1 | "1 0 0" |
| :book2 | "1 0 1" |
| :book3 | "1 1 0" |
--------------------

これは質問の出力にはるかに近く、任意の数のカテゴリを処理します。?categoryただし、各 の値が同じ順序で処理されるかどうかに依存し、それ?bookが保証されるかどうかはわかりません。

このアプローチを使用して、テーブルのヘッダー行を生成することもできます。?category繰り返しますが、これは各 に対して同じ順序で処理される値に依存します?book。これは保証されていない可能性がありますが、Jena では機能するようです。カテゴリ ヘッダーを取得するには、?bookがバインドされていない行を作成するだけで、 の値が?isCat特定のカテゴリを示します。

prefix : <http://example.org/books/>

select ?book (group_concat(?isCat) as ?matrix) where { 
  { 
    select ?category where { 
      ?category a :Category 
    }
    order by ?category 
  }

  # This generates the header row where ?isCat is just
  # the category, so the group_concat gives headers.
  { 
    bind(?category as ?isCat) 
  }
  UNION 
  # This is the table as before
  {
    ?book a :Book .
    OPTIONAL { bind( 1 as ?isCat )              ?book a ?category . }
    OPTIONAL { bind( 0 as ?isCat ) NOT EXISTS { ?book a ?category } }
  }
}
group by ?book
order by ?book

次の出力が得られます。

--------------------------------------------------------------------------------------------------------
| book   | matrix                                                                                      |
========================================================================================================
|        | "http://example.org/books/Cat1 http://example.org/books/Cat2 http://example.org/books/Cat3" |
| :book1 | "1 0 0"                                                                                     |
| :book2 | "1 0 1"                                                                                     |
| :book3 | "1 1 0"                                                                                     |
--------------------------------------------------------------------------------------------------------

いくつかの文字列操作を使用して、カテゴリに使用される URI を短縮したり、配列エントリを広げて正しい位置合わせを取得したりできます。1つの可能性はこれです:

prefix : <http://example.org/books/>

select ?book (group_concat(?isCat) as ?categories) where { 
  { 
    select ?category
           (strafter(str(?category),"http://example.org/books/") as ?name)
     where { 
      ?category a :Category 
    }
    order by ?category 
  }

  { 
    bind(?name as ?isCat)
  }
  UNION 
  {
    ?book a :Book .
    # The string manipulation here takes the name of the category (which should
    # be at least two character), trims off the first character (string indexing
    # in XPath functions starts at 1), and replaces the rest with " ". The resulting
    # spaces are concatenated with "1" or "0" depending on whether the book is a
    # member of the category.  The resulting string has the same width as the
    #  category name, and makes for a nice table.
    OPTIONAL { bind( concat(replace(substr(?name,2),"."," "),"1") as ?isCat )              ?book a ?category . }
    OPTIONAL { bind( concat(replace(substr(?name,2),"."," "),"0") as ?isCat ) NOT EXISTS { ?book a ?category } }
  }
}
group by ?book
order by ?book

次の出力が生成されます。

$ arq --data data.n3 --query matrix3.query
-----------------------------
| book   | categories       |
=============================
|        | "Cat1 Cat2 Cat3" |
| :book1 | "   1    0    0" |
| :book2 | "   1    0    1" |
| :book3 | "   1    1    0" |
-----------------------------

これは、質問で持っていたものとほぼ同じです。

于 2013-07-29T16:06:26.450 に答える