查找点的两个最近邻域 [英] Find the two nearest neighbors of points

查看:15
本文介绍了查找点的两个最近邻域的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我要查找每个点最近的两个邻居

数据集:

:p1 :has_position 1 .
:p2 :has_position 2 .
:p3 :has_position 3 .
:p4 :has_position 4 .

预期结果:

?POINT  ?NEIGHBORS
"p1"    "p2; p3"
"p2"    "p1; p3"
"p3"    "p2; p4"
"p4"    "p2; p3"

我尝试这样做:

SELECT ?POINT ?POS (group_concat(?idPointN;separator='; ' )as ?NEIGHBORS)
WHERE{
    ?idPoint :has_position ?POS .
    ?idPointN :has_position ?POSN . FILTER (?idPoint != ?idPointN)
}
GROUP BY ?POINT ?POS

这将返回点的所有邻居。我想做一些像group_concat中的ORDER BY(?POS-?POSN)limit 2这样的事情,但是我不知道怎么做。

编辑:

我编写此查询

SELECT ?POINT ?NEIGHBOR
WHERE{
    ?idPoint rdfs:label ?POINT . FILTER(?idN != ?idPoint)
    ?idPoint :has_position ?POS .


    ?idN rdfs:label ?NEIGHBOR .
    ?idN :has_position ?POSN .
}
ORDER BY ?POINT abs(?POS-?POSN)

它为我提供所有邻居按最近点排序的每个点。

我怎么能只有最接近的2个?并且在同一行上?

推荐答案

在SPARQL中获取每个事物的前n的查询非常棘手,而且目前还没有很好的方法来做到这一点。它几乎总是归结为一些奇怪的黑客攻击。首先,带有前缀声明的数据:

@prefix : <urn:ex:>

:p1 :has_position 1 .
:p2 :has_position 2 .
:p3 :has_position 3 .
:p4 :has_position 4 .

然后查询。select行中有一个很长的字符串连接,但这只是去掉您在问题中描述的前缀。本例中的"黑客"是认识到最接近的两个点qr将使|p&减去;q|+|p&减去;r|的数量最小化,因此我们可以计算该数量并取给我们的qr的值。您还需要确保对qr进行某种排序,否则会得到重复的结果(因为您可以只交换qr)。

prefix : <urn:ex:>

select ?p (concat(strafter(str(?q),str(:)),", ",strafter(str(?r),str(:))) as ?neighbors) {
  ?p :has_position ?pos1 .
  ?q :has_position ?pos2 .
  ?r :has_position ?pos3 .
  filter(?p != ?q && ?p != ?r)
  filter(str(?q) < str(?r))

  filter not exists {
    ?qq :has_position ?pos22 .
    ?rr :has_position ?pos33 .
    filter(?p != ?qq && ?p != ?rr)
    filter(str(?qq) < str(?rr))
    filter((abs(?pos1 - ?pos22) + abs(?pos1 - ?pos33)) < 
           (abs(?pos1 - ?pos2)  + abs(?pos1 - ?pos3)))
  }
}
-------------------
| p   | neighbors |
===================
| :p1 | "p2, p3"  |
| :p2 | "p1, p3"  |
| :p3 | "p2, p4"  |
| :p4 | "p2, p3"  |
-------------------

现在,您还可以使用子查询执行此操作,该子查询为每个p查找最小数量,然后在外部查询中查找生成该数量的qr值:

prefix : <urn:ex:>

select ?p (concat(strafter(str(?q), str(:)), ", ", strafter(str(?r), str(:))) as ?neighbors) {
  { select ?p (min(abs(?pos1 - ?pos2) + abs(?pos1 - ?pos3)) as ?d) {
      ?p :has_position ?pos1 .
      ?q :has_position ?pos2 .
      ?r :has_position ?pos3 .
      filter(?p != ?q && ?p != ?r)
      filter(str(?q) < str(?r))
    }
    group by ?p
  }

  ?p :has_position ?pos1 .
  ?q :has_position ?pos2 .
  ?r :has_position ?pos3 .
  filter(?p != ?q && ?p != ?r)
  filter(str(?q) < str(?r))
  filter(abs(?pos1 - ?pos2) + abs(?pos1 - ?pos3) = ?d)
}
-------------------
| p   | neighbors |
===================
| :p1 | "p2, p3"  |
| :p2 | "p1, p3"  |
| :p3 | "p2, p4"  |
| :p4 | "p2, p3"  |
-------------------

这篇关于查找点的两个最近邻域的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