/// <summary> /// feature here is each row/SNP /// </summary> /// <param name="xMatrix"></param> /// <param name="isOKToDestroyXMatrix"></param> /// <param name="weightForEachFeature"></param> /// <param name="parallelOptions"></param> /// <returns></returns> ///!!! Should be possible to do this with a one pass algo instead of with two passes, one for the mean, and one for the rest public static Matrix <string, string, double> CreateXMatrixWithColumnMeansZeroWithWeights(Matrix <string, string, double> xMatrix, bool isOKToDestroyXMatrix, IList <double> weightForEachFeature, ParallelOptions parallelOptions, out List <double> columnMeans) { //Console.WriteLine("create xMatrixWithColumnMeansZeroWithWeights"); List <double> columnMeansTmp = SpecialFunctions.CreateListWithDefaultElements <double>(xMatrix.ColCount); Matrix <string, string, double> xMatrixWithColumnMeansZero; { xMatrixWithColumnMeansZero = isOKToDestroyXMatrix ? xMatrix : DenseMatrix <string, string, double> .CreateDefaultInstance(xMatrix.RowKeys, xMatrix.ColKeys, double.NaN); Parallel.ForEach(Enumerable.Range(0, xMatrix.ColCount), parallelOptions, cidIndex => { //Console.Write(string.Format("\r{0}/{1}\t", cidIndex, xMatrix.ColCount)); double sum = 0; double weightSum = 0; for (int varIndex = 0; varIndex < xMatrix.RowCount; ++varIndex) { sum += weightForEachFeature[varIndex] * xMatrix[varIndex, cidIndex]; weightSum += weightForEachFeature[varIndex]; } //double columnMean = sum / xMatrix.RowCount; double columnMean = sum / weightSum; columnMeansTmp[cidIndex] = columnMean; for (int varIndex = 0; varIndex < xMatrix.RowCount; ++varIndex) { xMatrixWithColumnMeansZero[varIndex, cidIndex] = xMatrix[varIndex, cidIndex] - columnMean; } }); Console.WriteLine(); } columnMeans = columnMeansTmp; return(xMatrixWithColumnMeansZero); }