这是重现问题的最低数据:
@prefix rs: <http://example.org/rs#>
@prefix bo: <http://example.org/bo#>
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
@prefix xsd: <http://www.w3.org/2001/XMLSchema#>
rs:user1 rs:hasRated [rs:by "1.0"^^xsd:float ; rs:item bo:animalFarm] .
rs:user2 rs:hasRated [rs:by "0.9"^^xsd:float ; rs:item bo:animalFarm] .
rs:user3 rs:hasRated [rs:by "0.9"^^xsd:float ; rs:item bo:animalFarm] .
rs:user4 rs:hasRated [rs:by "0.5"^^xsd:float ; rs:item bo:book3] .
rs:user5 rs:hasRated [rs:by "0.6"^^xsd:float ; rs:item bo:book3] .
rs:user6 rs:hasRated [rs:by "0.8"^^xsd:float ; rs:item bo:algorithem1] .
rs:user7 rs:hasRated [rs:by "0.9"^^xsd:float ; rs:item bo:algorithem1] .
rs:user8 rs:hasRated [rs:by "0.3"^^xsd:float ; rs:item bo:book4] .
我想要规范化每个项目的平均评分,并标准化每个项目的评分数量
我可以计算每个项目的平均评分以及每个项目的评分数量,如下所示:
PREFIX bo: <http://example.org/bo#>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX rs: <http://example.org/rs#>
select ?item (AVG(?ratingValue) as ?avg) (COUNT(*) as ?count)
{
?user rs:hasRated [ rs:item ?item ; rs:by ?ratingValue ] .
}
group by ?item
结果是:
如果可能的话,我想要的是以下内容:
bo:book3 (0.55/(0.55 + 0.93333334 + 0.85 + 0.3 )) (2/(2 + 3 + 2 + 1))
当然其他项目也是如此。
我的问题是我不知道如何进行求和,同时进行除法。
非常感谢您的帮助。
更新 1
我询问是否有可能这样做,如果没有(或者性能太差)我得到了不同的解决方案
最佳答案
在 SPARQL 中,数据要么被分组,要么不分组。你无法真正从群体中“伸出援手”并获得比群体更大的信息。这意味着要获得此结果,您可能需要一个子查询来单独获取总值。根据您提供的数据:
select ?item
(avg(?rating_)/?sumAvgRating as ?rating)
(count(*)/?countRating as ?percentCount)
{
?user rs:hasRated [ rs:by ?rating_ ; rs:item ?item ]
#-- get number of ratings
{ select (count(*) as ?countRating) { ?user rs:hasRated [] }}
#-- get sum of average ratings
{ select (sum(?avgRating) as ?sumAvgRating) {
{ select (avg(?rating_) as ?avgRating) {
?user rs:hasRated [ rs:by ?rating_ ; rs:item ?item ]
}
group by ?item
}
}
}
}
group by ?item ?countRating ?sumAvgRating
-----------------------------------------------------------
| item | rating | percentCount |
===========================================================
| bo:book3 | "0.20886075"^^xsd:float | 0.25 |
| bo:book4 | "0.11392405"^^xsd:float | 0.125 |
| bo:algorithem1 | "0.3227848"^^xsd:float | 0.25 |
| bo:animalFarm | "0.35443038"^^xsd:float | 0.375 |
-----------------------------------------------------------
我认为,要获取您真正想要的数据,并且无需冗余子查询,您需要对结果进行一些后处理。我这么说是因为您确实要求进行一些涉及以两种不同方式分组的计算。要获得评分总数,您需要对所有结果进行分组(或者至少对某些分组结果进行分组)。要获得每个项目的平均值,您需要对项目进行分组。要获得平均值的总和,您需要对分组数据进行分组。因此,我认为如果没有一些冗余查询,您就无法完美地完成此操作。
但是,您可以在查询中进行一些处理。我想我会得到项目及其评分,并对每个项目的评分进行计数并求和平均值,如下所示:
select ?item (sum(?rating_) as ?sumRating) (count(*) as ?countRating) {
?user rs:hasRated [ rs:by ?rating_ ; rs:item ?item ]
}
group by ?item
我这样做的原因,而不是平均评分,是因为根据计数和总和,您可以轻松地重建平均值(只需将总和除以计数),然后您可以得到总和的总和以及计数的总和。如果你太早求平均值,那么你就无法确定所有评分的实际总和是多少。
关于sparql - 如何标准化此数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36771027/