Python sklearn-pandas Преобразование нескольких столбцов одновременно с ошибкой

Я использую python с pandas и sklearn и пытаюсь использовать новый и очень удобный sklearn-pandas.

У меня есть большой фрейм данных, и мне нужно аналогичным образом преобразовать несколько столбцов.

У меня есть несколько имен столбцов в переменной other, в документации по исходному коду здесь указано явно существует возможность преобразования нескольких столбцов одним и тем же преобразованием, но следующий код ведет себя не так, как ожидалось:

from sklearn.preprocessing import MinMaxScaler, LabelEncoder

mapper = DataFrameMapper([[other[0],other[1]],LabelEncoder()])
mapper.fit_transform(df.copy())

Я получаю следующую ошибку:

поднять ValueError("плохая форма ввода {0}".format(shape)) ValueError: ['EFW', 'BPD']: неверная форма ввода (154, 2)

Когда я использую следующий код, он отлично работает:

cols = [(other[i], LabelEncoder()) for i,col in enumerate(other)]
mapper = DataFrameMapper(cols)
mapper.fit_transform(df.copy())

Насколько я понимаю, оба должны работать хорошо и давать одинаковые результаты. Что я здесь делаю неправильно?

Спасибо!


person thebeancounter    schedule 07.11.2017    source источник


Ответы (1)


Проблема, с которой вы здесь столкнетесь, заключается в том, что два фрагмента кода совершенно различны с точки зрения структуры данных.

cols = [(other[i], LabelEncoder()) for i,col in enumerate(other)] строит список кортежей. Обратите внимание, что вы можете сократить эту строку кода до:

cols = [(col, LabelEncoder()) for col in other]

В любом случае, первый фрагмент [[other[0],other[1]],LabelEncoder()] приводит к списку, содержащему два элемента: список и экземпляр LabelEncoder. Теперь документировано, что вы можете преобразовать несколько столбцов, указав:

Для преобразований может потребоваться несколько входных столбцов. В этих случаях имена столбцов можно указать в виде списка:

mapper2 = DataFrameMapper([ (['дети', 'зарплата'], sklearn.decomposition.PCA(1)) ])

Это list, содержащий tuple(list, object) структурированных элементов, а не list[list, object] структурированных элементов.

Если мы посмотрим на сам исходный код,

class DataFrameMapper(BaseEstimator, TransformerMixin):
    """
    Map Pandas data frame column subsets to their own
    sklearn transformation.
    """

    def __init__(self, features, default=False, sparse=False, df_out=False,
                 input_df=False):
        """
        Params:
        features    a list of tuples with features definitions.
                    The first element is the pandas column selector. This can
                    be a string (for one column) or a list of strings.
                    The second element is an object that supports
                    sklearn's transform interface, or a list of such objects.
                    The third element is optional and, if present, must be
                    a dictionary with the options to apply to the
                    transformation. Example: {'alias': 'day_of_week'}

В определении класса также четко указано, что аргумент features для DataFrameMapper должен быть списком кортежей, где элементы кортежа могут быть списками.

И последнее замечание о том, почему вы на самом деле получаете сообщение об ошибке: преобразователь LabelEncoder в sklearn предназначен для маркировки одномерных массивов. Таким образом, он принципиально не может обрабатывать 2 столбца одновременно и вызовет исключение. Итак, если вы хотите использовать LabelEncoder, вам нужно будет построить N кортежей с 1 именем столбца и преобразователем, где N — количество столбцов, которые вы хотите преобразовать.

person Uvar    schedule 07.11.2017
comment
А ошибка пропадает, если использовать MinMaxScaler() вместо LabelEncoder()? -- похоже, что LabelEncoder не может работать с несколькими столбцами одновременно, а еще лучше... явно проверяет данные 1D. - person Uvar; 07.11.2017
comment
@captainshai Да. LabelEncoder предназначен для меток и обрабатывает только одномерные массивы. Для каждого столбца, который вы хотите преобразовать, вам нужно использовать отдельный LabelEncoder(). - person Vivek Kumar; 08.11.2017