Bell Curve plot problem !

I am trying to write a code to plot bell curve. First, it generates some random numbers and store it in a FloatList. Then I iterate over the FloatList to calculate to mean (mu), standard deviation (sd), z score, normal distribution (nd).

First I thought, since these number are generated randomly they would not be in order so I sort them and plotted them on canvas. It was bell curve. success, right? But no then it struck me that if this bell curve is correct then the lowest number and highest number have the lowest probability of occurrence and the numbers that are towards the center would have the high chances of occurrence. since they are sorted and in the order (lowest --> highest)

After realizing that, I removed the sort() function and try to plot them again, and I got the same result.

I don't know what is happening but I can guess there could be two things happening

  1. Either I haven't implemented the bell curve code correctly
  2. Or There is something wrong with the processing. I have concluded this because it may be happening that processing is not clearing its memory (I guess buffer memory) and plotting the same graph because of it.

    FloatList floatValue;
    boolean press=false;
    int t=0;
    
    void setup() {
      size(900, 300);
      floatValue = new FloatList();
    }
    
    
    void draw() {
      background(0); 
      //--------------------------
      if (t<20 ) { // number of elements
        floatValue.append(random(width)); ///add data
        t++;
      } else {
        press=true;
      }
    
    
      //---------------------------
      if (press) {
        float mu = mean(); // calculate mean
        float sd = SD(mu); // calculate standard deviation 
        // floatValue.sort(); // Sort FloatList
        for (int i=0; i<floatValue.size (); i++) {
          float P = floatValue.get(i);
          println(P);
          float z = zScore(P, mu, sd); // calculate z score if you want to represets Standard distribution
          float nd = normalDistribution(P, mu, sd); // calculate Normal distribution   
          float y = height-nd*6000;
          fill(#FC003B);
          ellipse(P, y, 2, 2);
          lable(P, y-40);
        }
        stroke(255, 0, 255);
        line(mu, height, mu, 0);
      }
      //  stroke(-1, 50);
      //  line(mouseX, 0, mouseX, height);
      //  line(0, mouseY, width, mouseY);
    }
    
    float mean() {
      float mu=0;
      for (int i=0; i<floatValue.size (); i++) {
        float P = floatValue.get(i);
        mu=mu+P;
      }
      mu = mu/floatValue.size();
      return mu;
    }
    
    
    float SD(float mu) {
      float sd=0;
      for (int i=0; i<floatValue.size (); i++) {
        float P = floatValue.get(i);
        sd = sd + sq(P-mu);
      }
      sd = sqrt(sd/floatValue.size());
      return sd;
    }
    
    
    float zScore(float num, float mu, float sd) {
      float z = 0;
      z = (num - mu)/sd;
      return z;
    }
    
    
    float normalDistribution(float num, float mu, float sd) {
      float e = 2.71828182845904523536; 
      float ND  =  (1/sqrt(TWO_PI * sd ))*pow (e, (-(sq(num - mu))/(2*sq(sd ))));
      return ND;
    }
    
    
    class Point {
      float x;
      Point(float x) {
        this.x =x;
      }
    }
    
    
    void lable(float x, float y) {
      fill(#FAC903);
      pushMatrix();
      translate(x, y);
      rotate(3*PI/2);
      textAlign(CENTER);
      text(x, 0, 0);
      popMatrix();
    }
    

Answers

  • edited March 2015

    The Processing code looks correct but I think you got confused on the statistics. What you did is generating some random numbers and calculated the mean and standard deviation. Then you did something weird: you plotted the points on an x/y plot where their y value is according to the gaussian curve. Why is that?

    That gaussian is meaningless here anyway since these values are random and thus NOT normal distributed. I don't have my book on statistics nearby but there is some kind of test you could implement to test if the random values are normal distributed and then you should see that they're not (but you're only generating 20 anyway and that's pretty low for statistics so the test could give you a false positive). What you could do is generate several lists of random values (several floatlists, you can store them in an array or arraylist), calculate their mean and plot them. According to central limit theorem, those mean values will be normal distributed.

    Additional remarks about your code:

    • you can replace pow(e, ... ) by exp(...), which is a little cleaner
    • This structure:

    .

    if (t<20 ) { 
        (...)
        t++;
      } else {
        press=true;
      }
    
      if (press) {
    

    is a bit questionable. It would be cleaner if you just filled the floatValue FloatList inside setup():

    void setup()
    {
       (...)
       for(int i = 0; i < 20; i++)
       {
          floatValue.append(random(width));
       }
    }
    

    You can then calculate mean, sd and z-value inside setup so you don't have to do that again on each draw() saving the processor a bit (they'd need to be global variables of course).

  • edited March 2015

    You can simulate getting random values from a normally distribution bu taking the average of 6 random numbers.

    The code below demonstrates what I mean.

    void setup() {
      for (int i = 0; i < 10; i++)
        println(getRandomNormalDistributedValue());
    }
    
    // Get a random value in the range -1 to 1 with a mean
    // of 0 (zero) and a standard deviation ~ 0.17
    float getRandomNormalDistributedValue() {
      float n = 0;
      for (int i = 0; i < 6; i++)
        n += random(-1.0, 1.0);
      n /= 6;
      return n;
    }
    
  • edited March 2015

    ... by taking the average of 6 random numbers.

    Are you sure it's 6 random() numbers? Your loop's condition is i < 5! :-?
    Nonetheless, here's a tweaked version w/ an extra avg parameter: O:-)

    // forum.processing.org/two/discussion/9914/bell-curve-plot-problem
    // by Quark (2015/Mar/18)
    
    static final int QTY = 10, AVG = 6;
    final FloatList floats = new FloatList(QTY);
    
    void setup() {
      for (int i = 0; i++ != QTY; floats.append(randomNormalDistribution(AVG)));
      println(floats);
      exit();
    }
    
    float randomNormalDistribution(int avg) {
      float f = 0.0;
      for (int i = 0; i++ != avg; f += random(-1.0, 1.0));
      return f/avg;
    }
    
  • Thanks for spotting the typo it should have been 6 - modified the code above.

    Taking it a bit further I have modified the function above so that it returns a random number from a user specified normal distribution.

    void setup() {
      for (int i = 0; i < 10; i++)
        println(getRandomNormalDistributedValue(100, 20));
    }
    
    // Get a random value from a normal distribution 
    // with the specified mean and standard deviation
    float getRandomNormalDistributedValue(float mean, float sd) {
      float n = 0;
      for (int i = 0; i < 6; i++)
        n += random(-1.0, 1.0);
      return mean + n * sd / 6;
    }
    
Sign In or Register to comment.