Random 如何从SPARQL中选择随机DBPedia节点?

Random 如何从SPARQL中选择随机DBPedia节点?,random,sample,sparql,dbpedia,Random,Sample,Sparql,Dbpedia,如何使用sparql端点从DBpedia中选择随机样本 这个问题 SELECT ?s WHERE { ?s ?p ?o . FILTER ( 1 > bif:rnd (10, ?s, ?p, ?o) ) } LIMIT 10 (发现) 在大多数SPARQL端点上似乎工作正常,但在它上会被缓存(因此它总是返回相同的10个节点) 如果我从JENA处尝试,我会得到以下异常: Unresolved prefixed name: bif:rnd 我找不到“bif”名称空间是什么 有没有办法解决这

如何使用sparql端点从DBpedia中选择随机样本

这个问题

SELECT ?s WHERE { ?s ?p ?o . FILTER ( 1 > bif:rnd (10, ?s, ?p, ?o) ) } LIMIT 10
(发现) 在大多数SPARQL端点上似乎工作正常,但在它上会被缓存(因此它总是返回相同的10个节点)

如果我从JENA处尝试,我会得到以下异常:

Unresolved prefixed name: bif:rnd
我找不到“bif”名称空间是什么

有没有办法解决这个问题


Mulone:rnd不是SPARQL标准,因此不能移植到任何SPARQL端点。您可以使用“限制”、“顺序”和“偏移”来模拟带有标准查询的随机样本。类似于

SELECT * WHERE { ?s ?p ?o } 
ORDER BY ?s OFFSET $some_random_number$ LIMIT 10
其中
some\u random\u number
是由应用程序生成的数字。这应该可以避免缓存问题,但这个查询无论如何都非常昂贵,我不知道公共端点是否会支持它


尽量避免像
?s?p?o这样的完全开放模式,您的查询将更加高效。

在SPARQL 1.1中,您可以执行以下操作:

SELECT ?s
WHERE {
  ?s ?p ?o
}
ORDER BY RAND()
LIMIT 10
我还不知道有多少商店会进行优化,甚至还没有实施

[见下面的评论,这不太管用]

另一种选择是:

SELECT (SAMPLE(?s) AS ?ss)
WHERE { ?s ?p ?o }
GROUP BY ?s
但我认为这更不可能被优化


bif:rnd是一个特定于Virtuoso的扩展,因此只能在Virtuoso SPARQL端点上再次工作


是Virtuoso内置函数的前缀,该函数允许在SPARQL中调用任何Virtuoso函数,并且是用于返回随机数的Virtuoso函数。

我遇到了相同的问题,这里的解决方案都没有解决我的问题。这是我的解决方案;这件事非同小可,而且相当棘手。到目前为止,这适用于DBPedia,也可能适用于其他SPARQL端点,但不能保证在将来的版本中适用

DBPedia使用Virtuoso,它支持
RAND
函数的未记录参数;该参数有效地指定了用于PRNG的范围。该游戏旨在欺骗Virtuoso,使其相信在计算每个结果行之前无法静态计算输入参数,从而迫使程序为每个绑定计算
RAND()

select * {
    ?s dbo:isPartOf ?o .  # Whatever your pattern is
    bind(rand(1 + strlen(str(?s))*0) as ?rid)
} order by ?rid
神奇发生在
rand(1+strlen(str(?s))*0)
中,它生成了与
rand()等价的
;但通过利用程序无法预测包含某个变量的表达式的值这一事实(在本例中,我们只是将IRI的长度计算为字符串),强制它在每个匹配上运行。实际表达式并不重要,因为我们将其乘以
0
以完全忽略它,然后添加
1
以使
rand
正常执行

这只是因为开发人员在表达式的静态代码求值中没有走这么远。他们本可以很容易地为“乘零”编写一个分支,但可惜他们没有:)

SELECT?s WHERE{
?s?p?o。
绑定((10,?s,?p,?o)为rid)
}
凭什么订货
限制10
这个怎么样

可能比你的好。 ()


您只需将random id(?rid)绑定到每一行绑定(?s?p?o),然后按random id对结果排序。

以上方法都不适用于Jena/Fuseki,因此我采用了另一种方式:

SELECT DISTINCT ?s ?p ?o
{
  ?s ?p ?o.
  BIND ( MD5 ( ?s ) AS ?rnd)
}
ORDER BY ?rnd ?p
LIMIT 100

显然,这不会选择随机三元组,但前k个MD5排序的受试者组应该具有统计显著性样本的相关特征(即样本代表整个人群,没有特定的选择偏差)。

经过大量实验后,我得出以下解决方案,使用散列避免静态计算
RAND()
,以及使用
RAND()
避免仅使用散列导致的选择偏差的组合

SELECT ?s WHERE {
  ?s ?p ?o .
  BIND(SHA512(CONCAT(STR(RAND()), STR(?s))) AS ?random) .
} ORDER BY ?random
LIMIT 1
此处用于从Wikidata中随机选择山谷冰川:

SELECT ?item ?itemLabel ?random WHERE {
  ?item wdt:P31 wd:Q11762356 .
  BIND(SHA512(CONCAT(STR(RAND()), STR(?item))) AS ?random) .
  SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE], en" . }
} ORDER BY ?random
LIMIT 1

(该服务缓存响应,您可以在运行查询之前只做一个新的注释来绕过它)

我想您的解决方案的问题在于选择顺序没有改变,因此它不是真正随机的。也许我可以通过将来自不同查询的样本放在一起来改善其“随机性”,比如(偏移量为x1的查询)UNION(偏移量为x2的查询)UNION(偏移量为xn的查询)UNION。我的选择顺序不是随机的,但随机数上的偏移量会给你一个随机样本。这是需要随机生成的偏移量。实际上,第二个偏移量不起作用,SAMPLE()返回一个任意值。但不是随机的。我只想添加'DISTINCT':SELECT DISTINCT?我相信RAND()只被调用一次,所以所有结果的值都是相同的。如果是这样的话,试着使用“(SHA512(CONCAT(str(?s),str(RAND()))作为?random)”和“ORDER BY?random”我自己已经多次使用过这种方法,最后发现不幸的是存在选择偏差。将大样本的分布与其原始数据集进行比较,选择偏向于确定的特征。我建议在可用时使用
RAND()
bif:rnd
。感谢@mommi84,我很想知道存在哪些偏差,以及是否有其他函数与MD5哈希相结合,以使返回的结果更加无偏。
SELECT ?item ?itemLabel ?random WHERE {
  ?item wdt:P31 wd:Q11762356 .
  BIND(SHA512(CONCAT(STR(RAND()), STR(?item))) AS ?random) .
  SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE], en" . }
} ORDER BY ?random
LIMIT 1