/// <summary> /// Estimates the sample mean. /// Returns NaN if data is empty or if any entry is NaN. /// </summary> /// <param name="data">The data to calculate the mean of.</param> /// <returns>The mean of the sample.</returns> public static double Mean(this IEnumerable <double> data) { var array = data as double[]; return(array != null ? ArrayStatistics.Mean(array) : StreamingStatistics.Mean(data)); }
/// <summary> /// The internal method for calculating the auto-correlation. /// </summary> /// <param name="x">The data array to calculate auto-correlation for</param> /// <param name="kLow">Min lag to calculate ACF for (0 = no shift with acf=1) must be zero or positive and smaller than x.Length</param> /// <param name="kHigh">Max lag (EXCLUSIVE) to calculate ACF for must be positive and smaller than x.Length</param> /// <returns>An array with the ACF as a function of the lags k.</returns> private static double[] AutoCorrelationFft(double[] x, int kLow, int kHigh) { if (x == null) { throw new ArgumentNullException(nameof(x)); } int N = x.Length; // Sample size if (kLow < 0 || kLow >= N) { throw new ArgumentOutOfRangeException(nameof(kLow), "kMin must be zero or positive and smaller than x.Length"); } if (kHigh < 0 || kHigh >= N) { throw new ArgumentOutOfRangeException(nameof(kHigh), "kMax must be positive and smaller than x.Length"); } if (N < 1) { return(new double[0]); } int nFFT = Euclid.CeilingToPowerOfTwo(N) * 2; Complex[] xFFT = new Complex[nFFT]; Complex[] xFFT2 = new Complex[nFFT]; double xDash = ArrayStatistics.Mean(x); double xArrNow = 0.0d; // copy values in range and substract mean - all the remaining parts are padded with zero. for (int i = 0; i < x.Length; i++) { xFFT[i] = new Complex(x[i] - xDash, 0.0); // copy values in range and substract mean } Fourier.Forward(xFFT, FourierOptions.Matlab); // maybe a Vector<Complex> implementation here would be faster for (int i = 0; i < xFFT.Length; i++) { xFFT2[i] = Complex.Multiply(xFFT[i], Complex.Conjugate(xFFT[i])); } Fourier.Inverse(xFFT2, FourierOptions.Matlab); double dc = xFFT2[0].Real; double[] result = new double[kHigh - kLow + 1]; // normalize such that acf[0] would be 1.0 for (int i = 0; i < (kHigh - kLow + 1); i++) { result[i] = xFFT2[kLow + i].Real / dc; } return(result); }