【问题标题】:How to calculate the statistical mode in Processing / Arduino如何在 Processing / Arduino 中计算统计模式
【发布时间】:2011-12-15 07:54:46
【问题描述】:

我是一名设计老师,试图帮助学生应对编程挑战,所以我为了好玩而编写代码,但我不是专家。

她需要在使用与 Arduino 耦合的传感器的数据构建的数据集中找到mode(最常见的值),然后根据结果激活一些功能。

除了如何在 Arduino 中计算模式之外,我们已经弄清楚了大部分。我发现帖子 Get the element with the highest occurrence in an array 解决了 JavaScript 中的问题,但我无法“移植”它。

【问题讨论】:

  • 您所指的“数据集”采用什么形式?它是一个(Arduino)整数数组吗?
  • 嗨,马修。我们还没有编写代码,但是是的,它可能是一个整数数组,尽管我们也可能采用浮点方式。她(学生)将测量物体的速度,并据此采取行动。对于比例原型,速度也会“按比例缩小”,所以我们必须测试整数是否可以,或者我们是否应该使用十进制数进行评估。
  • 如果您使用的是浮点数,我会担心可能没有单一的“模式”(即每个结果都可能不同)。这可能是一个问题,还是我们可以假设在这种情况下不会发生这种情况?

标签: processing arduino mode


【解决方案1】:

我已经使用HashMap 替换了 js {} 动态对象实例和浮动,但@weberik 的端口看起来更直接。

void setup() {
    int numValues = 10;
    float[] values = new float[numValues]; //Create an empty sample array
    for(int i = 0 ; i < numValues ; i++) values[i] = random(0.0,100.0); //Populate it with random values.
    println("mode: " + mode(values));
}

float mode(float[] source) {
    if (source.length == 0)
        return -1;
    HashMap<Float,Integer> modeMap = new HashMap<Float,Integer>();
    float result = source[0];
    int maxCount = 1;
    for (int i = 0; i < source.length; i++) {
        float el = source[i];
        if (modeMap.get(el) == null)
            modeMap.put(el,1);
        else
            modeMap.put(el,modeMap.get(el)+1);
        if (modeMap.get(el) > maxCount) {
            result = el;
            maxCount = modeMap.get(el);
        }
    }
    return result;
}

您提到了传感器输入,所以我假设数据将被连续采样,因此可以按一定间隔存储值,然后发送到处理模式。 只是一个疯狂的猜测,但她不是希望平均/平滑传感器读数吗? 如果是这样,她可以在 Arduino 的一个数组中缓存一些值(比如 10 个),并在每次添加新值时获取平均值:

int vals[10]; //Array to store caches values.

void setup() {
    Serial.begin(9600);
    for (int i=0 ; i < 10 ; i++) 
        vals[i] = 0; //Init with zeroes
}

void loop() {
    delay(100);
    int currentVal = average(analogRead(0));
    //Serial.print(currentVal,BYTE);
    Serial.println(currentVal);
}

int average(int newVal) {
    int total = 0; //Used to store the addition of all currently cached values
    for(int i = 9; i > 0; i--) { //Loop backwards from the one before last to 0
        vals[i] = vals[i-1]; //Overwrite the prev. value with the current(shift values in array by 1)
        total += vals[i]; //Add to total
    }
    vals[0] = newVal; //Add the newest value at the start of the array
    total += vals[0]; //Add that to the total as well
    return total *= .1; //Get the average (for 10 elemnts) same as total /= 10, but multiplication is faster than division.
}

【讨论】:

  • 在微控制器上使用模板的想法让我心血来潮。效率低下是痛苦的。在那张纸条上,你确实展示了如何移植代码,如果它会在 arduino 上编译,我不确定。
  • 谢谢乔治,非常周到的回应。事实上,她必须对读数进行平均,你的解决方案很清楚,让我了解了 HashMaps!你认为它可以单独在 Arduino 中完成吗(不包括处理部分)?不要给我看代码,但答案:)
  • Kortuk,您对效率的看法是对的,但这不是 Arduino 的目标……它应该让任何编程经验很少或没有编程经验的人使用微控制器变得简单/不那么可怕。关于移植的代码,即用于处理/Java,而不是 Arduino,因此它不会在 Arduino 上运行,但可以通过内置的串行库将值从 Arduino 发送到处理。
  • 谢谢乔治。最后我根据之前的回复采取了一种方法,但是你的让我了解了哈希图!
【解决方案2】:

我将您链接帖子中的代码移植到 Processing,但仅限于 int 数组。 我希望这会有所帮助。

void setup()
{
    int[] numbers = {1, 2, 3, 2, 1, 1, 1, 3, 4, 5, 2};
    println(mode(numbers));
}


int mode(int[] array) {
    int[] modeMap = new int [array.length];
    int maxEl = array[0];
    int maxCount = 1;

    for (int i = 0; i < array.length; i++) {
        int el = array[i];
        if (modeMap[el] == 0) {
            modeMap[el] = 1;
        }
        else {
            modeMap[el]++;
        }

        if (modeMap[el] > maxCount) {
            maxEl = el;
            maxCount = modeMap[el];
        }
    }
    return maxEl;
}

【讨论】:

  • 感谢 weberik,您的解决方案清晰易懂!
  • 我是否正确地说这段代码要求原始数组中的元素小于原始数组的长度?
  • 这个解决方案既错误又不是原始 JS 代码的移植。在原始 JS 代码中,modeMap 是一个映射(一个 JavaScript 对象),如果该键不存在,则将自动添加当前模式的新条目(键)。正如@j_v_wow_d 所述,此代码仅在偶然且仅当数组元素的值始终小于数组长度时才有效。
猜你喜欢
  • 2010-10-05
  • 1970-01-01
  • 2022-01-22
  • 1970-01-01
  • 2013-09-15
  • 1970-01-01
  • 2019-02-27
相关资源
最近更新 更多