Changeset 9122:bc73a69830f9 in orange


Ignore:
Timestamp:
10/19/11 14:48:09 (3 years ago)
Author:
ales_erjavec <ales.erjavec@…>
Branch:
default
Convert:
b93ce3b7fdfef1f36197c046c608a9bdcc2c2a92
Message:

Moved group_by function to Orange.data.utils

Location:
orange
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • orange/Orange/data/utils.py

    r9108 r9122  
    77 
    88""" 
    9 from __future__ import absolute_import 
     9#from __future__ import absolute_import 
     10 
     11import random 
     12import math 
     13from operator import itemgetter 
    1014 
    1115from collections import defaultdict 
    1216 
    13 from Orange.data import Table, Domain  
     17from Orange.data import Table, Domain, Instance, variable  
    1418 
    1519def table_map(table, attrs, exclude_special=True): 
     
    166170    Parameters 
    167171    ========== 
    168     table : Orange.data.Table 
    169         The ids will be added to this table. 
    170     start : int 
    171         Start id for the ids. It can also be an iterator yielding 
    172         unique values. 
     172    :param table: The ids will be added to this table. 
     173    :type table: Orange.data.Table 
     174         
     175    :param start: Start id for the ids. It can also be an iterator 
     176        yielding unique values. 
     177    :type start: int 
     178         
    173179         
    174180    """ 
     
    183189    for ex in table: 
    184190        ex[_id_variable] = str(ids.next()) 
    185      
    186          
    187      
    188  
     191 
     192     
     193from Orange.statistics import distribution 
     194 
     195def modus(values): 
     196    dist = distribution.Distribution(values[0].variable) 
     197    for v in values: 
     198        dist.add(v) 
     199    return dist.modus() 
     200 
     201def mean(values): 
     202    dist = distribution.Distribution(values[0].variable) 
     203    for v in values: 
     204        dist.add(v) 
     205    return dist.average() 
     206 
     207def geometric_mean(values): 
     208    values = [float(v) for v in values if not v.is_special()] 
     209    if values: 
     210        prod = reduce(float.__mul__, values, 1.0) 
     211        print prod, len(values) 
     212        return math.pow(prod, 1.0/len(values)) 
     213    else: 
     214        return "?" 
     215     
     216def harmonic_mean(values): 
     217    values = [float(v) for v in values if not v.is_special()] 
     218    if values: 
     219        hsum = sum(map(lambda v: 1.0 / (v or 1e-6), values)) 
     220        return len(values) / (hsum or 1e-6)  
     221    else: 
     222        return "?" 
     223 
     224_aggregate_mapping = {"random": random.choice, 
     225                      "first": itemgetter(0), 
     226                      "last": itemgetter(-1), 
     227                      "modus": modus, 
     228                      "mean": mean, 
     229                      "geometric mean": geometric_mean, 
     230                      "harmonic mean": harmonic_mean, 
     231                      "join": lambda values: ", ".join(map(str, values)) 
     232                      } 
     233 
     234def _aggregate_func(func): 
     235    if isinstance(func, basestring): 
     236        if func in _aggregate_mapping: 
     237            return _aggregate_mapping[func] 
     238        else: 
     239            raise ValueError("Unknown aggregate function %r." % func) 
     240    return func 
     241         
     242def group_by(table, group_attrs, aggregate_disc="first", aggregate_cont="mean", 
     243             aggregate_string="join", attr_aggregate=None): 
     244    if attr_aggregate is None: 
     245        attr_aggregate = {} 
     246    else: 
     247        attr_aggregate = dict(attr_aggregate) # It is modified later 
     248         
     249    all_vars = table.domain.variables + table.domain.getmetas().values() 
     250    aggregate_vars = [] 
     251    for v in all_vars: 
     252        if v not in group_attrs: 
     253            if v in attr_aggregate: 
     254                pass 
     255            elif isinstance(v, variable.Continuous): 
     256                attr_aggregate[v] = aggregate_cont 
     257            elif isinstance(v, variable.Discrete): 
     258                attr_aggregate[v] = aggregate_disc 
     259            elif isinstance(v, variable.String): 
     260                attr_aggregate[v] = aggregate_string 
     261            else: 
     262                raise TypeError(v) 
     263            aggregate_vars.append(v) 
     264            attr_aggregate[v] = _aggregate_func(attr_aggregate[v]) 
     265             
     266    indices_map = table_map(table, group_attrs, exclude_special=False) 
     267    new_instances = [] 
     268    key_set = set() 
     269     
     270    for inst in table: # Iterate over the table instead of the inidces_map to preserve order 
     271        key = tuple([str(inst[v]) for v in group_attrs]) 
     272        if key in key_set: 
     273            continue # Already seen this group 
     274        indices = indices_map[key] 
     275        new_instance = Instance(inst) # Copy 
     276        for v in aggregate_vars: 
     277            values = [table[i][v] for i in indices] # Values to aggregate 
     278            new_instance[v] = attr_aggregate[v](values) 
     279        new_instances.append(new_instance) 
     280        key_set.add(key) 
     281    return Table(new_instances) 
  • orange/OrangeWidgets/Prototypes/OWAddRowIds.py

    r9092 r9122  
    1111import Orange 
    1212 
    13 from threading import Lock 
    14 global_curent_id_lock = Lock() 
    15 global_curent_id = 0 
    16  
    17 class OWAddRowIds(OWWidget): 
    18     meta_id = Orange.data.new_meta_id() 
    19     id_var = Orange.data.variable.String("Row Id") 
    20      
     13class OWAddRowIds(OWWidget):     
    2114    def __init__(self, parent=None, signalManager=None, title="Add row ids"): 
    2215        OWWidget.__init__(self, parent, signalManager, title, wantMainArea=False) 
     
    3023                       label="Use unique global identifiers",  
    3124                       tooltip="Use unique global identifiers. Identifiers will\ 
    32 be unique across all widget istances.",  
     25be unique across all widget istances and orange sessions.",  
    3326                       callback=self.commit 
    3427                       ) 
     
    4033         
    4134    def commit(self): 
     35        from Orange.data import utils 
    4236        if self.table is not None: 
    4337            table = Orange.data.Table(self.table) 
    44             table.domain.add_meta(self.meta_id, self.id_var) 
    45             global global_curent_id 
    46             for ex in table: 
    47                 if self.use_guid: 
    48                     ex[self.id_var] = str(uuid.uuid4()) 
    49                 else: 
    50                     with global_curent_id_lock: 
    51                         ex[self.id_var] = str(global_curent_id) 
    52                         global_curent_id += 1  
     38            if self.use_guid: 
     39                utils.add_row_id(table, utils.uuid_generator()) 
     40            else: 
     41                utils.add_row_id(table, utils.range_generator()) 
    5342        else: 
    5443            table = None 
  • orange/OrangeWidgets/Prototypes/OWGroupBy.py

    r9116 r9122  
    1010import Orange 
    1111from Orange.data import Table, Domain, variable, utils 
    12 from Orange.statistics import distribution 
    13  
    14 import random 
    15 import math 
    16 from operator import itemgetter 
    17  
    18 def modus(values): 
    19     dist = distribution.Distribution(values[0].variable) 
    20     for v in values: 
    21         dist.add(v) 
    22     return dist.modus() 
    23  
    24 def mean(values): 
    25     dist = distribution.Distribution(values[0].variable) 
    26     for v in values: 
    27         dist.add(v) 
    28     return dist.average() 
    29  
    30 def geometric_mean(values): 
    31     values = [float(v) for v in values if not v.is_special()] 
    32     if values: 
    33         prod = reduce(float.__mul__, values, 1.0) 
    34         return math.pow(prod, 1.0/len(values)) 
    35     else: 
    36         return "?" 
    37      
    38 def harmonic_mean(values): 
    39     values = [float(v) for v in values if not v.is_special()] 
    40     if values: 
    41         hsum = sum(map(lambda v: 1.0 / (v or 1e-6), values)) 
    42         return len(values) / (hsum or 1e-6)  
    43     else: 
    44         return "?" 
    45  
    46 def aggregate_func(func): 
    47     if isinstance(func, basestring): 
    48         mapping = {"random": random.choice, 
    49                    "first": itemgetter(0), 
    50                    "last": itemgetter(-1), 
    51                    "modus": modus, 
    52                    "mean": mean, 
    53                    "geometric mean": geometric_mean, 
    54                    "harmonic mean": harmonic_mean, 
    55                    "join": lambda values: ", ".join(map(str, values)) 
    56                    } 
    57         return mapping[func] 
    58     return func 
    59          
    60 def group_by(table, group_attrs, aggregate_disc="first", aggregate_cont="mean", 
    61              aggregate_string="join", attr_aggregate=None): 
    62     if attr_aggregate is None: 
    63         attr_aggregate = {} 
    64     else: 
    65         attr_aggregate = dict(attr_aggregate) # It is modified later 
    66          
    67     all_vars = table.domain.variables + table.domain.getmetas().values() 
    68     aggregate_vars = [] 
    69     for v in all_vars: 
    70         if v not in group_attrs: 
    71             if v in attr_aggregate: 
    72                 pass 
    73             elif isinstance(v, variable.Continuous): 
    74                 attr_aggregate[v] = aggregate_cont 
    75             elif isinstance(v, variable.Discrete): 
    76                 attr_aggregate[v] = aggregate_disc 
    77             elif isinstance(v, variable.String): 
    78                 attr_aggregate[v] = aggregate_string 
    79             else: 
    80                 raise TypeError(v) 
    81             aggregate_vars.append(v) 
    82             attr_aggregate[v] = aggregate_func(attr_aggregate[v]) 
    83              
    84     indices_map = utils.table_map(table, group_attrs, exclude_special=False) 
    85     new_instances = [] 
    86     key_set = set() 
    87     print group_attrs, indices_map 
    88     for inst in table: # Iterate over the table instead of the inidces_map to preserve order 
    89         key = tuple([str(inst[v]) for v in group_attrs]) 
    90         if key in key_set: 
    91             continue # Already seen this group 
    92         indices = indices_map[key] 
    93         new_instance = Orange.data.Instance(inst) # Copy 
    94         for v in aggregate_vars: 
    95             values = [table[i][v] for i in indices] # Values to aggregate 
    96             print attr_aggregate[v], values, " -> ", attr_aggregate[v](values) 
    97             new_instance[v] = attr_aggregate[v](values) 
    98         new_instances.append(new_instance) 
    99         key_set.add(key) 
    100     return Orange.data.Table(new_instances) 
    10112 
    10213AggregateMethodRole = OWGUI.OrangeUserRole.next() 
     
    303214            aggregates = self.get_aggregates_from_hints() 
    304215            print aggregates 
    305             data = group_by(self.data, group, attr_aggregate=aggregates) 
     216            data = utils.group_by(self.data, group, attr_aggregate=aggregates) 
    306217        else: 
    307218            data = None 
Note: See TracChangeset for help on using the changeset viewer.