qesuite 1.0.51 → 1.0.52

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -294,6 +294,20 @@ declare const Gamma: {
294
294
  * @param x The value to be evaluated.
295
295
  **/
296
296
  Trigamma(x: number): number;
297
+ /**
298
+ * Evaluates the lower incomplete gamma function for the specified value.
299
+ * @customfunction
300
+ * @param n
301
+ * @param x
302
+ **/
303
+ LowerIncomplete(n: number, x: number): number;
304
+ /**
305
+ * Evaluates the upper incomplete gamma function for the specified value.
306
+ * @customfunction
307
+ * @param n
308
+ * @param x
309
+ **/
310
+ UpperIncomplete(n: number, x: number): number;
297
311
  };
298
312
  /** ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
299
313
  */
@@ -340,6 +354,7 @@ declare const Distributions: {
340
354
  inv(p: number, a: number, b: number): any;
341
355
  };
342
356
  ChiSq: {
357
+ pdf(x: number, df: number): number;
343
358
  cdf(x: number, df: number): number;
344
359
  RightTail(x: number, df: number): number;
345
360
  };
@@ -1021,6 +1036,8 @@ declare const ANOVA: {
1021
1036
  };
1022
1037
  Multifactor: {
1023
1038
  MainEffectsPlot(factors: any, response: any): HTMLCanvasElement;
1039
+ Table(factors: any, response: any): {};
1040
+ GLM(factors: any, response: any): {};
1024
1041
  };
1025
1042
  };
1026
1043
  declare function SumSquaredDeviation(data: number[], referenceValue?: any): number;
package/dist/index.d.ts CHANGED
@@ -294,6 +294,20 @@ declare const Gamma: {
294
294
  * @param x The value to be evaluated.
295
295
  **/
296
296
  Trigamma(x: number): number;
297
+ /**
298
+ * Evaluates the lower incomplete gamma function for the specified value.
299
+ * @customfunction
300
+ * @param n
301
+ * @param x
302
+ **/
303
+ LowerIncomplete(n: number, x: number): number;
304
+ /**
305
+ * Evaluates the upper incomplete gamma function for the specified value.
306
+ * @customfunction
307
+ * @param n
308
+ * @param x
309
+ **/
310
+ UpperIncomplete(n: number, x: number): number;
297
311
  };
298
312
  /** ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
299
313
  */
@@ -340,6 +354,7 @@ declare const Distributions: {
340
354
  inv(p: number, a: number, b: number): any;
341
355
  };
342
356
  ChiSq: {
357
+ pdf(x: number, df: number): number;
343
358
  cdf(x: number, df: number): number;
344
359
  RightTail(x: number, df: number): number;
345
360
  };
@@ -1021,6 +1036,8 @@ declare const ANOVA: {
1021
1036
  };
1022
1037
  Multifactor: {
1023
1038
  MainEffectsPlot(factors: any, response: any): HTMLCanvasElement;
1039
+ Table(factors: any, response: any): {};
1040
+ GLM(factors: any, response: any): {};
1024
1041
  };
1025
1042
  };
1026
1043
  declare function SumSquaredDeviation(data: number[], referenceValue?: any): number;
package/dist/index.js CHANGED
@@ -937,6 +937,28 @@ var Gamma = {
937
937
  **/
938
938
  Trigamma(x) {
939
939
  return 1 / x + 1 / (2 * (x ^ 2)) + 1 / (6 * (x ^ 3)) - 1 / (30 * (x ^ 5)) + 1 / (42 * (x ^ 7)) - 1 / (30 * (x ^ 9)) + 5 / (66 * (x ^ 11)) - 691 / (2730 * (x ^ 13)) + 15 / (6 * (x ^ 15));
940
+ },
941
+ /**
942
+ * Evaluates the lower incomplete gamma function for the specified value.
943
+ * @customfunction
944
+ * @param n
945
+ * @param x
946
+ **/
947
+ LowerIncomplete(n, x) {
948
+ return Gamma.fn(n) - Gamma.UpperIncomplete(n, x);
949
+ },
950
+ /**
951
+ * Evaluates the upper incomplete gamma function for the specified value.
952
+ * @customfunction
953
+ * @param n
954
+ * @param x
955
+ **/
956
+ UpperIncomplete(n, x) {
957
+ let expSum = 0;
958
+ for (let k = 0; k < n; k++) {
959
+ expSum += Math.pow(x, k) / Probability.Factorialize(k);
960
+ }
961
+ return Probability.Factorialize(n - 1) * Math.exp(-x) * expSum;
940
962
  }
941
963
  };
