I'm trying to find a way to get the Arduino to calculate the Mode, the number that has been repeated the most over the last ___ number of data points. I've searched the forum and library and didn't see anything. My current sketch is reading sensor output, which is very sporadic. Averaging the data, or trying numerous other methods of smoothing the data aren't sufficient. However, if I import the sensor outputs into excel and calculate MODE, it is giving me back exactly what I need. So now I need to make the Arduino determine MODE. Any suggestions?
Finding the mode requires that you keep track of the number of occurrences of each item - if you've got RAM available for it, just use an array to count the frequencies. Since you probably don't need 10-bit precision, scale the sensor values down to 8-bit (0-255 instead of 0-1024), and use an array of 8-bit unsigned integers (uint8_t) to keep track of counts. This will not work if a) you need more precision or b) there will be more than 255 counts of a given value in the time period you need.
general idea:
uint8_t counts[256];
// ...
// increment count for the sensor value
counts[analogRead(pin)/4]++;
// find mode
uint8_t mode = 0;
for (uint8_t i = 0; i < 256; i++) {
mode = (counts[i] > counts[mode]) ? i : mode;
}
Note: code is untested.
Your big limitation is going to be the Arduino's measly 2 kilobytes of RAM - for example, using 16-bit counts and 10-bit sensor values would use up 100% of your available RAM, and could make your program fail to act as you expect it to.
What aeturnalus said is correct, the amount of RAM is a limiting factor. The code he supplied works for max 255 samples (worst case) if you need more you must change the line
uint8_t counts[256]; ==> int counts[256]; Or use (external) EEPROM to store the counts / or even the samples. Or you might even store the samples on an SDcard... His code does not deal with multi-modal datasets. See below
Can you provide some background data?
How many samples do you make before calculating the modus?
What is the range of valid values? MIN/MAX values?
Are the samples distributed evenly across the whole range or is only a subset possible / relevant?
How much time is there between two samples?
How much time do you have to calculate the modus? (must it be realtime)
After detemining the modus, may the samples be dumped? or only the oldest ones? sort of running Modus?
How do you intend to handle bi-modal data? e.g. {1,2,4,2,4,2,4,5,5 } has 2 identical max values for freq. count
e.g. a modus of 100 samples made and to be computed within a second gives a completely other solutionspace than 1000 samples made over a day.
The mode is not well behaved - there may be several disparate sample values that all occur the same number of times. Maybe all sample values occur the same number of times - are you able to deal with these cases?
Maybe all sample values occur the same number of times - are you able to deal with these cases?
Yep that's what I called multi- and bi-modal.
There is a (very partial) solution for finite value sets (like the range of an ADC) and that is to use a samplecount that is larger than the number of possible values and not a multiple of the number of values. Possibly prime numbers may do better, but I have no proof of that - http://primes.utm.edu/lists/small/10000.txt .
example:
value set = {0..1023}
sampleCount = 1025
There are is at least one value that gets an extra point.
Another related problem with using modus is that in some timeframe/#samples some counters are absolutely almost the same (+ - 1) and the difference is relatively very small (<1% or less) e.g. counter 1 = 1001 and counter2 =1002. Strictly speaking counter2 indicates the modus. The question arises if the timeframe or # samples was slightly different would these 2 counters "change places"?
So maybe yo could tell more about thegoal of the project as there might be other solutions than using the Modus.