Tools.cs 74 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813
  1. namespace VisualMath.Accord.Statistics
  2. {
  3. using System;
  4. using System.Collections.Generic;
  5. using VisualMath.Accord.Math;
  6. /// <summary>
  7. /// Set of statistics functions
  8. /// </summary>
  9. ///
  10. /// <remarks>
  11. /// This class represents collection of functions used in statistics.
  12. /// Every Matrix function assumes data is organized in a table-like
  13. /// model, where Columns represents variables and Rows represents a
  14. /// observation of each variable.
  15. /// </remarks>
  16. ///
  17. public static class Tools
  18. {
  19. #region Arrays
  20. /// <summary>Computes the Mean of the given values.</summary>
  21. /// <param name="values">A double array containing the vector members.</param>
  22. /// <returns>The mean of the given data.</returns>
  23. public static double Mean(this double[] values)
  24. {
  25. double sum = 0.0;
  26. double n = values.Length;
  27. for (int i = 0; i < values.Length; i++)
  28. {
  29. sum += values[i];
  30. }
  31. return sum / n;
  32. }
  33. /// <summary>Computes the Weighted Mean of the given values.</summary>
  34. /// <param name="values">A double array containing the vector members.</param>
  35. /// <param name="weights">An unit vector containing the importance of each sample
  36. /// in <see param="values"/>. The sum of this array elements should add up to 1.</param>
  37. /// <returns>The mean of the given data.</returns>
  38. public static double Mean(this double[] values, double[] weights)
  39. {
  40. double sum = 0.0;
  41. for (int i = 0; i < values.Length; i++)
  42. {
  43. sum += values[i] * weights[i];
  44. }
  45. return sum;
  46. }
  47. /// <summary>Computes the Standard Deviation of the given values.</summary>
  48. /// <param name="values">A double array containing the vector members.</param>
  49. /// <returns>The standard deviation of the given data.</returns>
  50. public static double StandardDeviation(this double[] values)
  51. {
  52. return StandardDeviation(values, Mean(values));
  53. }
  54. /// <summary>Computes the Standard Deviation of the given values.</summary>
  55. /// <param name="values">A double array containing the vector members.</param>
  56. /// <param name="mean">The mean of the vector, if already known.</param>
  57. /// <returns>The standard deviation of the given data.</returns>
  58. public static double StandardDeviation(this double[] values, double mean)
  59. {
  60. return System.Math.Sqrt(Variance(values, mean));
  61. }
  62. /// <summary>Computes the Standard Deviation of the given values.</summary>
  63. /// <param name="values">A double array containing the vector members.</param>
  64. /// <param name="mean">The mean of the vector, if already known.</param>
  65. /// <param name="weights">An unit vector containing the importance of each sample
  66. /// in <see param="values"/>. The sum of this array elements should add up to 1.</param>
  67. /// <returns>The standard deviation of the given data.</returns>
  68. public static double StandardDeviation(this double[] values, double mean, double[] weights)
  69. {
  70. return System.Math.Sqrt(Variance(values, mean, weights));
  71. }
  72. /// <summary>
  73. /// Computes the Standard Error for a sample size, which estimates the
  74. /// standard deviation of the sample mean based on the population mean.
  75. /// </summary>
  76. /// <param name="samples">The sample size.</param>
  77. /// <param name="standardDeviation">The sample standard deviation.</param>
  78. /// <returns>The standard error for the sample.</returns>
  79. public static double StandardError(int samples, double standardDeviation)
  80. {
  81. return standardDeviation / System.Math.Sqrt(samples);
  82. }
  83. /// <summary>
  84. /// Computes the Standard Error for a sample size, which estimates the
  85. /// standard deviation of the sample mean based on the population mean.
  86. /// </summary>
  87. /// <param name="values">A double array containing the samples.</param>
  88. /// <returns>The standard error for the sample.</returns>
  89. public static double StandardError(double[] values)
  90. {
  91. return StandardError(values.Length, StandardDeviation(values));
  92. }
  93. /// <summary>Computes the Median of the given values.</summary>
  94. /// <param name="values">A double array containing the vector members.</param>
  95. /// <returns>The median of the given data.</returns>
  96. public static double Median(double[] values)
  97. {
  98. return Median(values, false);
  99. }
  100. /// <summary>Computes the Median of the given values.</summary>
  101. /// <param name="values">An integer array containing the vector members.</param>
  102. /// <param name="alreadySorted">A boolean parameter informing if the given values have already been sorted.</param>
  103. /// <returns>The median of the given data.</returns>
  104. public static double Median(double[] values, bool alreadySorted)
  105. {
  106. double[] data = new double[values.Length];
  107. values.CopyTo(data, 0); // Creates a copy of the given values,
  108. if (!alreadySorted) // So we can sort it without modifying the original array.
  109. Array.Sort(data);
  110. int N = data.Length;
  111. if (N % 2 == 0)
  112. return (data[N / 2] + data[(N / 2) - 1]) * 0.5; // N is even
  113. else return data[N / 2]; // N is odd
  114. }
  115. /// <summary>Computes the Variance of the given values.</summary>
  116. /// <param name="values">A double precision number array containing the vector members.</param>
  117. /// <returns>The variance of the given data.</returns>
  118. public static double Variance(double[] values)
  119. {
  120. return Variance(values, Mean(values));
  121. }
  122. /// <summary>Computes the Variance of the given values.</summary>
  123. /// <param name="values">A number array containing the vector members.</param>
  124. /// <param name="mean">The mean of the array, if already known.</param>
  125. /// <returns>The variance of the given data.</returns>
  126. public static double Variance(double[] values, double mean)
  127. {
  128. double variance = 0.0;
  129. double N = values.Length;
  130. double x;
  131. for (int i = 0; i < values.Length; i++)
  132. {
  133. x = values[i] - mean;
  134. variance += x * x;
  135. }
  136. // Sample variance
  137. return variance / (N - 1);
  138. }
  139. /// <summary>Computes the weighted Variance of the given values.</summary>
  140. /// <param name="values">A number array containing the vector members.</param>
  141. /// <param name="mean">The mean of the array, if already known.</param>
  142. /// <param name="weights">An unit vector containing the importance of each sample
  143. /// in <see param="values"/>. The sum of this array elements should add up to 1.</param>
  144. /// <returns>The variance of the given data.</returns>
  145. public static double Variance(double[] values, double mean, double[] weights)
  146. {
  147. // http://en.wikipedia.org/wiki/Weighted_variance#Weighted_sample_variance
  148. // http://www.gnu.org/software/gsl/manual/html_node/Weighted-Samples.html
  149. double variance = 0.0;
  150. double V2 = 0.0;
  151. double x, w;
  152. for (int i = 0; i < values.Length; i++)
  153. {
  154. x = values[i] - mean;
  155. variance += x * x * weights[i];
  156. w = weights[i];
  157. V2 += w * w;
  158. }
  159. return variance / (1 - V2);
  160. }
  161. /// <summary>Computes the Mode of the given values.</summary>
  162. /// <param name="values">A number array containing the vector values.</param>
  163. /// <returns>The variance of the given data.</returns>
  164. public static double Mode(double[] values)
  165. {
  166. int[] itemCount = new int[values.Length];
  167. double[] itemArray = new double[values.Length];
  168. int count = 0;
  169. for (int i = 0; i < values.Length; i++)
  170. {
  171. int index = Array.IndexOf<double>(itemArray, values[i], 0, count);
  172. if (index >= 0)
  173. {
  174. itemCount[index]++;
  175. }
  176. else
  177. {
  178. itemArray[count] = values[i];
  179. itemCount[count] = 1;
  180. count++;
  181. }
  182. }
  183. int maxValue = 0;
  184. int maxIndex = 0;
  185. for (int i = 0; i < count; i++)
  186. {
  187. if (itemCount[i] > maxValue)
  188. {
  189. maxValue = itemCount[i];
  190. maxIndex = i;
  191. }
  192. }
  193. return itemArray[maxIndex];
  194. }
  195. /// <summary>Computes the Covariance between two values arrays.</summary>
  196. /// <param name="u">A number array containing the first vector members.</param>
  197. /// <param name="v">A number array containing the second vector members.</param>
  198. /// <returns>The variance of the given data.</returns>
  199. public static double[,] Covariance(double[] u, double[] v)
  200. {
  201. double[][] vectors = new double[][] { u, v };
  202. return Scatter(vectors, Mean(vectors, 1), vectors.Length, 1);
  203. }
  204. /// <summary>
  205. /// Computes the Skewness for the given values.
  206. /// </summary>
  207. /// <remarks>
  208. /// Skewness characterizes the degree of asymmetry of a distribution
  209. /// around its mean. Positive skewness indicates a distribution with
  210. /// an asymmetric tail extending towards more positive values. Negative
  211. /// skewness indicates a distribution with an asymmetric tail extending
  212. /// towards more negative values.
  213. /// </remarks>
  214. /// <param name="values">A number array containing the vector values.</param>
  215. /// <returns>The skewness of the given data.</returns>
  216. public static double Skewness(double[] values)
  217. {
  218. double mean = Mean(values);
  219. return Skewness(values, mean, StandardDeviation(values, mean));
  220. }
  221. /// <summary>
  222. /// Computes the Skewness for the given values.
  223. /// </summary>
  224. /// <remarks>
  225. /// Skewness characterizes the degree of asymmetry of a distribution
  226. /// around its mean. Positive skewness indicates a distribution with
  227. /// an asymmetric tail extending towards more positive values. Negative
  228. /// skewness indicates a distribution with an asymmetric tail extending
  229. /// towards more negative values.
  230. /// </remarks>
  231. /// <param name="values">A number array containing the vector values.</param>
  232. /// <param name="mean">The values' mean, if already known.</param>
  233. /// <param name="standardDeviation">The values' standard deviations, if already known.</param>
  234. /// <returns>The skewness of the given data.</returns>
  235. public static double Skewness(double[] values, double mean, double standardDeviation)
  236. {
  237. int n = values.Length;
  238. double sum = 0.0;
  239. for (int i = 0; i < n; i++)
  240. {
  241. // Sum of third moment deviations
  242. sum += System.Math.Pow(values[i] - mean, 3);
  243. }
  244. return sum / ((double)n * System.Math.Pow(standardDeviation, 3));
  245. }
  246. /// <summary>
  247. /// Computes the Kurtosis for the given values.
  248. /// </summary>
  249. /// <param name="values">A number array containing the vector values.</param>
  250. /// <returns>The kurtosis of the given data.</returns>
  251. public static double Kurtosis(double[] values)
  252. {
  253. double mean = Mean(values);
  254. return Kurtosis(values, mean, StandardDeviation(values, mean));
  255. }
  256. /// <summary>
  257. /// Computes the Kurtosis for the given values.
  258. /// </summary>
  259. /// <param name="values">A number array containing the vector values.</param>
  260. /// <param name="mean">The values' mean, if already known.</param>
  261. /// <param name="standardDeviation">The values' variance, if already known.</param>
  262. /// <returns>The kurtosis of the given data.</returns>
  263. public static double Kurtosis(double[] values, double mean, double standardDeviation)
  264. {
  265. int n = values.Length;
  266. double sum = 0.0, deviation;
  267. for (int i = 0; i < n; i++)
  268. {
  269. // Sum of fourth moment deviations
  270. deviation = (values[i] - mean);
  271. sum += System.Math.Pow(deviation, 4);
  272. }
  273. return sum / ((double)n * System.Math.Pow(standardDeviation, 4)) - 3.0;
  274. }
  275. #endregion
  276. // ------------------------------------------------------------
  277. #region Matrix
  278. /// <summary>Calculates the matrix Mean vector.</summary>
  279. /// <param name="matrix">A matrix whose means will be calculated.</param>
  280. /// <returns>Returns a row vector containing the column means of the given matrix.</returns>
  281. /// <example>
  282. /// <code>
  283. /// double[,] matrix =
  284. /// {
  285. /// { 2, -1.0, 5 },
  286. /// { 7, 0.5, 9 },
  287. /// };
  288. ///
  289. /// // column means are equal to (4.5, -0.25, 7.0)
  290. /// double[] means = Accord.Statistics.Tools.Mean(matrix);
  291. /// </code>
  292. /// </example>
  293. public static double[] Mean(double[,] matrix)
  294. {
  295. return Mean(matrix, 0);
  296. }
  297. /// <summary>Calculates the matrix Mean vector.</summary>
  298. /// <param name="matrix">A matrix whose means will be calculated.</param>
  299. /// <param name="dimension">
  300. /// The dimension along which the means will be calculated. Pass
  301. /// 0 to compute a row vector containing the mean of each column,
  302. /// or 1 to compute a column vector containing the mean of each row.
  303. /// Default value is 0.
  304. /// </param>
  305. /// <returns>Returns a vector containing the means of the given matrix.</returns>
  306. /// <example>
  307. /// <code>
  308. /// double[,] matrix =
  309. /// {
  310. /// { 2, -1.0, 5 },
  311. /// { 7, 0.5, 9 },
  312. /// };
  313. ///
  314. /// // column means are equal to (4.5, -0.25, 7.0)
  315. /// double[] colMeans = Accord.Statistics.Tools.Mean(matrix, 0);
  316. ///
  317. /// // row means are equal to (2.0, 5.5)
  318. /// double[] rowMeans = Accord.Statistics.Tools.Mean(matrix, 1);
  319. /// </code>
  320. /// </example>
  321. public static double[] Mean(double[,] matrix, int dimension)
  322. {
  323. if (dimension == 0)
  324. {
  325. double[] mean = new double[matrix.GetLength(1)];
  326. double rows = matrix.GetLength(0);
  327. // for each column
  328. for (int j = 0; j < matrix.GetLength(1); j++)
  329. {
  330. // for each row
  331. for (int i = 0; i < matrix.GetLength(0); i++)
  332. mean[j] += matrix[i, j];
  333. mean[j] = mean[j] / rows;
  334. }
  335. return mean;
  336. }
  337. else if (dimension == 1)
  338. {
  339. double[] mean = new double[matrix.GetLength(0)];
  340. double cols = matrix.GetLength(1);
  341. // for each row
  342. for (int j = 0; j < matrix.GetLength(0); j++)
  343. {
  344. // for each column
  345. for (int i = 0; i < matrix.GetLength(1); i++)
  346. mean[j] += matrix[j, i];
  347. mean[j] = mean[j] / cols;
  348. }
  349. return mean;
  350. }
  351. else
  352. {
  353. throw new ArgumentException("Invalid dimension.", "dimension");
  354. }
  355. }
  356. /// <summary>Calculates the matrix Mean vector.</summary>
  357. /// <param name="matrix">A matrix whose means will be calculated.</param>
  358. /// <returns>Returns a row vector containing the column means of the given matrix.</returns>
  359. /// <example>
  360. /// <code>
  361. /// double[][] matrix =
  362. /// {
  363. /// new double[] { 2, -1.0, 5 },
  364. /// new double[] { 7, 0.5, 9 },
  365. /// };
  366. ///
  367. /// // column means are equal to (4.5, -0.25, 7.0)
  368. /// double[] means = Accord.Statistics.Tools.Mean(matrix);
  369. /// </code>
  370. /// </example>
  371. public static double[] Mean(double[][] matrix)
  372. {
  373. return Mean(matrix, 0);
  374. }
  375. /// <summary>Calculates the matrix Mean vector.</summary>
  376. /// <param name="matrix">A matrix whose means will be calculated.</param>
  377. /// <param name="dimension">
  378. /// The dimension along which the means will be calculated. Pass
  379. /// 0 to compute a row vector containing the mean of each column,
  380. /// or 1 to compute a column vector containing the mean of each row.
  381. /// Default value is 0.
  382. /// </param>
  383. /// <returns>Returns a vector containing the means of the given matrix.</returns>
  384. /// <example>
  385. /// <code>
  386. /// double[][] matrix =
  387. /// {
  388. /// new double[] { 2, -1.0, 5 },
  389. /// new double[] { 7, 0.5, 9 },
  390. /// };
  391. ///
  392. /// // column means are equal to (4.5, -0.25, 7.0)
  393. /// double[] colMeans = Accord.Statistics.Tools.Mean(matrix, 0);
  394. ///
  395. /// // row means are equal to (2.0, 5.5)
  396. /// double[] rowMeans = Accord.Statistics.Tools.Mean(matrix, 1);
  397. /// </code>
  398. /// </example>
  399. public static double[] Mean(double[][] matrix, int dimension)
  400. {
  401. int rows = matrix.Length;
  402. if (rows == 0) return new double[0];
  403. int cols = matrix[0].Length;
  404. if (dimension == 0)
  405. {
  406. double[] mean = new double[cols];
  407. double N = rows;
  408. // for each column
  409. for (int j = 0; j < cols; j++)
  410. {
  411. // for each row
  412. for (int i = 0; i < rows; i++)
  413. mean[j] += matrix[i][j];
  414. mean[j] = mean[j] / N;
  415. }
  416. return mean;
  417. }
  418. else if (dimension == 1)
  419. {
  420. double[] mean = new double[rows];
  421. double N = cols;
  422. // for each row
  423. for (int j = 0; j < rows; j++)
  424. {
  425. // for each column
  426. for (int i = 0; i < cols; i++)
  427. mean[j] += matrix[j][i];
  428. mean[j] = mean[j] / N;
  429. }
  430. return mean;
  431. }
  432. else
  433. {
  434. throw new ArgumentException("Invalid dimension.", "dimension");
  435. }
  436. }
  437. /// <summary>Calculates the weighted matrix Mean vector.</summary>
  438. /// <param name="matrix">A matrix whose means will be calculated.</param>
  439. /// <param name="weights">A vector containing the importance of each sample in the matrix.</param>
  440. /// <returns>Returns a vector containing the means of the given matrix.</returns>
  441. ///
  442. public static double[] Mean(double[][] matrix, double[] weights)
  443. {
  444. return Mean(matrix, weights, 0);
  445. }
  446. /// <summary>Calculates the weighted matrix Mean vector.</summary>
  447. /// <param name="matrix">A matrix whose means will be calculated.</param>
  448. /// <param name="weights">A vector containing the importance of each sample in the matrix.</param>
  449. /// <param name="dimension">
  450. /// The dimension along which the means will be calculated. Pass
  451. /// 0 to compute a row vector containing the mean of each column,
  452. /// or 1 to compute a column vector containing the mean of each row.
  453. /// Default value is 0.
  454. /// </param>
  455. /// <returns>Returns a vector containing the means of the given matrix.</returns>
  456. ///
  457. public static double[] Mean(double[][] matrix, double[] weights, int dimension)
  458. {
  459. int rows = matrix.Length;
  460. if (rows == 0) return new double[0];
  461. int cols = matrix[0].Length;
  462. if (dimension == 0)
  463. {
  464. double[] mean = new double[cols];
  465. // for each row
  466. for (int i = 0; i < rows; i++)
  467. {
  468. double[] row = matrix[i];
  469. double w = weights[i];
  470. // for each column
  471. for (int j = 0; j < cols; j++)
  472. mean[j] += row[j] * w;
  473. }
  474. return mean;
  475. }
  476. else if (dimension == 1)
  477. {
  478. double[] mean = new double[rows];
  479. // for each row
  480. for (int j = 0; j < rows; j++)
  481. {
  482. double[] row = matrix[j];
  483. double w = weights[j];
  484. // for each column
  485. for (int i = 0; i < cols; i++)
  486. mean[j] += row[i] * w;
  487. }
  488. return mean;
  489. }
  490. else
  491. {
  492. throw new ArgumentException("Invalid dimension.", "dimension");
  493. }
  494. }
  495. /// <summary>Calculates the matrix Mean vector.</summary>
  496. /// <param name="matrix">A matrix whose means will be calculated.</param>
  497. /// <param name="sums">The sum vector containing already calculated sums for each column of the matix.</param>
  498. /// <returns>Returns a vector containing the means of the given matrix.</returns>
  499. public static double[] Mean(double[,] matrix, double[] sums)
  500. {
  501. int rows = matrix.GetLength(0);
  502. int cols = matrix.GetLength(1);
  503. double[] mean = new double[cols];
  504. double N = rows;
  505. for (int j = 0; j < cols; j++)
  506. mean[j] = sums[j] / N;
  507. return mean;
  508. }
  509. /// <summary>Calculates the matrix Standard Deviations vector.</summary>
  510. /// <param name="matrix">A matrix whose deviations will be calculated.</param>
  511. /// <returns>Returns a vector containing the standard deviations of the given matrix.</returns>
  512. public static double[] StandardDeviation(double[,] matrix)
  513. {
  514. return StandardDeviation(matrix, Mean(matrix));
  515. }
  516. /// <summary>Calculates the matrix Standard Deviations vector.</summary>
  517. /// <param name="matrix">A matrix whose deviations will be calculated.</param>
  518. /// <param name="means">The mean vector containing already calculated means for each column of the matix.</param>
  519. /// <returns>Returns a vector containing the standard deviations of the given matrix.</returns>
  520. public static double[] StandardDeviation(this double[,] matrix, double[] means)
  521. {
  522. return Matrix.Sqrt(Variance(matrix, means));
  523. }
  524. /// <summary>Calculates the matrix Standard Deviations vector.</summary>
  525. /// <param name="matrix">A matrix whose deviations will be calculated.</param>
  526. /// <param name="means">The mean vector containing already calculated means for each column of the matix.</param>
  527. /// <returns>Returns a vector containing the standard deviations of the given matrix.</returns>
  528. public static double[] StandardDeviation(this double[][] matrix, double[] means)
  529. {
  530. return Matrix.Sqrt(Variance(matrix, means));
  531. }
  532. /// <summary>Calculates the matrix Standard Deviations vector.</summary>
  533. /// <param name="matrix">A matrix whose deviations will be calculated.</param>
  534. /// <returns>Returns a vector containing the standard deviations of the given matrix.</returns>
  535. public static double[] StandardDeviation(this double[][] matrix)
  536. {
  537. return StandardDeviation(matrix, Mean(matrix));
  538. }
  539. /// <summary>Centers an observation, subtracting the empirical mean from the variable.</summary>
  540. public static void Center(double[] observation)
  541. {
  542. Center(observation, Mean(observation));
  543. }
  544. /// <summary>Centers an observation, subtracting the empirical mean from the variable.</summary>
  545. public static void Center(double[] observation, double mean)
  546. {
  547. for (int i = 0; i < observation.Length; i++)
  548. observation[i] -= mean;
  549. }
  550. /// <summary>Calculates the matrix Variance vector.</summary>
  551. /// <param name="matrix">A matrix whose variancees will be calculated.</param>
  552. /// <returns>Returns a vector containing the variances of the given matrix.</returns>
  553. public static double[] Variance(this double[,] matrix)
  554. {
  555. return Variance(matrix, Mean(matrix));
  556. }
  557. /// <summary>Calculates the matrix Variance vector.</summary>
  558. /// <param name="matrix">A matrix whose variances will be calculated.</param>
  559. /// <param name="means">The mean vector containing already calculated means for each column of the matix.</param>
  560. /// <returns>Returns a vector containing the variances of the given matrix.</returns>
  561. public static double[] Variance(this double[,] matrix, double[] means)
  562. {
  563. int rows = matrix.GetLength(0);
  564. int cols = matrix.GetLength(1);
  565. double N = rows;
  566. double[] variance = new double[cols];
  567. // for each column (for each variable)
  568. for (int j = 0; j < cols; j++)
  569. {
  570. double sum1 = 0.0;
  571. double sum2 = 0.0;
  572. double x = 0.0;
  573. // for each row (observation of the variable)
  574. for (int i = 0; i < rows; i++)
  575. {
  576. x = matrix[i, j] - means[j];
  577. sum1 += x;
  578. sum2 += x * x;
  579. }
  580. // calculate the variance
  581. variance[j] = (sum2 - ((sum1 * sum1) / N)) / (N - 1);
  582. }
  583. return variance;
  584. }
  585. /// <summary>Calculates the matrix Variance vector.</summary>
  586. /// <param name="matrix">A matrix whose variances will be calculated.</param>
  587. /// <returns>Returns a vector containing the variances of the given matrix.</returns>
  588. public static double[] Variance(this double[][] matrix)
  589. {
  590. return Variance(matrix, Mean(matrix));
  591. }
  592. /// <summary>Calculates the matrix Variance vector.</summary>
  593. /// <param name="matrix">A matrix whose variances will be calculated.</param>
  594. /// <param name="means">The mean vector containing already calculated means for each column of the matix.</param>
  595. /// <returns>Returns a vector containing the variances of the given matrix.</returns>
  596. public static double[] Variance(this double[][] matrix, double[] means)
  597. {
  598. int rows = matrix.Length;
  599. if (rows == 0) return new double[0];
  600. int cols = matrix[0].Length;
  601. double N = rows;
  602. double[] variance = new double[cols];
  603. // for each column (for each variable)
  604. for (int j = 0; j < cols; j++)
  605. {
  606. double sum1 = 0.0;
  607. double sum2 = 0.0;
  608. double x = 0.0;
  609. // for each row (observation of the variable)
  610. for (int i = 0; i < rows; i++)
  611. {
  612. x = matrix[i][j] - means[j];
  613. sum1 += x;
  614. sum2 += x * x;
  615. }
  616. // calculate the variance
  617. variance[j] = (sum2 - ((sum1 * sum1) / N)) / (N - 1);
  618. }
  619. return variance;
  620. }
  621. /// <summary>Calculates the matrix Medians vector.</summary>
  622. /// <param name="matrix">A matrix whose medians will be calculated.</param>
  623. /// <returns>Returns a vector containing the medians of the given matrix.</returns>
  624. public static double[] Median(double[,] matrix)
  625. {
  626. int rows = matrix.GetLength(0);
  627. int cols = matrix.GetLength(1);
  628. double[] medians = new double[cols];
  629. for (int i = 0; i < cols; i++)
  630. {
  631. double[] data = new double[rows];
  632. // Creates a copy of the given values
  633. for (int j = 0; j < rows; j++)
  634. data[j] = matrix[j, i];
  635. Array.Sort(data); // Sort it
  636. int N = data.Length;
  637. if (N % 2 == 0)
  638. medians[i] = (data[N / 2] + data[(N / 2) - 1]) * 0.5; // N is even
  639. else medians[i] = data[N / 2]; // N is odd
  640. }
  641. return medians;
  642. }
  643. /// <summary>Calculates the matrix Medians vector.</summary>
  644. /// <param name="matrix">A matrix whose medians will be calculated.</param>
  645. /// <returns>Returns a vector containing the medians of the given matrix.</returns>
  646. public static double[] Median(double[][] matrix)
  647. {
  648. int rows = matrix.Length;
  649. int cols = matrix[0].Length;
  650. double[] medians = new double[cols];
  651. for (int i = 0; i < cols; i++)
  652. {
  653. double[] data = new double[rows];
  654. // Creates a copy of the given values
  655. for (int j = 0; j < rows; j++)
  656. data[j] = matrix[j][i];
  657. Array.Sort(data); // Sort it
  658. int N = data.Length;
  659. if (N % 2 == 0)
  660. medians[i] = (data[N / 2] + data[(N / 2) - 1]) * 0.5; // N is even
  661. else medians[i] = data[N / 2]; // N is odd
  662. }
  663. return medians;
  664. }
  665. /// <summary>Calculates the matrix Modes vector.</summary>
  666. /// <param name="matrix">A matrix whose modes will be calculated.</param>
  667. /// <returns>Returns a vector containing the modes of the given matrix.</returns>
  668. public static double[] Mode(this double[,] matrix)
  669. {
  670. int rows = matrix.GetLength(0);
  671. int cols = matrix.GetLength(1);
  672. double[] mode = new double[cols];
  673. for (int i = 0; i < cols; i++)
  674. {
  675. int[] itemCount = new int[rows];
  676. double[] itemArray = new double[rows];
  677. int count = 0;
  678. // for each row
  679. for (int j = 0; j < rows; j++)
  680. {
  681. int index = Array.IndexOf<double>(itemArray, matrix[j, i], 0, count);
  682. if (index >= 0)
  683. {
  684. itemCount[index]++;
  685. }
  686. else
  687. {
  688. itemArray[count] = matrix[j, i];
  689. itemCount[count] = 1;
  690. count++;
  691. }
  692. }
  693. int maxValue = 0;
  694. int maxIndex = 0;
  695. for (int j = 0; j < count; j++)
  696. {
  697. if (itemCount[j] > maxValue)
  698. {
  699. maxValue = itemCount[j];
  700. maxIndex = j;
  701. }
  702. }
  703. mode[i] = itemArray[maxIndex];
  704. }
  705. return mode;
  706. }
  707. /// <summary>
  708. /// Computes the Skewness for the given values.
  709. /// </summary>
  710. /// <remarks>
  711. /// Skewness characterizes the degree of asymmetry of a distribution
  712. /// around its mean. Positive skewness indicates a distribution with
  713. /// an asymmetric tail extending towards more positive values. Negative
  714. /// skewness indicates a distribution with an asymmetric tail extending
  715. /// towards more negative values.
  716. /// </remarks>
  717. /// <param name="matrix">A number matrix containing the matrix values.</param>
  718. /// <returns>The skewness of the given data.</returns>
  719. public static double[] Skewness(double[,] matrix)
  720. {
  721. double[] means = Mean(matrix);
  722. return Skewness(matrix, means, StandardDeviation(matrix, means));
  723. }
  724. /// <summary>
  725. /// Computes the Skewness vector for the given matrix.
  726. /// </summary>
  727. /// <remarks>
  728. /// Skewness characterizes the degree of asymmetry of a distribution
  729. /// around its mean. Positive skewness indicates a distribution with
  730. /// an asymmetric tail extending towards more positive values. Negative
  731. /// skewness indicates a distribution with an asymmetric tail extending
  732. /// towards more negative values.
  733. /// </remarks>
  734. /// <param name="matrix">A number array containing the vector values.</param>
  735. /// <param name="means">The values' mean, if already known.</param>
  736. /// <param name="standardDeviations">The values' standard deviations, if already known.</param>
  737. /// <returns>The skewness of the given data.</returns>
  738. public static double[] Skewness(double[,] matrix, double[] means, double[] standardDeviations)
  739. {
  740. int n = matrix.GetLength(0);
  741. double[] skewness = new double[matrix.GetLength(1)];
  742. for (int j = 0; j < skewness.Length; j++)
  743. {
  744. double sum = 0.0;
  745. for (int i = 0; i < n; i++)
  746. {
  747. // Sum of third moment deviations
  748. sum += System.Math.Pow(matrix[i, j] - means[j], 3);
  749. }
  750. skewness[j] = sum / ((n - 1) * System.Math.Pow(standardDeviations[j], 3));
  751. }
  752. return skewness;
  753. }
  754. /// <summary>
  755. /// Computes the Kurtosis vector for the given matrix.
  756. /// </summary>
  757. /// <param name="matrix">A number multi-dimensional array containing the matrix values.</param>
  758. /// <returns>The kurtosis vector of the given data.</returns>
  759. public static double[] Kurtosis(double[,] matrix)
  760. {
  761. double[] means = Mean(matrix);
  762. return Kurtosis(matrix, means, StandardDeviation(matrix, means));
  763. }
  764. /// <summary>
  765. /// Computes the Kurtosis vector for the given matrix.
  766. /// </summary>
  767. /// <param name="matrix">A number multi-dimensional array containing the matrix values.</param>
  768. /// <param name="means">The values' mean vector, if already known.</param>
  769. /// <param name="standardDeviations">The values' standard deviation vector, if already known.</param>
  770. /// <returns>The kurtosis vector of the given data.</returns>
  771. public static double[] Kurtosis(double[,] matrix, double[] means, double[] standardDeviations)
  772. {
  773. int n = matrix.GetLength(0);
  774. double[] kurtosis = new double[matrix.GetLength(1)];
  775. for (int j = 0; j < kurtosis.Length; j++)
  776. {
  777. double sum = 0.0;
  778. for (int i = 0; i < n; i++)
  779. {
  780. // Sum of fourth moment deviations
  781. sum += System.Math.Pow(matrix[i, j] - means[j], 4);
  782. }
  783. kurtosis[j] = sum / (n * System.Math.Pow(standardDeviations[j], 4)) - 3.0;
  784. }
  785. return kurtosis;
  786. }
  787. /// <summary>
  788. /// Computes the Standard Error vector for a given matrix.
  789. /// </summary>
  790. /// <param name="matrix">A number multi-dimensional array containing the matrix values.</param>
  791. /// <returns>Returns the standard error vector for the matrix.</returns>
  792. public static double[] StandardError(double[,] matrix)
  793. {
  794. return StandardError(matrix.GetLength(0), StandardDeviation(matrix));
  795. }
  796. /// <summary>
  797. /// Computes the Standard Error vector for a given matrix.
  798. /// </summary>
  799. /// <param name="samples">The number of samples in the matrix.</param>
  800. /// <param name="standardDeviations">The values' standard deviation vector, if already known.</param>
  801. /// <returns>Returns the standard error vector for the matrix.</returns>
  802. public static double[] StandardError(int samples, double[] standardDeviations)
  803. {
  804. double[] standardErrors = new double[standardDeviations.Length];
  805. double sqrt = System.Math.Sqrt(samples);
  806. for (int i = 0; i < standardDeviations.Length; i++)
  807. {
  808. standardErrors[i] = standardDeviations[i] / sqrt;
  809. }
  810. return standardErrors;
  811. }
  812. /// <summary>
  813. /// Calculates the covariance matrix of a sample matrix.
  814. /// </summary>
  815. /// <remarks>
  816. /// In statistics and probability theory, the covariance matrix is a matrix of
  817. /// covariances between elements of a vector. It is the natural generalization
  818. /// to higher dimensions of the concept of the variance of a scalar-valued
  819. /// random variable.
  820. /// </remarks>
  821. /// <param name="matrix">A number multi-dimensional array containing the matrix values.</param>
  822. /// <returns>The covariance matrix.</returns>
  823. public static double[,] Covariance(this double[,] matrix)
  824. {
  825. return Covariance(matrix, Mean(matrix));
  826. }
  827. /// <summary>
  828. /// Calculates the covariance matrix of a sample matrix.
  829. /// </summary>
  830. /// <remarks>
  831. /// In statistics and probability theory, the covariance matrix is a matrix of
  832. /// covariances between elements of a vector. It is the natural generalization
  833. /// to higher dimensions of the concept of the variance of a scalar-valued
  834. /// random variable.
  835. /// </remarks>
  836. /// <param name="matrix">A number multi-dimensional array containing the matrix values.</param>
  837. /// <param name="dimension">
  838. /// The dimension of the matrix to consider as observations. Pass 0 if the matrix has
  839. /// observations as rows and variables as columns, pass 1 otherwise. Default is 0.
  840. /// </param>
  841. /// <returns>The covariance matrix.</returns>
  842. public static double[,] Covariance(this double[,] matrix, int dimension)
  843. {
  844. return Scatter(matrix, Mean(matrix, dimension), matrix.GetLength(dimension) - 1, dimension);
  845. }
  846. /// <summary>
  847. /// Calculates the covariance matrix of a sample matrix.
  848. /// </summary> /// <remarks>
  849. /// In statistics and probability theory, the covariance matrix is a matrix of
  850. /// covariances between elements of a vector. It is the natural generalization
  851. /// to higher dimensions of the concept of the variance of a scalar-valued
  852. /// random variable.
  853. /// </remarks>
  854. /// <param name="matrix">A number multi-dimensional array containing the matrix values.</param>
  855. /// <param name="means">The values' mean vector, if already known.</param>
  856. /// <returns>The covariance matrix.</returns>
  857. public static double[,] Covariance(this double[,] matrix, double[] means)
  858. {
  859. return Scatter(matrix, means, matrix.GetLength(0) - 1, 0);
  860. }
  861. /// <summary>
  862. /// Calculates the scatter matrix of a sample matrix.
  863. /// </summary>
  864. /// <remarks>
  865. /// By dividing the Scatter matrix by the sample size, we get the population
  866. /// Covariance matrix. By dividing by the sample size minus one, we get the
  867. /// sample Covariance matrix.
  868. /// </remarks>
  869. /// <param name="matrix">A number multi-dimensional array containing the matrix values.</param>
  870. /// <param name="means">The values' mean vector, if already known.</param>
  871. /// <returns>The covariance matrix.</returns>
  872. public static double[,] Scatter(double[,] matrix, double[] means)
  873. {
  874. return Scatter(matrix, means, 1.0, 0);
  875. }
  876. /// <summary>
  877. /// Calculates the scatter matrix of a sample matrix.
  878. /// </summary>
  879. /// <remarks>
  880. /// By dividing the Scatter matrix by the sample size, we get the population
  881. /// Covariance matrix. By dividing by the sample size minus one, we get the
  882. /// sample Covariance matrix.
  883. /// </remarks>
  884. /// <param name="matrix">A number multi-dimensional array containing the matrix values.</param>
  885. /// <param name="means">The values' mean vector, if already known.</param>
  886. /// <param name="divisor">A real number to divide each member of the matrix.</param>
  887. /// <returns>The covariance matrix.</returns>
  888. public static double[,] Scatter(double[,] matrix, double[] means, double divisor)
  889. {
  890. return Scatter(matrix, means, divisor, 0);
  891. }
  892. /// <summary>
  893. /// Calculates the scatter matrix of a sample matrix.
  894. /// </summary>
  895. /// <remarks>
  896. /// By dividing the Scatter matrix by the sample size, we get the population
  897. /// Covariance matrix. By dividing by the sample size minus one, we get the
  898. /// sample Covariance matrix.
  899. /// </remarks>
  900. /// <param name="matrix">A number multi-dimensional array containing the matrix values.</param>
  901. /// <param name="means">The values' mean vector, if already known.</param>
  902. /// <param name="dimension">
  903. /// Pass 0 to if mean vector is a row vector, 1 otherwise. Default value is 0.
  904. /// </param>
  905. /// <returns>The covariance matrix.</returns>
  906. public static double[,] Scatter(double[,] matrix, double[] means, int dimension)
  907. {
  908. return Scatter(matrix, means, 1.0, dimension);
  909. }
  910. /// <summary>
  911. /// Calculates the scatter matrix of a sample matrix.
  912. /// </summary>
  913. /// <remarks>
  914. /// By dividing the Scatter matrix by the sample size, we get the population
  915. /// Covariance matrix. By dividing by the sample size minus one, we get the
  916. /// sample Covariance matrix.
  917. /// </remarks>
  918. /// <param name="matrix">A number multi-dimensional array containing the matrix values.</param>
  919. /// <param name="means">The values' mean vector, if already known.</param>
  920. /// <param name="divisor">A real number to divide each member of the matrix.</param>
  921. /// <param name="dimension">
  922. /// Pass 0 if the mean vector is a row vector, 1 otherwise. Default value is 0.
  923. /// </param>
  924. /// <returns>The covariance matrix.</returns>
  925. public static double[,] Scatter(double[,] matrix, double[] means, double divisor, int dimension)
  926. {
  927. int rows = matrix.GetLength(0);
  928. int cols = matrix.GetLength(1);
  929. double[,] cov;
  930. if (dimension == 0)
  931. {
  932. if (means.Length != cols) throw new ArgumentException(
  933. "Length of the mean vector should equal the number of columns", "mean");
  934. cov = new double[cols, cols];
  935. for (int i = 0; i < cols; i++)
  936. {
  937. for (int j = i; j < cols; j++)
  938. {
  939. double s = 0.0;
  940. for (int k = 0; k < rows; k++)
  941. s += (matrix[k, j] - means[j]) * (matrix[k, i] - means[i]);
  942. s /= divisor;
  943. cov[i, j] = s;
  944. cov[j, i] = s;
  945. }
  946. }
  947. }
  948. else if (dimension == 1)
  949. {
  950. if (means.Length != rows) throw new ArgumentException(
  951. "Length of the mean vector should equal the number of rows", "mean");
  952. cov = new double[rows, rows];
  953. for (int i = 0; i < rows; i++)
  954. {
  955. for (int j = i; j < rows; j++)
  956. {
  957. double s = 0.0;
  958. for (int k = 0; k < cols; k++)
  959. s += (matrix[j, k] - means[j]) * (matrix[i, k] - means[i]);
  960. s /= divisor;
  961. cov[i, j] = s;
  962. cov[j, i] = s;
  963. }
  964. }
  965. }
  966. else
  967. {
  968. throw new ArgumentException("Invalid dimension.", "dimension");
  969. }
  970. return cov;
  971. }
  972. /// <summary>
  973. /// Calculates the covariance matrix of a sample matrix.
  974. /// </summary>
  975. /// <remarks>
  976. /// In statistics and probability theory, the covariance matrix is a matrix of
  977. /// covariances between elements of a vector. It is the natural generalization
  978. /// to higher dimensions of the concept of the variance of a scalar-valued
  979. /// random variable.
  980. /// </remarks>
  981. /// <param name="matrix">A number multi-dimensional array containing the matrix values.</param>
  982. /// <returns>The covariance matrix.</returns>
  983. public static double[,] Covariance(this double[][] matrix)
  984. {
  985. return Covariance(matrix, Mean(matrix));
  986. }
  987. /// <summary>
  988. /// Calculates the covariance matrix of a sample matrix.
  989. /// </summary>
  990. /// <remarks>
  991. /// In statistics and probability theory, the covariance matrix is a matrix of
  992. /// covariances between elements of a vector. It is the natural generalization
  993. /// to higher dimensions of the concept of the variance of a scalar-valued
  994. /// random variable.
  995. /// </remarks>
  996. /// <param name="matrix">A number multi-dimensional array containing the matrix values.</param>
  997. /// <param name="dimension">
  998. /// The dimension of the matrix to consider as observations. Pass 0 if the matrix has
  999. /// observations as rows and variables as columns, pass 1 otherwise. Default is 0.
  1000. /// </param>
  1001. /// <returns>The covariance matrix.</returns>
  1002. public static double[,] Covariance(this double[][] matrix, int dimension)
  1003. {
  1004. int size = (dimension == 0) ? matrix.Length : matrix[0].Length;
  1005. return Scatter(matrix, Mean(matrix, dimension), size - 1, dimension);
  1006. }
  1007. /// <summary>
  1008. /// Calculates the covariance matrix of a sample matrix.
  1009. /// </summary>
  1010. /// <remarks>
  1011. /// In statistics and probability theory, the covariance matrix is a matrix of
  1012. /// covariances between elements of a vector. It is the natural generalization
  1013. /// to higher dimensions of the concept of the variance of a scalar-valued
  1014. /// random variable.
  1015. /// </remarks>
  1016. /// <param name="matrix">A number multi-dimensional array containing the matrix values.</param>
  1017. /// <param name="means">The values' mean vector, if already known.</param>
  1018. /// <returns>The covariance matrix.</returns>
  1019. public static double[,] Covariance(this double[][] matrix, double[] means)
  1020. {
  1021. return Scatter(matrix, means, matrix.Length - 1, 0);
  1022. }
  1023. /// <summary>
  1024. /// Calculates the scatter matrix of a sample matrix.
  1025. /// </summary>
  1026. /// <remarks>
  1027. /// By dividing the Scatter matrix by the sample size, we get the population
  1028. /// Covariance matrix. By dividing by the sample size minus one, we get the
  1029. /// sample Covariance matrix.
  1030. /// </remarks>
  1031. /// <param name="matrix">A number multi-dimensional array containing the matrix values.</param>
  1032. /// <param name="means">The values' mean vector, if already known.</param>
  1033. /// <returns>The covariance matrix.</returns>
  1034. public static double[,] Scatter(double[][] matrix, double[] means)
  1035. {
  1036. return Scatter(matrix, means, 1.0, 0);
  1037. }
  1038. /// <summary>
  1039. /// Calculates the scatter matrix of a sample matrix.
  1040. /// </summary>
  1041. /// <remarks>
  1042. /// By dividing the Scatter matrix by the sample size, we get the population
  1043. /// Covariance matrix. By dividing by the sample size minus one, we get the
  1044. /// sample Covariance matrix.
  1045. /// </remarks>
  1046. /// <param name="matrix">A number multi-dimensional array containing the matrix values.</param>
  1047. /// <param name="means">The values' mean vector, if already known.</param>
  1048. /// <param name="divisor">A real number to divide each member of the matrix.</param>
  1049. /// <returns>The covariance matrix.</returns>
  1050. public static double[,] Scatter(double[][] matrix, double[] means, double divisor)
  1051. {
  1052. return Scatter(matrix, means, divisor, 0);
  1053. }
  1054. /// <summary>
  1055. /// Calculates the scatter matrix of a sample matrix.
  1056. /// </summary>
  1057. /// <remarks>
  1058. /// By dividing the Scatter matrix by the sample size, we get the population
  1059. /// Covariance matrix. By dividing by the sample size minus one, we get the
  1060. /// sample Covariance matrix.
  1061. /// </remarks>
  1062. /// <param name="matrix">A number multi-dimensional array containing the matrix values.</param>
  1063. /// <param name="means">The values' mean vector, if already known.</param>
  1064. /// <param name="dimension">
  1065. /// Pass 0 to if mean vector is a row vector, 1 otherwise. Default value is 0.
  1066. /// </param>
  1067. /// <returns>The covariance matrix.</returns>
  1068. public static double[,] Scatter(double[][] matrix, double[] means, int dimension)
  1069. {
  1070. return Scatter(matrix, means, 1.0, dimension);
  1071. }
  1072. /// <summary>
  1073. /// Calculates the scatter matrix of a sample matrix.
  1074. /// </summary>
  1075. /// <remarks>
  1076. /// By dividing the Scatter matrix by the sample size, we get the population
  1077. /// Covariance matrix. By dividing by the sample size minus one, we get the
  1078. /// sample Covariance matrix.
  1079. /// </remarks>
  1080. /// <param name="matrix">A number multi-dimensional array containing the matrix values.</param>
  1081. /// <param name="means">The values' mean vector, if already known.</param>
  1082. /// <param name="weights">An unit vector containing the importance of each sample
  1083. /// in <see param="values"/>. The sum of this array elements should add up to 1.</param>
  1084. /// <returns>The covariance matrix.</returns>
  1085. public static double[,] Covariance(double[][] matrix, double[] means, double[] weights)
  1086. {
  1087. double sw = 1.0;
  1088. for (int i = 0; i < weights.Length; i++)
  1089. sw -= weights[i] * weights[i];
  1090. return Scatter(matrix, means, sw, 0, weights);
  1091. }
  1092. /// <summary>
  1093. /// Calculates the scatter matrix of a sample matrix.
  1094. /// </summary>
  1095. /// <remarks>
  1096. /// By dividing the Scatter matrix by the sample size, we get the population
  1097. /// Covariance matrix. By dividing by the sample size minus one, we get the
  1098. /// sample Covariance matrix.
  1099. /// </remarks>
  1100. /// <param name="matrix">A number multi-dimensional array containing the matrix values.</param>
  1101. /// <param name="means">The values' mean vector, if already known.</param>
  1102. /// <param name="divisor">A real number to divide each member of the matrix.</param>
  1103. /// <param name="dimension">
  1104. /// Pass 0 to if mean vector is a row vector, 1 otherwise. Default value is 0.
  1105. /// </param>
  1106. /// <param name="weights">An unit vector containing the importance of each sample
  1107. /// in <see param="values"/>. The sum of this array elements should add up to 1.</param>
  1108. /// <returns>The covariance matrix.</returns>
  1109. public static double[,] Scatter(double[][] matrix, double[] means, double divisor, int dimension, double[] weights)
  1110. {
  1111. int rows = matrix.Length;
  1112. if (rows == 0) return new double[0, 0];
  1113. int cols = matrix[0].Length;
  1114. double[,] cov;
  1115. if (dimension == 0)
  1116. {
  1117. if (means.Length != cols) throw new ArgumentException(
  1118. "Length of the mean vector should equal the number of columns", "mean");
  1119. cov = new double[cols, cols];
  1120. for (int i = 0; i < cols; i++)
  1121. {
  1122. for (int j = i; j < cols; j++)
  1123. {
  1124. double s = 0.0;
  1125. for (int k = 0; k < rows; k++)
  1126. s += weights[k] * (matrix[k][j] - means[j]) * (matrix[k][i] - means[i]);
  1127. s /= divisor;
  1128. cov[i, j] = s;
  1129. cov[j, i] = s;
  1130. }
  1131. }
  1132. }
  1133. else if (dimension == 1)
  1134. {
  1135. if (means.Length != rows) throw new ArgumentException(
  1136. "Length of the mean vector should equal the number of rows", "mean");
  1137. cov = new double[rows, rows];
  1138. for (int i = 0; i < rows; i++)
  1139. {
  1140. for (int j = i; j < rows; j++)
  1141. {
  1142. double s = 0.0;
  1143. for (int k = 0; k < cols; k++)
  1144. s += weights[k] * (matrix[j][k] - means[j]) * (matrix[i][k] - means[i]);
  1145. s /= divisor;
  1146. cov[i, j] = s;
  1147. cov[j, i] = s;
  1148. }
  1149. }
  1150. }
  1151. else
  1152. {
  1153. throw new ArgumentException("Invalid dimension.", "dimension");
  1154. }
  1155. return cov;
  1156. }
  1157. /// <summary>
  1158. /// Calculates the scatter matrix of a sample matrix.
  1159. /// </summary>
  1160. /// <remarks>
  1161. /// By dividing the Scatter matrix by the sample size, we get the population
  1162. /// Covariance matrix. By dividing by the sample size minus one, we get the
  1163. /// sample Covariance matrix.
  1164. /// </remarks>
  1165. /// <param name="matrix">A number multi-dimensional array containing the matrix values.</param>
  1166. /// <param name="means">The values' mean vector, if already known.</param>
  1167. /// <param name="divisor">A real number to divide each member of the matrix.</param>
  1168. /// <param name="dimension">
  1169. /// Pass 0 to if mean vector is a row vector, 1 otherwise. Default value is 0.
  1170. /// </param>
  1171. /// <returns>The covariance matrix.</returns>
  1172. public static double[,] Scatter(double[][] matrix, double[] means, double divisor, int dimension)
  1173. {
  1174. int rows = matrix.Length;
  1175. int cols = matrix[0].Length;
  1176. double[,] cov;
  1177. if (dimension == 0)
  1178. {
  1179. if (means.Length != cols) throw new ArgumentException(
  1180. "Length of the mean vector should equal the number of columns", "mean");
  1181. cov = new double[cols, cols];
  1182. for (int i = 0; i < cols; i++)
  1183. {
  1184. for (int j = i; j < cols; j++)
  1185. {
  1186. double s = 0.0;
  1187. for (int k = 0; k < rows; k++)
  1188. s += (matrix[k][j] - means[j]) * (matrix[k][i] - means[i]);
  1189. s /= divisor;
  1190. cov[i, j] = s;
  1191. cov[j, i] = s;
  1192. }
  1193. }
  1194. }
  1195. else if (dimension == 1)
  1196. {
  1197. if (means.Length != rows) throw new ArgumentException(
  1198. "Length of the mean vector should equal the number of rows", "mean");
  1199. cov = new double[rows, rows];
  1200. for (int i = 0; i < rows; i++)
  1201. {
  1202. for (int j = i; j < rows; j++)
  1203. {
  1204. double s = 0.0;
  1205. for (int k = 0; k < cols; k++)
  1206. s += (matrix[j][k] - means[j]) * (matrix[i][k] - means[i]);
  1207. s /= divisor;
  1208. cov[i, j] = s;
  1209. cov[j, i] = s;
  1210. }
  1211. }
  1212. }
  1213. else
  1214. {
  1215. throw new ArgumentException("Invalid dimension.", "dimension");
  1216. }
  1217. return cov;
  1218. }
  1219. /// <summary>
  1220. /// Calculates the correlation matrix for a matrix of samples.
  1221. /// </summary>
  1222. /// <remarks>
  1223. /// In statistics and probability theory, the correlation matrix is the same
  1224. /// as the covariance matrix of the standardized random variables.
  1225. /// </remarks>
  1226. /// <param name="matrix">A multi-dimensional array containing the matrix values.</param>
  1227. /// <returns>The correlation matrix.</returns>
  1228. public static double[,] Correlation(double[,] matrix)
  1229. {
  1230. double[] means = Mean(matrix);
  1231. return Correlation(matrix, means, StandardDeviation(matrix, means));
  1232. }
  1233. /// <summary>
  1234. /// Calculates the correlation matrix for a matrix of samples.
  1235. /// </summary>
  1236. /// <remarks>
  1237. /// In statistics and probability theory, the correlation matrix is the same
  1238. /// as the covariance matrix of the standardized random variables.
  1239. /// </remarks>
  1240. /// <param name="matrix">A multi-dimensional array containing the matrix values.</param>
  1241. /// <param name="means">The values' mean vector, if already known.</param>
  1242. /// <param name="standardDeviations">The values' standard deviation vector, if already known.</param>
  1243. /// <returns>The correlation matrix.</returns>
  1244. public static double[,] Correlation(double[,] matrix, double[] means, double[] standardDeviations)
  1245. {
  1246. double[,] scores = ZScores(matrix, means, standardDeviations);
  1247. int rows = matrix.GetLength(0);
  1248. int cols = matrix.GetLength(1);
  1249. double N = rows;
  1250. double[,] cor = new double[cols, cols];
  1251. for (int i = 0; i < cols; i++)
  1252. {
  1253. for (int j = i; j < cols; j++)
  1254. {
  1255. double c = 0.0;
  1256. for (int k = 0; k < rows; k++)
  1257. c += scores[k, j] * scores[k, i];
  1258. c /= N - 1.0;
  1259. cor[i, j] = c;
  1260. cor[j, i] = c;
  1261. }
  1262. }
  1263. return cor;
  1264. }
  1265. /// <summary>Generates the Standard Scores, also known as Z-Scores, the core from the given data.</summary>
  1266. /// <param name="matrix">A number multi-dimensional array containing the matrix values.</param>
  1267. /// <returns>The Z-Scores for the matrix.</returns>
  1268. public static double[,] ZScores(double[,] matrix)
  1269. {
  1270. double[] mean = Mean(matrix);
  1271. return ZScores(matrix, mean, StandardDeviation(matrix, mean));
  1272. }
  1273. /// <summary>Generates the Standard Scores, also known as Z-Scores, the core from the given data.</summary>
  1274. /// <param name="matrix">A number multi-dimensional array containing the matrix values.</param>
  1275. /// <param name="means">The values' mean vector, if already known.</param>
  1276. /// <param name="standardDeviations">The values' standard deviation vector, if already known.</param>
  1277. /// <returns>The Z-Scores for the matrix.</returns>
  1278. public static double[,] ZScores(double[,] matrix, double[] means, double[] standardDeviations)
  1279. {
  1280. double[,] m = (double[,])matrix.Clone();
  1281. Center(m, means);
  1282. Standardize(m, standardDeviations);
  1283. return m;
  1284. }
  1285. /// <summary>Generates the Standard Scores, also known as Z-Scores, the core from the given data.</summary>
  1286. /// <param name="matrix">A number multi-dimensional array containing the matrix values.</param>
  1287. /// <returns>The Z-Scores for the matrix.</returns>
  1288. public static double[][] ZScores(double[][] matrix)
  1289. {
  1290. double[] mean = Mean(matrix);
  1291. return ZScores(matrix, mean, StandardDeviation(matrix, mean));
  1292. }
  1293. /// <summary>Generates the Standard Scores, also known as Z-Scores, the core from the given data.</summary>
  1294. /// <param name="matrix">A number multi-dimensional array containing the matrix values.</param>
  1295. /// <param name="means">The values' mean vector, if already known.</param>
  1296. /// <param name="standardDeviations">The values' standard deviation vector, if already known.</param>
  1297. /// <returns>The Z-Scores for the matrix.</returns>
  1298. public static double[][] ZScores(double[][] matrix, double[] means, double[] standardDeviations)
  1299. {
  1300. double[][] m = (double[][])matrix.Clone();
  1301. Center(m, means);
  1302. Standardize(m, standardDeviations);
  1303. return m;
  1304. }
  1305. /// <summary>Centers column data, subtracting the empirical mean from each variable.</summary>
  1306. /// <param name="matrix">A matrix where each column represent a variable and each row represent a observation.</param>
  1307. public static void Center(double[,] matrix)
  1308. {
  1309. Center(matrix, Mean(matrix));
  1310. }
  1311. /// <summary>Centers column data, subtracting the empirical mean from each variable.</summary>
  1312. /// <param name="matrix">A matrix where each column represent a variable and each row represent a observation.</param>
  1313. /// <param name="means">The values' mean vector, if already known.</param>
  1314. public static void Center(double[,] matrix, double[] means)
  1315. {
  1316. int rows = matrix.GetLength(0);
  1317. int cols = matrix.GetLength(1);
  1318. for (int i = 0; i < rows; i++)
  1319. for (int j = 0; j < cols; j++)
  1320. matrix[i, j] -= means[j];
  1321. }
  1322. /// <summary>Centers column data, subtracting the empirical mean from each variable.</summary>
  1323. /// <param name="matrix">A matrix where each column represent a variable and each row represent a observation.</param>
  1324. public static void Center(double[][] matrix)
  1325. {
  1326. Center(matrix, Mean(matrix));
  1327. }
  1328. /// <summary>Centers column data, subtracting the empirical mean from each variable.</summary>
  1329. /// <param name="matrix">A matrix where each column represent a variable and each row represent a observation.</param>
  1330. /// <param name="means">The values' mean vector, if already known.</param>
  1331. public static void Center(double[][] matrix, double[] means)
  1332. {
  1333. for (int i = 0; i < matrix.Length; i++)
  1334. {
  1335. double[] row = matrix[i];
  1336. for (int j = 0; j < row.Length; j++)
  1337. row[j] -= means[j];
  1338. }
  1339. }
  1340. /// <summary>Standardizes column data, removing the empirical standard deviation from each variable.</summary>
  1341. /// <param name="matrix">A matrix where each column represent a variable and each row represent a observation.</param>
  1342. /// <remarks>This method does not remove the empirical mean prior to execution.</remarks>
  1343. public static void Standardize(double[,] matrix)
  1344. {
  1345. Standardize(matrix, StandardDeviation(matrix));
  1346. }
  1347. /// <summary>Standardizes column data, removing the empirical standard deviation from each variable.</summary>
  1348. /// <param name="matrix">A matrix where each column represent a variable and each row represent a observation.</param>
  1349. /// <remarks>This method does not remove the empirical mean prior to execution.</remarks>
  1350. /// <param name="standardDeviations">The values' standard deviation vector, if already known.</param>
  1351. public static void Standardize(this double[,] matrix, double[] standardDeviations)
  1352. {
  1353. int rows = matrix.GetLength(0);
  1354. int cols = matrix.GetLength(1);
  1355. for (int i = 0; i < rows; i++)
  1356. for (int j = 0; j < cols; j++)
  1357. matrix[i, j] /= standardDeviations[j];
  1358. }
  1359. /// <summary>Standardizes column data, removing the empirical standard deviation from each variable.</summary>
  1360. /// <param name="matrix">A matrix where each column represent a variable and each row represent a observation.</param>
  1361. /// <remarks>This method does not remove the empirical mean prior to execution.</remarks>
  1362. public static void Standardize(double[][] matrix)
  1363. {
  1364. Standardize(matrix, StandardDeviation(matrix));
  1365. }
  1366. /// <summary>Standardizes column data, removing the empirical standard deviation from each variable.</summary>
  1367. /// <param name="matrix">A matrix where each column represent a variable and each row represent a observation.</param>
  1368. /// <remarks>This method does not remove the empirical mean prior to execution.</remarks>
  1369. /// <param name="standardDeviations">The values' standard deviation vector, if already known.</param>
  1370. public static void Standardize(this double[][] matrix, double[] standardDeviations)
  1371. {
  1372. for (int i = 0; i < matrix.Length; i++)
  1373. {
  1374. double[] row = matrix[i];
  1375. for (int j = 0; j < row.Length; j++)
  1376. row[j] /= standardDeviations[j];
  1377. }
  1378. }
  1379. #endregion
  1380. // ------------------------------------------------------------
  1381. #region Summarizing, grouping and extending operations
  1382. /// <summary>
  1383. /// Calculates the prevalence of a class.
  1384. /// </summary>
  1385. /// <param name="positives">An array of counts detailing the occurence of the first class.</param>
  1386. /// <param name="negatives">An array of counts detailing the occurence of the second class.</param>
  1387. /// <returns>An array containing the proportion of the first class over the total of occurances.</returns>
  1388. public static double[] Proportions(int[] positives, int[] negatives)
  1389. {
  1390. double[] r = new double[positives.Length];
  1391. for (int i = 0; i < r.Length; i++)
  1392. r[i] = (double)positives[i] / (positives[i] + negatives[i]);
  1393. return r;
  1394. }
  1395. /// <summary>
  1396. /// Calculates the prevalence of a class.
  1397. /// </summary>
  1398. /// <param name="data">A matrix containing counted, grouped data.</param>
  1399. /// <param name="positiveColumn">The index for the column which contains counts for occurence of the first class.</param>
  1400. /// <param name="negativeColumn">The index for the column which contains counts for occurence of the second class.</param>
  1401. /// <returns>An array containing the proportion of the first class over the total of occurances.</returns>
  1402. public static double[] Proportions(int[][] data, int positiveColumn, int negativeColumn)
  1403. {
  1404. double[] r = new double[data.Length];
  1405. for (int i = 0; i < r.Length; i++)
  1406. r[i] = (double)data[i][positiveColumn] / (data[i][positiveColumn] + data[i][negativeColumn]);
  1407. return r;
  1408. }
  1409. /// <summary>
  1410. /// Groups the occurances contained in data matrix of binary (dichotomous) data.
  1411. /// </summary>
  1412. /// <param name="data">A data matrix containing at least a column of binary data.</param>
  1413. /// <param name="labelColumn">Index of the column which contains the group label name.</param>
  1414. /// <param name="dataColumn">Index of the column which contains the binary [0,1] data.</param>
  1415. /// <returns>
  1416. /// A matrix containing the group label in the first column, the number of occurances of the first class
  1417. /// in the second column and the number of occurances of the second class in the third column.
  1418. /// </returns>
  1419. public static int[][] Group(int[][] data, int labelColumn, int dataColumn)
  1420. {
  1421. var groups = new List<int>();
  1422. var groupings = new List<int[]>();
  1423. for (int i = 0; i < data.Length; i++)
  1424. {
  1425. int group = data[i][labelColumn];
  1426. if (!groups.Contains(group))
  1427. {
  1428. groups.Add(group);
  1429. int positives = 0, negatives = 0;
  1430. for (int j = 0; j < data.Length; j++)
  1431. {
  1432. if (data[j][labelColumn] == group)
  1433. {
  1434. if (data[j][dataColumn] == 0)
  1435. negatives++;
  1436. else positives++;
  1437. }
  1438. }
  1439. groupings.Add(new int[] { group, positives, negatives });
  1440. }
  1441. }
  1442. return groupings.ToArray();
  1443. }
  1444. /// <summary>
  1445. /// Extends a grouped data into a full observation matrix.
  1446. /// </summary>
  1447. /// <param name="group">The group labels.</param>
  1448. /// <param name="positives">
  1449. /// An array containing he occurence of the positive class
  1450. /// for each of the groups.</param>
  1451. /// <param name="negatives">
  1452. /// An array containing he occurence of the negative class
  1453. /// for each of the groups.</param>
  1454. /// <returns>A full sized observation matrix.</returns>
  1455. public static int[][] Extend(int[] group, int[] positives, int[] negatives)
  1456. {
  1457. List<int[]> rows = new List<int[]>();
  1458. for (int i = 0; i < group.Length; i++)
  1459. {
  1460. for (int j = 0; j < positives[i]; j++)
  1461. rows.Add(new int[] { group[i], 1 });
  1462. for (int j = 0; j < negatives[i]; j++)
  1463. rows.Add(new int[] { group[i], 0 });
  1464. }
  1465. return rows.ToArray();
  1466. }
  1467. /// <summary>
  1468. /// Extendes a grouped data into a full observation matrix.
  1469. /// </summary>
  1470. /// <param name="data">The grouped data matrix.</param>
  1471. /// <param name="labelColumn">Index of the column which contains the labels
  1472. /// in the grouped data matrix. </param>
  1473. /// <param name="positiveColumn">Index of the column which contains
  1474. /// the occurances for the first class.</param>
  1475. /// <param name="negativeColumn">Index of the column which contains
  1476. /// the occurances for the second class.</param>
  1477. /// <returns>A full sized observation matrix.</returns>
  1478. public static int[][] Extend(int[][] data, int labelColumn, int positiveColumn, int negativeColumn)
  1479. {
  1480. List<int[]> rows = new List<int[]>();
  1481. for (int i = 0; i < data.Length; i++)
  1482. {
  1483. for (int j = 0; j < data[i][positiveColumn]; j++)
  1484. rows.Add(new int[] { data[i][labelColumn], 1 });
  1485. for (int j = 0; j < data[i][negativeColumn]; j++)
  1486. rows.Add(new int[] { data[i][labelColumn], 0 });
  1487. }
  1488. return rows.ToArray();
  1489. }
  1490. #endregion
  1491. #region Determination and performance measures
  1492. /// <summary>
  1493. /// Gets the coefficient of determination, as known as the R-Squared (R²)
  1494. /// </summary>
  1495. /// <remarks>
  1496. /// The coefficient of determination is used in the context of statistical models
  1497. /// whose main purpose is the prediction of future outcomes on the basis of other
  1498. /// related information. It is the proportion of variability in a data set that
  1499. /// is accounted for by the statistical model. It provides a measure of how well
  1500. /// future outcomes are likely to be predicted by the model.
  1501. ///
  1502. /// The R^2 coefficient of determination is a statistical measure of how well the
  1503. /// regression approximates the real data points. An R^2 of 1.0 indicates that the
  1504. /// regression perfectly fits the data.
  1505. /// </remarks>
  1506. public static double Determination(double[] actual, double[] expected)
  1507. {
  1508. // R-squared = 100 * SS(regression) / SS(total)
  1509. int N = actual.Length;
  1510. double SSe = 0.0;
  1511. double SSt = 0.0;
  1512. double avg = 0.0;
  1513. double d;
  1514. // Calculate expected output mean
  1515. for (int i = 0; i < N; i++)
  1516. avg += expected[i];
  1517. avg /= N;
  1518. // Calculate SSe and SSt
  1519. for (int i = 0; i < N; i++)
  1520. {
  1521. d = expected[i] - actual[i];
  1522. SSe += d * d;
  1523. d = expected[i] - avg;
  1524. SSt += d * d;
  1525. }
  1526. // Calculate R-Squared
  1527. return 1.0 - (SSe / SSt);
  1528. }
  1529. #endregion
  1530. #region Permutations and combinatorials
  1531. /// <summary>
  1532. /// Returns a random sample of size k from a population of size n.
  1533. /// </summary>
  1534. public static int[] Random(int n, int k)
  1535. {
  1536. int[] idx = Tools.Random(n);
  1537. return idx.Submatrix(k);
  1538. }
  1539. /// <summary>
  1540. /// Returns a random permutation of size n.
  1541. /// </summary>
  1542. public static int[] Random(int n)
  1543. {
  1544. Random random = Accord.Math.Tools.Random;
  1545. double[] x = new double[n];
  1546. int[] idx = Matrix.Indexes(0, n);
  1547. for (int i = 0; i < n; i++)
  1548. x[i] = random.NextDouble();
  1549. Array.Sort(x, idx);
  1550. return idx;
  1551. }
  1552. /// <summary>
  1553. /// Shuffles an array.
  1554. /// </summary>
  1555. public static void Shuffle(int[] array)
  1556. {
  1557. Random random = Accord.Math.Tools.Random;
  1558. // i is the number of items remaining to be shuffled.
  1559. for (int i = array.Length; i > 1; i--)
  1560. {
  1561. // Pick a random element to swap with the i-th element.
  1562. int j = random.Next(i);
  1563. // Swap array elements.
  1564. var aux = array[j];
  1565. array[j] = array[i - 1];
  1566. array[i - 1] = aux;
  1567. }
  1568. }
  1569. #endregion
  1570. }
  1571. }