942
964
  function NewtonRaphson(parameter, parameterizedFunction, derivativeFunction) {
@@ -1058,11 +1080,39 @@ var Distributions = {
1058
1080
  }
1059
1081
  },
1060
1082
  ChiSq: {
1083
+ pdf(x, df) {
1084
+ let num = Math.pow(x, df / 2 - 1) * Math.exp(-x / 2);
1085
+ let den = Math.pow(2, df / 2) * Gamma.fn(df / 2);
1086
+ return num / den;
1087
+ },
1061
1088
  cdf(x, df) {
1062
1089
  if (df === 2) {
1063
1090
  return 1 - Math.exp(-x / 2);
1064
1091
  }
1065
- return NaN;
1092
+ if (df % 2) {
1093
+ let test = 0;
1094
+ let stepCount = 1e7;
1095
+ let stepSize = x / stepCount;
1096
+ for (let i = 0; i < stepCount + 1; i++) {
1097
+ test += stepSize * Distributions.ChiSq.pdf(i * stepSize, df);
1098
+ }
1099
+ return test;
1100
+ if (x < df) {
1101
+ let y = Math.sqrt(df / 2) * Math.log(df / x);
1102
+ const aFunc = (c1, c2, c3, c4) => {
1103
+ return c1 + c2 * Math.pow(2 / df, 0.5) + c3 * (2 / df) + c4 * Math.pow(2 / df, 1 / 5);
1104
+ };
1105
+ let A = aFunc(0.5, 0.1323, 36e-4, -38e-4);
1106
+ let a1 = aFunc(0.1968, -0.0452, -0.0128, -0.0168);
1107
+ let a2 = aFunc(0.1152, -0.099, 0.0539, -0.0168);
1108
+ let a3 = aFunc(4e-4, 0.0442, -0.0866, 0.0398);
1109
+ let a4 = aFunc(0.0195, -0.0629, 0.0708, 0.0269);
1110
+ return A / Math.pow(1 + a1 * y + a2 * Math.pow(y, 2) + a3 * Math.pow(y, 3) + a4 * Math.pow(y, 4), 4);
1111
+ }
1112
+ }
1113
+ let num = Gamma.LowerIncomplete(df / 2, x / 2);
1114
+ let den = Gamma.fn(df / 2);
1115
+ return num / den;
1066
1116
  },
1067
1117
  RightTail(x, df) {
1068
1118
  return 1 - Distributions.ChiSq.cdf(x, df);
@@ -2594,6 +2644,57 @@ function Sum(data) {
2594
2644
  });
2595
2645
  return sum;
2596
2646
  }
