Strange behavior constructing simple Histogram

My goal is to identify the frequency of an exact number in a float[] set. So far it all works excluding the frequency counting part. If someone would be kind enough to explain the mistake I've made, it would be very appreciated.

void setup() {
  // Testing dataset. Normally loaded from disk.
  float[] samples = { 1.01, 0.32, 1.0, 1.01, 1.05, 1.0, 1.01, 0.55, 0.0, -100.0,
                      0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.0, 0.0, 0.0, 0.0, 3.0 }; 
  int index = samples.length;


  // Identify multiples.
  float[] knockSpread = samples; // Copy array to one safe to write on.
  for(int k=0; k<index; k++) {        // for each sample entry.
    if(knockSpread[k] != -100.0) {    // if not void entry.
      for(int sample=0; sample<index; sample++) { 
        if(knockSpread[k] == knockSpread[sample]   &&   k != sample) 
          knockSpread[sample] = -100.0; // if duplicate number then void this entry.
      } // end for(sample)
    } // end if ! 0
  } // end for(k)


  // Construct the lists.
  IntList   spreadCount = new IntList();
  FloatList spreadValue = new FloatList();  
  for(int k=0; k<index; k++) {
    if(knockSpread[k] != -100.0) {   // if not void then append lists.
      spreadValue.append(knockSpread[k]);
      spreadCount.append(0);
    } // end if ! 0
  } // end for(k)


  // Count unique numbers. ERROR in here...
  for(int value=0; value<spreadValue.size(); value++) { // for each value in list.
    for(int scan=0; scan<index; scan++) {  // for each value in sample.
      if(spreadValue.get(value) == samples[scan]) // ERROR: only passes once per list entry. Why?
        spreadCount.add(value, 1);  // Increment value's frequency count.
    } // end for(scan)
  } // end for(value)


  // Construct the display string.
  String printout = "Samples: ";
  for(int p=0; p<spreadCount.size(); p++) 
    printout += spreadValue.get(p) + "(" + spreadCount.get(p) + ")\t";

  println(printout);
} // end setup()

void draw() { exit(); }

Answers

  • edited April 2016

    Apologies, not used to formatting code here yet.

  • edited April 2016

    Redundant post.

  • Are you effing kidding me? Now it's properly colored?

    Ok, lol...whatever, at least it "works."

    BTW, I've been using Processing since 2.4.1. Still teaching myself what I can, but I'm really happy this API exists. You've saved so many people so many hours of work. Thank you all very much.

  • edited April 2016 Answer ✓
      // Count unique numbers.
      for(int value=0; value<spreadValue.size(); value++) { // for each value in list.
        for(int scan=0; scan<index; scan++) {  // for each value in sample.
          print("[" + value + "][" + scan + "] Comparing [" + spreadValue.get(value) + "] and [" + samples[scan] + "]");
          if(spreadValue.get(value) == samples[scan]) {             // ERROR: only pases once per list entry. Why?
            println(" - match");
            spreadCount.add(value, 1);  // Increment value's frequency count.
          } else {
            println(" - no match");
          }
        } // end for(scan)
      } // end for(value)
    

    a bit of debug and you can see what it's comparing.

    i think your problem is line 13:

    float[] knockSpread = samples; // Copy array to one safe to write on.
    

    this is NOT a copy, it's a reference. so you mangle the original array.

    a hashmap is a better choice for a histogram, imo

    import java.util.HashMap;
    
    HashMap<Float, Integer> hash = new HashMap<Float, Integer>();
    for (float value : values) {
      Integer i = hash.get(value); 
      if (i == null) {
        // first time we've seen this, create an entry
        hash.put(value, 1);
      } else {
        // increment existing entry
        hash.put(value, i + 1);
      }
    }
    println(hash);
    
  • A HashMap is a better choice for a histogram, iMO.

    He's already using a FloatList @ line #20:

    // Construct the lists.
    IntList   spreadCount = new IntList();
    FloatList spreadValue = new FloatList();
    
  • edited April 2016

    koogs: This detail is not covered in the reference.
    https://processing.org/reference/assign.html

    I'm going to have a good look at those HashMaps. They look fascinating.

    Attempting to find a work around, Replacing:

    float[] knockSpread = samples; // Copy array to one safe to write on.


    With:

      float[] knockSpread = new float[index]; // Copy array to one safe to write on.
      for(int f=0; f<index; f++)
        knockSpread[f] = samples[f];
    

    ...makes the code work correctly, but it just feels logically weird.
    Are there any other simple methods beyond HashMaps recommended for irregular histogram binning?

    koogs & GoToLoop: Thanks for the enlightenment!

    Edit: This unmentioned property of the assign operator explains a whole lot of problems I was having with some other stuff too. Should the Processing 3 Reference be updated to state that assign does both copy and reference functions? It makes sense that lots of people learning to program without a structured course wouldn't be aware of this Java feature.

  • He's already using a FloatList @ line #20:

    Yeah, but then needs a separate intlist to store the counts...

Sign In or Register to comment.