简体   繁体   English

查找数组的平均值

[英]Finding average of an array

I am really struggling with finding weighted sum from an array. 我真的很难从数组中找到加权和。 I have an array (1D size 28) called frequency[28] and same sized same indexed array called peak[28]. 我有一个称为frequency [28]的数组(一维大小为28),以及具有相同大小的相同索引数组称为peak [28]。 Arrays will always have either a value or zero. 数组将始终具有值或零。 What I want to achieve is go through the array, retrieve both values from frequency and magnitude array while ignoring zero. 我要实现的是遍历数组,从频率和幅度数组中检索两个值,而忽略零。 In addition, I am not trying to find weighted average of the whole array. 另外,我不是要找到整个数组的加权平均值。

I think I am not making myself clear enough. 我想我还不够清楚。

For instance say 例如说

frequency[n] = [0,0,0, a,b, 0,0,0, c,d,e, 0,0, f]
peak[n] = [0,0,0, z,y, 0,0,0, x,w,v, 0,0, u]

Thus, I want to ignore first three bins since they are zero, and find weighted average of (a,b) paired with (z,y) and ignore next three bins and then again find average of (c,d,e) paired with (x,w,v) and so on. 因此,我想忽略前三个仓,因为它们为零,并找到与(z,y)配对的(a,b)的加权平均值,而忽略接下来的三个仓,然后再次求出(c,d,e)配对的平均值与(x,w,v)等。
Note that my values in arrays (size is fixed) are not fixed. 请注意,数组中的值(大小是固定的)不是固定的。 Index where a value may appear is always varying. 可能出现值的索引总是变化的。

I've attached snippet of the code retrieving the arrays. 我已附加了检索数组的代码段。 Any suggestion or guidance would be a great help! 任何建议或指导都会有很大帮助!

// peak search
threshold = 0;
for (ctr=0; ctr<n1; ctr++)
{   
    peak[ctr] = 0; // initialise arrays
    freq_bin[ctr] =0;
    frequency[ctr] = 0;

    // magnitude calculation from fft output
    fft_mag[ctr] = 10*(sqrt((fft_output[ctr].r * fft_output[ctr].r) + (fft_output[ctr].i * fft_output[ctr].i)))/(n);
    threshold = 12; 
    if (fft_mag[ctr] >= threshold) // extract fft magnitudes only above threshold
    {
        peak[ctr] = fft_mag[ctr]; // store magnitude above threshold into peak array
        freq_bin[ctr] = ctr;        // location of each magnitude above threshold
        frequency[ctr] = (freq_bin[ctr]*(10989/n)); // frequency calculation from magnitude location        
    }
}

My apologies for not commenting the codes. 对于未评论代码,我深表歉意。

  • peak[ctr] contains peak magnitudes of fft output peak[ctr]包含fft输出的峰值幅度
  • frequency[ctr] contains frequency value of corresponding fft peak magnitudes. frequency[ctr]包含相应的fft峰值幅度的频率值。

And I have multiple peaks from fft and the output array looks like this; 而且我从fft有多个峰,输出数组看起来像这样;

peak[28] =      [0 0 0 0 0 0 0 0 0 0  14 0 0 0 0 0 0  14 0 0 0  29  74   45 0 0 0 0]
frequency[28] = [0 0 0 0 0 0 0 0 0 0 462 0 0 0 0 0 0 714 0 0 0 924 966 1008 0 0 0 0]

Thus, I need to calculate: 因此,我需要计算:

  • average 1 = (14x462)/14 = 462 Hz 平均1 =(14x462)/ 14 = 462 Hz
  • average 2 = (14x714)/14 = 714 Hz 平均2 =(14x714)/ 14 = 714 Hz
  • average 3 = (29x924 + 74x966 + 45x1008)/(29+74+45) = 938.8 Hz 平均3 =(29x924 + 74x966 + 45x1008)/(29 + 74 + 45)= 938.8 Hz

You can think of this as a state machine. 您可以将其视为状态机。 It reads in a symbol at a time and based on it changes state. 它一次读取一个符号,并根据它更改状态。

There are two states: the starting state and a state where some data is already read. 有两种状态:开始状态和已经读取某些数据的状态。

In the starting state, if the next symbol is zero, remain in this state. 在开始状态下,如果下一个符号为零,则保持此状态。 If not, process the symbol and change state. 如果不是,请处理符号并更改状态。

