如何从连续数据中找出近似中值?

时间:2017-06-13 02:52:58

标签: c math arduino

我正在构建一个设备,通过使用Arduino并在C中写入来检测环境噪声的变化。

因为声音传感器会每秒给我一个声级,我怎么能找到近似的中位数而不存储所有连续数据呢?什么是决定当前环境噪声水平发生变化的最佳方法?

2 个答案:

答案 0 :(得分:1)

你想要的是一个叫做移动中位数(非常类似于moving average)。这将是您需要将最后n个值存储在数组中并计算中位数。

以下是这样的:

int data[5] = {0, 0, 0, 0, 0};
int dataI = 0;

int sortedData[5] = {0, 0, 0, 0, 0};

void pushNewData(int d) {
    data[dataI] = d;

    dataI++;
    if(dataI > 4) {
        dataI = 0;
    }
}

int median() {
    for(int i = 0; i < 5; i++) {
        sortedData[i] = data[i];
    }

    // Use a sorting algorithm here to sort sortedData

    return sortedData[3];
}

另一方面,如果要获得数百小时数据的中位数,则必须存储每个数据值。如果这是您的使用案例,我强烈建议您使用平均值。由于平均值只是sum / n,因此您只能有两个变量并添加它们。当然,您必须考虑溢出。

让我们说你仍然想要一个中位数(例如,如果你担心你的数据不是对称的,或者你担心异常值)。在这种情况下,您可以轻松地构建直方图并使用它来估计中位数。

您可以通过创建一组int来完成此操作。索引0适用于值0-5,索引2适用于值6-10,依此类推。 (每个值范围的大小将根据您的设置而有所不同。)每次有新数据点进入时,您都会检查哪个&#34;存储桶&#34; (值范围)该点落入并且您将增加该数组中的相应计数器。

从这些数据中很容易估算出中位数。我们假设你提取了这些数据:

Values 00-05: 1
Values 06-10: 7
Values 11-15: 8
Values 16-20: 2
Values 21-25: 1
Values 26-30: 5

由于n = 24,中位数将是n = 12。第12个数据点将在11-15范围内,因此您的中位数将在11到15之间。

而不是5的范围,您可以轻松地执行3或1的范围,具有相同的效果。只要注意溢出和内存使用:除了确保不使用太多桶之外,你应该使用unsigned long数组。

答案 1 :(得分:0)

搜索“查找运行中位数”。首先搜索stackoverflow。有许多方法,基于数据的已知特征适用性。

一种简单的方法是创建一个整数数组,比如20个相等范围的元素。在获取每个样本时,将值映射到范围集,并将1添加到该计数器。完成后,可以分析计数器值以计算近似中值。

您可能需要尝试一些不同的方法,以确定哪种方法最适合您。