• We’re currently investigating an issue related to the forum theme and styling that is impacting page layout and visual formatting. The problem has been identified, and we are actively working on a resolution. There is no impact to user data or functionality, this is strictly a front-end display issue. We’ll post an update once the fix has been deployed. Thanks for your patience while we get this sorted.

PHP - more of a math problem, dealing with weighting

Al Neri

Diamond Member
I have a set of values for particular years and I wish to weight the more recent data more heavily and the most distant (timewise) less heavily, and I wish to do it so that the weighting drops exponentially. It's been some time since I took a math course and for some reason I cannot think straight.

The data that I am using is annual data for bodyweight and wastline for many different people and there are varied amounts of years.

here's 2 examples (The data I have are sometimes over 20 years, so the two below are brief)

Example One
PersonID-Bodyweight-Waistline
2009-28-135
2008-27-132
2007-27-129
2006-26-115

Example Two
PersonID-Bodyweight-Waistline
2009-32-225
2008-31-215
2007-36-240
2006-36-245
2005-36-240
2004-42-275


I put together a linear weighting system if I wanted to weight the most recent year as 1 and the least recent year as .1 as such:

(Beginning Weight-Ending Weight)/(#years-1)
so for "Example One" above there are 4 years, so each year would drop down by (1-.1)/3 or .3... or:

PersonID-Bodyweight-Waistline-Weighting
2009-28-135-1
2008-27-132-0.7
2007-27-129-0.4
2006-26-115-0.1


How would I do this exponentially so that 2009 is weighted heaviest, 2008 slightly less, 2007 slightly less than that, etc. Again, the examples I have are sometimes over 20 years, so the two above are brief examples.

Thanks,

Alfonse


 
Incidentally I just had to implement this myself. Exponential weighting is done with the following formula (with 0 < a < 1):

y_{n+1} = a * x_{n+1} + (1-a) * y_n

That is, multiply the current input by a and the running weighted average by (1-a), then sum. You can see why this is exponential, since for example you'll have:

y_1 = a * x_1 + (1-a) * y_0
y_2 = a * x_2 + a * (1-a) * x_1 + (1-a)^2 * y_0
y_3 = a * x_3 + a * (1-a) * x_2 + a * (1-a)^2 * x_1 + (1-a)^3 * y_0
...

So you can see the weighting of past values drops exponentially (as 1-a).

Note that in general, small a means past values will have a stronger impact while a large a means past values will disappear more quickly (consider the limiting case that a = 0 means y_{n+1} = y_n and a = 1 means y_{n+1} = x_{n+1}).

Anyway, more details on the theory can be found at http://en.wikipedia.org/wiki/Moving_average

To implement it, I would do something like this (pseudocode):

exp_avg = x[0]
for (k = 1; k < n; k++)
{
...exp_avg = a*x[k] + (1-a)*exp_avg;
}

a is your weighting factor.
exp_avg will be the result at the end of the loop.
 
Back
Top