Changeset 8831:906beffb1f3b in orange


Ignore:
Timestamp:
08/29/11 16:12:03 (3 years ago)
Author:
ales_erjavec <ales.erjavec@…>
Branch:
default
Convert:
f40efd9521fbbc922a0f35a42cbc1cc65e83a9c0
Message:

Added load_csv function (not yet documented and not registered for the .csv extension - references #931).

File:
1 edited

Legend:

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

    r8746 r8831  
    88     C45ExampleGenerator, TabDelimExampleGenerator, registerFileType 
    99 
    10  
    11 def loadARFF(filename, create_on_new = Orange.data.variable.Variable.MakeStatus.Incompatible, **kwargs): 
     10from Orange.data import variable 
     11from Orange.data.variable import Variable 
     12MakeStatus = Variable.MakeStatus 
     13 
     14def loadARFF(filename, create_on_new = MakeStatus.Incompatible, **kwargs): 
    1215    """Return class:`Orange.data.Table` containing data from file in Weka ARFF format""" 
    1316    if not os.path.exists(filename) and os.path.exists(filename + ".arff"): 
     
    7376                        if len(sy)>0: 
    7477                            vals.append(sy) 
    75                     a, s = Orange.data.variable.Variable.make(atn, Orange.data.Type.Discrete, vals, [], create_on_new) 
     78                    a, s = Variable.make(atn, Orange.data.Type.Discrete, vals, [], create_on_new) 
    7679                else: 
    7780                    # real... 
    78                     a, s = Orange.data.variable.Variable.make(atn, Orange.data.Type.Continuous, [], [], create_on_new) 
     81                    a, s = Variable.make(atn, Orange.data.Type.Continuous, [], [], create_on_new) 
    7982                     
    8083                attributes.append(a) 
     
    261264    Orange.classification.svm.tableToSVMFormat(example, open(filename, "wb")) 
    262265     
    263 def loadLibSVM(filename, create_on_new=Orange.data.variable.Variable.MakeStatus.Incompatible, **kwargs): 
     266def loadLibSVM(filename, create_on_new=MakeStatus.Incompatible, **kwargs): 
    264267    """Return class:`Orange.data.Table` containing data from file in LibSVM format""" 
    265268    attributeLoadStatus = {} 
     
    292295)(loadLibSVM) 
    293296 
     297 
     298"""\ 
     299CSV file reader. 
     300---------------- 
     301 
     302Currently not yet documented and not registered (needs testing). 
     303 
     304""" 
     305def split_escaped_str(str, split_str=" ", escape="\\"): 
     306    res = [] 
     307    index = 0 
     308    start = 0 
     309    find_start = 0 
     310    while index != -1: 
     311        index = str.find(split_str, find_start) 
     312        if index != -1 and index > 0: 
     313            if str[index - 1] == escape: # Skip the escaped split_str 
     314                find_start = index + 1 
     315            else: 
     316                res.append(str[start:index]) 
     317                start = find_start = index + 1 
     318                 
     319        elif index == -1: 
     320            res.append(str[start:]) 
     321    return res 
     322     
     323def is_standard_var_def(cell): 
     324    """Is the cell a standard variable definition (empty, cont, disc, string) 
     325    """ 
     326    try: 
     327        var_type(cell) 
     328        return True 
     329    except ValueError, ex: 
     330        return False 
     331     
     332def is_var_types_row(row): 
     333    """ Is the row a variable type definition row (as in the orange .tab file) 
     334    """ 
     335    return all(map(is_standard_var_def, row)) 
     336         
     337def 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     
     342    """ 
     343    if cell in ["c", "continuous"]: 
     344        return variable.Continuous 
     345    elif cell in ["d", "discrete"]: 
     346        return variable.Discrete 
     347    elif cell in ["s", "string"]: 
     348        return variable.String 
     349    elif cell.startswith("pyhton"): 
     350        return variable.Python 
     351    elif cell == "": 
     352        return Variable 
     353    else: 
     354        raise ValueError("Unknown variable type definition %r." % cell) 
     355 
     356def var_types(row): 
     357    """ Return variable types from row.  
     358    """ 
     359    return map(var_type, row) 
     360     
     361def is_var_attributes_row(row): 
     362    """ Is the row an attribute definition row (i.e. the third row in the 
     363    standard orange .tab file format). 
     364     
     365    """ 
     366    return all(map(is_var_attributes_def, row)) 
     367 
     368def is_var_attributes_def(cell): 
     369    """ Is the cell a standard variables attributes definition.  
     370    """ 
     371    try: 
     372        var_attribute(cell) 
     373        return True 
     374    except ValueError, ex: 
     375        raise 
     376        return False 
     377 
     378def _var_attribute_label_parse(cell): 
     379    """  
     380    """ 
     381    key_value = split_escaped_str(cell, "=") 
     382    if len(key_value): 
     383        return tuple(key_value) 
     384    else: 
     385        raise ValueError("Invalid attribute label definition %r." % cell) 
     386 
     387def var_attribute(cell): 
     388    """ Return variable specifier ("meta" or "class" or None) and attributes 
     389    labels dict.  
     390    """ 
     391    items = split_escaped_str(cell, " ") 
     392    if cell == "": 
     393        return None, {} 
     394    elif items: 
     395        specifier = None 
     396        if items[0] in ["m", "meta"]: 
     397            specifier = "meta" 
     398            items = items[1:] 
     399        elif items[0] == "class": 
     400            specifier = "class" 
     401            items = items[1:] 
     402        return specifier, dict(map(_var_attribute_label_parse, items)) 
     403    else: 
     404        raise ValueError("Unknown attribute label definition") 
     405     
     406def var_attributes(row): 
     407    """ Return variable specifiers and label definitions for row 
     408    """ 
     409    return map(var_attribute, row) 
     410     
     411         
     412class _var_placeholder(object): 
     413    """ A place holder for an arbitrary variable while it's values are still unknown. 
     414    """ 
     415    def __init__(self, name="", values=[]): 
     416        self.name = name 
     417        self.values = set(values) 
     418         
     419class _disc_placeholder(_var_placeholder): 
     420    """ A place holder for discrete variables while their values are not yet known. 
     421    """ 
     422    pass 
     423 
     424def is_val_cont(cell): 
     425    """ Is cell a string representing a real value. 
     426    """ 
     427    try: 
     428        float(cell) 
     429        return True 
     430    except ValueError: 
     431        return False 
     432     
     433def is_variable_cont(values, n=None, cutoff=0.5): 
     434    """ Is variable with ``values`` in column (``n`` rows) a continuous variable.  
     435    """ 
     436    cont = sum(map(is_val_cont, values)) or 1e-30 
     437    if n is None: 
     438        n = len(values) 
     439    return (float(cont) / n) > cutoff 
     440     
     441     
     442def is_variable_discrete(values, n=None, cutoff=0.3): 
     443    """ Is variable with ``values`` in column (``n`` rows) a discrete variable.  
     444    """ 
     445    return not is_variable_cont(values, n) 
     446 
     447def is_variable_string(values, n=None, cutuff=0.1): 
     448    """ Is variable with ``values`` in column (``n`` rows) a string variable.  
     449    """ 
     450    return False 
     451 
     452def load_csv(filename, create_new_on=MakeStatus.Incompatible, **kwargs): 
     453    """ Load an Orange.data.Table from s csv file. 
     454    """ 
     455    import csv 
     456    file = open(filename, "rb") 
     457    snifer = csv.Sniffer() 
     458    sample = file.read(5 * 2 ** 20) # max 5MB sample TODO: What if this is not enough. Try with a bigger sample 
     459    dialect = snifer.sniff(sample) 
     460    has_header = snifer.has_header(sample) 
     461    file.seek(0) # Rewind 
     462    reader = csv.reader(file, dialect=dialect) 
     463     
     464    header = types = var_attrs = None 
     465     
     466#    if not has_header: 
     467#        raise ValueError("No header in the data file.") 
     468     
     469    header = reader.next() 
     470     
     471    if header: 
     472        # Try to get variable definitions 
     473        types_row = reader.next() 
     474        if is_var_types_row(types_row): 
     475            types = var_types(types_row) 
     476     
     477    if types: 
     478        # Try to get the variable attributes 
     479        # (third line in the standard orange tab format). 
     480        labels_row = reader.next() 
     481        if is_var_attributes_row(labels_row): 
     482            var_attrs = var_attributes(labels_row) 
     483             
     484    # If definitions not present fill with blanks 
     485    if not types: 
     486        types = [None] * len(header) 
     487    if not var_attrs: 
     488        var_attrs = [None] * len(header) 
     489     
     490    # start from the beginning 
     491    file.seek(0) 
     492    reader = csv.reader(file, dialect=dialect) 
     493    for defined in [header, types, var_attrs]: 
     494        if defined: # skip definition rows if present 
     495            reader.next() 
     496     
     497    variables = [] 
     498    undefined_vars = [] 
     499    for i, (name, var_t) in enumerate(zip(header, types)): 
     500        if var_t == variable.Discrete:# We do not have values yet. 
     501            variables.append(_disc_placeholder(name)) 
     502            undefined_vars.append((i, variables[-1])) 
     503        elif var_t == variable.Continuous: 
     504            variables.append(variable.make(name, Orange.data.Type.Continuous, [], [], create_new_on)) 
     505        elif var_t == variable.String: 
     506            variables.append(variable.make(name, Orange.data.Type.String, [], [], create_new_on)) 
     507        elif var_t == variable.Python: 
     508            variables.append(variable.Python(name)) 
     509        elif isinstance(var_t, tuple): 
     510            var_t, values = var_t 
     511            if var_t == variable.Discrete: 
     512                variables.append(variable.make(name, Orange.data.Type.Discrete, values, [], create_new_on)) 
     513            elif var_t == variable.Python: 
     514                raise NotImplementedError() 
     515        elif var_t is None: 
     516            variables.append(_var_placeholder(name)) 
     517            undefined_vars.append((i, variables[-1])) 
     518             
     519    data = [] 
     520    for row in reader: 
     521        data.append(row) 
     522        for ind, var_def in undefined_vars: 
     523            var_def.values.add(row[ind]) 
     524     
     525    for ind, var_def in undefined_vars: 
     526        values = var_def.values - set(["?", ""]) # TODO: Other unknown strings? 
     527        values = sorted(values)   
     528        if isinstance(var_def, _disc_placeholder): 
     529            variables[ind] = variable.make(var_def.name, Orange.data.Type.Discrete, [], values, create_new_on) 
     530        elif isinstance(var_def, _var_placeholder): 
     531            if is_variable_cont(values): 
     532                variables[ind] = variable.make(var_def.name, Orange.data.Type.Continuous, [], [], create_new_on) 
     533            elif is_variable_discrete(values): 
     534                variables[ind] = variable.make(var_def.name, Orange.data.Type.Discrete, [], values, create_new_on) 
     535            elif is_variable_string(values): 
     536                variables[ind] = variable.make(var_def.name, Orange.data.Type.String, [], [], create_new_on) 
     537            else: 
     538                raise ValueError("Strange column in the data") 
     539     
     540    vars = [] 
     541    vars_load_status = [] 
     542    attribute_load_status = [] 
     543    meta_attribute_load_status = {} 
     544    class_var_load_status = [] 
     545    for var, status in vars: 
     546        vars.append(var) 
     547        vars_load_status.append(status) 
     548         
     549    attributes = [] 
     550    class_var = [] 
     551    metas = {} 
     552    for (var, status), var_attr in zip(variables, var_attrs): 
     553        if var_attr: 
     554            flag, attrs = var_attr 
     555            if flag == "class": 
     556                class_var.append(var) 
     557                class_var_load_status.append(status) 
     558            elif flag == "meta": 
     559                mid = Orange.core.newmetaid() 
     560                metas[mid] = var 
     561                meta_attribute_load_status[mid] = status 
     562            else: 
     563                attributes.append(var) 
     564                attribute_load_status.append(status) 
     565            var.attributes.update(attrs) 
     566        else: 
     567            attributes.append(var) 
     568            attribute_load_status.append(status) 
     569    if len(class_var) > 1: 
     570        raise ValueError("Multiple class variables defined") 
     571     
     572    class_var = class_var[0] if class_var else None 
     573     
     574    attribute_load_status += class_var_load_status 
     575     
     576    domain = Orange.data.Domain(attributes, class_var) 
     577    domain.add_metas(metas) 
     578    table = Orange.data.Table(domain, data) 
     579    table.metaAttributeLoadStatus = meta_attribute_load_status 
     580    table.attributeLoadStatus = attribute_load_status 
     581     
     582    return table 
     583 
     584def save_csv(filename, table, delimiter=",", include_orange): 
     585    pass 
     586 
     587 
    294588registerFileType("R", None, toR, ".R") 
    295589registerFileType("Weka", loadARFF, toARFF, ".arff") 
    296590#registerFileType("C50", None, toC50, [".names", ".data", ".test"]) 
    297591registerFileType("libSVM", loadLibSVM, toLibSVM, ".svm") 
     592 
     593#registerFileType("csv", load_csv, save_csv, ".csv") # Not yet fully tested, might conflict with builtin readers.  
Note: See TracChangeset for help on using the changeset viewer.