Changeset 8926:6c59050757b8 in orange


Ignore:
Timestamp:
09/08/11 15:27:46 (3 years ago)
Author:
ales_erjavec <ales.erjavec@…>
Branch:
default
Convert:
3900dadb5bba60482ad08df57472663d98f47166
Message:

Added save_csv function.
Fixed meta attribute handling in load_csv.
Added simple test case for loading saving .csv files.
(References #931)

Files:
2 edited

Legend:

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

    r8832 r8926  
    297297 
    298298"""\ 
    299 CSV file reader. 
    300 ---------------- 
     299A general CSV file reader. 
     300-------------------------- 
    301301 
    302302Currently not yet documented and not registered (needs testing). 
    303303 
    304304""" 
     305 
    305306def split_escaped_str(str, split_str=" ", escape="\\"): 
    306307    res = [] 
     
    336337         
    337338def var_type(cell): 
    338     """ Return variable type from a variable type definition in cell. 
    339      
    340     .. todo:: discrete type definition by listing space separated values.  
    341      
     339    """ Return variable type from a variable type definition in cell.  
    342340    """ 
    343341    if cell in ["c", "continuous"]: 
     
    350348        return variable.Python 
    351349    elif cell == "": 
    352         return Variable 
     350        return variable.Variable 
     351    elif len(cell.split(",")) > 1: 
     352        return variable.Discrete, cell.split(",") 
    353353    else: 
    354354        raise ValueError("Unknown variable type definition %r." % cell) 
     
    367367 
    368368def is_var_attributes_def(cell): 
    369     """ Is the cell a standard variables attributes definition.  
     369    """ Is the cell a standard variable attributes definition.  
    370370    """ 
    371371    try: 
     
    380380    """ 
    381381    key_value = split_escaped_str(cell, "=") 
    382     if len(key_value): 
     382    if len(key_value) == 2: 
    383383        return tuple(key_value) 
    384384    else: 
     
    436436    cont = sum(map(is_val_cont, values)) or 1e-30 
    437437    if n is None: 
    438         n = len(values) 
     438        n = len(values) or 1 
    439439    return (float(cont) / n) > cutoff 
    440440     
     
    450450    return False 
    451451 
    452 def load_csv(filename, create_new_on=MakeStatus.Incompatible, **kwargs): 
     452def load_csv(file, create_new_on=MakeStatus.Incompatible, **kwargs): 
    453453    """ Load an Orange.data.Table from s csv file. 
    454454    """ 
    455     import csv 
    456     file = open(filename, "rb") 
     455    import csv, numpy 
     456    file = as_open_file(file, "rb") 
    457457    snifer = csv.Sniffer() 
    458458    sample = file.read(5 * 2 ** 20) # max 5MB sample TODO: What if this is not enough. Try with a bigger sample 
     
    492492    reader = csv.reader(file, dialect=dialect) 
    493493    for defined in [header, types, var_attrs]: 
    494         if defined: # skip definition rows if present 
     494        if any(defined): # skip definition rows if present in the file 
    495495            reader.next() 
    496496     
     
    550550    class_var = [] 
    551551    metas = {} 
    552     for (var, status), var_attr in zip(variables, var_attrs): 
     552    attribute_indices = [] 
     553    variable_indices = [] 
     554    class_indices = [] 
     555    meta_indices = [] 
     556    for i, ((var, status), var_attr) in enumerate(zip(variables, var_attrs)): 
    553557        if var_attr: 
    554558            flag, attrs = var_attr 
     
    556560                class_var.append(var) 
    557561                class_var_load_status.append(status) 
     562                class_indices.append(i) 
    558563            elif flag == "meta": 
    559564                mid = Orange.core.newmetaid() 
    560565                metas[mid] = var 
    561566                meta_attribute_load_status[mid] = status 
     567                meta_indices.append((i, var)) 
    562568            else: 
    563569                attributes.append(var) 
    564570                attribute_load_status.append(status) 
     571                attribute_indices.append(i) 
    565572            var.attributes.update(attrs) 
    566573        else: 
    567574            attributes.append(var) 
    568575            attribute_load_status.append(status) 
     576            attribute_indices.append(i) 
     577             
    569578    if len(class_var) > 1: 
    570579        raise ValueError("Multiple class variables defined") 
     
    573582     
    574583    attribute_load_status += class_var_load_status 
    575      
     584    variable_indices = attribute_indices + class_indices 
    576585    domain = Orange.data.Domain(attributes, class_var) 
    577586    domain.add_metas(metas) 
    578     table = Orange.data.Table(domain, data) 
     587    normal = [[row[i] for i in variable_indices] for row in data] 
     588    meta_part = [[row[i] for i,_ in meta_indices] for row in data] 
     589    table = Orange.data.Table(domain, normal) 
     590    for ex, m_part in zip(table, meta_part): 
     591        for (column, var), val in zip(meta_indices, m_part): 
     592            ex[var] = var(val) 
     593             
    579594    table.metaAttributeLoadStatus = meta_attribute_load_status 
    580595    table.attributeLoadStatus = attribute_load_status 
     
    582597    return table 
    583598 
    584 def save_csv(filename, table): 
    585     pass 
    586  
     599def as_open_file(file, mode="rb"): 
     600    if isinstance(file, basestring): 
     601        file = open(file, mode) 
     602    else: # assuming it is file like with proper mode, could check for write, read 
     603        pass 
     604    return file 
     605         
     606def save_csv(file, table, orange_specific=True, **kwargs): 
     607    import csv 
     608    file = as_open_file(file, "wb") 
     609    writer = csv.writer(file, **kwargs) 
     610    attrs = table.domain.attributes 
     611    class_var = table.domain.class_var 
     612    metas = [v for _, v in sorted(table.domain.get_metas().items(), 
     613                                  reverse=True)] 
     614    all_vars = attrs + ([class_var] if class_var else []) + metas 
     615    names = [v.name for v in all_vars] 
     616    writer.writerow(names) 
     617     
     618    if orange_specific: 
     619        type_cells = [] 
     620        for v in all_vars: 
     621            if isinstance(v, variable.Discrete): 
     622                type_cells.append(",".join(v.values)) 
     623            elif isinstance(v, variable.Continuous): 
     624                type_cells.append("continuous") 
     625            elif isinstance(v, variable.String): 
     626                type_cells.append("string") 
     627            elif isinstance(v, variable.Python): 
     628                type_cells.append("python") 
     629            else: 
     630                raise TypeError("Unknown variable type") 
     631        writer.writerow(type_cells) 
     632         
     633        var_attr_cells = [] 
     634        for spec, var in [("", v) for v in attrs] + \ 
     635                         ([("class", class_var)] if class_var else []) +\ 
     636                         [("m", v) for v in metas]: 
     637             
     638            labels = ["{0}={1}".format(*t) for t in var.attributes.items()] # TODO escape spaces 
     639            var_attr_cells.append(" ".join([spec] if spec else [] + labels)) 
     640             
     641        writer.writerow(var_attr_cells) 
     642         
     643    for instance in table: 
     644        instance = list(instance) + [instance[m] for m in metas] 
     645        writer.writerow(instance) 
     646     
     647         
    587648 
    588649registerFileType("R", None, toR, ".R") 
     
    590651#registerFileType("C50", None, toC50, [".names", ".data", ".test"]) 
    591652registerFileType("libSVM", loadLibSVM, toLibSVM, ".svm") 
    592  
    593 #registerFileType("csv", load_csv, save_csv, ".csv") # Not yet fully tested, might conflict with builtin readers.  
     653  
  • testing/unittests/tests/test_table.py

    r8763 r8926  
    6666            f.flush() 
    6767            data_svm = Orange.data.Table(f.name) 
     68         
     69    @testing.test_on_datasets 
     70    def test_csv_on(self, data): 
     71        with tempfile.NamedTemporaryFile(suffix=".csv") as f: 
     72            Orange.data.io.save_csv(f, data, dialect="excel-tab") 
     73            f.flush() 
     74            f.seek(0) 
     75            Orange.data.io.load_csv(f) 
     76             
     77         
    6878             
    6979         
Note: See TracChangeset for help on using the changeset viewer.