e231d173a9bee19af2a31ec8193c00a294a1a3a0 kent Tue May 27 20:03:59 2014 -0700 Polishing doubleBoxWhiskerCalc to work well for small Ns. diff --git src/lib/common.c src/lib/common.c index 50d6c69..494a201 100644 --- src/lib/common.c +++ src/lib/common.c @@ -479,42 +479,67 @@ doubleSort(count, array); if ((count&1) == 1) median = array[count>>1]; else { count >>= 1; median = (array[count] + array[count-1]) * 0.5; } return median; } void doubleBoxWhiskerCalc(int count, double *array, double *retMin, double *retQ1, double *retMedian, double *retQ3, double *retMax) /* Calculate what you need to draw a box and whiskers plot from an array of doubles. */ { +if (count <= 0) + errAbort("doubleBoxWhiskerCalc needs a positive number, not %d for count", count); +if (count == 1) + { + *retMin = *retQ1 = *retMedian = *retQ3 = *retMax = array[0]; + return; + } doubleSort(count, array); -*retMin = array[0]; -*retQ1 = array[(count+2)/4]; +double min = array[0]; +double max = array[count-1]; +double median; int halfCount = count>>1; if ((count&1) == 1) - *retMedian = array[halfCount]; + median = array[halfCount]; else { - *retMedian = (array[halfCount] + array[halfCount-1]) * 0.5; + median = (array[halfCount] + array[halfCount-1]) * 0.5; } -*retQ3 = array[(3*count+2)/4]; -*retMax = array[count-1]; +double q1, q3; +if (count <= 3) + { + q1 = 0.5 * (median + min); + q3 = 0.5 * (median + max); + } +else + { + int q1Ix = count/4; + int q3Ix = count - 1 - q1Ix; + uglyf("count %d, q1Ix %d, q3Ix %d\n", count, q1Ix, q3Ix); + q1 = array[q1Ix]; + q3 = array[q3Ix]; + } +*retMin = min; +*retQ1 = q1; +*retMedian = median; +*retQ3 = q3; +*retMax = max; } struct slDouble *slDoubleNew(double x) /* Return a new double. */ { struct slDouble *a; AllocVar(a); a->val = x; return a; } int slDoubleCmp(const void *va, const void *vb) /* Compare two slDoubles. */ { const struct slDouble *a = *((struct slDouble **)va);