[rrd-developers] Patch for Percentil calculation that ignores NAN
Tobias Oetiker
tobi at oetiker.ch
Wed Jan 14 08:22:46 CET 2009
Hi Martin,
thanks for your contrib, I applied it to trunk.
Friday Martin Sperl wrote:
> Hi!
>
> As this is missing for my needs here a patch for percentil calculation
> that does ignore NAN's...
>
> Ciao,
> Martin
>
> Index: src/rrd_graph.c
> ===================================================================
> --- src/rrd_graph.c (revision 1726)
> +++ src/rrd_graph.c (working copy)
> @@ -4586,6 +4586,8 @@
> }
> if (!strcmp("PERCENT", func))
> gdes->vf.op = VDEF_PERCENT;
> + else if (!strcmp("PERCENTNAN", func))
> + gdes->vf.op = VDEF_PERCENTNAN;
> else if (!strcmp("MAXIMUM", func))
> gdes->vf.op = VDEF_MAXIMUM;
> else if (!strcmp("AVERAGE", func))
> @@ -4613,6 +4615,7 @@
> };
> switch (gdes->vf.op) {
> case VDEF_PERCENT:
> + case VDEF_PERCENTNAN:
> if (isnan(param)) { /* no parameter given */
> rrd_set_error
> ("Function '%s' needs parameter in VDEF '%s'\n",
> @@ -4697,6 +4700,34 @@
> #endif
> }
> break;
> + case VDEF_PERCENTNAN:{
> + rrd_value_t *array;
> + int field;
> + /* count number of "valid" values */
> + int nancount=0;
> + for (step = 0; step < steps; step++) {
> + if (!isnan(data[step * src->ds_cnt])) { nancount++; }
> + }
> + /* and allocate it */
> + if ((array = (rrd_value_t*)malloc(nancount * sizeof(double)))
> == NULL) {
> + rrd_set_error("malloc VDEV_PERCENT");
> + return -1;
> + }
> + /* and fill it in */
> + field=0;
> + for (step = 0; step < steps; step++) {
> + if (!isnan(data[step * src->ds_cnt])) {
> + array[field] = data[step * src->ds_cnt];
> + field++;
> + }
> + }
> + qsort(array, nancount, sizeof(double), vdef_percent_compar);
> + field = (nancount - 1) * dst->vf.param / 100;
> + dst->vf.val = array[field];
> + dst->vf.when = 0; /* no time component */
> + free(array);
> + }
> + break;
> case VDEF_MAXIMUM:
> step = 0;
> while (step != steps && isnan(data[step * src->ds_cnt]))
> Index: src/rrd_graph.h
> ===================================================================
> --- src/rrd_graph.h (revision 1726)
> +++ src/rrd_graph.h (working copy)
> @@ -70,6 +70,7 @@
> , VDEF_LSLSLOPE /* least squares line slope */
> , VDEF_LSLINT /* least squares line y_intercept */
> , VDEF_LSLCORREL /* least squares line correlation
> coefficient */
> + , VDEF_PERCENTNAN /* Nth percentile ignoring NAN*/
> };
> enum text_prop_en {
> TEXT_PROP_DEFAULT = 0, /* default settings */
> Index: doc/rrdgraph_rpn.pod
> ===================================================================
> --- doc/rrdgraph_rpn.pod (revision 1726)
> +++ doc/rrdgraph_rpn.pod (working copy)
> @@ -357,12 +357,13 @@
>
> Example: C<VDEF:total=mydata,TOTAL>
>
> -=item PERCENT
> +=item PERCENT, PERCENTNAN
>
> This should follow a B<DEF> or B<CDEF> I<vname>. The I<vname> is popped,
> another number is popped which is a certain percentage (0..100). The
> data set is then sorted and the value returned is chosen such that
> I<percentage> percent of the values is lower or equal than the result.
> +For PERCENTNAN I<Unknown> values are ignored, but for PERCENT
> I<Unknown> values are considered lower than any finite number for this
> purpose so if this operator returns an I<unknown> you have quite a lot
> of them in your data. B<Inf>inite numbers are lesser, or more, than the
> @@ -370,6 +371,7 @@
> (NaN E<lt> -INF E<lt> finite values E<lt> INF)
>
> Example: C<VDEF:perc95=mydata,95,PERCENT>
> + C<VDEF:percnan95=mydata,95,PERCENTNAN>
>
> =item LSLSLOPE, LSLINT, LSLCORREL
>
>
> _______________________________________________
> rrd-developers mailing list
> rrd-developers at lists.oetiker.ch
> https://lists.oetiker.ch/cgi-bin/listinfo/rrd-developers
>
>
--
Tobi Oetiker, OETIKER+PARTNER AG, Aarweg 15 CH-4600 Olten, Switzerland
http://it.oetiker.ch tobi at oetiker.ch ++41 62 775 9902 / sb: -9900
More information about the rrd-developers
mailing list