In the other state, if the next symbol is zero, emit a result and change state. 在另一种状态下,如果下一个符号为零,则发出结果并更改状态。 If not, process it. 如果没有,请进行处理。 If the end is encountered in this state, emit a result. 如果在此状态下遇到终点,则发出结果。

Here is a very clean Python implementation: 这是一个非常干净的Python实现:

class Averager:

    def __init__(self):

        self.averages = []

        self.sumOfNumbers = 0
        self.count = 0

    def addToAverage(self, number, weight):
        self.sumOfNumbers += number * weight
        self.count += weight

    def emitAverage(self):
        self.averages.append(self.sumOfNumbers / self.count)
        self.sumOfNumbers = 0
        self.count = 0


def averagesOf(data, weights):

    averager = Averager()
    dataRead = False

    def emitIfData():
        if dataRead:
            averager.emitAverage()

    for number, weight in zip(data, weights):
        if number == 0:
            emitIfData()
            dataRead = False
        else:
            averager.addToAverage(number, weight)
            dataRead = True

    emitIfData()

    return averager.averages

print(averagesOf([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 462, 0, 0, 0, 0, 0, 0, 714, 0, 0, 0, 924, 966, 1008, 0, 0, 0, 0],
                 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  14, 0, 0, 0, 0, 0, 0,  14, 0, 0, 0,  29,  74,   45, 0, 0, 0, 0]))

Output: 输出:

[462.0, 714.0, 970.5405405405405]

Here's some code that approximates an MCVE ( How to create a Minimal, Complete, and Verifiable Example? ). 这是一些近似MCVE的代码( 如何创建最小,完整和可验证的示例? )。 Amongst other things, I've compressed the operational/interesting data by leaving one set of zeros before and in between the sets of non-zero data. 除其他外,我通过在一组非零数据之前和之间保留一组零来压缩操作/有趣的数据。 The calculation for the 3-term weighted average seems to be wrong in the question: 在这个问题中,三项加权平均值的计算似乎是错误的:

  • average 3 = (29x924 + 74x966 + 45x1008)/(29+74+45) = 938.8 Hz 平均3 =(29x924 + 74x966 + 45x1008)/(29 + 74 + 45)= 938.8 Hz
  • average 3 = (26796 + 71484 + 45360) / 148 平均3 =(26796 + 71484 + 45360)/ 148
  • average 3 = 143640 / 148 平均3 = 143640/148
  • average 3 = 970.54 平均3 = 970.54

This agrees with the program's calculation. 这与程序的计算相符。

Code: 码:

#include <stdio.h>

int main(void)
{
    enum { NUM_ENTRIES = 28 };

    /* Input data */
    double peak[NUM_ENTRIES] = { 0,  14, 0,  14, 0,  29,  74,   45, 0, };
    double freq[NUM_ENTRIES] = { 0, 462, 0, 714, 0, 924, 966, 1008, 0, };

    /* Output data */
    double bin_av[NUM_ENTRIES];
    int bin_lo[NUM_ENTRIES];
    int bin_hi[NUM_ENTRIES];
    int out = 0;

    int ctr = 0;
    while (ctr < NUM_ENTRIES)
    {
        /* Skip zeroed entries */
        while (ctr < NUM_ENTRIES && (peak[ctr] == 0.0 || freq[ctr] == 0.0))
            ctr++;
        if (ctr < NUM_ENTRIES)
        {
            bin_lo[out] = ctr;
            bin_hi[out] = ctr;
            double w_sum = 0.0;
            double f_sum = 0.0;
            while (ctr < NUM_ENTRIES && (peak[ctr] != 0.0 && freq[ctr] != 0.0))
            {
                bin_hi[out] = ctr;
                w_sum += peak[ctr] * freq[ctr];
                f_sum += peak[ctr];
                ctr++;
            }
            bin_av[out++] = w_sum / f_sum;
        }
    }

    for (int i = 0; i < out; i++)
        printf("%d .. %d: %6.1f\n", bin_lo[i], bin_hi[i], bin_av[i]);

    return 0;
}

Example output: 输出示例:

1 .. 1:  462.0
3 .. 3:  714.0
5 .. 7:  970.5

There's plenty of room to improve the output (it would not be a bad idea to echo the relevant subset of the input data, for example). 有很多空间可以改善输出(例如,回显输入数据的相关子集将是一个不错的主意)。

With this framework in place, you can go back to complicating the scenario by calculating the values in peak and freq from the values in the FFT outputs, instead of using hard-coded arrays. 有了这个框架,您就可以通过根据FFT输出中的值计算peakfreq值,而不是使用硬编码数组,来使方案复杂化。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM