Subject: | Stackedbar and sparse data; round 2 |
The fixes I submitted earlier were not complete. In particular, it fails
badly when all datasets to not start at the same point.
Since there is no obvious way to retrieve a value for key = ?; we go
through a bit of acrobatics to fill in the gaps. It is possible that
filling in gaps with zero should be a standard function in the DataSet
module.
Subject: | StackedBar.patch |
*** StackedBar.pm.orig 2010-05-09 00:21:50.000000000 -0400
--- StackedBar.pm 2010-06-04 01:08:00.000000000 -0400
***************
*** 77,96 ****
# Fetch all the colors we'll need. Since we build each vertical bar from
# top to bottom, we'll need to change colors vertically.
! for (my $i = 0; $i < $self->{SCOUNT}; $i++) {
push(@{ $self->{COLORS} }, $clicker->color_allocator->next);
}
my @keys = $dses->[0]->get_all_series_keys;
# Iterate over each key...
for (my $i = 0; $i < scalar(@keys); $i++) {
# Get all the values from every dataset's series for each key
! my @values;
! foreach my $ds (@{ $dses }) {
! push(@values, $ds->get_series_values($i));
! }
# Mark the x, since it's the same for each Y value
my $x = $domain->mark($width, $keys[$i],);
--- 77,123 ----
# Fetch all the colors we'll need. Since we build each vertical bar from
# top to bottom, we'll need to change colors vertically.
! for (1 .. $self->{SCOUNT}) {
push(@{ $self->{COLORS} }, $clicker->color_allocator->next);
}
my @keys = $dses->[0]->get_all_series_keys;
+ # To properly handle sparse data, including keysets with gaps at the
+ # beginning of the data provided, we need to create an array of values
+ # for each key and fill in zeros for missing values. Dataset is position
+ # based and does not have an easy way of retrieving a value for a specific
+ # key
+ my @accum;
+ foreach my $ds (@{ $dses }) {
+ foreach my $series (@{ $ds->series }) {
+ my @seriesVals = @{ $series->values };
+ my @seriesKeys = @{ $series->keys };
+ my $kcount = $series->key_count - 1;
+
+ my %hashed;
+ for my $j (0 .. $kcount) {
+ $hashed{$seriesKeys[$j]} = $seriesVals[$j];
+ }
+
+ for (my $i = 0; $i < scalar(@keys); $i++) {
+ my $key = $keys[$i];
+ my $val = $hashed{$key} // 0;
+
+ if(exists($accum[$i])) {
+ push(@{$accum[$i]}, $val);
+ } else {
+ $accum[$i] = [$val];
+ }
+ }
+ }
+ }
+
# Iterate over each key...
for (my $i = 0; $i < scalar(@keys); $i++) {
# Get all the values from every dataset's series for each key
! my @values = @{$accum[$i]};
# Mark the x, since it's the same for each Y value
my $x = $domain->mark($width, $keys[$i],);