in reply to Interpolating data slope for multiple points
BTW, your progress is amazing! And very consistent! Great!
To do this yourself, I would convert date/time to say epoch time. calculate min,max of X and Y scale. Then decide how many "buckets" you will have in each direction. Place each data point to closest X,Y coordinate that your scaling system allows. Calculate intermediate y points along the x axis between 2 points with y=mx+b. A line graph is better here than a bar.
Your data is so consistent that I don't see any need, but in some cases you would want to make a single line that represents the "best fit" of all the data points. One technique is least squares approximation. There is a way to get Excel and other spreadsheet programs to do that.
Update:
Oh, I see that this is some CGI thing. Ok, some code that shows a bit of a different way is below..hope it helps..
Update to Update:#!/usr/bin/perl -w use strict; use Time::Local; use Data::Dumper; my @data; my @graph; my $one_day = 60*60*24; #one day in seconds while (<DATA>) { next if /^\s*$/; #skip blank lines my ($date, $weight) = split; my $epoch = epoch($date); push (@data, [$epoch, $weight]); } # input data is sorted already sorted # But the algortihm depends upon sorted date information # so I did that to make sure # @data = sort{$a->[0] <=> $b->[0]} @data; # axis x will be adjusted to #days from the date of first data # axis y is in weight my ($x_base_epoch, $y1) = @{shift(@data)}; my $x1_day =0; foreach my $r_xy(@data) { my ($x2, $y2) = @$r_xy; $x2 -= $x_base_epoch; my $x2_day = int($x2/$one_day); # slope is delta weight/ delta days my $slope = ($y2-$y1)/($x2_day-$x1_day); # fill in missing data points... # by linear interpolation for (; $x1_day< $x2_day; $x1_day++) # x interval not tested for # other than 1 { my $y = $slope*($x1_day-$x2_day) + $y2; push @graph, [$x1_day,$y]; } $y1= $y2; } #fix-up for last data point my ($fx,$fy) = @{$data[-1]}; push @graph, [($fx-$x_base_epoch)/$one_day, $fy]; ### data to graph is in @graph ### ### I leave that part to the OP ### print "$_->[0] $_->[1]\n" foreach @graph; sub epoch { my $date = shift; my ($month, $day, $year) = split(m|/|,$date); my $time = timelocal(0,0,0, $day, $month-1, $year-1900); return $time; } =prints 0 334 1 333.527659574468 2 333.055319148936 3 332.582978723404 4 332.110638297872 ..... 74 298.95 75 298.6 76 298.32 77 298.04 78 297.76 79 297.48 80 297.2 81 295.4 82 293.6 =cut __DATA__ 6/26/2010 334 8/12/2010 311.8 8/19/2010 308.4 9/5/2010 300.0 9/9/2010 298.6 9/14/2010 297.2 9/16/2010 293.6
Using a different x axis increment than "one" can get to problematic depending upon what you are trying to do. Often one would want to show the actual data points with some special character and the points inbetween with another character. So if you just want to show say weekly progress, then you have to decide what that would mean in terms of the graphical representation - eg the "weekly Monday point" may not represent any factual point at all. Generating the "weight" for each day is very efficient. If you want something like a "Monday" value it would not be ridiculous to generate all points in the week or year and then just print every 7th value.
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re^2: Interpolating data slope for multiple points
by GrandFather (Saint) on Sep 17, 2010 at 05:49 UTC | |
by Marshall (Canon) on Sep 17, 2010 at 11:39 UTC | |
|
Re^2: Interpolating data slope for multiple points
by oko1 (Deacon) on Sep 17, 2010 at 15:29 UTC |