2647
+ function SumSquareByGroups(groups, response) {
2648
+ let groupKeys = Object.keys(groups);
2649
+ let groupSets = [];
2650
+ let treatmentCount = 0;
2651
+ groupKeys.forEach((group) => {
2652
+ let set = new Set(groups[group]);
2653
+ groupSets.push(set);
2654
+ treatmentCount += set.size;
2655
+ });
2656
+ let placeFactors = [];
2657
+ groupSets.forEach((s, sI) => {
2658
+ if (sI === groupSets.length - 1) {
2659
+ placeFactors.push(1);
2660
+ } else {
2661
+ placeFactors.push(groupSets[sI + 1].size);
2662
+ }
2663
+ });
2664
+ let returnObject = {};
2665
+ let groupNObject = {};
2666
+ response[Object.keys(response)[0]].forEach((value, index) => {
2667
+ let indexer = [];
2668
+ groupKeys.forEach((k, kI) => {
2669
+ let currentKey = groups[k][index];
2670
+ groupSets[kI].forEach((s, sI) => {
2671
+ if (s === currentKey) {
2672
+ indexer.push(sI);
2673
+ }
2674
+ });
2675
+ });
2676
+ returnObject[JSON.stringify(indexer)] = 0;
2677
+ groupNObject[JSON.stringify(indexer)] = 0;
2678
+ });
2679
+ response[Object.keys(response)[0]].forEach((value, index) => {
2680
+ let indexer = [];
2681
+ groupKeys.forEach((k, kI) => {
2682
+ let currentKey = groups[k][index];
2683
+ groupSets[kI].forEach((s, sI) => {
2684
+ if (s === currentKey) {
2685
+ indexer.push(sI);
2686
+ }
2687
+ });
2688
+ });
2689
+ returnObject[JSON.stringify(indexer)] += value;
2690
+ groupNObject[JSON.stringify(indexer)] += 1;
2691
+ });
2692
+ let sumsq = 0;
2693
+ Object.keys(returnObject).forEach((k) => {
2694
+ sumsq += Math.pow(returnObject[k], 2) / groupNObject[k];
2695
+ });
2696
+ return sumsq;
2697
+ }
2597
2698
  function Rang(data) {
2598
2699
  let dataNumbers = data.map((d) => {
2599
2700
  return Number(d);
@@ -3714,7 +3815,125 @@ var ANOVA = {
3714
3815
  chartSet.width += 1e3;
3715
3816
  chartSet.axis.y.tickOnly = true;
3716
3817
  let graph = CreateSplitGraph(individualCharts, `Main Effects Plot of ${Object.keys(response)[0]}`, chartSet);
3818
+ console.log(graph);
3717
3819
  return graph;
3820
+ },
3821
+ Table(factors, response) {
3822
+ let anovaTable = {};
3823
+ let factorKeys = Object.keys(factors);
3824
+ let responseKey = Object.keys(response)[0];
3825
+ let Ntotal = response[responseKey].length;
3826
+ let DFE = 1;
3827
+ let correctionFactor = Math.pow(Sum(response[responseKey]), 2) / Ntotal;
3828
+ factorKeys.forEach((f) => {
3829
+ let fSet = new Set(factors[f]);
3830
+ let Nf = fSet.size;
3831
+ let SS_f = 0;
3832
+ fSet.forEach((level) => {
3833
+ let levelTotal = 0;
3834
+ let levelN = 0;
3835
+ factors[f].forEach((v, j) => {
3836
+ if (v === level) {
3837
+ levelTotal += response[responseKey][j];
3838
+ levelN += 1;
3839
+ }
3840
+ });
3841
+ SS_f += Math.pow(levelTotal, 2) / levelN;
3842
+ });
3843
+ SS_f = SS_f - correctionFactor;
3844
+ anovaTable[f] = {
3845
+ DF: Nf - 1,
3846
+ SS: SS_f,
3847
+ MS: SS_f / (Nf - 1),
3848
+ F: void 0,
3849
+ p: void 0
3850
+ };
3851
+ DFE = DFE * Nf;
3852
+ });
3853
+ DFE = Ntotal - DFE;
3854
+ for (let i = 0; i < factorKeys.length - 1; i++) {
3855
+ let f_i_Set = new Set(factors[factorKeys[i]]);
3856
+ for (let j = i + 1; j < factorKeys.length; j++) {
3857
+ let f_j_Set = new Set(factors[factorKeys[j]]);
3858
+ let SS_subtotal = 0;
3859
+ f_i_Set.forEach((fi) => {
3860
+ f_j_Set.forEach((fj) => {
3861
+ let groupSum = 0;
3862
+ let groupN = 0;
3863
+ response[responseKey].forEach((val, index) => {
3864
+ if (factors[factorKeys[i]][index] === fi && factors[factorKeys[j]][index] === fj) {
3865
+ groupSum += val;
3866
+ groupN += 1;
3867
+ }
3868
+ });
3869
+ SS_subtotal += Math.pow(groupSum, 2) / groupN;
3870
+ });
3871
+ });
3872
+ SS_subtotal = SS_subtotal - correctionFactor;
3873
+ let iRow = anovaTable[factorKeys[i]];
3874
+ let jRow = anovaTable[factorKeys[j]];
3875
+ let fi_fj_DF = iRow.DF * jRow.DF;
3876
+ let fi_fj_SS = SS_subtotal - iRow.SS - jRow.SS;
3877
+ anovaTable[`${factorKeys[i]}*${factorKeys[j]}`] = { DF: fi_fj_DF, SS: fi_fj_SS, MS: fi_fj_SS / fi_fj_DF, F: void 0, p: void 0 };
3878
+ }
3879
+ }
3880
+ let interactionSS_subtotal = SumSquareByGroups(factors, response) - correctionFactor;
3881
+ let fullInteractionDF = 1;
3882
+ let SSE = 0;
3883
+ factorKeys.forEach((source) => {
3884
+ fullInteractionDF = fullInteractionDF * anovaTable[source].DF;
3885
+ });
3886
+ Object.keys(anovaTable).forEach((source) => {
3887
+ interactionSS_subtotal = interactionSS_subtotal - anovaTable[source].SS;
3888
+ SSE += anovaTable[source].SS;
3889
+ });
3890
+ let fullInteractionName = factorKeys.join("*");
3891
+ anovaTable[fullInteractionName] = { DF: fullInteractionDF, SS: interactionSS_subtotal, MS: interactionSS_subtotal / fullInteractionDF, F: void 0, p: void 0 };
3892
+ SSE += interactionSS_subtotal;
3893
+ let SStotal = SumSquaredDeviation(response[responseKey], 0) - correctionFactor;
3894
+ SSE = SStotal - SSE;
3895
+ let MSE = SSE / DFE;
3896
+ Object.keys(anovaTable).forEach((source) => {
3897
+ let sourceF = anovaTable[source].MS / MSE;
3898
+ anovaTable[source].F = sourceF;
3899
+ anovaTable[source].p = Distributions.F.RightTail(sourceF, anovaTable[source].DF, DFE);
3900
+ });
3901
+ anovaTable["Error"] = { DF: DFE, SS: SSE, MS: MSE };
3902
+ anovaTable["Total"] = { DF: Ntotal - 1, SS: SStotal };
3903
+ return anovaTable;
3904
+ },
3905
+ GLM(factors, response) {
3906
+ let factorKeys = Object.keys(factors);
3907
+ let anovaTable = {};
3908
+ let responseKey = Object.keys(response)[0];
3909
+ let Ntotal = response[responseKey].length;
3910
+ let DFE = 1;
3911
+ let responseData = response[responseKey];
3912
+ factorKeys.forEach((k) => {
3913
+ let SS = 0;
3914
+ let levels = new Set(factors[k]);
3915
+ let groupedData = GroupData(factors[k], responseData);
3916
+ let descriptiveStats = {};
3917
+ let mean_0;
3918
+ Object.keys(groupedData).forEach((k2, k_i) => {
3919
+ let mean = Mean(groupedData[k2]);
3920
+ descriptiveStats[k2].mean = mean;
3921
+ descriptiveStats[k2].std = StDev.S(groupedData[k2]);
3922
+ descriptiveStats[k2].N = groupedData[k2].length;
3923
+ if (k_i === 0) {
3924
+ mean_0 = mean;
3925
+ groupedData[k2].forEach((d) => {
3926
+ SS += mean;
3927
+ });
3928
+ } else {
3929
+ groupedData[k2].forEach((d) => {
3930
+ SS += mean - Math.pow(mean - d, 2);
3931
+ });
3932
+ }
3933
+ });
3934
+ console.log(k, SS);
3935
+ });
3936
+ return anovaTable;
3718
3937
  }
3719
3938
  }
3720
3939
  };
@@ -3742,6 +3961,21 @@ var Probability = {
3742
3961
  }
3743
3962
  }
