找到点的两个最近邻点
Find the two nearest neighbors of points
我想找到每个点的两个最近邻
数据集:
: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
这个return点的所有邻居。我想在 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 行中有一个长字符串连接,但这只是为了去掉问题中描述的前缀。 "hack" 在这种情况下识别出两个最近的点 q 和 r 将最小化数量 |p - q| + |p − r|,因此我们可以计算该数量并取 q 和 r 的值我们。您还需要确保对 q 和 r 施加一些排序,否则您会得到重复的结果(因为您可以只需交换 q 和 r).
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 的最小数量,然后在外部查询中查找 q 和 r 产生它的值:
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" |
-------------------
我想找到每个点的两个最近邻
数据集:
: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
这个return点的所有邻居。我想在 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 行中有一个长字符串连接,但这只是为了去掉问题中描述的前缀。 "hack" 在这种情况下识别出两个最近的点 q 和 r 将最小化数量 |p - q| + |p − r|,因此我们可以计算该数量并取 q 和 r 的值我们。您还需要确保对 q 和 r 施加一些排序,否则您会得到重复的结果(因为您可以只需交换 q 和 r).
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 的最小数量,然后在外部查询中查找 q 和 r 产生它的值:
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" |
-------------------