11import { DataSource } from "../commonTypes" ;
2-
3- export function chiSquared ( matrix : number [ ] [ ] = [ [ ] ] ) : number {
4- let rowSums = matrix . map ( m => 0 ) ;
5- let colSums = matrix [ 0 ] . map ( m => 0 ) ;
2+ type nestTree = Map < string , Map < string , number > > ;
3+ export function chiSquared ( nestTree : nestTree , xSet : Set < string > , ySet : Set < string > ) : number {
4+ if ( typeof nestTree === 'undefined' || typeof xSet === 'undefined' || typeof ySet === 'undefined' ) {
5+ return 0 ;
6+ }
7+ let rowSums = new Map < string , number > ( ) ;
8+ let colSums = new Map < string , number > ( ) ;
69 let totalSum = 0 ;
7- for ( let i = 0 ; i < matrix . length ; i ++ ) {
8- for ( let j = 0 ; j < matrix [ i ] . length ; j ++ ) {
9- rowSums [ i ] += matrix [ i ] [ j ] ;
10- colSums [ j ] += matrix [ i ] [ j ] ;
11- totalSum += matrix [ i ] [ j ] ;
10+ for ( let x of xSet ) {
11+ rowSums . set ( x , 0 ) ;
12+ }
13+ for ( let y of ySet ) {
14+ colSums . set ( y , 0 ) ;
15+ }
16+ for ( let [ x , node ] of nestTree ) {
17+ for ( let [ y , counter ] of node ) {
18+ rowSums . set ( x , rowSums . get ( x ) + counter ) ;
19+ colSums . set ( y , colSums . get ( y ) + counter ) ;
20+ totalSum += counter ;
1221 }
1322 }
23+
1424 let chis = 0 ;
15- for ( let i = 0 ; i < matrix . length ; i ++ ) {
16- for ( let j = 0 ; j < matrix [ i ] . length ; j ++ ) {
17- let observed = matrix [ i ] [ j ] ;
18- let expected = rowSums [ i ] * colSums [ j ] / totalSum ;
25+ for ( let [ x , node ] of nestTree ) {
26+ for ( let [ y , observed ] of node ) {
27+ let expected = rowSums . get ( x ) * colSums . get ( y ) / totalSum ;
1928 chis += ( observed - expected ) ** 2 / expected ;
2029 }
2130 }
2231 return chis ;
2332}
2433
25- export function crammersV ( dataSource : DataSource , fieldX : string , fieldY : string ) {
26- const xSet = new Set ( dataSource . map ( d => d [ fieldX ] ) )
27- const ySet = new Set ( dataSource . map ( d => d [ fieldY ] ) )
28- const xMembers = [ ...xSet ] ;
29- const yMembers = [ ...ySet ] ;
30- let xDict = { } ;
31- let yDict = { } ;
32- for ( let i = 0 ; i < xMembers . length ; i ++ ) {
33- xDict [ xMembers [ i ] ] = i ;
34- }
35- for ( let i = 0 ; i < yMembers . length ; i ++ ) {
36- yDict [ yMembers [ i ] ] = i ;
37- }
38- let matrix : number [ ] [ ] = xMembers . map ( x => yMembers . map ( y => 0 ) ) ;
39- for ( let record of dataSource ) {
40- matrix [ xDict [ record [ fieldX ] ] ] [ yDict [ record [ fieldY ] ] ] ++ ;
34+
35+ export function crammersV ( dataSource : DataSource , fieldX : string , fieldY : string ) : number {
36+ const xSet = new Set < string > ( )
37+ const ySet = new Set < string > ( )
38+ const nestTree = new Map < string , Map < string , number > > ( ) ;
39+ let len = dataSource . length ;
40+ for ( let i = 0 ; i < len ; i ++ ) {
41+ let record = dataSource [ i ] ;
42+ xSet . add ( record [ fieldX ] )
43+ ySet . add ( record [ fieldY ] ) ;
44+ if ( ! nestTree . has ( record [ fieldX ] ) ) {
45+ nestTree . set ( record [ fieldX ] , new Map ( ) ) ;
46+ }
47+ let node = nestTree . get ( record [ fieldX ] ) ;
48+ if ( ! node . has ( record [ fieldY ] ) ) {
49+ node . set ( record [ fieldY ] , 0 ) ;
50+ }
51+ node . set ( record [ fieldY ] , node . get ( record [ fieldY ] ) + 1 ) ;
4152 }
42- const chis = chiSquared ( matrix ) ;
43- const V = Math . sqrt ( chis / ( dataSource . length * Math . min ( xMembers . length - 1 , yMembers . length - 1 ) ) )
53+ const chis = chiSquared ( nestTree , xSet , ySet ) ;
54+ const V = Math . sqrt ( chis / ( dataSource . length * Math . min ( xSet . size - 1 , ySet . size - 1 ) ) )
4455 return V ;
45- }
56+ }
57+
58+
59+ // can be used for test
60+ // export function crammersV(dataSource: DataSource, fieldX: string, fieldY: string): number {
61+ // const xSet = new Set(dataSource.map(d => d[fieldX]))
62+ // const ySet = new Set(dataSource.map(d => d[fieldY]))
63+ // const xMembers = [...xSet];
64+ // const yMembers = [...ySet];
65+ // let xDict = {};
66+ // let yDict = {};
67+ // for (let i = 0; i < xMembers.length; i++) {
68+ // xDict[xMembers[i]] = i;
69+ // }
70+ // for (let i = 0; i < yMembers.length; i++) {
71+ // yDict[yMembers[i]] = i;
72+ // }
73+ // // let matrix: number[][] = xMembers.map(x => yMembers.map(y => 0));
74+ // let matrix: number[][] = [];
75+ // for (let i = 0; i < xMembers.length; i++) {
76+ // matrix.push([]);
77+ // for (let j = 0; j < yMembers.length; j++) {
78+ // matrix[i].push(0);
79+ // }
80+ // }
81+ // for (let record of dataSource) {
82+ // matrix[xDict[record[fieldX]]][yDict[record[fieldY]]]++;
83+ // }
84+ // const chis = chiSquared(matrix);
85+ // const V = Math.sqrt(chis / (dataSource.length * Math.min(xMembers.length - 1, yMembers.length - 1)))
86+ // return V;
87+ // }
88+
89+ // export function chiSquared(matrix: number[][] = [[]]): number {
90+ // let rowSums = matrix.map(m => 0);
91+ // let colSums = matrix[0].map(m => 0);
92+ // let totalSum = 0;
93+ // for (let i = 0; i < matrix.length; i++) {
94+ // for (let j = 0; j < matrix[i].length; j++) {
95+ // rowSums[i] += matrix[i][j];
96+ // colSums[j] += matrix[i][j];
97+ // totalSum += matrix[i][j];
98+ // }
99+ // }
100+ // let chis = 0;
101+ // for (let i = 0; i < matrix.length; i++) {
102+ // for (let j = 0; j < matrix[i].length; j++) {
103+ // let observed = matrix[i][j];
104+ // let expected = rowSums[i] * colSums[j] / totalSum;
105+ // chis += (observed - expected) ** 2 / expected;
106+ // }
107+ // }
108+ // return chis;
109+ // }
0 commit comments