manicmonkey21421
manicmonkey21421

Reputation: 113

Calculating exponential growth equation from data points c#

I am trying to analyse some data using a C# app and need to calculate trend lines. I am aware that there are multiple types of trend line but for now I am trying to calculate exponential growth; I am going to be using it to predict future values. The equation I have been working off is

x(t) = x(0) * ((1+r)^t)

And this is the code that I have written to try and replicate the graph:

public void ExponentialBestFit(List<DateTime> xvalues, List<double> yvalues)

        {
            //Find the first value of y (The start value) and the first value of x (The start date)
            xzero = Convert.ToDouble(xvalues[0].ToOADate());
            yzero = yvalues[0];
            if (yzero == 0)
                yzero += 0.1;

            //For every value of x (exluding the 1st value) find the r value
            //
            //                       |   y   |          Where t = the time sinse the start time (time period)
            //Equation for r = t root|-------| - 1      Where y = the current y value
            //                       |  y[0] |          Where y[0] = the first y value  #IMPROVMENT - Average 1st y value in range
            //
            double r = 0;

            //c is a count of how many r values are added; it is not equal to the count of all the values
            int c = 0;
            for (int i = 1; i < xvalues.Count; i++)
            {
                r += Math.Pow(yvalues[i]/yzero, 1/(Convert.ToDouble(xvalues[i].ToOADate()) - xzero)) - 1;
                c++;
            }

            r = r / c;           
        }

The data I am passing in is over a period of time however the increments in which the time increases are not the same. When I created a chart in excel they use a different formula

x(t) = x(0)*(e^kt)

I think however I have no idea where the k value is being generated from. The two lists that I am passing in are Date and Value and each row in each list corresponds to the same row in the other list. The question is - Is there a better way of creating the equation and variables and are the variables I am getting the most accurate it can be for my data?

Upvotes: 5

Views: 4646

Answers (3)

TYY
TYY

Reputation: 2716

This is the c# version of the javascript provided.

    // Calculate Exponential Trendline / Growth
    IEnumerable<double> Growth(IList<double> knownY, IList<double> knownX, IList<double> newX, bool useConst)
    {
        // Credits: Ilmari Karonen

        // Default values for optional parameters:
        if (knownY == null) return null;
        if (knownX == null)
        {
            knownX = new List<double>();
            for (var i  = 0; i<=knownY.Count; i++)
                knownX.Add(i);
        }
        if (newX == null)
        {
            newX = new List<double>();
            for (var i = 0; i <= knownY.Count; i++)
                newX.Add(i);
        }

        int n = knownY.Count;
        double avg_x = 0.0;
        double avg_y = 0.0;
        double avg_xy = 0.0;
        double avg_xx = 0.0;
        double beta = 0.0;
        double alpha = 0.0;
        for (var i = 0; i < n; i++)
        {
            var x = knownX[i];
            var y = Math.Log(knownY[i]);
            avg_x += x;
            avg_y += y;
            avg_xy += x * y;
            avg_xx += x * x;
        }
        avg_x /= n;
        avg_y /= n;
        avg_xy /= n;
        avg_xx /= n;

        // Compute linear regression coefficients:
        if (useConst)
        {
            beta = (avg_xy - avg_x * avg_y) / (avg_xx - avg_x * avg_x);
            alpha = avg_y - beta * avg_x;
        }
        else
        {
            beta = avg_xy / avg_xx;
            alpha = 0.0;
        }

        // Compute and return result array:
        return newX.Select(t => Math.Exp(alpha + beta*t)).ToList();

    }

Upvotes: 5

Teepeemm
Teepeemm

Reputation: 4518

Since x(t)=x(0)*e^{kt}, we can take logarithms to get ln x(t)=ln x(0) + kt. This means that to find ln x(0) and k, you can find the least squares fit for the data {(t,ln x(t))}. This will tell you that ln x(t) = b + at, so that k=a and x(0)=e^b.

Upvotes: 0

Ismael Ghalimi
Ismael Ghalimi

Reputation: 3565

The following JavaScript code should help. I used it to implement Excel's GROWTH function. It's written in JavaScript, but porting it to C# should be very easy. Please note that most of it was written by someone else (credits in the code).

function GROWTH(known_y, known_x, new_x, use_const) {
  // Credits: Ilmari Karonen

  // Default values for optional parameters:
  if (typeof(known_x) == 'undefined') {
    known_x = [];
    for (var i = 1; i <= known_y.length; i++) known_x.push(i);
  }
  if (typeof(new_x) == 'undefined') {
    new_x = [];
    for (var i = 1; i <= known_y.length; i++) new_x.push(i);
  }
  if (typeof(use_const) == 'undefined') use_const = true;

  // Calculate sums over the data:
  var n = known_y.length;
  var avg_x = 0;
  var avg_y = 0;
  var avg_xy = 0;
  var avg_xx = 0; 
  for (var i = 0; i < n; i++) {
    var x = known_x[i];
    var y = Math.log(known_y[i]);
    avg_x += x;
    avg_y += y;
    avg_xy += x*y;
    avg_xx += x*x;
  }
  avg_x /= n;
  avg_y /= n;
  avg_xy /= n;
  avg_xx /= n;

  // Compute linear regression coefficients:
  if (use_const) {
    var beta = (avg_xy - avg_x*avg_y) / (avg_xx - avg_x*avg_x);
    var alpha = avg_y - beta*avg_x;
  } else {
    var beta = avg_xy / avg_xx;
    var alpha = 0;
  }

  // Compute and return result array:
  var new_y = [];
  for (var i = 0; i < new_x.length; i++) {
    new_y.push(Math.exp(alpha + beta * new_x[i]));
  }
  return new_y;
}

Upvotes: 1

Related Questions