XSL百分位函数

时间:2018-03-22 15:29:54

标签: xml xslt xslt-2.0

有没有办法如何从XSLT 2.0或3.0的输入值中获得90,95或99百分位数?以下是此问题How to print percentile using xsl的代码,但无效。这给了我两个值的平均值,而不是一个想要百分位值的值。

  

从这个"在线计算器"结果为5. https://www.emathhelp.net/calculators/probability-statistics/percentile-calculator/?i=2%2C4%2C3%2C1%2C5&p=90&steps=on

XML

<root>
    <value t="5"></value>
    <value t="1"></value>
    <value t="2"></value>
    <value t="4"></value>
    <value t="3"></value>
</root>

XSL

    <xsl:template match="/">
      <xsl:variable name="thisPercentile">
         <xsl:call-template name="percentiles">
            <xsl:with-param name="responsetimes" select="/root/*/@t" />
            <xsl:with-param name="percentile" select="0.9" />
         </xsl:call-template>
      </xsl:variable>

      <xsl:value-of select="$thisPercentile" />
    </xsl:template>



<xsl:template name="percentiles">
   <xsl:param name="responsetimes" select="." />
   <xsl:param name="percentile" select="." />
   <xsl:variable name="sortedresponsetimes">
        <xsl:for-each select="$responsetimes">
            <xsl:sort data-type="number" />
            <xsl:element name="time">
                <xsl:value-of select="." />
            </xsl:element>
        </xsl:for-each>
   </xsl:variable>
   <xsl:variable name="n" select="count($responsetimes)-1" />
   <xsl:variable name="k" select="floor($percentile*$n)+1" />
   <xsl:variable name="f" select="($percentile*$n+1)-$k" />
   <xsl:variable name="a0" select="$sortedresponsetimes[1]/time[$k]" />
   <xsl:variable name="a1" select="$sortedresponsetimes[1]/time[$k+1]" />
    <xsl:value-of select="$a0 + ( $f * ( $a1 - $a0))" />
</xsl:template>

转换后的输出

  

4.6

1 个答案:

答案 0 :(得分:2)

在XPath 3.1中使用sort函数,您可以在链接页面上实现该算法

  <xsl:function name="mf:percentile" as="xs:decimal">
      <xsl:param name="input-sequence" as="xs:decimal*"/>
      <xsl:param name="p" as="xs:integer"/>
      <xsl:sequence select="let $sorted-input := sort($input-sequence),
                            $i := round($p div 100 * count($sorted-input))
                            return $sorted-input[$i]"/>
  </xsl:function>

在完整的样本中

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:mf="http://example.com/mf"
    exclude-result-prefixes="xs mf"
    version="3.0">

  <xsl:function name="mf:percentile" as="xs:decimal">
      <xsl:param name="input-sequence" as="xs:decimal*"/>
      <xsl:param name="p" as="xs:integer"/>
      <xsl:sequence select="let $sorted-input := sort($input-sequence),
                            $i := round($p div 100 * count($sorted-input))
                            return $sorted-input[$i]"/>
  </xsl:function>

  <xsl:output method="text"/>

  <xsl:template match="root">
      <xsl:value-of select="mf:percentile(value/@t, 90)"/>
  </xsl:template>

</xsl:stylesheet>

https://xsltfiddle.liberty-development.net/bFukv8u

在XSLT / XPath 2.0中,您可以使用perform-sort,然后在函数中使用本地XSLT变量:

  <xsl:function name="mf:percentile" as="xs:decimal">
      <xsl:param name="input-sequence" as="xs:decimal*"/>
      <xsl:param name="p" as="xs:integer"/>
      <xsl:variable name="sorted-input" as="xs:decimal*">
          <xsl:perform-sort select="$input-sequence">
              <xsl:sort select="."/>
          </xsl:perform-sort>
      </xsl:variable>
      <xsl:variable name="i" select="round($p div 100 * count($sorted-input))"/>
      <xsl:sequence select="$sorted-input[$i]"/>
  </xsl:function>

http://xsltransform.hikmatu.com/3Nqn5Yc