Changeset 1916:bbef37dc8a3e in orange-bioinformatics


Ignore:
Timestamp:
11/25/13 14:23:24 (5 months ago)
Author:
Ales Erjavec <ales.erjavec@…>
Branch:
default
Message:

Horizontal output table merge.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • orangecontrib/bio/widgets/OWVennDiagram.py

    r1915 r1916  
    66import math 
    77 
    8 from collections import namedtuple, OrderedDict 
     8from collections import namedtuple, defaultdict, OrderedDict 
    99 
    1010from xml.sax.saxutils import escape 
     
    443443                return str(val) in selected_items 
    444444 
    445         for key, input in self.data.items(): 
     445        source_mid = Orange.core.newmetaid() 
     446        source_var = Orange.feature.String("source") 
     447        item_mid = Orange.core.newmetaid() 
     448        item_id_var = Orange.feature.String("item_id") 
     449 
     450        for i, (key, input) in enumerate(self.data.items()): 
    446451            attr = self.itemsetAttr(key) 
    447452            if attr is not None: 
     
    450455                mask = [False] * len(input.table) 
    451456 
    452             subset = input.table.select(mask) 
     457            subset = Orange.data.Table(input.table.domain.clone(), 
     458                                       input.table.select(mask)) 
     459 
     460            assert subset.domain is not input.table.domain 
     461 
     462            # add a column with source table id to the data 
     463            subset.domain.add_meta(source_mid, source_var) 
     464            subset.add_meta_attribute(source_var, 
     465                                      "%s %i" % (str(input.name), i)) 
     466            # add a column with instance set id 
     467            subset.domain.add_meta(item_mid, item_id_var) 
     468            subset.add_meta_attribute(item_mid) 
     469            for inst in subset: 
     470                inst[item_id_var] = str(inst[attr]) 
    453471 
    454472            if subset: 
     
    457475        if selected_subsets: 
    458476            data = table_concat(selected_subsets) 
     477            # Get all variables which are not constant between the same 
     478            # item set 
     479            varying = varying_between(data, [item_id_var]) 
     480            if source_var in varying: 
     481                varying.remove(source_var) 
     482 
     483            data = reshape_wide(data, varying, [item_id_var], [source_var]) 
     484            # remove the temporary item set id column 
     485            data.remove_meta_attribute(item_id_var) 
     486            data.domain.remove_meta(item_id_var) 
    459487        else: 
    460488            data = None 
     
    473501 
    474502def table_concat(tables): 
     503    """ 
     504    Concatenate a list of tables. 
     505 
     506    The resulting table will have a union of all attributes of `tables`. 
     507 
     508    """ 
    475509    features = [] 
    476510    features_seen = set() 
     
    513547 
    514548    return new_table 
     549 
     550 
     551def copy_descriptor(descriptor, newname=None): 
     552    """ 
     553    Create a copy of the descriptor. 
     554 
     555    If newname is not None the new descriptor will have the same 
     556    name as the input. 
     557 
     558    """ 
     559    if newname is None: 
     560        newname = descriptor.name 
     561 
     562    if isinstance(descriptor, Orange.feature.Discrete): 
     563        newf = Orange.feature.Discrete( 
     564            newname, 
     565            values=descriptor.values, 
     566            base_value=descriptor.base_value, 
     567            ordered=descriptor.ordered, 
     568            attributes=dict(descriptor.attributes)) 
     569 
     570    elif isinstance(descriptor, Orange.feature.Continuous): 
     571        newf = Orange.feature.Continuous( 
     572            newname, 
     573            number_of_decimals=descriptor.number_of_decimals, 
     574            scientific_format=descriptor.scientific_format, 
     575            adjust_decimals=descriptor.adjust_decimals, 
     576            attributes=dict(descriptor.attributes)) 
     577 
     578    else: 
     579        newf = type(descriptor)( 
     580            newname, 
     581            attributes=dict(descriptor.attributes)) 
     582 
     583    return newf 
     584 
     585 
     586def reshape_wide(table, varlist, idvarlist, groupvarlist): 
     587    """ 
     588    Reshape a data table into a wide format. 
     589 
     590    :param Orange.data.Table table: 
     591        Source data table in long format. 
     592    :param varlist: 
     593        A list of variables to reshape. 
     594    :param list idvarlist: 
     595        A list of variables in `table` uniquely identifying multiple 
     596        records in `table` (i.e. subject id). 
     597    :param groupvarlist: 
     598        A list of variables differentiating multiple records 
     599        (i.e. conditions). 
     600 
     601    """ 
     602    def inst_key(inst, vars): 
     603        return tuple(str(inst[var]) for var in vars) 
     604 
     605    instance_groups = [inst_key(inst, groupvarlist) for inst in table] 
     606    # A list of groups (for each element in a group the varying variable 
     607    # will be duplicated) 
     608    groups = list(unique(instance_groups)) 
     609    group_names = [", ".join(group) for group in groups] 
     610 
     611    # A list of instance ids (subject ids) 
     612    # Each instance in the output will correspond to one of these ids) 
     613    instance_ids = [inst_key(inst, idvarlist) for inst in table] 
     614    ids = list(unique(instance_ids)) 
     615 
     616    # an mapping from ids to an list of input instance indices 
     617    # each instance in this list belongs to one group (but not all 
     618    # groups need to be present). 
     619    inst_by_id = defaultdict(list) 
     620 
     621    for i, inst in enumerate(table): 
     622        inst_id = instance_ids[i] 
     623        inst_by_id[inst_id].append(i) 
     624 
     625    newfeatures = [] 
     626    newmetas = [] 
     627    expanded_features = {} 
     628 
     629    def expanded(feat): 
     630        return [copy_descriptor(feat, newname="%s (%s)" % 
     631                                (feat.name, group_name)) 
     632                for group_name in group_names] 
     633 
     634    for feat in table.domain.variables: 
     635        if feat in varlist: 
     636            features = expanded(feat) 
     637            newfeatures.extend(features) 
     638            expanded_features[feat] = dict(zip(groups, features)) 
     639        elif feat not in groupvarlist: 
     640            newfeatures.append(feat) 
     641 
     642    for mid, meta in table.domain.getmetas().items(): 
     643        if meta in varlist: 
     644            metas = expanded(meta) 
     645            newmetas.extend((Orange.core.newmetaid(), meta) 
     646                            for meta in metas) 
     647            expanded_features[meta] = dict(zip(groups, metas)) 
     648        elif meta not in groupvarlist: 
     649            newmetas.append((mid, meta)) 
     650 
     651    if table.domain.class_var and table.domain.class_var is newfeatures[-1]: 
     652        new_class_var = table.domain.class_var 
     653        newfeatures = newfeatures[:-1] 
     654    else: 
     655        new_class_var = None 
     656 
     657    domain = Orange.data.Domain(newfeatures, new_class_var) 
     658    domain.addmetas(dict(newmetas)) 
     659 
     660    newtable = Orange.data.Table(domain) 
     661 
     662    for inst_id in ids: 
     663        indices = inst_by_id[inst_id] 
     664        inst = Orange.data.Instance(domain, table[indices[0]]) 
     665        for index in indices: 
     666            source_inst = table[index] 
     667            group = instance_groups[index] 
     668            for source_var in varlist: 
     669                newf = expanded_features[source_var][group] 
     670                inst[newf] = source_inst[source_var].value 
     671        newtable.append(inst) 
     672 
     673    return newtable 
     674 
     675 
     676def unique(seq): 
     677    """ 
     678    Return an iterator over unique items of `seq`. 
     679 
     680    .. note:: Items must be hashable. 
     681 
     682    """ 
     683    seen = set() 
     684    for item in seq: 
     685        if item not in seen: 
     686            yield item 
     687            seen.add(item) 
     688 
     689 
     690def varying_between(table, idvarlist): 
     691    """ 
     692    Return a list of all variables with non constant values between 
     693    groups defined by `idvarlist`. 
     694 
     695    """ 
     696    def inst_key(inst, vars): 
     697        return tuple(str(inst[var]) for var in vars) 
     698 
     699    excluded = set(idvarlist) 
     700    all_possible = [var for var in (table.domain.variables + 
     701                                    table.domain.getmetas().values()) 
     702                    if var not in excluded] 
     703    candidate_set = set(all_possible) 
     704 
     705    idmap = Orange.data.utils.table_map(table, idvarlist) 
     706    values = {} 
     707    varying = set() 
     708    for indices in idmap.values(): 
     709        for var in list(candidate_set): 
     710            values = [table[i][var].native() for i in indices] 
     711            if len(set(values)) != 1: 
     712                varying.add(var) 
     713                candidate_set.remove(var) 
     714 
     715    return sorted(varying, key=all_possible.index) 
    515716 
    516717 
     
    11681369 
    11691370 
    1170 if __name__ == "__main__": 
     1371def test(): 
    11711372    app = QApplication([]) 
    11721373    w = OWVennDiagram() 
     
    11951396    w.show() 
    11961397    app.exec_() 
    1197     w.saveSettings() 
     1398 
     1399    del w 
     1400    app.processEvents() 
     1401    return app 
     1402 
     1403 
     1404def test1(): 
     1405    app = QApplication([]) 
     1406    w = OWVennDiagram() 
     1407    data1 = Orange.data.Table("brown-selected") 
     1408    data2 = Orange.data.Table("brown-selected") 
     1409    w.setData(data1, 1) 
     1410    w.setData(data2, 2) 
     1411    w.handleNewSignals() 
     1412 
     1413    w.show() 
     1414    app.exec_() 
     1415 
     1416    del w 
     1417    return app 
     1418 
     1419if __name__ == "__main__": 
     1420    test() 
Note: See TracChangeset for help on using the changeset viewer.