3744
3963
  };
3964
+ function GroupData(groupingArray, responseArray) {
3965
+ if (groupingArray.length != responseArray.length) {
3966
+ return { forEachGroup() {
3967
+ } };
3968
+ }
3969
+ let returnObj = {};
3970
+ let levels = new Set(groupingArray);
3971
+ levels.forEach((l) => {
3972
+ returnObj[l] = [];
3973
+ });
3974
+ for (let i = 0; i < groupingArray.length; i++) {
3975
+ returnObj[groupingArray[i]].push(responseArray[i]);
3976
+ }
3977
+ return returnObj;
3978
+ }
3745
3979
  function CreateCanvas(width, height) {
3746
3980
  let canvas = document.createElement("canvas");
3747
3981
  canvas.height = height;
package/dist/index.mjs CHANGED
@@ -845,6 +845,28 @@ var Gamma = {
845
845
  **/
846
846
  Trigamma(x) {
847
847
  return 1 / x + 1 / (2 * (x ^ 2)) + 1 / (6 * (x ^ 3)) - 1 / (30 * (x ^ 5)) + 1 / (42 * (x ^ 7)) - 1 / (30 * (x ^ 9)) + 5 / (66 * (x ^ 11)) - 691 / (2730 * (x ^ 13)) + 15 / (6 * (x ^ 15));
848
+ },
849
+ /**
850
+ * Evaluates the lower incomplete gamma function for the specified value.
851
+ * @customfunction
852
+ * @param n
853
+ * @param x
854
+ **/
855
+ LowerIncomplete(n, x) {
856
+ return Gamma.fn(n) - Gamma.UpperIncomplete(n, x);
857
+ },
858
+ /**
859
+ * Evaluates the upper incomplete gamma function for the specified value.
860
+ * @customfunction
861
+ * @param n
862
+ * @param x
863
+ **/
864
+ UpperIncomplete(n, x) {
865
+ let expSum = 0;
866
+ for (let k = 0; k < n; k++) {
867
+ expSum += Math.pow(x, k) / Probability.Factorialize(k);
868
+ }
869
+ return Probability.Factorialize(n - 1) * Math.exp(-x) * expSum;
848
870
  }
849
871
  };
850
872
  function NewtonRaphson(parameter, parameterizedFunction, derivativeFunction) {
@@ -966,11 +988,39 @@ var Distributions = {
966
988
  }
967
989
  },
968
990
  ChiSq: {
991
+ pdf(x, df) {
992
+ let num = Math.pow(x, df / 2 - 1) * Math.exp(-x / 2);
993
+ let den = Math.pow(2, df / 2) * Gamma.fn(df / 2);
994
+ return num / den;
995
+ },
969
996
  cdf(x, df) {
970
997
  if (df === 2) {
971
998
  return 1 - Math.exp(-x / 2);
972
999
  }
973
- return NaN;
1000
+ if (df % 2) {
1001
+ let test = 0;
1002
+ let stepCount = 1e7;
1003
+ let stepSize = x / stepCount;
1004
+ for (let i = 0; i < stepCount + 1; i++) {
1005
+ test += stepSize * Distributions.ChiSq.pdf(i * stepSize, df);
1006
+ }
1007
+ return test;
1008
+ if (x < df) {
1009
+ let y = Math.sqrt(df / 2) * Math.log(df / x);
1010
+ const aFunc = (c1, c2, c3, c4) => {
1011
+ return c1 + c2 * Math.pow(2 / df, 0.5) + c3 * (2 / df) + c4 * Math.pow(2 / df, 1 / 5);
1012
+ };
1013
+ let A = aFunc(0.5, 0.1323, 36e-4, -38e-4);
1014
+ let a1 = aFunc(0.1968, -0.0452, -0.0128, -0.0168);
1015
+ let a2 = aFunc(0.1152, -0.099, 0.0539, -0.0168);
1016
+ let a3 = aFunc(4e-4, 0.0442, -0.0866, 0.0398);
1017
+ let a4 = aFunc(0.0195, -0.0629, 0.0708, 0.0269);
1018
+ return A / Math.pow(1 + a1 * y + a2 * Math.pow(y, 2) + a3 * Math.pow(y, 3) + a4 * Math.pow(y, 4), 4);
1019
+ }
1020
+ }
1021
+ let num = Gamma.LowerIncomplete(df / 2, x / 2);
1022
+ let den = Gamma.fn(df / 2);
1023
+ return num / den;
974
1024
  },
975
1025
  RightTail(x, df) {
976
1026
  return 1 - Distributions.ChiSq.cdf(x, df);
@@ -2502,6 +2552,57 @@ function Sum(data) {
2502
2552
  });
2503
2553
  return sum;
2504
2554
  }
2555
+ function SumSquareByGroups(groups, response) {
2556
+ let groupKeys = Object.keys(groups);
2557
+ let groupSets = [];
2558
+ let treatmentCount = 0;
2559
+ groupKeys.forEach((group) => {
2560
+ let set = new Set(groups[group]);
2561
+ groupSets.push(set);
2562
+ treatmentCount += set.size;
2563
+ });
2564
+ let placeFactors = [];
2565
+ groupSets.forEach((s, sI) => {
2566
+ if (sI === groupSets.length - 1) {
2567
+ placeFactors.push(1);
2568
+ } else {
2569
+ placeFactors.push(groupSets[sI + 1].size);
2570
+ }
2571
+ });
2572
+ let returnObject = {};
2573
+ let groupNObject = {};
2574
+ response[Object.keys(response)[0]].forEach((value, index) => {
2575
+ let indexer = [];
2576
+ groupKeys.forEach((k, kI) => {
2577
+ let currentKey = groups[k][index];
2578
+ groupSets[kI].forEach((s, sI) => {
2579
+ if (s === currentKey) {
2580
+ indexer.push(sI);
2581
+ }
2582
+ });
2583
+ });
2584
+ returnObject[JSON.stringify(indexer)] = 0;
2585
+ groupNObject[JSON.stringify(indexer)] = 0;
2586
+ });
2587
+ response[Object.keys(response)[0]].forEach((value, index) => {
2588
+ let indexer = [];
2589
+ groupKeys.forEach((k, kI) => {
2590
+ let currentKey = groups[k][index];
2591
+ groupSets[kI].forEach((s, sI) => {
2592
+ if (s === currentKey) {
2593
+ indexer.push(sI);
2594
+ }
2595
+ });
2596
+ });
2597
+ returnObject[JSON.stringify(indexer)] += value;
2598
+ groupNObject[JSON.stringify(indexer)] += 1;
2599
+ });
2600
+ let sumsq = 0;
2601
+ Object.keys(returnObject).forEach((k) => {
2602
+ sumsq += Math.pow(returnObject[k], 2) / groupNObject[k];
2603
+ });
2604
+ return sumsq;
2605
+ }
2505
2606
  function Rang(data) {
2506
2607
  let dataNumbers = data.map((d) => {
2507
2608
  return Number(d);
@@ -3622,7 +3723,125 @@ var ANOVA = {
3622
3723
  chartSet.width += 1e3;
3623
3724
  chartSet.axis.y.tickOnly = true;
3624
3725
  let graph = CreateSplitGraph(individualCharts, `Main Effects Plot of ${Object.keys(response)[0]}`, chartSet);
3726
+ console.log(graph);
3625
3727
  return graph;
3728
+ },
3729
+ Table(factors, response) {
3730
+ let anovaTable = {};
3731
+ let factorKeys = Object.keys(factors);
3732
+ let responseKey = Object.keys(response)[0];
3733
+ let Ntotal = response[responseKey].length;
3734
+ let DFE = 1;
3735
+ let correctionFactor = Math.pow(Sum(response[responseKey]), 2) / Ntotal;
3736
+ factorKeys.forEach((f) => {
3737
+ let fSet = new Set(factors[f]);
3738
+ let Nf = fSet.size;
3739
+ let SS_f = 0;
3740
+ fSet.forEach((level) => {
3741
+ let levelTotal = 0;
3742
+ let levelN = 0;
3743
+ factors[f].forEach((v, j) => {
3744
+ if (v === level) {
3745
+ levelTotal += response[responseKey][j];
3746
+ levelN += 1;
3747
+ }
3748
+ });
3749
+ SS_f += Math.pow(levelTotal, 2) / levelN;
3750
+ });
3751
+ SS_f = SS_f - correctionFactor;
3752
+ anovaTable[f] = {
3753
+ DF: Nf - 1,
3754
+ SS: SS_f,
3755
+ MS: SS_f / (Nf - 1),
3756
+ F: void 0,
3757
+ p: void 0
3758
+ };
3759
+ DFE = DFE * Nf;
3760
+ });
3761
+ DFE = Ntotal - DFE;
3762
+ for (let i = 0; i < factorKeys.length - 1; i++) {
3763
+ let f_i_Set = new Set(factors[factorKeys[i]]);
3764
+ for (let j = i + 1; j < factorKeys.length; j++) {
3765
+ let f_j_Set = new Set(factors[factorKeys[j]]);
3766
+ let SS_subtotal = 0;
3767
+ f_i_Set.forEach((fi) => {
3768
+ f_j_Set.forEach((fj) => {
3769
+ let groupSum = 0;
3770
+ let groupN = 0;
3771
+ response[responseKey].forEach((val, index) => {
3772
+ if (factors[factorKeys[i]][index] === fi && factors[factorKeys[j]][index] === fj) {
3773
+ groupSum += val;
3774
+ groupN += 1;
3775
+ }
3776
+ });
3777
+ SS_subtotal += Math.pow(groupSum, 2) / groupN;
3778
+ });
3779
+ });
3780
+ SS_subtotal = SS_subtotal - correctionFactor;
3781
+ let iRow = anovaTable[factorKeys[i]];
3782
+ let jRow = anovaTable[factorKeys[j]];
3783
+ let fi_fj_DF = iRow.DF * jRow.DF;
3784
+ let fi_fj_SS = SS_subtotal - iRow.SS - jRow.SS;
3785
+ anovaTable[`${factorKeys[i]}*${factorKeys[j]}`] = { DF: fi_fj_DF, SS: fi_fj_SS, MS: fi_fj_SS / fi_fj_DF, F: void 0, p: void 0 };
3786
+ }
3787
+ }
3788
+ let interactionSS_subtotal = SumSquareByGroups(factors, response) - correctionFactor;
3789
+ let fullInteractionDF = 1;
3790
+ let SSE = 0;
3791
+ factorKeys.forEach((source) => {
3792
+ fullInteractionDF = fullInteractionDF * anovaTable[source].DF;
3793
+ });
3794
+ Object.keys(anovaTable).forEach((source) => {
3795
+ interactionSS_subtotal = interactionSS_subtotal - anovaTable[source].SS;
3796
+ SSE += anovaTable[source].SS;
3797
+ });
3798
+ let fullInteractionName = factorKeys.join("*");
3799
+ anovaTable[fullInteractionName] = { DF: fullInteractionDF, SS: interactionSS_subtotal, MS: interactionSS_subtotal / fullInteractionDF, F: void 0, p: void 0 };
3800
+ SSE += interactionSS_subtotal;
3801
+ let SStotal = SumSquaredDeviation(response[responseKey], 0) - correctionFactor;
3802
+ SSE = SStotal - SSE;
3803
+ let MSE = SSE / DFE;
3804
+ Object.keys(anovaTable).forEach((source) => {
3805
+ let sourceF = anovaTable[source].MS / MSE;
3806
+ anovaTable[source].F = sourceF;
3807
+ anovaTable[source].p = Distributions.F.RightTail(sourceF, anovaTable[source].DF, DFE);
3808
+ });
3809
+ anovaTable["Error"] = { DF: DFE, SS: SSE, MS: MSE };
3810
+ anovaTable["Total"] = { DF: Ntotal - 1, SS: SStotal };
3811
+ return anovaTable;
3812
+ },
3813
+ GLM(factors, response) {
3814
+ let factorKeys = Object.keys(factors);
3815
+ let anovaTable = {};
3816
+ let responseKey = Object.keys(response)[0];
3817
+ let Ntotal = response[responseKey].length;
3818
+ let DFE = 1;
3819
+ let responseData = response[responseKey];
3820
+ factorKeys.forEach((k) => {
3821
+ let SS = 0;
3822
+ let levels = new Set(factors[k]);
3823
+ let groupedData = GroupData(factors[k], responseData);
3824
+ let descriptiveStats = {};
3825
+ let mean_0;
3826
+ Object.keys(groupedData).forEach((k2, k_i) => {
3827
+ let mean = Mean(groupedData[k2]);
3828
+ descriptiveStats[k2].mean = mean;
3829
+ descriptiveStats[k2].std = StDev.S(groupedData[k2]);
3830
+ descriptiveStats[k2].N = groupedData[k2].length;
3831
+ if (k_i === 0) {
3832
+ mean_0 = mean;
3833
+ groupedData[k2].forEach((d) => {
3834
+ SS += mean;
3835
+ });
3836
+ } else {
3837
+ groupedData[k2].forEach((d) => {
3838
+ SS += mean - Math.pow(mean - d, 2);
3839
+ });
3840
+ }
3841
+ });
3842
+ console.log(k, SS);
3843
+ });
3844
+ return anovaTable;
3626
3845
  }
3627
3846
  }
3628
3847
  };
@@ -3650,6 +3869,21 @@ var Probability = {
3650
3869
  }
3651
3870
  }
3652
3871
  };
3872
+ function GroupData(groupingArray, responseArray) {
3873
+ if (groupingArray.length != responseArray.length) {
3874
+ return { forEachGroup() {
3875
+ } };
3876
+ }
3877
+ let returnObj = {};
3878
+ let levels = new Set(groupingArray);
3879
+ levels.forEach((l) => {
3880
+ returnObj[l] = [];
3881
+ });
3882
+ for (let i = 0; i < groupingArray.length; i++) {
3883
+ returnObj[groupingArray[i]].push(responseArray[i]);
3884
+ }
3885
+ return returnObj;
3886
+ }
3653
3887
  function CreateCanvas(width, height) {
3654
3888
  let canvas = document.createElement("canvas");
3655
3889
  canvas.height = height;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "qesuite",
3
- "version": "1.0.51",
3
+ "version": "1.0.52",
4
4
  "description": "Performs advanced statistical analysis of data. Specifically designed for engineering statistical analysis",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -0,0 +1 @@
1
+ - Rebuild of v1.0.51 see for details