Is there way how to get 90, 95 or 99 percentile from input values with XSLT 2.0 or 3.0? Below is a code from this question How to print percentile using xsl, but is is not working correctly. This gives me a avarage from two values and not one value which is that wanted percentil.
From this "online calculator" is result 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>
Ouput after transform
4.6
In XPath 3.1 making use of the sort
function you could implement that algorithm given on the linked page as
<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>
in a complete sample as
<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
In XSLT/XPath 2.0 you can use perform-sort
and then local XSLT variables in the function:
<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>