[python] scikit-learn에서 여러 열의 레이블 인코딩

scikit-learn LabelEncoder을 사용하여 팬더 DataFrame문자열 문자열 을 인코딩 하려고합니다 . 데이터 프레임에 많은 (50+) 열 LabelEncoder이 있으므로 각 열에 대한 개체를 만드는 것을 피하고 싶습니다 . 차라리 모든 데이터 열에서 LabelEncoder작동하는 하나의 큰 객체가 있습니다 .

전체 DataFrame를 던지면 LabelEncoder아래 오류가 발생합니다. 여기에서 더미 데이터를 사용하고 있음을 명심하십시오. 실제로 약 50 열의 문자열 레이블이 지정된 데이터를 처리하므로 이름으로 열을 참조하지 않는 솔루션이 필요합니다.

import pandas
from sklearn import preprocessing

df = pandas.DataFrame({
    'pets': ['cat', 'dog', 'cat', 'monkey', 'dog', 'dog'],
    'owner': ['Champ', 'Ron', 'Brick', 'Champ', 'Veronica', 'Ron'],
    'location': ['San_Diego', 'New_York', 'New_York', 'San_Diego', 'San_Diego',
                 'New_York']
})

le = preprocessing.LabelEncoder()

le.fit(df)

역 추적 (가장 최근 호출) : 파일 “”, 1 행, 파일 “/Users/bbalin/anaconda/lib/python2.7/site-packages/sklearn/preprocessing/label.py”의 103 행, y에 적합 = column_or_1d (y, warn = True) column_or_1d의 파일 “/Users/bbalin/anaconda/lib/python2.7/site-packages/sklearn/utils/validation.py”, 306 행, value_Error ( “잘못된 입력 형태 { 0} “. format (shape)) ValueError : 잘못된 입력 모양 (6, 3)

이 문제를 해결하는 방법에 대한 생각이 있습니까?



답변

그래도 쉽게 할 수 있습니다.

df.apply(LabelEncoder().fit_transform)

EDIT2 :

scikit-learn 0.20에서 권장되는 방법은

OneHotEncoder().fit_transform(df)

OneHotEncoder는 이제 문자열 입력을 지원합니다. ColumnTransformer를 사용하면 특정 열에 만 OneHotEncoder를 적용 할 수 있습니다.

편집하다:

이 답변은 1 년 전에 끝났으며 현상금을 포함한 많은 공감대를 생성했기 때문에 아마도 이것을 더 확장해야합니다.

inverse_transform 및 transform의 경우 약간의 해킹이 필요합니다.

from collections import defaultdict
d = defaultdict(LabelEncoder)

이를 통해 이제 모든 열 LabelEncoder을 사전으로 유지합니다 .

# Encoding the variable
fit = df.apply(lambda x: d[x.name].fit_transform(x))

# Inverse the encoded
fit.apply(lambda x: d[x.name].inverse_transform(x))

# Using the dictionary to label future data
df.apply(lambda x: d[x.name].transform(x))


답변

larsmans가 언급했듯이 LabelEncoder ()는 1 차원 배열 만 인수로 사용 합니다. 즉, 선택한 여러 열에서 작동하고 변환 된 데이터 프레임을 반환하는 자체 레이블 인코더를 롤링하는 것은 매우 쉽습니다. 여기 내 코드는 Zac Stewart의 훌륭한 블로그 게시물에 있습니다 .

사용자 지정 인코더를 만들기 단순히 클래스를 만드는 작업이 포함됩니다 그에게 응답 fit(), transform()fit_transform()방법. 귀하의 경우 좋은 시작은 다음과 같습니다.

import pandas as pd
from sklearn.preprocessing import LabelEncoder
from sklearn.pipeline import Pipeline

# Create some toy data in a Pandas dataframe
fruit_data = pd.DataFrame({
    'fruit':  ['apple','orange','pear','orange'],
    'color':  ['red','orange','green','green'],
    'weight': [5,6,3,4]
})

