Skip to content

Commit d9cf3a5

Browse files
committed
Allow histogram bin bounds to be specified explicitly
1 parent f136854 commit d9cf3a5

File tree

5 files changed

+46
-17
lines changed

5 files changed

+46
-17
lines changed

CHANGELOG

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
- Rename `Histogram::from_vec` to `Histogram::from_slice`.
1717
- Rename `view::View` to `view::ContinuousView` and introduce `view::View` as a trait.
1818
- Change `svg_render` functions to take data slices rather than Representations.
19+
- `Histogram::from_slice` now takes either a bin count or a bin bound list as its second argument.
1920

2021
## 0.3.0 - 2018-03-01
2122
### Added

examples/histogram_svg.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use plotlib::style::Bar;
44

55
fn main() {
66
let data = [0.3, 0.5, 6.4, 5.3, 3.6, 3.6, 3.5, 7.5, 4.0];
7-
let h = plotlib::histogram::Histogram::from_slice(&data, 10)
7+
let h = plotlib::histogram::Histogram::from_slice(&data, plotlib::histogram::Bins::Count(10))
88
.style(plotlib::histogram::Style::new().fill("burlywood"));
99
let v = plotlib::view::ContinuousView::new().add(&h);
1010
plotlib::page::Page::single(&v)

examples/histogram_text.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ extern crate plotlib;
22

33
fn main() {
44
let data = [0.3, 0.5, 6.4, 5.3, 3.6, 3.6, 3.5, 7.5, 4.0];
5-
let h = plotlib::histogram::Histogram::from_slice(&data, 10);
5+
let h = plotlib::histogram::Histogram::from_slice(&data, plotlib::histogram::Bins::Count(10));
66
let v = plotlib::view::ContinuousView::new().add(&h);
77
println!("{}", plotlib::page::Page::single(&v).dimensions(60, 15).to_text().unwrap());
88
}

src/histogram.rs

Lines changed: 42 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ A module for Histograms
1010
let data = vec![0.3, 0.5, 6.4, 5.3, 3.6, 3.6, 3.5, 7.5, 4.0];
1111
1212
// and create a histogram out of it
13-
let h = Histogram::from_slice(&data, 30);
13+
let h = Histogram::from_slice(&data, plotlib::histogram::Bins::Count(30));
1414
```
1515
1616
TODO:
@@ -68,6 +68,12 @@ enum HistogramType {
6868
Density,
6969
}
7070

71+
#[derive(Debug)]
72+
pub enum Bins {
73+
Count(usize),
74+
Bounds(Vec<f64>),
75+
}
76+
7177
/**
7278
A one-dimensional histogram with equal binning.
7379
*/
@@ -81,7 +87,7 @@ pub struct Histogram {
8187
}
8288

8389
impl Histogram {
84-
pub fn from_slice(v: &[f64], num_bins: usize) -> Histogram {
90+
pub fn from_slice(v: &[f64], bins: Bins) -> Histogram {
8591
let mut max = v.iter().fold(-1. / 0., |a, &b| f64::max(a, b));
8692
let mut min = v.iter().fold(1. / 0., |a, &b| f64::min(a, b));
8793

@@ -90,18 +96,22 @@ impl Histogram {
9096
max += 0.5;
9197
}
9298

93-
let mut bins = vec![0; num_bins];
99+
let (num_bins, bounds) = match bins {
100+
Bins::Count(num_bins) => {
101+
let range = max - min;
102+
let mut bounds: Vec<f64> = (0..num_bins)
103+
.map(|n| (n as f64 / num_bins as f64) * range + min)
104+
.collect();
105+
bounds.push(max);
106+
(num_bins, bounds)
107+
}
108+
Bins::Bounds(bounds) => (bounds.len(), bounds),
109+
};
94110

95-
let range = max - min;
111+
let mut bins = vec![0; num_bins];
96112

97113
let bin_width = (max - min) / num_bins as f64; // width of bin in real units
98114

99-
let mut bounds: Vec<f64> = (0..num_bins)
100-
.map(|n| (n as f64 / num_bins as f64) * range + min)
101-
.collect();
102-
bounds.push(max);
103-
let bounds = bounds;
104-
105115
for &val in v.iter() {
106116
/*
107117
let mut bin = ((val - min) / bin_width) as usize;
@@ -211,15 +221,33 @@ mod tests {
211221

212222
#[test]
213223
fn test_histogram_from_slice() {
214-
assert_eq!(Histogram::from_slice(&[], 3).get_values(), [0., 0., 0.]);
215-
assert_eq!(Histogram::from_slice(&[0.], 3).get_values(), [0., 1., 0.]);
216224
assert_eq!(
217-
Histogram::from_slice(&[0., 3.], 3).get_values(),
225+
Histogram::from_slice(&[], Bins::Count(3)).get_values(),
226+
[0., 0., 0.]
227+
);
228+
assert_eq!(
229+
Histogram::from_slice(&[0.], Bins::Count(3)).get_values(),
230+
[0., 1., 0.]
231+
);
232+
assert_eq!(
233+
Histogram::from_slice(&[0., 3.], Bins::Count(3)).get_values(),
218234
[1., 0., 1.]
219235
);
220236
assert_eq!(
221-
Histogram::from_slice(&[0., 1., 2., 3.], 3).get_values(),
237+
Histogram::from_slice(&[0., 1., 2., 3.], Bins::Count(3)).get_values(),
222238
[2., 1., 1.]
223239
);
224240
}
241+
242+
#[test]
243+
fn test_histogram_define_bin_bounds() {
244+
assert_eq!(
245+
Histogram::from_slice(&[0., 1.], Bins::Count(3)).bin_bounds,
246+
[0., 1. / 3., 2. / 3., 1.]
247+
);
248+
assert_eq!(
249+
Histogram::from_slice(&[], Bins::Bounds([0., 1., 1.5, 2., 5.6].to_vec())).bin_bounds,
250+
[0., 1., 1.5, 2., 5.6]
251+
);
252+
}
225253
}

src/text_render.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -593,7 +593,7 @@ mod tests {
593593
#[test]
594594
fn test_render_face_bars() {
595595
let data = vec![0.3, 0.5, 6.4, 5.3, 3.6, 3.6, 3.5, 7.5, 4.0];
596-
let h = histogram::Histogram::from_slice(&data, 10);
596+
let h = histogram::Histogram::from_slice(&data, histogram::Bins::Count(10));
597597
let x_axis = axis::ContinuousAxis::new(0.3, 7.5);
598598
let y_axis = axis::ContinuousAxis::new(0., 3.);
599599
let strings = render_face_bars(&h, &x_axis, &y_axis, 20, 10);

0 commit comments

Comments
 (0)