Converting Pandas DataFrame to Orange Table

后端 未结 7 1651
感动是毒
感动是毒 2020-12-08 17:18

I notice that this is an issue on GitHub already. Does anyone have any code that converts a Pandas DataFrame to an Orange Table?

Explicitly, I have the following tab

相关标签:
7条回答
  • 2020-12-08 17:35

    In order to convert pandas DataFrame to Orange Table you need to construct a domain, which specifies the column types.

    For continuous variables, you only need to provide the name of the variable, but for Discrete variables, you also need to provide a list of all possible values.

    The following code will construct a domain for your DataFrame and convert it to an Orange Table:

    import numpy as np
    from Orange.feature import Discrete, Continuous
    from Orange.data import Domain, Table
    domain = Domain([
        Discrete('user', values=[str(v) for v in np.unique(df.user)]),
        Discrete('hotel', values=[str(v) for v in np.unique(df.hotel)]),
        Continuous('star_rating'),
        Discrete('user', values=[str(v) for v in np.unique(df.user)]),
        Discrete('home_continent', values=[str(v) for v in np.unique(df.home_continent)]),
        Discrete('gender', values=['male', 'female'])], False)
    table = Table(domain, [map(str, row) for row in df.as_matrix()])
    

    The map(str, row) step is needed so Orange know that the data contains values of discrete features (and not the indices of values in the values list).

    0 讨论(0)
  • 2020-12-08 17:36
    from Orange.data.pandas_compat import table_from_frame,table_to_frame
    df= table_to_frame(in_data)
    #here you go
    out_data = table_from_frame(df)
    

    based on answer of Creo

    0 讨论(0)
  • 2020-12-08 17:39

    Something like this?

    table = Orange.data.Table(df.as_matrix())
    

    The columns in Orange will get generic names (a1, a2...). If you want to copy the names and the types from the data frame, construct Orange.data.Domain object (http://docs.orange.biolab.si/reference/rst/Orange.data.domain.html#Orange.data.Domain.init) from the data frame and pass it as the first argument above.

    See the constructors in http://docs.orange.biolab.si/reference/rst/Orange.data.table.html.

    0 讨论(0)
  • 2020-12-08 17:47

    Answer below from a closed issue on github

    from Orange.data.pandas_compat import table_from_frame
    out_data = table_from_frame(df)
    

    Where df is your dataFrame. So far I've only noticed a need to manually define a domain to handle dates if the data source wasn't 100% clean and to the required ISO standard.

    I realize this is an old question and a lot changed from when it was first asked - but this question comes up top on google search results on the topic.

    0 讨论(0)
  • 2020-12-08 17:49

    This code is revised from @TurtleIzzy for Python3.

    import numpy as np
    from Orange.data import Table, Domain, ContinuousVariable, DiscreteVariable
    
    
    def series2descriptor(d):
        if d.dtype is np.dtype("float") or d.dtype is np.dtype("int"):
            return ContinuousVariable(str(d.name))
        else:
            t = d.unique()
            t.sort()
            return DiscreteVariable(str(d.name), list(t.astype("str")))
    
    def df2domain(df):
        featurelist = [series2descriptor(df.iloc[:,col]) for col in range(len(df.columns))]
        return Domain(featurelist)
    
    def df2table(df):
        tdomain = df2domain(df)
        ttables = [series2table(df.iloc[:,i], tdomain[i]) for i in range(len(df.columns))]
        ttables = np.array(ttables).reshape((len(df.columns),-1)).transpose()
        return Table(tdomain , ttables)
    
    def series2table(series, variable):
        if series.dtype is np.dtype("int") or series.dtype is np.dtype("float"):
            series = series.values[:, np.newaxis]
            return Table(series)
        else:
            series = series.astype('category').cat.codes.reshape((-1,1))
            return Table(series)
    
    0 讨论(0)
  • 2020-12-08 17:51

    table_from_frame, which is available in Python 3, doesn't allow the definition of a class column and therefore, the generated table cannot be used directly to train a classification model. I tweaked the table_from_frame function so it'll allow the definition of a class column. Notice that the class name should be given as an additional parameter.

    """Pandas DataFrame↔Table conversion helpers"""
    import numpy as np
    import pandas as pd
    from pandas.api.types import (
        is_categorical_dtype, is_object_dtype,
        is_datetime64_any_dtype, is_numeric_dtype,
    )
    
    from Orange.data import (
        Table, Domain, DiscreteVariable, StringVariable, TimeVariable,
        ContinuousVariable,
    )
    
    __all__ = ['table_from_frame', 'table_to_frame']
    
    
    def table_from_frame(df,class_name, *, force_nominal=False):
        """
        Convert pandas.DataFrame to Orange.data.Table
    
        Parameters
        ----------
        df : pandas.DataFrame
        force_nominal : boolean
            If True, interpret ALL string columns as nominal (DiscreteVariable).
    
        Returns
        -------
        Table
        """
    
        def _is_discrete(s):
            return (is_categorical_dtype(s) or
                    is_object_dtype(s) and (force_nominal or
                                            s.nunique() < s.size**.666))
    
        def _is_datetime(s):
            if is_datetime64_any_dtype(s):
                return True
            try:
                if is_object_dtype(s):
                    pd.to_datetime(s, infer_datetime_format=True)
                    return True
            except Exception:  # pylint: disable=broad-except
                pass
            return False
    
        # If df index is not a simple RangeIndex (or similar), put it into data
        if not (df.index.is_integer() and (df.index.is_monotonic_increasing or
                                           df.index.is_monotonic_decreasing)):
            df = df.reset_index()
    
        attrs, metas,calss_vars = [], [],[]
        X, M = [], []
    
        # Iter over columns
        for name, s in df.items():
            name = str(name)
            if name == class_name:
                discrete = s.astype('category').cat
                calss_vars.append(DiscreteVariable(name, discrete.categories.astype(str).tolist()))
                X.append(discrete.codes.replace(-1, np.nan).values)
            elif _is_discrete(s):
                discrete = s.astype('category').cat
                attrs.append(DiscreteVariable(name, discrete.categories.astype(str).tolist()))
                X.append(discrete.codes.replace(-1, np.nan).values)
            elif _is_datetime(s):
                tvar = TimeVariable(name)
                attrs.append(tvar)
                s = pd.to_datetime(s, infer_datetime_format=True)
                X.append(s.astype('str').replace('NaT', np.nan).map(tvar.parse).values)
            elif is_numeric_dtype(s):
                attrs.append(ContinuousVariable(name))
                X.append(s.values)
            else:
                metas.append(StringVariable(name))
                M.append(s.values.astype(object))
    
        return Table.from_numpy(Domain(attrs, calss_vars, metas),
                                np.column_stack(X) if X else np.empty((df.shape[0], 0)),
                                None,
                                np.column_stack(M) if M else None)
    
    0 讨论(0)
提交回复
热议问题