Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit456b54a

Browse files
authored
Merge pull request#7150 from gmolledaj/master
Add Cochran rule indicator to Sieve + tests
2 parents44e6628 +12d27df commit456b54a

File tree

3 files changed

+81
-11
lines changed

3 files changed

+81
-11
lines changed

‎Orange/widgets/visualize/owsieve.py‎

Lines changed: 34 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
fromAnyQt.QtGuiimportQColor,QPen,QBrush
99
fromAnyQt.QtWidgetsimportQGraphicsScene,QGraphicsLineItem,QSizePolicy
1010

11-
fromOrange.dataimportTable,filter,Variable
11+
fromOrange.dataimportTable,filterasdata_filter,Variable
1212
fromOrange.data.sql.tableimportSqlTable,LARGE_TABLE,DEFAULT_SAMPLE_TIME
1313
fromOrange.preprocessimportDiscretize
1414
fromOrange.preprocess.discretizeimportEqualFreq
@@ -24,7 +24,8 @@
2424
VizRankMixin
2525
fromOrange.widgets.visualize.utilsimport (
2626
CanvasText,CanvasRectangle,ViewWithPress)
27-
fromOrange.widgets.widgetimportOWWidget,AttributeList,Input,Output
27+
fromOrange.widgets.widgetimportOWWidget,AttributeList,Input,Output, \
28+
Msg
2829

2930

3031
classChiSqStats:
@@ -54,7 +55,6 @@ def __init__(self, data, attr1, attr2):
5455
self.p=chi2.sf(
5556
self.chisq, (len(self.probs_x)-1)* (len(self.probs_y)-1))
5657

57-
5858
classSieveRank(VizRankDialogAttrPair):
5959
sort_names_in_row=True
6060

@@ -84,6 +84,9 @@ class Outputs:
8484

8585
graph_name="canvas"# QGraphicsScene
8686

87+
classWarning(OWWidget.Warning):
88+
cochran=Msg("Data does not meet the Cochran's rule\n{}")
89+
8790
want_control_area=False
8891