class MultiColumnLabelEncoder:
    def __init__(self,columns = None):
        self.columns = columns # array of column names to encode

    def fit(self,X,y=None):
        return self # not relevant here

    def transform(self,X):
        '''
        Transforms columns of X specified in self.columns using
        LabelEncoder(). If no columns specified, transforms all
        columns in X.
        '''
        output = X.copy()
        if self.columns is not None:
            for col in self.columns:
                output[col] = LabelEncoder().fit_transform(output[col])
        else:
            for colname,col in output.iteritems():
                output[colname] = LabelEncoder().fit_transform(col)
        return output

    def fit_transform(self,X,y=None):
        return self.fit(X,y).transform(X)

숫자 속성 만 남겨두고 두 범주 형 속성 ( fruitcolor) 을 인코딩하려고한다고 가정 합니다 weight. 우리는 다음과 같이 할 수 있습니다 :

MultiColumnLabelEncoder(columns = ['fruit','color']).fit_transform(fruit_data)

어떤 우리의 변환 fruit_data에서 데이터 집합을

여기에 이미지 설명을 입력하십시오

여기에 이미지 설명을 입력하십시오

전적으로 범주 형 변수로 구성된 데이터 프레임을 전달하고 columns매개 변수를 생략하면 모든 열이 인코딩됩니다 (원래 찾고있는 것으로 생각합니다).

MultiColumnLabelEncoder().fit_transform(fruit_data.drop('weight',axis=1))

이것은 변환

여기에 이미지 설명을 입력하십시오

여기에 이미지 설명을 입력하십시오.

이미 숫자 인 속성을 인코딩하려고 할 때 질식 할 수 있습니다 (원하는 경우이를 처리하는 코드를 추가하십시오).

이것에 대한 또 다른 좋은 특징은 파이프 라인 에서이 맞춤형 변압기를 사용할 수 있다는 것입니다.

encoding_pipeline = Pipeline([
    ('encoding',MultiColumnLabelEncoder(columns=['fruit','color']))
    # add more pipeline steps as needed
])
encoding_pipeline.fit_transform(fruit_data)


답변

0.20 scikit이 배우기 때문에 당신이 사용할 수있는 sklearn.compose.ColumnTransformersklearn.preprocessing.OneHotEncoder:

범주 형 변수 만있는 경우 OneHotEncoder직접 :

from sklearn.preprocessing import OneHotEncoder

OneHotEncoder(handle_unknown='ignore').fit_transform(df)

유형이 다른 유형의 기능이있는 경우 :

from sklearn.compose import make_column_transformer
from sklearn.preprocessing import RobustScaler
from sklearn.preprocessing import OneHotEncoder

