1
1
/**
2
2
* STatistical INformation Grid-based method
3
- * @deprecated Not implemented
4
3
*/
5
4
export default class STING {
6
5
// https://en.wikipedia.org/wiki/Cluster_analysis
7
6
// "STING : A Statistical Information Grid Approach to Spatial Data Mining"
8
- constructor ( ) {
7
+ /**
8
+ * @param {number } c specified density
9
+ */
10
+ constructor ( c ) {
11
+ this . _c = c
9
12
this . _cells = null
13
+ this . _t = 0.05
10
14
}
11
15
12
16
/**
@@ -24,14 +28,14 @@ export default class STING {
24
28
ranges : ranges ,
25
29
children : [ ] ,
26
30
}
27
- let stack = [ this . _cells ]
31
+ let layer = [ this . _cells ]
28
32
const spl_size = 2 ** dim
29
- const average_number = 20
33
+ const average_number = 5
30
34
const max_depth = Math . log ( n / average_number ) / Math . log ( spl_size )
31
- const cells = [ stack ]
35
+ const cells = [ layer ]
32
36
for ( let a = 0 ; a < max_depth ; a ++ ) {
33
37
const new_stack = [ ]
34
- for ( const c of stack ) {
38
+ for ( const c of layer ) {
35
39
const rng = c . ranges
36
40
for ( let i = 0 ; i < spl_size ; i ++ ) {
37
41
let p = i
@@ -53,53 +57,141 @@ export default class STING {
53
57
c . children . push ( t )
54
58
}
55
59
}
56
- stack = new_stack
57
- cells . push ( stack )
60
+ layer = new_stack
61
+ cells . push ( layer )
62
+ }
63
+
64
+ let bottomSpace = 1
65
+ for ( let d = 0 ; d < dim ; d ++ ) {
66
+ const range = layer [ 0 ] . ranges [ d ]
67
+ bottomSpace *= range [ 1 ] - range [ 0 ]
58
68
}
59
- for ( let i = 0 ; i < stack . length ; i ++ ) {
60
- const c = stack [ i ]
69
+ for ( let i = 0 ; i < layer . length ; i ++ ) {
70
+ const c = layer [ i ]
61
71
const d = x . filter ( v => {
62
72
return c . ranges . every ( ( r , i ) => r [ 0 ] <= v [ i ] && ( r [ 1 ] === maxs [ i ] ? v [ i ] <= r [ 1 ] : v [ i ] < r [ 1 ] ) )
63
73
} )
64
- const n = ( c . n = d . length )
65
- const m = Array ( dim ) . fill ( 0 )
66
- const min = ( c . min = Array ( dim ) . fill ( Infinity ) )
67
- const max = ( c . max = Array ( dim ) . fill ( - Infinity ) )
68
- for ( let j = 0 ; j < n ; j ++ ) {
74
+ c . n = d . length
75
+ c . min = Array ( dim ) . fill ( Infinity )
76
+ c . max = Array ( dim ) . fill ( - Infinity )
77
+ const sum = Array ( dim ) . fill ( 0 )
78
+ for ( let j = 0 ; j < c . n ; j ++ ) {
69
79
for ( let k = 0 ; k < dim ; k ++ ) {
70
- m [ k ] += d [ j ] [ k ]
71
- min [ k ] = Math . min ( min [ k ] , d [ j ] [ k ] )
72
- max [ k ] = Math . max ( max [ k ] , d [ j ] [ k ] )
80
+ sum [ k ] += d [ j ] [ k ]
81
+ c . min [ k ] = Math . min ( c . min [ k ] , d [ j ] [ k ] )
82
+ c . max [ k ] = Math . max ( c . max [ k ] , d [ j ] [ k ] )
73
83
}
74
84
}
75
- c . m = m . map ( v => ( n > 0 ? v / n : 0 ) )
85
+ c . m = sum . map ( v => ( c . n > 0 ? v / c . n : 0 ) )
76
86
const s = Array ( dim ) . fill ( 0 )
77
- for ( let j = 0 ; j < n ; j ++ ) {
87
+ for ( let j = 0 ; j < c . n ; j ++ ) {
78
88
for ( let k = 0 ; k < dim ; k ++ ) {
79
- s [ k ] += ( d [ j ] [ k ] - m [ k ] ) ** 2
89
+ s [ k ] += ( d [ j ] [ k ] - c . m [ k ] ) ** 2
80
90
}
81
91
}
82
- c . s = s . map ( v => ( n > 0 ? Math . sqrt ( v / n ) : 0 ) )
92
+ c . s = s . map ( v => ( c . n > 0 ? Math . sqrt ( v / c . n ) : 0 ) )
93
+ c . dist = Array ( dim ) . fill ( 'normal' )
94
+
95
+ c . area = bottomSpace
83
96
}
84
97
for ( let k = cells . length - 2 ; k >= 0 ; k -- ) {
85
98
for ( let i = 0 ; i < cells [ k ] . length ; i ++ ) {
86
- let n = 0
87
- const m = Array ( dim ) . fill ( 0 )
99
+ let nki = 0
100
+ let aki = 0
101
+ const sum = Array ( dim ) . fill ( 0 )
88
102
const min = ( cells [ k ] [ i ] . min = Array ( dim ) . fill ( Infinity ) )
89
103
const max = ( cells [ k ] [ i ] . max = Array ( dim ) . fill ( - Infinity ) )
90
104
const s = Array ( dim ) . fill ( 0 )
91
- for ( const ccell of cells [ k + 1 ] . slice ( i * spl_size , ( i + 1 ) * spl_size ) ) {
92
- n += ccell . n
105
+ const ccells = cells [ k + 1 ] . slice ( i * spl_size , ( i + 1 ) * spl_size )
106
+ for ( const ccell of ccells ) {
107
+ nki += ccell . n
108
+ aki += ccell . area
93
109
for ( let p = 0 ; p < dim ; p ++ ) {
94
- m [ p ] += ccell . m [ p ] * ccell . n
110
+ sum [ p ] += ccell . m [ p ] * ccell . n
95
111
min [ p ] = Math . min ( min [ p ] , ccell . min [ p ] )
96
112
max [ p ] = Math . max ( max [ p ] , ccell . max [ p ] )
97
113
s [ p ] += ( ccell . s [ p ] ** 2 + ccell . m [ p ] ** 2 ) * ccell . n
98
114
}
99
115
}
100
- cells [ k ] [ i ] . n = n
101
- cells [ k ] [ i ] . m = m . map ( v => ( n > 0 ? v / n : 0 ) )
102
- cells [ k ] [ i ] . s = s . map ( ( v , p ) => ( n > 0 ? Math . sqrt ( v / n - m [ p ] ** 2 ) : 0 ) )
116
+ cells [ k ] [ i ] . n = nki
117
+ cells [ k ] [ i ] . m = sum . map ( v => ( nki > 0 ? v / nki : 0 ) )
118
+ cells [ k ] [ i ] . s = s . map ( ( v , p ) => ( nki > 0 ? Math . sqrt ( v / nki - ( sum [ p ] / nki ) ** 2 ) : 0 ) )
119
+ const eps = 0.1
120
+ cells [ k ] [ i ] . dist = Array ( dim ) . fill ( 'normal' )
121
+ cells [ k ] [ i ] . area = aki
122
+ for ( let d = 0 ; d < dim ; d ++ ) {
123
+ let confl = 0
124
+ let dist = 'normal'
125
+ for ( const ccell of ccells ) {
126
+ let mdiff = 0
127
+ let sdiff = 0
128
+ if ( cells [ k ] [ i ] . m [ d ] !== 0 ) {
129
+ mdiff += Math . abs ( ( cells [ k ] [ i ] . m [ d ] - ccell . m [ d ] ) / cells [ k ] [ i ] . m [ d ] )
130
+ } else if ( ccell . m [ d ] !== 0 ) {
131
+ mdiff += Math . abs ( ( cells [ k ] [ i ] . m [ d ] - ccell . m [ d ] ) / ccell . m [ d ] )
132
+ }
133
+ if ( cells [ k ] [ i ] . s [ d ] !== 0 ) {
134
+ sdiff += Math . abs ( ( cells [ k ] [ i ] . s [ d ] - ccell . s [ d ] ) / cells [ k ] [ i ] . s [ d ] )
135
+ } else if ( ccell . s [ d ] !== 0 ) {
136
+ sdiff += Math . abs ( ( cells [ k ] [ i ] . s [ d ] - ccell . s [ d ] ) / ccell . s [ d ] )
137
+ }
138
+ if ( dist !== ccell . dist && mdiff < eps && sdiff < eps ) {
139
+ confl += ccell . n
140
+ } else if ( mdiff >= eps || sdiff >= eps ) {
141
+ confl = nki
142
+ }
143
+ }
144
+ if ( nki > 0 && confl / nki > this . _t ) {
145
+ dist = 'none'
146
+ }
147
+ cells [ k ] [ i ] . dist [ d ] = dist
148
+ }
149
+ }
150
+ }
151
+
152
+ let relevantCells = [ this . _cells ]
153
+ for ( let k = 1 ; k < cells . length ; k ++ ) {
154
+ const childRelevantCells = [ ]
155
+ for ( let i = 0 ; i < relevantCells . length ; i ++ ) {
156
+ for ( const child of relevantCells [ i ] . children ) {
157
+ if ( child . n < child . area * this . _c ) {
158
+ continue
159
+ }
160
+ childRelevantCells . push ( child )
161
+ }
162
+ }
163
+ relevantCells = childRelevantCells
164
+ }
165
+
166
+ this . _clusters = [ ]
167
+ const stack = [ ]
168
+ while ( true ) {
169
+ if ( stack . length === 0 ) {
170
+ if ( relevantCells . length === 0 ) {
171
+ break
172
+ }
173
+ stack . push ( relevantCells . pop ( ) )
174
+ this . _clusters . push ( [ ] )
175
+ }
176
+ const curcell = stack . pop ( )
177
+ this . _clusters [ this . _clusters . length - 1 ] . push ( curcell )
178
+
179
+ for ( let k = relevantCells . length - 1 ; k >= 0 ; k -- ) {
180
+ const c = relevantCells [ k ]
181
+ let adjointCnt = 0
182
+ for ( let d = 0 ; d < dim && adjointCnt < 2 ; d ++ ) {
183
+ if ( curcell . ranges [ d ] [ 0 ] === c . ranges [ d ] [ 0 ] && curcell . ranges [ d ] [ 1 ] === c . ranges [ d ] [ 1 ] ) {
184
+ continue
185
+ } else if ( curcell . ranges [ d ] [ 0 ] === c . ranges [ d ] [ 1 ] || curcell . ranges [ d ] [ 1 ] === c . ranges [ d ] [ 0 ] ) {
186
+ adjointCnt ++
187
+ } else {
188
+ adjointCnt = Infinity
189
+ }
190
+ }
191
+ if ( adjointCnt === 1 ) {
192
+ stack . push ( c )
193
+ relevantCells . splice ( k , 1 )
194
+ }
103
195
}
104
196
}
105
197
}
@@ -109,5 +201,19 @@ export default class STING {
109
201
* @param {Array<Array<number>> } datas Sample data
110
202
* @returns {number[] } Predicted values
111
203
*/
112
- predict ( datas ) { }
204
+ predict ( datas ) {
205
+ const p = [ ]
206
+ for ( let i = 0 ; i < datas . length ; i ++ ) {
207
+ p [ i ] = - 1
208
+ for ( let k = 0 ; k < this . _clusters . length && p [ i ] < 0 ; k ++ ) {
209
+ for ( const cell of this . _clusters [ k ] ) {
210
+ if ( datas [ i ] . every ( ( v , d ) => cell . ranges [ d ] [ 0 ] <= v && v <= cell . ranges [ d ] [ 1 ] ) ) {
211
+ p [ i ] = k
212
+ break
213
+ }
214
+ }
215
+ }
216
+ }
217
+ return p
218
+ }
113
219
}
0 commit comments