8992
settings_version=1
@@ -270,7 +273,7 @@ def resolve_shown_attributes(self):
270273
"Features from the input signal are not present in the data")
271274
return
272275
old_attrs=self.attr_x,self.attr_y
273-
self.attr_x,self.attr_y=[fforfin(features*2)[:2]]
276+
self.attr_x,self.attr_y= (features*2)[:2]
274277
self.attr_box.setEnabled(False)
275278
if (self.attr_x,self.attr_y)!=old_attrs:
276279
self.selection=set()
@@ -313,9 +316,9 @@ def update_selection(self):
313316
width=4
314317
val_x,val_y=area.value_pair
315318
filts.append(
316-
filter.Values([
317-
filter.FilterDiscrete(self.attr_x.name, [val_x]),
318-
filter.FilterDiscrete(self.attr_y.name, [val_y])
319+
data_filter.Values([
320+
data_filter.FilterDiscrete(self.attr_x.name, [val_x]),
321+
data_filter.FilterDiscrete(self.attr_y.name, [val_y])
319322
]))
320323
else:
321324
width=1
@@ -325,7 +328,7 @@ def update_selection(self):
325328
iflen(filts)==1:
326329
filts=filts[0]
327330
else:
328-
filts=filter.Values(filts,conjunction=False)
331+
filts=data_filter.Values(filts,conjunction=False)
329332
selection=filts(self.discrete_data)
330333
idset=set(selection.ids)
331334
sel_idx= [ifori,idinenumerate(self.data.ids)ifidinidset]
@@ -439,7 +442,7 @@ def _oper(attr, txt):
439442

440443
returnf"{xt}<br/>{yt}<hr/>{ct}"
441444

442-
445+
self.Warning.cochran.clear()
443446
foriteminself.canvas.items():
444447
self.canvas.removeItem(item)
445448
ifself.dataisNoneorlen(self.data)==0or \
@@ -516,6 +519,28 @@ def _oper(attr, txt):
516519
0,bottom)
517520
# Assume similar height for both lines
518521
text("N = "+fmt(chi.n),0,bottom-xl.boundingRect().height())
522+
msg=self._check_cochran(chi)
523+
ifmsgisnotNone:
524+
self.Warning.cochran(msg)
525+
526+
@staticmethod
527+
def_check_cochran(chi):
528+
"""
529+
Check Cochran's rule.
530+
Return None if it is met, otherwise a string describing the problem.
531+
"""
532+
expected=np.asarray(chi.expected,dtype=float)
533+
cells=expected.size
534+
ifcells==0:
535+
return"no cells in contingency table"
536+
eps=1e-12
537+
num_lt1= (expected<1.0-eps).sum()
538+
num_lt5= (expected<5.0-eps).sum()
539+
ifnum_lt1>0:
540+
return"some expected frequencies are below 1"
541+
ifnum_lt5>0.2*cells:
542+
return"more than 20% of expected frequencies are below 5"
543+
returnNone
519544

520545
defget_widget_name_extension(self):
521546
ifself.dataisnotNone:

‎Orange/widgets/visualize/tests/test_owsieve.py‎

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,33 @@ def test_chisquare(self):
110110
chi=ChiSqStats(table,0,1)
111111
self.assertFalse(isnan(chi.chisq))
112112

113+
deftest_cochran_messages(self):
114+
a=DiscreteVariable("A",values=("a1","a2","a3"))
115+
b=DiscreteVariable("B",values=("b1","b2","b3"))
116+
117+
# PASS: all expected frequencies >= 5 (20/20/20 × 20/20/20)
118+
rows_ok= ["a1"]*20+ ["a2"]*20+ ["a3"]*20
119+
cols_ok= ["b1"]*20+ ["b2"]*20+ ["b3"]*20
120+
table_ok=Table.from_list(Domain([a,b]),list(zip(rows_ok,cols_ok)))
121+
self.send_signal(self.widget.Inputs.data,table_ok)
122+
self.widget.attr_x,self.widget.attr_y=a,b
123+
self.widget.update_graph()
124+
self.assertFalse(self.widget.Warning.cochran.is_shown())
125+
126+
# FAIL: some expected frequencies < 5 (10/20/30 × 20/20/20)
127+
rows_bad= ["a1"]*10+ ["a2"]*20+ ["a3"]*30
128+
cols_bad= ["b1"]*20+ ["b2"]*20+ ["b3"]*20
129+
table_bad=Table.from_list(Domain([a,b]),list(zip(rows_bad,cols_bad)))
130+
self.send_signal(self.widget.Inputs.data,table_bad)
131+
self.widget.attr_x,self.widget.attr_y=a,b
132+
self.widget.update_graph()
133+
self.assertTrue(self.widget.Warning.cochran.is_shown())
134+
msg_text=str(self.widget.Warning.cochran)
135+
self.assertIn("expected",msg_text.lower())
136+
137+
self.send_signal(self.widget.Inputs.data,None)
138+
self.assertFalse(self.widget.Warning.cochran.is_shown())
139+
113140
deftest_metadata(self):
114141
"""
115142
Widget should interpret meta data which are continuous or discrete in
@@ -168,10 +195,22 @@ def test_vizrank_receives_manual_change(self, auto_select):
168195
deftest_input_features(self):
169196
self.assertTrue(self.widget.attr_box.isEnabled())
170197
self.send_signal(self.widget.Inputs.data,self.iris)
171-
self.send_signal(self.widget.Inputs.features,
172-
AttributeList(self.iris.domain.attributes))
198+
199+
# Force a known initial state different from the incoming features
200+
a0,a1,a2,a3=self.iris.domain.attributes
201+
self.widget.attr_x,self.widget.attr_y=a2,a3
202+
203+
# Send features -> triggers set_input_features -> resolve_shown_attributes
204+
feats=AttributeList([a0,a1])
205+
self.send_signal(self.widget.Inputs.features,feats)
206+
207+
# Attributes should now follow the provided features
208+
self.assertEqual((self.widget.attr_x,self.widget.attr_y), (a0,a1))
209+
173210
self.assertFalse(self.widget.attr_box.isEnabled())
174211
self.assertFalse(self.widget.vizrank_button().isEnabled())
212+
213+
# Remove features -> widget returns to interactive mode
175214
self.send_signal(self.widget.Inputs.features,None)
176215
self.assertTrue(self.widget.attr_box.isEnabled())
177216
self.assertTrue(self.widget.vizrank_button().isEnabled())

‎i18n/si/msgs.jaml‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15003,6 +15003,8 @@ widgets/visualize/owsieve.py:
1500315003
class `Outputs`:
1500415004
Selected Data: Izbrani podatki
1500515005
canvas: false
15006+
class `Warning`:
15007+
Data does not meet the Cochran's rule\n{}: Podatki ne ustrezajo Cochranovemu pravilu\n{}
1500615008
def `__init__`:
1500715009
attr_x: false
1500815010
\u2717: true
@@ -15041,6 +15043,10 @@ widgets/visualize/owsieve.py:
1504115043
Feature {} has no values: Spremenljivka {} nima znanih vrednosti.
1504215044
χ²={:.2f}, p={:.3f}: true
1504315045
'N = ': true
15046+
def `_check_cochran`:
15047+
no cells in contingency table: kontingenčna tabela nima celic
15048+
some expected frequencies are below 1: nekatere pričakovane pogostosti so manjše od 1
15049+
more than 20% of expected frequencies are below 5: več kot 20 % pričakovanih pogostosti je manjših od 5
1504415050
def `get_widget_name_extension`:
1504515051
{} vs {}: {} in {}
1504615052
__main__: false

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp