如何在XPath或XQuery中计算加权平均值?
我需要在XForms表单中计算一个简单的加权平均值。如何使用XPath和/或XQuery以优雅的声明方式实现这一点 [已编辑]这是源XML文档:如何在XPath或XQuery中计算加权平均值?,xpath,xquery,orbeon,xforms,xpath-2.0,Xpath,Xquery,Orbeon,Xforms,Xpath 2.0,我需要在XForms表单中计算一个简单的加权平均值。如何使用XPath和/或XQuery以优雅的声明方式实现这一点 [已编辑]这是源XML文档: <Examens> <Examen> <ExamenId>1</ExamenId> <Coef>1</Coef> <Notes> <Note> &
<Examens>
<Examen>
<ExamenId>1</ExamenId>
<Coef>1</Coef>
<Notes>
<Note>
<EleveId>100</EleveId>
<Valeur>4</Valeur>
</Note>
<Note>
<EleveId>101</EleveId>
<Valeur>4.2</Valeur>
</Note>
<Note>
<EleveId>102</EleveId>
<Valeur>3.8</Valeur>
</Note>
</Notes>
</Examen>
<Examen>
<ExamenId>2</ExamenId>
<Coef>2</Coef>
<Notes>
<Note>
<EleveId>100</EleveId>
<Valeur>5</Valeur>
</Note>
<Note>
<EleveId>101</EleveId>
<Valeur/>
</Note>
<Note>
<EleveId>102</EleveId>
<Valeur>3.5</Valeur>
</Note>
</Notes>
</Examen>
<Examen>
<ExamenId>3</ExamenId>
<Coef>3</Coef>
<Notes>
<Note>
<EleveId>100</EleveId>
<Valeur>6</Valeur>
</Note>
<Note>
<EleveId>101</EleveId>
<Valeur>5.4</Valeur>
</Note>
<Note>
<EleveId>102</EleveId>
<Valeur>2</Valeur>
</Note>
</Notes>
</Examen>
</Examens>
顺便说一句,我还需要排除Valeur
为空字符串的节点。例如,在下面使用XPathavg()
函数进行的简单平均值计算中,如果一个节点的内容是空字符串,则出现错误(“无法将“”转换为双精度”)。这是一个问题,因为节点存在(它是模型实例的一部分),并且当用户尚未输入值时,值是空字符串
<xforms:output ref="round(avg($currentBranche//Note[EleveId=$currentEleveId]/Valeur)*100) div 100"/>
[已编辑]
正确的计算是:如果EleveId=100:加权平均=(1*4+2*5+3*6)/(1+2+3)=5.333
如果EleveId=101:加权平均=(1*4.2+3*5.4)/(1+3)=5.1
如果EleveId=102:加权平均=(1*3.8+2*3.5+3*2)/(1+2+3)=2.8
在XPath 1.0中使用
sum($currentBranche//Note[EleveId=$currentEleveId]/Valeur[number(.)=number(.)])
div
count($currentBranche//Note[EleveId=$currentEleveId]/Valeur)
round(avg($currentBranche//Note[EleveId=$currentEleveId]/Valeur
[number(.)=number(.)])*100
) div 100
<Examens>
<Examen>
<ExamenId>1</ExamenId>
<Coef>1</Coef>
<Notes>
<Note>
<EleveId>100</EleveId>
<Valeur>4</Valeur>
</Note>
<Note>
<EleveId>101</EleveId>
<Valeur>4.2</Valeur>
</Note>
<Note>
<EleveId>102</EleveId>
<Valeur>3.8</Valeur>
</Note>
</Notes>
</Examen>
<Examen>
<ExamenId>2</ExamenId>
<Coef>2</Coef>
<Notes>
<Note>
<EleveId>100</EleveId>
<Valeur>5</Valeur>
</Note>
<Note>
<EleveId>101</EleveId>
<Valeur/>
</Note>
<Note>
<EleveId>102</EleveId>
<Valeur>3.5</Valeur>
</Note>
</Notes>
</Examen>
<Examen>
<ExamenId>3</ExamenId>
<Coef>3</Coef>
<Notes>
<Note>
<EleveId>100</EleveId>
<Valeur>6</Valeur>
</Note>
<Note>
<EleveId>101</EleveId>
<Valeur>5.4</Valeur>
</Note>
<Note>
<EleveId>102</EleveId>
<Valeur>2</Valeur>
</Note>
</Notes>
</Examen>
</Examens>
5.33 5.1 2.8
在Xpath 2.0(XQuery)中使用:
sum($currentBranche//Note[EleveId=$currentEleveId]/Valeur[number(.)=number(.)])
div
count($currentBranche//Note[EleveId=$currentEleveId]/Valeur)
round(avg($currentBranche//Note[EleveId=$currentEleveId]/Valeur
[number(.)=number(.)])*100
) div 100
<Examens>
<Examen>
<ExamenId>1</ExamenId>
<Coef>1</Coef>
<Notes>
<Note>
<EleveId>100</EleveId>
<Valeur>4</Valeur>
</Note>
<Note>
<EleveId>101</EleveId>
<Valeur>4.2</Valeur>
</Note>
<Note>
<EleveId>102</EleveId>
<Valeur>3.8</Valeur>
</Note>
</Notes>
</Examen>
<Examen>
<ExamenId>2</ExamenId>
<Coef>2</Coef>
<Notes>
<Note>
<EleveId>100</EleveId>
<Valeur>5</Valeur>
</Note>
<Note>
<EleveId>101</EleveId>
<Valeur/>
</Note>
<Note>
<EleveId>102</EleveId>
<Valeur>3.5</Valeur>
</Note>
</Notes>
</Examen>
<Examen>
<ExamenId>3</ExamenId>
<Coef>3</Coef>
<Notes>
<Note>
<EleveId>100</EleveId>
<Valeur>6</Valeur>
</Note>
<Note>
<EleveId>101</EleveId>
<Valeur>5.4</Valeur>
</Note>
<Note>
<EleveId>102</EleveId>
<Valeur>2</Valeur>
</Note>
</Notes>
</Examen>
</Examens>
5.33 5.1 2.8
如果所有Valeur
值都保证可以按xs:decimal
进行强制转换,则使用:
avg($currentBranche//Note[EleveId=$currentEleveId]/Valeur
[castable as xs:decimal]
/xs:decimal(.)
)
for $elevId in distinct-values(/*/*/*/*/EleveId)
return
round(100*
(sum(/*/*/*/Note
[EleveId eq $elevId
and number(Valeur) eq number(Valeur)
]
/(Valeur * ../../Coef)
)
div
sum(/*/*/*/Note
[EleveId eq $elevId
and number(Valeur) eq number(Valeur)
]
/../../Coef
)
)
)
div 100
在这种情况下,精度不会(明显)降低,您可以稍后使用format-number()
函数获取小数点后所需的位数
II。产生“加权平均数”:
sum($currentBranche//Note[EleveId=$currentEleveId]/Valeur[number(.)=number(.)])
div
count($currentBranche//Note[EleveId=$currentEleveId]/Valeur)
round(avg($currentBranche//Note[EleveId=$currentEleveId]/Valeur
[number(.)=number(.)])*100
) div 100
<Examens>
<Examen>
<ExamenId>1</ExamenId>
<Coef>1</Coef>
<Notes>
<Note>
<EleveId>100</EleveId>
<Valeur>4</Valeur>
</Note>
<Note>
<EleveId>101</EleveId>
<Valeur>4.2</Valeur>
</Note>
<Note>
<EleveId>102</EleveId>
<Valeur>3.8</Valeur>
</Note>
</Notes>
</Examen>
<Examen>
<ExamenId>2</ExamenId>
<Coef>2</Coef>
<Notes>
<Note>
<EleveId>100</EleveId>
<Valeur>5</Valeur>
</Note>
<Note>
<EleveId>101</EleveId>
<Valeur/>
</Note>
<Note>
<EleveId>102</EleveId>
<Valeur>3.5</Valeur>
</Note>
</Notes>
</Examen>
<Examen>
<ExamenId>3</ExamenId>
<Coef>3</Coef>
<Notes>
<Note>
<EleveId>100</EleveId>
<Valeur>6</Valeur>
</Note>
<Note>
<EleveId>101</EleveId>
<Valeur>5.4</Valeur>
</Note>
<Note>
<EleveId>102</EleveId>
<Valeur>2</Valeur>
</Note>
</Notes>
</Examen>
</Examens>
5.33 5.1 2.8
给定提供的XML文档:
sum($currentBranche//Note[EleveId=$currentEleveId]/Valeur[number(.)=number(.)])
div
count($currentBranche//Note[EleveId=$currentEleveId]/Valeur)
round(avg($currentBranche//Note[EleveId=$currentEleveId]/Valeur
[number(.)=number(.)])*100
) div 100
<Examens>
<Examen>
<ExamenId>1</ExamenId>
<Coef>1</Coef>
<Notes>
<Note>
<EleveId>100</EleveId>
<Valeur>4</Valeur>
</Note>
<Note>
<EleveId>101</EleveId>
<Valeur>4.2</Valeur>
</Note>
<Note>
<EleveId>102</EleveId>
<Valeur>3.8</Valeur>
</Note>
</Notes>
</Examen>
<Examen>
<ExamenId>2</ExamenId>
<Coef>2</Coef>
<Notes>
<Note>
<EleveId>100</EleveId>
<Valeur>5</Valeur>
</Note>
<Note>
<EleveId>101</EleveId>
<Valeur/>
</Note>
<Note>
<EleveId>102</EleveId>
<Valeur>3.5</Valeur>
</Note>
</Notes>
</Examen>
<Examen>
<ExamenId>3</ExamenId>
<Coef>3</Coef>
<Notes>
<Note>
<EleveId>100</EleveId>
<Valeur>6</Valeur>
</Note>
<Note>
<EleveId>101</EleveId>
<Valeur>5.4</Valeur>
</Note>
<Note>
<EleveId>102</EleveId>
<Valeur>2</Valeur>
</Note>
</Notes>
</Examen>
</Examens>
5.33 5.1 2.8
并生成预期的正确结果:
sum($currentBranche//Note[EleveId=$currentEleveId]/Valeur[number(.)=number(.)])
div
count($currentBranche//Note[EleveId=$currentEleveId]/Valeur)
round(avg($currentBranche//Note[EleveId=$currentEleveId]/Valeur
[number(.)=number(.)])*100
) div 100
<Examens>
<Examen>
<ExamenId>1</ExamenId>
<Coef>1</Coef>
<Notes>
<Note>
<EleveId>100</EleveId>
<Valeur>4</Valeur>
</Note>
<Note>
<EleveId>101</EleveId>
<Valeur>4.2</Valeur>
</Note>
<Note>
<EleveId>102</EleveId>
<Valeur>3.8</Valeur>
</Note>
</Notes>
</Examen>
<Examen>
<ExamenId>2</ExamenId>
<Coef>2</Coef>
<Notes>
<Note>
<EleveId>100</EleveId>
<Valeur>5</Valeur>
</Note>
<Note>
<EleveId>101</EleveId>
<Valeur/>
</Note>
<Note>
<EleveId>102</EleveId>
<Valeur>3.5</Valeur>
</Note>
</Notes>
</Examen>
<Examen>
<ExamenId>3</ExamenId>
<Coef>3</Coef>
<Notes>
<Note>
<EleveId>100</EleveId>
<Valeur>6</Valeur>
</Note>
<Note>
<EleveId>101</EleveId>
<Valeur>5.4</Valeur>
</Note>
<Note>
<EleveId>102</EleveId>
<Valeur>2</Valeur>
</Note>
</Notes>
</Examen>
</Examens>
5.33 5.1 2.8
谢谢你的帮助!我不知道去除空字符串的诀窍。这解决了我问题的第二部分,但(我的错误:一个问题中有两个问题)不是第一部分:如何使用从值(../../../Coef)放置在相对路径上的权重计算加权平均值?我真的不知道如何使用XPath/XQuery表达式。@cbosson,您没有提供任何包含名为
Coef
的元素的XML文档。如果您编辑问题并提供现在缺少的源XML文档,那么答案不会很难。请。@cbosson,我在我的答案中添加了第二部分,说明了我认为最简单的加权平均方法。加权平均不是这样计算的。正确的公式应该是sum(/*/num(val*weight))
除以sum(/*num/val)
,在这个例子中应该=4。@Flynn1179你想计算加权平均数的方法是正确的,但我认为你答案的第二个公式应该是sum(/*/num/weight)
,不是吗?无论如何,谢谢你的意见!