@@ -203,7 +203,7 @@ def __init__(self):
203203 self .scene_min_x = self .scene_max_x = self .scene_width = 0
204204 self .label_width = 0
205205
206- self .attrs = VariableListModel ( )
206+ self .attrs = DomainModel ( separators = False )
207207 view = gui .listView (
208208 self .controlArea , self , "attribute" , box = "Variable" ,
209209 model = self .attrs , callback = self .attr_changed )
@@ -212,18 +212,16 @@ def __init__(self):
212212 # set the minimal height (see the penultimate paragraph of
213213 # http://doc.qt.io/qt-4.8/qabstractscrollarea.html#addScrollBarWidget)
214214 view .setSizePolicy (QSizePolicy .Expanding , QSizePolicy .Ignored )
215- gui .separator (view .box , 6 , 6 )
215+ self .group_vars = VariableListModel (placeholder = "None" )
216+ self .group_view = view = gui .listView (
217+ self .controlArea , self , "group_var" , box = "Subgroups" ,
218+ model = self .group_vars , callback = self .grouping_changed )
219+ gui .separator (self .group_view .box , 6 , 6 )
216220 self .cb_order = gui .checkBox (
217221 view .box , self , "order_by_importance" ,
218222 "Order by relevance" ,
219223 tooltip = "Order by 𝜒² or ANOVA over the subgroups" ,
220224 callback = self .apply_sorting )
221- self .group_vars = DomainModel (
222- placeholder = "None" , separators = False ,
223- valid_types = Orange .data .DiscreteVariable )
224- self .group_view = view = gui .listView (
225- self .controlArea , self , "group_var" , box = "Subgroups" ,
226- model = self .group_vars , callback = self .grouping_changed )
227225 view .setEnabled (False )
228226 view .setMinimumSize (QSize (30 , 30 ))
229227 # See the comment above
@@ -289,11 +287,11 @@ def eventFilter(self, obj, event):
289287
290288 return super ().eventFilter (obj , event )
291289
292- def reset_attrs (self , domain ):
293- self .attrs [:] = [
290+ def reset_groups (self , domain ):
291+ self .group_vars [:] = [
294292 var for var in chain (
295293 domain .class_vars , domain .metas , domain .attributes )
296- if var .is_primitive () ]
294+ if var .is_discrete ]
297295
298296 # noinspection PyTypeChecker
299297 @Inputs .data
@@ -309,9 +307,9 @@ def set_data(self, dataset):
309307 self .attribute = None
310308 if dataset :
311309 domain = dataset .domain
312- self .group_vars .set_domain (domain )
310+ self .attrs .set_domain (domain )
311+ self .reset_groups (domain )
313312 self .group_view .setEnabled (len (self .group_vars ) > 1 )
314- self .reset_attrs (domain )
315313 self .select_default_variables (domain )
316314 self .openContext (self .dataset )
317315 self .grouping_changed ()
@@ -332,37 +330,34 @@ def select_default_variables(self, domain):
332330 self .group_var = None # Reset to trigger selection via callback
333331
334332 def apply_sorting (self ):
335- def compute_score (attr ):
336- if attr is group_var :
333+ def compute_anova (group ):
334+ group_col = data .get_column_view (group )[0 ].astype (float )
335+ groups = (attr_col [group_col == i ]
336+ for i in range (len (group .values )))
337+ groups = (col [~ np .isnan (col )] for col in groups )
338+ groups = [group for group in groups if len (group )]
339+ p = f_oneway (* groups )[1 ] if len (groups ) > 1 else 2
340+ return 2 if math .isnan (p ) else p
341+
342+ def compute_chi (group ):
343+ if group is attr :
337344 return 3
338- if attr .is_continuous :
339- # One-way ANOVA
340- col = data .get_column_view (attr )[0 ].astype (float )
341- groups = (col [group_col == i ] for i in range (n_groups ))
342- groups = (col [~ np .isnan (col )] for col in groups )
343- groups = [group for group in groups if len (group )]
344- p = f_oneway (* groups )[1 ] if len (groups ) > 1 else 2
345- else :
346- p = self ._chi_square (group_var , attr )[1 ]
347- if math .isnan (p ):
348- return 2
349- return p
345+ p = self ._chi_square (group , attr )[1 ]
346+ return 2 if math .isnan (p ) else p
350347
351348 data = self .dataset
352349 if data is None :
353350 return
354351 domain = data .domain
355- attribute = self .attribute
356- group_var = self .group_var
357- if self .order_by_importance and group_var is not None :
358- n_groups = len (group_var .values )
359- group_col = data .get_column_view (group_var )[0 ] if \
360- domain .has_continuous_attributes (
361- include_class = True , include_metas = True ) else None
362- self .attrs .sort (key = compute_score )
352+ attr = self .attribute
353+ if self .order_by_importance :
354+ if attr .is_continuous :
355+ attr_col = data .get_column_view (attr )[0 ]
356+ self .group_vars .sort (key = compute_anova )
357+ else :
358+ self .group_vars .sort (key = compute_chi )
363359 else :
364- self .reset_attrs (domain )
365- self .attribute = attribute
360+ self .reset_groups (domain )
366361
367362 def _chi_square (self , group_var , attr ):
368363 # Chi-square with the given distribution into groups
@@ -379,15 +374,14 @@ def _chi_square(self, group_var, attr):
379374 def reset_all_data (self ):
380375 self .clear_scene ()
381376 self .stat_test = ""
382- self .attrs .clear ( )
383- self .group_vars .set_domain ( None )
377+ self .attrs .set_domain ( None )
378+ self .group_vars .clear ( )
384379 self .group_view .setEnabled (False )
385380 self .is_continuous = False
386381 self .update_display_box ()
387382
388383 def grouping_changed (self ):
389384 self .cb_order .setEnabled (self .group_var is not None )
390- self .apply_sorting ()
391385 self .attr_changed ()
392386
393387 def select_box_items (self ):
@@ -399,6 +393,7 @@ def select_box_items(self):
399393
400394 def attr_changed (self ):
401395 self .compute_box_data ()
396+ self .apply_sorting ()
402397 self .update_display_box ()
403398 self .layout_changed ()
404399
0 commit comments