[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