2016-09-04 6 views
4

Я пытаюсь приписать отсутствующие значения в Python, а sklearn не имеет метода вне среднего (среднего, медианного или режима) вменения. Orange imputation model, по-видимому, обеспечивает жизнеспособный вариант. Однако, как представляется, Orange.data.Table не признает np.nan или каким-то образом вменяется.вменять отсутствующие значения с использованием предсказательной модели

import Orange 
import numpy as np 

tmp = np.array([[1, 2, np.nan, 5, 8, np.nan], [40, 4, 8, 1, 0.2, 9]]) 
data = Orange.data.Table(tmp) 
imputer = Orange.feature.imputation.ModelConstructor() 
imputer.learner_continuous = Orange.classification.tree.TreeLearner(min_subset=20) 
imputer = imputer(data) 
impdata = imputer(data) 
for i in range(0, len(tmp)): 
    print impdata[i] 

Выход

[1.000, 2.000, 1.#QO, 5.000, 8.000, 1.#QO] 
[40.000, 4.000, 8.000, 1.000, 0.200, 9.000] 

Любая идея, что мне не хватает? Благодаря!

+0

Вы пытались заменить 'np.nan' на' None'? – pyCthon

+0

Когда я попробовал 'None', я получаю это' TypeError: недопустимые аргументы для конструктора (домена или примеров или обоих ожидаемых) '. – sedeh

ответ

2

Похоже, что недостающее значение в Orange представлено как ? или ~. Как ни странно, конструктор Orange.data.Table(numpy.ndarray) не делает вывод, что numpy.nan следует преобразовать в ? или ~ и вместо этого преобразует их в 1.#QO. Пользовательская функция ниже, pandas_to_orange(), решает эту проблему.

import Orange 
import numpy as np 
import pandas as pd 

from collections import OrderedDict 

# Adapted from https://github.com/biolab/orange3/issues/68 

def construct_domain(df): 
    columns = OrderedDict(df.dtypes) 

    def create_variable(col): 
     if col[1].__str__().startswith('float'): 
      return Orange.feature.Continuous(col[0]) 
     if col[1].__str__().startswith('int') and len(df[col[0]].unique()) > 50: 
      return Orange.feature.Continuous(col[0]) 
     if col[1].__str__().startswith('date'): 
      df[col[0]] = df[col[0]].values.astype(np.str) 
     if col[1].__str__() == 'object': 
      df[col[0]] = df[col[0]].astype(type("")) 
     return Orange.feature.Discrete(col[0], values = df[col[0]].unique().tolist()) 
    return Orange.data.Domain(list(map(create_variable, columns.items()))) 

def pandas_to_orange(df): 
    domain = construct_domain(df) 
    df[pd.isnull(df)]='?' 
    return Orange.data.Table(Orange.data.Domain(domain), df.values.tolist()) 

df = pd.DataFrame({'col1':[1, 2, np.nan, 4, 5, 6, 7, 8, 9, np.nan, 11], 
        'col2': [10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110.]}) 

tmp = pandas_to_orange(df) 
for i in range(0, len(tmp)): 
    print tmp[i] 

Выход:

[1.000, 10.000] 
[2.000, 20.000] 
[?, 30.000] 
[4.000, 40.000] 
[5.000, 50.000] 
[6.000, 60.000] 
[7.000, 70.000] 
[8.000, 80.000] 
[9.000, 90.000] 
[?, 100.000] 
[11.000, 110.000] 

Поэтому я хотел, чтобы правильно кодировать пропущенные значения так, я могу использовать библиотеку вменения Orange. Однако, похоже, что предсказательная древовидная модель в библиотеке не намного больше, чем простое среднее вменение. В частности, он вменяет одно и то же значение для всех отсутствующих значений.

imputer = Orange.feature.imputation.ModelConstructor() 
imputer.learner_continuous = Orange.classification.tree.TreeLearner(min_subset=20) 
imputer = imputer(tmp) 
impdata = imputer(tmp) 
for i in range(0, len(tmp)): 
    print impdata[i] 

Вот результат:

[1.000, 10.000] 
[2.000, 20.000] 
[5.889, 30.000] 
[4.000, 40.000] 
[5.000, 50.000] 
[6.000, 60.000] 
[7.000, 70.000] 
[8.000, 80.000] 
[9.000, 90.000] 
[5.889, 100.000] 
[11.000, 110.000] 

Я искал что-то, что будет соответствовать моделям, скажу Knn, на полных случаях и использовать подобранную модель для прогнозирования отсутствующих дел. fancyimpute (a Python 3 package) делает это, но бросает MemoryError на мой 300K + вход.

from fancyimpute import KNN 

df = pd.DataFrame({'col1':[1, 2, np.nan, 4, 5, 6, 7, 8, 9, np.nan, 11], 
        'col2': [10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110.]}) 

X_filled_knn = KNN(k=3).complete(df) 
X_filled_knn 

Выход:

array([[ 1.  , 10.  ], 
     [ 2.  , 20.  ], 
     [ 2.77777784, 30.  ], 
     [ 4.  , 40.  ], 
     [ 5.  , 50.  ], 
     [ 6.  , 60.  ], 
     [ 7.  , 70.  ], 
     [ 8.  , 80.  ], 
     [ 9.  , 90.  ], 
     [ 9.77777798, 100.  ], 
     [ 11.  , 110.  ]]) 

я, вероятно, может найти обходной путь или разделить набор данных на куски (не идеально).

1

В Orange v2 вы можете передавать массивы с маской в ​​маске в конструктор Orange.data.Table. Изменение вашего примера:

import Orange 
import numpy as np 

tmp = np.array([[1, 2, np.nan, 5, 8, np.nan], [40, 4, 8, 1, 0.2, 9]]) 
tmp_masked = np.ma.masked_array(tmp, mask=np.isnan(tmp)) 
data = Orange.data.Table(tmp_masked) 
imputer = Orange.feature.imputation.ModelConstructor() 
imputer.learner_continuous = Orange.classification.tree.TreeLearner(min_subset=20) 
imputer = imputer(data) 
impdata = imputer(data) 
for i in range(0, len(tmp)): 
    print impdata[i] 

 Смежные вопросы

  • Нет связанных вопросов^_^