[rrd-developers] Patch for Percentil calculation that ignores NAN

Martin Sperl rrdtool at martin.sperl.org
Fri Jan 9 09:32:26 CET 2009


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




More information about the rrd-developers mailing list