标签编码器编码缺失值
Posted
技术标签:
【中文标题】标签编码器编码缺失值【英文标题】:label-encoder encoding missing values 【发布时间】:2016-08-16 22:43:41 【问题描述】:我正在使用标签编码器将分类数据转换为数值。
LabelEncoder 如何处理缺失值?
from sklearn.preprocessing import LabelEncoder
import pandas as pd
import numpy as np
a = pd.DataFrame(['A','B','C',np.nan,'D','A'])
le = LabelEncoder()
le.fit_transform(a)
输出:
array([1, 2, 3, 0, 4, 1])
对于上面的示例,标签编码器将 NaN 值更改为类别。我怎么知道哪个类别代表缺失值?
【问题讨论】:
***.com/a/60186800/10375049 【参考方案1】:这是我的尝试!
import numpy as np
from sklearn.preprocessing import LabelEncoder
le = LabelEncoder()
#Now lets encode the incomplete Cabin feature
titanic_train_le['Cabin'] = le.fit_transform(titanic_train_le['Cabin'].astype(str))
#get nan code for the cabin categorical feature
cabin_nan_code=le.transform(['nan'])[0]
#Now, retrieve the nan values in the encoded data
titanic_train_le['Cabin'].replace(cabin_nan_code,np.nan,inplace=True)
【讨论】:
请在您的回答中提供更多详细信息。正如目前所写的那样,很难理解您的解决方案。 请添加更多详细信息以扩展您的答案,例如工作代码或文档引用。【参考方案2】: 我想和你分享我的解决方案。 我创建了一个模块,它采用混合数据集并将其从分类转换为数值 和逆。这个模块也可以在my Github 中找到,并带有示例。 如果您喜欢我的解决方案,请点赞。
谢谢, 伊丹
class label_encoder_contain_missing_values :
def __init__ (self) :
pass
def categorical_to_numeric (self,dataset):
import numpy as np
import pandas as pd
self.dataset = dataset
self.summary = None
self.table_encoder=
for index in self.dataset.columns :
if self.dataset[index].dtypes == 'object' :
column_data_frame = pd.Series(self.dataset[index],name='column').to_frame()
unique_values = pd.Series(self.dataset[index].unique())
i = 0
label_encoder = pd.DataFrame('value_name':[],'Encode':[])
while i <= len(unique_values)-1:
if unique_values.isnull()[i] == True :
label_encoder = label_encoder.append('value_name': unique_values[i],'Encode':np.nan, ignore_index=True) #np.nan = -1
else:
label_encoder = label_encoder.append('value_name': unique_values[i],'Encode':i, ignore_index=True)
i+=1
output = pd.merge(left=column_data_frame,right = label_encoder, how='left',left_on='column',right_on='value_name')
self.summary = output[['column','Encode']].drop_duplicates().reset_index(drop=True)
self.dataset[index] = output.Encode
self.table_encoder.update(index:self.summary)
else :
pass
# ---- Show Encode Table ----- #
print('''\nLabel Encoding completed in Successfully.\n
Next steps: \n
1. To view table_encoder, Execute the follow: \n
for index in table_encoder :
print(f'\\nindex \\n',table_encoder[index])
2. For inverse, execute the follow : \n
df = label_encoder_contain_missing_values().
inverse_numeric_to_categorical(table_encoder, df) ''')
return self.table_encoder ,self.dataset
def inverse_numeric_to_categorical (self,table_encoder, df):
dataset = df.copy()
for column in table_encoder.keys():
df_column = df[column].to_frame()
output = pd.merge(left=df_column,right = table_encoder[column], how='left',left_on= column,right_on='Encode')#.rename(columns='column_x' :'encode','column_y':'category')
df[column]= output.column
print('\nInverse Label Encoding, from categorical to numerical completed in Successfully.\n')
return df
**execute command from categorical to numerical** <br>
table_encoder, df = label_encoder_contain_missing_values().categorical_to_numeric(df)
**execute command from numerical to categorical** <br>
df = label_encoder_contain_missing_values().inverse_numeric_to_categorical(table_encoder, df)
【讨论】:
【参考方案3】:此函数从数据框中获取一列并返回仅对非 NaN 进行标签编码的列,其余部分保持不变
import pandas as pd
from sklearn.preprocessing import LabelEncoder
def label_encode_column(col):
nans = col.isnull()
nan_lst = []
nan_idx_lst = []
label_lst = []
label_idx_lst = []
for idx, nan in enumerate(nans):
if nan:
nan_lst.append(col[idx])
nan_idx_lst.append(idx)
else:
label_lst.append(col[idx])
label_idx_lst.append(idx)
nan_df = pd.DataFrame(nan_lst, index=nan_idx_lst)
label_df = pd.DataFrame(label_lst, index=label_idx_lst)
label_encoder = LabelEncoder()
label_df = label_encoder.fit_transform(label_df.astype(str))
label_df = pd.DataFrame(label_df, index=label_idx_lst)
final_col = pd.concat([label_df, nan_df])
return final_col.sort_index()
【讨论】:
【参考方案4】:这是我的解决方案,因为我对此处发布的解决方案不满意。我需要一个 LabelEncoder
将我的缺失值保留为 NaN
以便之后使用 Imputer。所以我写了我自己的LabelEncoder
类。它适用于 DataFrame。
from sklearn.base import BaseEstimator
from sklearn.base import TransformerMixin
from sklearn.preprocessing import LabelEncoder
class LabelEncoderByCol(BaseEstimator, TransformerMixin):
def __init__(self,col):
#List of column names in the DataFrame that should be encoded
self.col = col
#Dictionary storing a LabelEncoder for each column
self.le_dic =
for el in self.col:
self.le_dic[el] = LabelEncoder()
def fit(self,x,y=None):
#Fill missing values with the string 'NaN'
x[self.col] = x[self.col].fillna('NaN')
for el in self.col:
#Only use the values that are not 'NaN' to fit the Encoder
a = x[el][x[el]!='NaN']
self.le_dic[el].fit(a)
return self
def transform(self,x,y=None):
#Fill missing values with the string 'NaN'
x[self.col] = x[self.col].fillna('NaN')
for el in self.col:
#Only use the values that are not 'NaN' to fit the Encoder
a = x[el][x[el]!='NaN']
#Store an ndarray of the current column
b = x[el].to_numpy()
#Replace the elements in the ndarray that are not 'NaN'
#using the transformer
b[b!='NaN'] = self.le_dic[el].transform(a)
#Overwrite the column in the DataFrame
x[el]=b
#return the transformed DataFrame
return x
您可以输入 DataFrame,而不仅仅是 1-dim Series。使用 col 你可以选择应该编码的列。
我想在这里提供一些反馈。
【讨论】:
我使用了newdf = LabelEncoderByCol(df)
- 现在如何将其转换为熊猫?
如果测试集的值不在训练集中怎么办。
@whatsnext 它与原始的 LabelEncoder 具有相同的行为,但具有看不见的值。您可能需要一些额外的行来实现体面的行为。参考:***.com/questions/21057621/…如果您编辑我的答案以改进,我会批准。
能否包含inverse_transform函数?【参考方案5】:
您可以通过将缺失值替换为字符串“NaN”来处理缺失值。类别可以通过le.transfrom()获取。
le.fit_transform(a.fillna('NaN'))
category = le.transform(['NaN'])
另一种解决方案是标签编码器忽略缺失值。
a = le.fit_transform(a.astype(str))
【讨论】:
【参考方案6】:@Kerem 投票最多的答案有错别字,因此我在此处发布更正和改进的答案:
from sklearn.preprocessing import LabelEncoder
import pandas as pd
import numpy as np
a = pd.DataFrame(['A','B','C',np.nan,'D','A'])
for j in a.columns.values:
le = LabelEncoder()
### fit with the desired col, col in position 0 for this ###example
fit_by = pd.Series([i for i in a[j].unique() if type(i) == str])
le.fit(fit_by)
### Set transformed col leaving np.NaN as they are
a["transformed"] = a[j].apply(lambda x: le.transform([x])[0] if type(x) == str else x)
【讨论】:
【参考方案7】:您也可以使用掩码替换标记后的原始数据框
df = pd.DataFrame('A': ['x', np.NaN, 'z'], 'B': [1, 6, 9], 'C': [2, 1, np.NaN])
A B C
0 x 1 2.0
1 NaN 6 1.0
2 z 9 NaN
original = df
mask = df_1.isnull()
A B C
0 False False False
1 True False False
2 False False True
df = df.astype(str).apply(LabelEncoder().fit_transform)
df.where(~mask, original)
A B C
0 1.0 0 1.0
1 NaN 1 0.0
2 2.0 2 NaN
【讨论】:
【参考方案8】:我也想贡献我的解决方法,因为在处理包含缺失值的分类数据时,我发现其他解决方法有点乏味
# Create a random dataframe
foo = pd.DataFrame(np.random.randint(0,100,size=(100, 4)), columns=list('ABCD'))
# Randomly intersperse column 'A' with missing data (NaN)
foo['A'][np.random.randint(0,len(foo), size=20)] = np.nan
# Convert this series to string, to simulate our problem
series = foo['A'].astype(str)
# np.nan are converted to the string "nan", mask these out
mask = (series == "nan")
# Apply the LabelEncoder to the unmasked series, replace the masked series with np.nan
series[~mask] = LabelEncoder().fit_transform(series[~mask])
series[mask] = np.nan
foo['A'] = series
【讨论】:
【参考方案9】:这是一个简单的方法
是Titanic的例子
LABEL_COL = ["Sex", "Embarked"]
def label(df):
_df = df.copy()
le = LabelEncoder()
for col in LABEL_COL:
# Not NaN index
idx = ~_df[col].isna()
_df.loc[idx, col] \
= le.fit(_df.loc[idx, col]).transform(_df.loc[idx, col])
return _df
【讨论】:
很好,您可以立即使用 fit_transform:_df.loc[idx, col] = le.fit_transform(_df.loc[idx, col])【参考方案10】:我就是这样做的:
import pandas as pd
from sklearn.preprocessing import LabelEncoder
UNKNOWN_TOKEN = '<unknown>'
a = pd.Series(['A','B','C', 'D','A'], dtype=str).unique().tolist()
a.append(UNKNOWN_TOKEN)
le = LabelEncoder()
le.fit_transform(a)
embedding_map = dict(zip(le.classes_, le.transform(le.classes_)))
当应用于新的测试数据时:
test_df = test_df.apply(lambda x: x if x in embedding_map else UNKNOWN_TOKEN)
le.transform(test_df)
【讨论】:
【参考方案11】:以下编码器地址每个类别中都没有值。
class MultiColumnLabelEncoder:
def __init__(self):
self.columns = None
self.led = defaultdict(preprocessing.LabelEncoder)
def fit(self, X):
self.columns = X.columns
for col in self.columns:
cat = X[col].unique()
cat = [x if x is not None else "None" for x in cat]
self.led[col].fit(cat)
return self
def fit_transform(self, X):
if self.columns is None:
self.fit(X)
return self.transform(X)
def transform(self, X):
return X.apply(lambda x: self.led[x.name].transform(x.apply(lambda e: e if e is not None else "None")))
def inverse_transform(self, X):
return X.apply(lambda x: self.led[x.name].inverse_transform(x))
使用示例
df = pd.DataFrame(
'pets': ['cat', 'dog', 'cat', 'monkey', 'dog', 'dog'],
'owner': ['Champ', 'Ron', 'Brick', None, 'Veronica', 'Ron'],
'location': ['San_Diego', 'New_York', 'New_York', 'San_Diego', 'San_Diego',
None]
)
print(df)
location owner pets
0 San_Diego Champ cat
1 New_York Ron dog
2 New_York Brick cat
3 San_Diego None monkey
4 San_Diego Veronica dog
5 None Ron dog
le = MultiColumnLabelEncoder()
le.fit(df)
transformed = le.transform(df)
print(transformed)
location owner pets
0 2 1 0
1 0 3 1
2 0 0 0
3 2 2 2
4 2 4 1
5 1 3 1
inverted = le.inverse_transform(transformed)
print(inverted)
location owner pets
0 San_Diego Champ cat
1 New_York Ron dog
2 New_York Brick cat
3 San_Diego None monkey
4 San_Diego Veronica dog
5 None Ron dog
【讨论】:
【参考方案12】:您好,我为自己的工作做了一点计算技巧:
from sklearn.preprocessing import LabelEncoder
import pandas as pd
import numpy as np
a = pd.DataFrame(['A','B','C',np.nan,'D','A'])
le = LabelEncoder()
### fit with the desired col, col in position 0 for this example
fit_by = pd.Series([i for i in a.iloc[:,0].unique() if type(i) == str])
le.fit(fit_by)
### Set transformed col leaving np.NaN as they are
a["transformed"] = fit_by.apply(lambda x: le.transform([x])[0] if type(x) == str else x)
【讨论】:
fit_by
是一个列表,列表没有.apply()
方法,请更正
他的回答可能只是一个错字。使用 apply(function,axis=1) 或 map。例如:df['col'] = df['col'].map(lambda x: le.transform([x])[0] if type(x)==str else x)【参考方案13】:
您可以用一些值填充 na,然后将数据框列类型更改为字符串以使其正常工作。
from sklearn.preprocessing import LabelEncoder
import pandas as pd
import numpy as np
a = pd.DataFrame(['A','B','C',np.nan,'D','A'])
a.fillna(99)
le = LabelEncoder()
le.fit_transform(a.astype(str))
【讨论】:
【参考方案14】:我遇到了同样的问题,但以上方法都不适合我。所以我在只包含“nan”的训练数据中添加了一个新行
【讨论】:
【参考方案15】:不要使用带有缺失值的LabelEncoder
。我不知道您使用的是哪个版本的 scikit-learn
,但在 0.17.1 中,您的代码会引发 TypeError: unorderable types: str() > float()
。
如您所见,in the source 它使用numpy.unique
对数据进行编码,如果发现缺失值,则会引发TypeError
。如果要对缺失值进行编码,首先将其类型改为字符串:
a[pd.isnull(a)] = 'NaN'
【讨论】:
所以您会将“NaN”编码为虚拟值?我有同样的问题,但想使用估算值进行线性回归。 模型对缺失值 (nan) 和“Nan”的处理方式不同。一种解决方法是仅使用具有非缺失值的 LabelEnconder,并让 nan 值保持不变: df['col'] = df['col'].map(lambda x: le.transform([x])[0] if type(x)==str else x)以上是关于标签编码器编码缺失值的主要内容,如果未能解决你的问题,请参考以下文章
详解支持向量机-SVC真实数据案例:预测明天是否会下雨-填补缺失值和编码菜菜的sklearn课堂笔记
R语言构建xgboost模型:使用xgboost模型训练tweedie回归模型,特征工程(dataframe转化到data.table独热编码缺失值删除DMatrix结构生成)
R语言使用caret包的predict函数对测试数据集进行数据预处理(和训练集的处理方式保持一致):缺失值填充数值变量最小最大缩放因子变量独热编码等
集成学习模型(xgboostlightgbmcatboost)进行回归预测构建实战:异常数据处理缺失值处理数据重采样resample独热编码预测特征检查特征可视化预测结构可视化模型