FREQUENCIES: Fixed crash showing histograms of limited range.
authorJohn Darrington <john@darrington.wattle.id.au>
Sat, 26 Apr 2014 05:33:08 +0000 (07:33 +0200)
committerJohn Darrington <john@darrington.wattle.id.au>
Sat, 26 Apr 2014 05:33:08 +0000 (07:33 +0200)
We had been using Freedman-Diaconis rule to select the bin width.
According to the literature this is better than Sturges rule.
However it cannot work when the interquartile range is zero, which
will happen for datasets with small range.

This change uses the Freedman-Diaconis rule and falls back to
Sturges when the IQR is zero.

src/language/stats/frequencies.c
tests/language/stats/frequencies.at

index 1f8290cf2c696d418b28d3c92a039dfecbd800a7..7bda6a13e050d6d46b4f0fb485289ade8779326a 100644 (file)
@@ -1195,9 +1195,16 @@ freq_tab_to_hist (const struct frq_proc *frq, const struct freq_tab *ft,
         }
     }
 
-  /* Freedman-Diaconis' choice of bin width. */
+
   iqr = calculate_iqr (frq);
-  bin_width = 2 * iqr / pow (valid_freq, 1.0 / 3.0);
+
+  if (iqr > 0)
+    /* Freedman-Diaconis' choice of bin width. */
+    bin_width = 2 * iqr / pow (valid_freq, 1.0 / 3.0);
+
+  else
+    /* Sturges Rule */
+    bin_width = (x_max - x_min) / (1 + log2 (valid_freq));
 
   histogram = histogram_create (bin_width, x_min, x_max);
 
@@ -1355,7 +1362,8 @@ dump_statistics (const struct frq_proc *frq, const struct var_freqs *vf,
     }
   calc_stats (vf, stat_value);
 
-  t = tab_create (3, ((frq->stats & FRQ_ST_MEDIAN) ? frq->n_stats - 1 : frq->n_stats) + frq->n_show_percentiles + 2);
+  t = tab_create (3, ((frq->stats & FRQ_ST_MEDIAN) ? frq->n_stats - 1 : frq->n_stats)
+                 + frq->n_show_percentiles + 2);
 
   tab_box (t, TAL_1, TAL_1, -1, -1 , 0 , 0 , 2, tab_nr(t) - 1) ;
 
index a2545b0f4c47ac2897bb33f422c677bc7d64dcf7..469ba82d185dd9c72199676b25528c55c93fd534 100644 (file)
@@ -516,6 +516,7 @@ FREQUENCIES
        VAR=x
        /PERCENTILES = 0 25 50 75 100.
 ])
+
 AT_CHECK([pspp -O format=csv frequencies.sps], [0],
   [Table: X
 Value Label,Value,Frequency,Percent,Valid Percent,Cum Percent
@@ -540,3 +541,36 @@ Percentiles,0,1.00
 ,100,5.00
 ])
 AT_CLEANUP
+
+AT_SETUP([FREQUENCIES dichotomous histogram])
+AT_DATA([frequencies.sps], [dnl
+data list notable list /d4 *.
+begin data.
+0 
+0 
+0 
+1 
+0 
+0 
+0 
+0 
+1 
+0 
+0 
+0 
+0 
+0 
+1 
+2 
+0 
+end data.
+
+FREQUENCIES
+       /VARIABLES = d4
+       /FORMAT=AVALUE TABLE
+       /HISTOGRAM=NORMAL
+       .
+])
+
+AT_CHECK([pspp frequencies.sps], [0],  [ignore])
+AT_CLEANUP