Ignore:
Timestamp:
03/18/11 14:53:13 (3 years ago)
Author:
markotoplak
Branch:
default
Convert:
5ddd67ca8e82c904ae3837cdc2e4cc8d9856626b
Message:

Imputation for 2.5.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • orange/Orange/feature/imputation.py

    r7611 r7764  
    8888    of some classifier. There are a few attributes that need to be set, though. 
    8989 
    90     .. attribute:: baseLearner  
     90    .. attribute:: base_learner  
    9191     
    9292    A wrapped learner. 
    9393 
    94     .. attribute:: imputerConstructor 
     94    .. attribute:: imputer_constructor 
    9595     
    9696    An instance of a class derived from :obj:`ImputerConstructor` (or a class 
    9797    with the same call operator). 
    9898 
    99     .. attribute:: dontImputeClassifier 
     99    .. attribute:: dont_impute_classifier 
    100100 
    101101    If given and set (this attribute is optional), the classifier will not be 
     
    107107 
    108108        def __call__(self, data, weight=0): 
    109             trained_imputer = self.imputerConstructor(data, weight) 
     109            trained_imputer = self.imputer_constructor(data, weight) 
    110110            imputed_data = trained_imputer(data, weight) 
    111             baseClassifier = self.baseLearner(imputed_data, weight) 
    112             if self.dontImputeClassifier: 
    113                 return baseClassifier 
     111            base_classifier = self.base_learner(imputed_data, weight) 
     112            if self.dont_impute_classifier: 
     113                return base_classifier 
    114114            else: 
    115                 return ImputeClassifier(baseClassifier, trained_imputer) 
     115                return ImputeClassifier(base_classifier, trained_imputer) 
    116116 
    117117    So "learning" goes like this. :obj:`ImputeLearner` will first construct 
    118     the imputer (that is, call :obj:`self.imputerConstructor` to get a (trained) 
     118    the imputer (that is, call :obj:`self.imputer_constructor` to get a (trained) 
    119119    imputer. Than it will use the imputer to impute the data, and call the 
    120120    given :obj:`baseLearner` to construct a classifier. For instance, 
    121121    :obj:`baseLearner` could be a learner for logistic regression and the 
    122122    result would be a logistic regression model. If the classifier can handle 
    123     unknown values (that is, if :obj:`dontImputeClassifier`, we return it as  
     123    unknown values (that is, if :obj:`dont_impute_classifier`, we return it as  
    124124    it is, otherwise we wrap it into :obj:`ImputeClassifier`, which is given 
    125125    the base classifier and the imputer which it can use to impute the missing 
     
    146146 
    147147        def __call__(self, ex, what=orange.GetValue): 
    148             return self.baseClassifier(self.imputer(ex), what) 
     148            return self.base_classifier(self.imputer(ex), what) 
    149149 
    150150    It imputes the missing values by calling the :obj:`imputer` and passes the 
     
    161161:obj:`Orange.feature.imputation.ImputeLearner` puts the keyword arguments into 
    162162the instance's  dictionary. You are expected to call it like 
    163 :obj:`ImputeLearner(baseLearner=<someLearner>, 
     163:obj:`ImputeLearner(base_learner=<someLearner>, 
    164164imputer=<someImputerConstructor>)`. When the learner is called with examples, it 
    165 trains the imputer, imputes the data, induces a :obj:`baseClassifier` by the 
    166 :obj:`baseLearner` and constructs :obj:`ImputeClassifier` that stores the 
    167 :obj:`baseClassifier` and the :obj:`imputer`. For classification, the missing 
     165trains the imputer, imputes the data, induces a :obj:`base_classifier` by the 
     166:obj:`base_cearner` and constructs :obj:`ImputeClassifier` that stores the 
     167:obj:`base_classifier` and the :obj:`imputer`. For classification, the missing 
    168168values are imputed and the classifier's prediction is returned. 
    169169 
     
    181181     
    182182        def __call__(self, data, weight=0): 
    183             trained_imputer = self.imputerConstructor(data, weight) 
     183            trained_imputer = self.imputer_constructor(data, weight) 
    184184            imputed_data = trained_imputer(data, weight) 
    185             baseClassifier = self.baseLearner(imputed_data, weight) 
    186             return ImputeClassifier(baseClassifier, trained_imputer) 
     185            base_classifier = self.base_learner(imputed_data, weight) 
     186            return ImputeClassifier(base_classifier, trained_imputer) 
    187187     
    188188    class ImputeClassifier(orange.Classifier): 
    189         def __init__(self, baseClassifier, imputer): 
    190             self.baseClassifier = baseClassifier 
     189        def __init__(self, base_classifier, imputer): 
     190            self.base_classifier = base_classifier 
    191191            self.imputer = imputer 
    192192     
    193193        def __call__(self, ex, what=orange.GetValue): 
    194             return self.baseClassifier(self.imputer(ex), what) 
     194            return self.base_classifier(self.imputer(ex), what) 
    195195 
    196196.. rubric:: Example 
     
    318318    :obj:`ImputerConstructor_Random`. 
    319319 
    320     .. attribute:: imputeClass 
    321      
    322     Tells whether to impute the class values or not. Defaults to :obj:`True`. 
     320    .. attribute:: impute_class 
     321     
     322    Tells whether to impute the class values or not. Defaults to True. 
    323323 
    324324    .. attribute:: deterministic 
    325325 
    326     If true (default is :obj:`False`), random generator is initialized for each 
     326    If true (default is False), random generator is initialized for each 
    327327    example using the example's hash value as a seed. This results in same 
    328328    examples being always imputed the same values. 
     
    340340    are used when needed. 
    341341 
    342     .. attribute:: learnerDiscrete, learnerContinuous 
     342    .. attribute:: learner_discrete, learner_continuous 
    343343     
    344344    Learner for discrete and for continuous attributes. If any of them is 
    345345    missing, the attributes of the corresponding type won't get imputed. 
    346346 
    347     .. attribute:: useClass 
     347    .. attribute:: use_class 
    348348     
    349349    Tells whether the imputer is allowed to use the class value. As this is 
    350     most often undesired, this option is by default set to :obj:`False`. It can 
     350    most often undesired, this option is by default set to False. It can 
    351351    however be useful for a more complex design in which we would use one 
    352352    imputer for learning examples (this one would use the class value) and 
     
    354354    is unavailable at that moment). 
    355355 
    356 ..class:: Imputer_model 
     356.. class:: Imputer_model 
    357357 
    358358    .. attribute: models 
     
    367367 
    368368The following imputer predicts the missing attribute values using 
    369 classification and regression trees with the minimum of 20 examples in a leaf. 
    370  
    371 <P class="header">part of <A href="imputation.py">imputation.py</A> (uses <a 
    372 href="bridges.tab">bridges.tab</a>)</P> <XMP class=code>import orngTree imputer 
    373 = orange.ImputerConstructor_model() imputer.learnerContinuous = 
    374 imputer.learnerDiscrete = orngTree.TreeLearner(minSubset = 20) imputer = 
    375 imputer(data) </XMP> 
    376  
    377 <P>We could even use the same learner for discrete and continuous attributes! 
    378 (The way this functions is rather tricky. If you desire to know: 
    379 <CODE>orngTree.TreeLearner</CODE> is a learning algorithm written in Python - 
    380 Orange doesn't mind, it will wrap it into a C++ wrapper for a Python-written 
    381 learners which then call-backs the Python code. When given the examples to 
    382 learn from, <CODE>orngTree.TreeLearner</CODE> checks the class type. If it's 
    383 continuous, it will set the <CODE>orange.TreeLearner</CODE> to construct 
    384 regression trees, and if it's discrete, it will set the components for 
    385 classification trees. The common parameters, such as the minimal number of 
    386 examples in leaves, are used in both cases.)</P> 
    387  
    388 <P>You can of course use different learning algorithms for discrete and 
     369classification and regression trees with the minimum of 20 examples in a leaf.  
     370Part of `imputation-complex.py`_ (uses `bridges.tab`_): 
     371 
     372.. literalinclude:: code/imputation-complex.py 
     373    :lines: 74-76 
     374 
     375We could even use the same learner for discrete and continuous attributes, 
     376as :class:`Orange.classification.tree.TreeLearner` checks the class type 
     377and constructs regression or classification trees accordingly. The  
     378common parameters, such as the minimal number of 
     379examples in leaves, are used in both cases. 
     380 
     381You can also use different learning algorithms for discrete and 
    389382continuous attributes. Probably a common setup will be to use 
    390 <CODE>BayesLearner</CODE> for discrete and <CODE>MajorityLearner</CODE> (which 
    391 just remembers the average) for continuous attributes, as follows.</P> 
    392  
    393 <P class="header">part of <A href="imputation.py">imputation.py</A> (uses <a 
    394 href="bridges.tab">bridges.tab</a>)</P> <XMP class=code>imputer = 
    395 orange.ImputerConstructor_model() imputer.learnerContinuous = 
    396 orange.MajorityLearner() imputer.learnerDiscrete = orange.BayesLearner() 
    397 imputer = imputer(data) </XMP> 
    398  
    399 <P>You can also construct an <CODE>Imputer_model</CODE> yourself. You will do this if different attributes need different treatment. Brace for an example that will be a bit more complex. First we shall construct an <CODE>Imputer_model</CODE> and initialize an empty list of models.</P> 
    400  
    401 <P class="header">part of <A href="imputation.py">imputation.py</A> (uses <a href="bridges.tab">bridges.tab</a>)</P> 
    402 <XMP class=code>imputer = orange.Imputer_model() 
    403 imputer.models = [None] * len(data.domain) 
    404 </XMP> 
    405  
    406 <P>Attributes "LANES" and "T-OR-D" will always be imputed values 2 and 
     383:class:`Orange.classification.bayes.BayesLearner` for discrete and  
     384:class:`Orange.regression.mean.MeanLearner` (which 
     385just remembers the average) for continuous attributes. Part of  
     386`imputation-complex.py`_ (uses `bridges.tab`_): 
     387 
     388.. literalinclude:: code/imputation-complex.py 
     389    :lines: 91-94 
     390 
     391You can also construct an :class:`Imputer_model` yourself. You will do  
     392this if different attributes need different treatment. Brace for an  
     393example that will be a bit more complex. First we shall construct an  
     394:class:`Imputer_model` and initialize an empty list of models.  
     395The following code snippets are from 
     396`imputation-complex.py`_ (uses `bridges.tab`_): 
     397 
     398.. literalinclude:: code/imputation-complex.py 
     399    :lines: 108-109 
     400 
     401Attributes "LANES" and "T-OR-D" will always be imputed values 2 and 
    407402"THROUGH". Since "LANES" is continuous, it suffices to construct a 
    408 <CODE>DefaultClassifier</CODE> with the default value 2.0 (don't forget the 
     403:obj:`DefaultClassifier` with the default value 2.0 (don't forget the 
    409404decimal part, or else Orange will think you talk about an index of a discrete 
    410405value - how could it tell?). For the discrete attribute "T-OR-D", we could 
    411 construct a <CODE>DefaultClassifier</CODE> and give the index of value 
     406construct a :class:`Orange.classification.ConstantClassifier` and give the index of value 
    412407"THROUGH" as an argument. But we shall do it nicer, by constructing a 
    413 <CODE>Value</CODE>. Both classifiers will be stored at the appropriate places 
    414 in <CODE>imputer.models</CODE>.</P> 
    415  
    416 <XMP class=code>imputer.models[data.domain.index("LANES")] = orange.DefaultClassifier(2.0) 
    417  
    418 tord = orange.DefaultClassifier(orange.Value(data.domain["T-OR-D"], "THROUGH")) 
    419 imputer.models[data.domain.index("T-OR-D")] = tord 
    420 </XMP> 
    421  
    422 <P>"LENGTH" will be computed with a regression tree induced from "MATERIAL", "SPAN" and "ERECTED" (together with "LENGTH" as the class attribute, of course). Note that we initialized the domain by simply giving a list with the names of the attributes, with the domain as an additional argument in which Orange will look for the named attributes.</P> 
    423  
    424 <XMP class=code>import orngTree 
    425 len_domain = orange.Domain(["MATERIAL", "SPAN", "ERECTED", "LENGTH"], data.domain) 
    426 len_data = orange.ExampleTable(len_domain, data) 
    427 len_tree = orngTree.TreeLearner(len_data, minSubset=20) 
    428 imputer.models[data.domain.index("LENGTH")] = len_tree 
    429 orngTree.printTxt(len_tree) 
    430 </XMP> 
    431  
    432 <P>We printed the tree just to see what it looks like.</P> 
    433  
    434 <XMP class=code>SPAN=SHORT: 1158 
    435 SPAN=LONG: 1907 
    436 SPAN=MEDIUM 
    437 |    ERECTED<1908.500: 1325 
    438 |    ERECTED>=1908.500: 1528 
    439 </XMP> 
    440  
    441 <P>Small and nice. Now for the "SPAN". Wooden bridges and walkways are short, while the others are mostly medium. This could be done by <a href="lookup.htm"><CODE>ClassifierByLookupTable</CODE></A> - this would be faster than what we plan here. See the corresponding documentation on lookup classifier. Here we are gonna do it with a Python function.</P> 
    442  
    443 <XMP class=code>spanVar = data.domain["SPAN"] 
    444  
    445 def computeSpan(ex, returnWhat): 
    446     if ex["TYPE"] == "WOOD" or ex["PURPOSE"] == "WALK": 
    447         span = "SHORT" 
    448     else: 
    449         span = "MEDIUM" 
    450     return orange.Value(spanVar, span) 
    451  
    452 imputer.models[data.domain.index("SPAN")] = computeSpan 
    453 </XMP> 
    454  
    455  
    456 <P><CODE>computeSpan</CODE> could also be written as a class, if you'd prefer 
     408:class:`Orange.data.Value`. Both classifiers will be stored at the appropriate places 
     409in :obj:`imputer.models`. 
     410 
     411.. literalinclude:: code/imputation-complex.py 
     412    :lines: 110-112 
     413 
     414 
     415"LENGTH" will be computed with a regression tree induced from "MATERIAL",  
     416"SPAN" and "ERECTED" (together with "LENGTH" as the class attribute, of 
     417course). Note that we initialized the domain by simply giving a list with 
     418the names of the attributes, with the domain as an additional argument 
     419in which Orange will look for the named attributes. 
     420 
     421.. literalinclude:: code/imputation-complex.py 
     422    :lines: 114-119 
     423 
     424We printed the tree just to see what it looks like. 
     425 
     426:: 
     427 
     428    <XMP class=code>SPAN=SHORT: 1158 
     429    SPAN=LONG: 1907 
     430    SPAN=MEDIUM 
     431    |    ERECTED<1908.500: 1325 
     432    |    ERECTED>=1908.500: 1528 
     433    </XMP> 
     434 
     435Small and nice. Now for the "SPAN". Wooden bridges and walkways are short, 
     436while the others are mostly medium. This could be done by 
     437:class:`Orange.classifier.ClassifierByLookupTable` - this would be faster 
     438than what we plan here. See the corresponding documentation on lookup 
     439classifier. Here we are going to do it with a Python function. 
     440 
     441.. literalinclude:: code/imputation-complex.py 
     442    :lines: 121-128 
     443 
     444:obj:`compute_span` could also be written as a class, if you'd prefer 
    457445it. It's important that it behaves like a classifier, that is, gets an example 
    458446and returns a value. The second element tells, as usual, what the caller expect 
    459447the classifier to return - a value, a distribution or both. Since the caller, 
    460 <CODE>Imputer_model</CODE>, always wants values, we shall ignore the argument 
     448:obj:`Imputer_model`, always wants values, we shall ignore the argument 
    461449(at risk of having problems in the future when imputers might handle 
    462 distribution as well).</P> 
    463  
    464  
    465 Treating the missing values as special values 
    466 ============================================= 
    467  
    468 <P>Missing values sometimes have a special meaning. The fact that something was 
     450distribution as well). 
     451 
     452Missing values as special values 
     453================================ 
     454 
     455Missing values sometimes have a special meaning. The fact that something was 
    469456not measured can sometimes tell a lot. Be, however, cautious when using such 
    470457values in decision models; it the decision not to measure something (for 
    471458instance performing a laboratory test on a patient) is based on the expert's 
    472 knowledge of the class value, such unknown values clearly should not be used in 
    473 models.</P> 
    474  
    475 <P><CODE><INDEX name="classes/ImputerConstructor_asValue">ImputerConstructor_asValue</INDEX></CODE> constructs a new domain in which each discrete attribute is replaced with a new attribute that has one value more: "NA". The new attribute will compute its values on the fly from the old one, copying the normal values and replacing the unknowns with "NA".</P> 
    476  
    477 <P>For continuous attributes, <CODE>ImputerConstructor_asValue</CODE> will 
    478 construct a two-valued discrete attribute with values "def" and "undef", 
    479 telling whether the continuous attribute was defined or not. The attribute's 
    480 name will equal the original's with "_def" appended. The original continuous 
    481 attribute will remain in the domain and its unknowns will be replaced by 
    482 averages.</P> 
    483  
    484 <P><CODE>ImputerConstructor_asValue</CODE> has no specific attributes.</P> 
    485  
    486 <P>The constructed imputer is named <CODE>Imputer_asValue</CODE> (I bet you 
    487 wouldn't guess). It converts the example into the new domain, which imputes the 
    488 values for discrete attributes. If continuous attributes are present, it will 
    489 also replace their values by the averages.</P> 
    490  
    491 <P class=section>Attributes of <CODE>Imputer_asValue</CODE></P> 
    492 <DL class=attributes> 
    493 <DT>domain</DT> 
    494 <DD>The domain with the new attributes constructed by <CODE>ImputerConstructor_asValue</CODE>.</DD> 
    495  
    496 <DT>defaults</DT> 
    497 <DD>Default values for continuous attributes. Present only if there are any.</DD> 
    498 </DL> 
    499  
    500 <P>Here's a script that shows what this imputer actually does to the domain.</P> 
    501  
    502 <P class="header">part of <A href="imputation.py">imputation.py</A> (uses <a href="bridges.tab">bridges.tab</a>)</P> 
    503 <XMP class=code>imputer = orange.ImputerConstructor_asValue(data) 
    504  
    505 original = data[19] 
    506 imputed = imputer(data[19]) 
    507  
    508 print original.domain 
    509 print 
    510 print imputed.domain 
    511 print 
    512  
    513 for i in original.domain: 
    514     print "%s: %s -> %s" % (original.domain[i].name, original[i], imputed[i.name]), 
    515     if original.domain[i].varType == orange.VarTypes.Continuous: 
    516         print "(%s)" % imputed[i.name+"_def"] 
    517     else: 
    518         print 
    519 print 
    520 </XMP> 
    521  
    522 <P>The script's output looks like this.</P> 
    523  
    524 <XMP class=code>[RIVER, ERECTED, PURPOSE, LENGTH, LANES, CLEAR-G, T-OR-D, 
    525 MATERIAL, SPAN, REL-L, TYPE] 
    526  
    527 [RIVER, ERECTED_def, ERECTED, PURPOSE, LENGTH_def, LENGTH, 
    528 LANES_def, LANES, CLEAR-G, T-OR-D, 
    529 MATERIAL, SPAN, REL-L, TYPE] 
    530  
    531  
    532 RIVER: M -> M 
    533 ERECTED: 1874 -> 1874 (def) 
    534 PURPOSE: RR -> RR 
    535 LENGTH: ? -> 1567 (undef) 
    536 LANES: 2 -> 2 (def) 
    537 CLEAR-G: ? -> NA 
    538 T-OR-D: THROUGH -> THROUGH 
    539 MATERIAL: IRON -> IRON 
    540 SPAN: ? -> NA 
    541 REL-L: ? -> NA 
    542 TYPE: SIMPLE-T -> SIMPLE-T 
    543 </XMP> 
    544  
    545 <P>Seemingly, the two examples have the same attributes (with 
    546 <CODE>imputed</CODE> having a few additional ones). If you check this by 
    547 <CODE>original.domain[0] == imputed.domain[0]</CODE>, you shall see that this 
    548 first glance is <CODE>False</CODE>. The attributes only have the same names, 
     459knowledge of the class value, such unknown values clearly should not be used  
     460in models. 
     461 
     462.. class:: ImputerConstructor_asValue 
     463 
     464    Constructs a new domain in which each 
     465    discrete attribute is replaced with a new attribute that has one value more: 
     466    "NA". The new attribute will compute its values on the fly from the old one, 
     467    copying the normal values and replacing the unknowns with "NA". 
     468 
     469    For continuous attributes, it will 
     470    construct a two-valued discrete attribute with values "def" and "undef", 
     471    telling whether the continuous attribute was defined or not. The attribute's 
     472    name will equal the original's with "_def" appended. The original continuous 
     473    attribute will remain in the domain and its unknowns will be replaced by 
     474    averages. 
     475 
     476    :class:`ImputerConstructor_asValue` has no specific attributes. 
     477 
     478    It constructs :class:`Imputer_asValue` (I bet you 
     479    wouldn't guess). It converts the example into the new domain, which imputes  
     480    the values for discrete attributes. If continuous attributes are present, it  
     481    will also replace their values by the averages. 
     482 
     483.. class:: Imputer_asValue 
     484 
     485    .. attribute:: domain 
     486 
     487        The domain with the new attributes constructed by  
     488        :class:`ImputerConstructor_asValue`. 
     489 
     490    .. attribute:: defaults 
     491 
     492        Default values for continuous attributes. Present only if there are any. 
     493 
     494The following code shows what this imputer actually does to the domain. 
     495Part of `imputation-complex.py`_ (uses `bridges.tab`_): 
     496 
     497.. literalinclude:: code/imputation-complex.py 
     498    :lines: 137-151 
     499 
     500 
     501The script's output looks like this:: 
     502 
     503    [RIVER, ERECTED, PURPOSE, LENGTH, LANES, CLEAR-G, T-OR-D, MATERIAL, SPAN, REL-L, TYPE] 
     504 
     505    [RIVER, ERECTED_def, ERECTED, PURPOSE, LENGTH_def, LENGTH, LANES_def, LANES, CLEAR-G, T-OR-D, MATERIAL, SPAN, REL-L, TYPE] 
     506 
     507    RIVER: M -> M 
     508    ERECTED: 1874 -> 1874 (def) 
     509    PURPOSE: RR -> RR 
     510    LENGTH: ? -> 1567 (undef) 
     511    LANES: 2 -> 2 (def) 
     512    CLEAR-G: ? -> NA 
     513    T-OR-D: THROUGH -> THROUGH 
     514    MATERIAL: IRON -> IRON 
     515    SPAN: ? -> NA 
     516    REL-L: ? -> NA 
     517    TYPE: SIMPLE-T -> SIMPLE-T 
     518 
     519Seemingly, the two examples have the same attributes (with 
     520:samp:`imputed` having a few additional ones). If you check this by 
     521:samp:`original.domain[0] == imputed.domain[0]`, you shall see that this 
     522first glance is False. The attributes only have the same names, 
    549523but they are different attributes. If you read this page (which is already a 
    550524bit advanced), you know that Orange does not really care about the attribute 
    551 names).</P> 
    552  
    553 <P>Therefore, if we wrote "<CODE>imputed[i]</CODE>" the program would fail 
    554 since <CODE>imputed</CODE> has no attribute <CODE>i</CODE>. But it has an 
     525names). 
     526 
     527Therefore, if we wrote :samp:`imputed[i]` the program would fail 
     528since :samp:`imputed` has no attribute :samp:`i`. But it has an 
    555529attribute with the same name (which even usually has the same value). We 
    556 therefore use <CODE>i.name</CODE> to index the attributes of 
    557 <CODE>imputed</CODE>. (Using names for indexing is not fast, though; if you do 
     530therefore use :samp:`i.name` to index the attributes of 
     531:samp:`imputed`. (Using names for indexing is not fast, though; if you do 
    558532it a lot, compute the integer index with 
    559 <CODE>imputed.domain.index(i.name)</CODE>.)</P> 
    560  
    561 <P>For continuous attributes, there is an additional attribute with "_def" 
    562 appended; we get it by <CODE>i.name+"_def"</CODE>. Not really nice, but it 
    563 works.</P> 
    564  
    565 <P>The first continuous attribute, "ERECTED" is defined. Its value remains 1874 
     533:samp:`imputed.domain.index(i.name)`.)</P> 
     534 
     535For continuous attributes, there is an additional attribute with "_def" 
     536appended; we get it by :samp:`i.name+"_def"`. 
     537 
     538The first continuous attribute, "ERECTED" is defined. Its value remains 1874 
    566539and the additional attribute "ERECTED_def" has value "def". Not so for 
    567540"LENGTH". Its undefined value is replaced by the average (1567) and the new 
    568541attribute has value "undef". The undefined discrete attribute "CLEAR-G" (and 
    569 all other undefined discrete attributes) is assigned the value "NA".</P> 
     542all other undefined discrete attributes) is assigned the value "NA". 
    570543 
    571544Using imputers 
     
    644617    def __new__(cls, examples = None, weightID = 0, **keyw): 
    645618        self = orange.Learner.__new__(cls, **keyw) 
    646         self.dontImputeClassifier = False 
     619        self.dont_impute_classifier = False 
    647620        self.__dict__.update(keyw) 
    648621        if examples: 
     
    652625         
    653626    def __call__(self, data, weight=0): 
    654         trained_imputer = self.imputerConstructor(data, weight) 
     627        trained_imputer = self.imputer_constructor(data, weight) 
    655628        imputed_data = trained_imputer(data, weight) 
    656         baseClassifier = self.baseLearner(imputed_data, weight) 
    657         if self.dontImputeClassifier: 
    658             return baseClassifier 
     629        base_classifier = self.base_learner(imputed_data, weight) 
     630        if self.dont_impute_classifier: 
     631            return base_classifier 
    659632        else: 
    660             return ImputeClassifier(baseClassifier, trained_imputer) 
     633            return ImputeClassifier(base_classifier, trained_imputer) 
    661634 
    662635class ImputeClassifier(orange.Classifier): 
    663     def __init__(self, baseClassifier, imputer, **argkw): 
    664         self.baseClassifier = baseClassifier 
     636    def __init__(self, base_classifier, imputer, **argkw): 
     637        self.base_classifier = base_classifier 
    665638        self.imputer = imputer 
    666639        self.__dict__.update(argkw) 
    667640 
    668641    def __call__(self, ex, what=orange.GetValue): 
    669         return self.baseClassifier(self.imputer(ex), what) 
     642        return self.base_classifier(self.imputer(ex), what) 
Note: See TracChangeset for help on using the changeset viewer.