categorical_columns = ['pets', 'owner', 'location']
numerical_columns = ['age', 'weigth', 'height']
column_trans = make_column_transformer(
    (categorical_columns, OneHotEncoder(handle_unknown='ignore'),
    (numerical_columns, RobustScaler())
column_trans.fit_transform(df)

설명서의 추가 옵션 : http://scikit-learn.org/stable/modules/compose.html#columntransformer-for-heterogeneous-data


답변

LabelEncoder가 필요하지 않습니다.

열을 범주 형으로 변환 한 다음 해당 코드를 가져올 수 있습니다. 아래의 사전 이해를 사용하여이 프로세스를 모든 열에 적용하고 결과를 동일한 인덱스 및 열 이름을 가진 동일한 모양의 데이터 프레임으로 다시 래핑했습니다.

>>> pd.DataFrame({col: df[col].astype('category').cat.codes for col in df}, index=df.index)
   location  owner  pets
0         1      1     0
1         0      2     1
2         0      0     0
3         1      1     2
4         1      3     1
5         0      2     1

매핑 사전을 만들려면 사전 이해를 사용하여 범주를 열거하면됩니다.

>>> {col: {n: cat for n, cat in enumerate(df[col].astype('category').cat.categories)}
     for col in df}

{'location': {0: 'New_York', 1: 'San_Diego'},
 'owner': {0: 'Brick', 1: 'Champ', 2: 'Ron', 3: 'Veronica'},
 'pets': {0: 'cat', 1: 'dog', 2: 'monkey'}}


답변

이것은 귀하의 질문에 직접 답변하지 않습니다 (Naputipulu Jon과 PriceHardman은 환상적인 답글을 가지고 있습니다)

그러나 몇 가지 분류 작업 등의 목적으로 사용할 수 있습니다.

pandas.get_dummies(input_df) 

이것은 범주 형 데이터로 데이터 프레임을 입력하고 이진 값을 가진 데이터 프레임을 반환 할 수 있습니다. 변수 값은 결과 데이터 프레임에서 열 이름으로 인코딩됩니다.


답변

단순히 sklearn.preprocessing.LabelEncoder()열을 나타내는 데 사용할 수 있는 객체 를 얻으려고한다고 가정하면 다음과 같이하면 됩니다.

le.fit(df.columns)

위의 코드에는 각 열에 해당하는 고유 번호가 있습니다. 1 매핑 : 더 정확하게, 당신은 일 것 df.columns까지를 le.transform(df.columns.get_values()). 열의 인코딩을 얻으려면 간단히 전달하십시오 le.transform(...). 예를 들어, 다음은 각 열에 대한 인코딩을 가져옵니다.

le.transform(df.columns.get_values())

sklearn.preprocessing.LabelEncoder()모든 행 레이블에 대한 오브젝트 를 작성한다고 가정하면 다음을 수행 할 수 있습니다.

le.fit([y for x in df.get_values() for y in x])

이 경우 질문에 표시된 것처럼 고유하지 않은 행 레이블이있을 가능성이 큽니다. 인코더가 생성 한 클래스를 확인하려면 수행 할 수 있습니다 le.classes_. 이것과의 요소는 동일해야합니다 set(y for x in df.get_values() for y in x). 다시 한 번 행 레이블을 인코딩 된 레이블로 변환하려면 사용하십시오 le.transform(...). 예를 들어 df.columns배열의 첫 번째 열과 첫 번째 행 의 레이블을 검색하려는 경우 다음을 수행 할 수 있습니다.

le.transform([df.get_value(0, df.columns[0])])

귀하의 의견에 대한 질문은 조금 더 복잡하지만 여전히 달성 할 수 있습니다.

le.fit([str(z) for z in set((x[0], y) for x in df.iteritems() for y in x[1])])

위의 코드는 다음을 수행합니다.

  1. (열, 행)의 모든 쌍을 고유하게 조합하십시오.
  2. 각 쌍을 튜플의 문자열 버전으로 나타냅니다. 이 해결 방법은LabelEncoder 튜플을 클래스 이름으로 지원하지 않는 클래스 입니다.
  3. 새 항목을에 맞 춥니 다 LabelEncoder.

이 새로운 모델을 사용하려면 조금 더 복잡합니다. 이전 예제에서 찾은 것과 동일한 항목 (df.columns의 첫 번째 열과 첫 번째 행)에 대한 표현을 추출한다고 가정하면 다음을 수행 할 수 있습니다.

le.transform([str((df.columns[0], df.get_value(0, df.columns[0])))])

각 조회는 이제 (열, 행)을 포함하는 튜플의 문자열 표현입니다.


답변

아니요, LabelEncoder이 작업을 수행하지 않습니다. 클래스 레이블의 1 차원 배열을 취하고 1 차원 배열을 생성합니다. 클래스 레이블을 임의의 데이터가 아닌 분류 문제에서 처리하도록 설계되었으며 다른 용도로 강요하려고 시도하면 실제 문제를 해결하는 문제 (및 원래 공간으로 솔루션을 다시 변환)하는 코드가 필요합니다.