为什么 OneHotEncoder 最多只适用于 5 个不同的分类变量值?
Why does OneHotEncoder only work for up to 5 different categorical variable values?
我注意到当分类变量列有 6 个或更多类别时,OneHotEncoder 会失败。
例如,我有一个包含两列的 TestData.csv 文件:Geography 和 Continent。
地理的不同值是法国、西班牙、肯尼亚、博茨瓦纳和尼日利亚,而大陆的不同值是欧洲和非洲。
我的目标是使用 OneHotEncoder 对地理列进行编码。我执行以下代码来执行此操作:
import numpy as np
import pandas as pd
#Importing the dataset
dataset = pd.read_csv('TestData.csv')
X = dataset.iloc[:,:].values #X is hence a 2-dimensional numpy.ndarray
#Encoding categorical column Geography
from sklearn.preprocessing import OneHotEncoder
from sklearn.compose import ColumnTransformer
ct = ColumnTransformer(transformers=[('encoder', OneHotEncoder(), [0])], remainder='passthrough') #the 0 is the column index for the categorical column we want to encode, in this case Geography
X = np.array(ct.fit_transform(X))
然后我 print(X)
以确保我得到预期的输出,它看起来像这样 (还要注意 X 的大小):
但是,如果我向 TestData 文件添加一个新国家/地区,假设是比利时。我们现在有 6 个不同的国家。现在 运行 完全相同的代码产生以下内容:
在第
行失败
X = np.array(ct.fit_transform(X))
如您所见,X 没有改变,也没有完成编码。我已经多次测试过这个。所以看起来 OneHotEncoder 最多只能处理 5 个不同的类别值。
是否有我可以更改的参数或我可以执行的其他方法来对具有 5 个以上值的分类变量进行编码?
PS - 我知道在编码后删除虚拟变量 ;)
我是运行Python3.7.7
谢谢!
我认为问题出在 ColumnTransformer 中的“sparse_threshold”参数。尝试将其设置为 0,以便所有输出 numpy 数组都是密集的。您的输出密度低于 0.3(默认值),这会提示它尝试切换到稀疏数组,但它仍然包含字符串列 Continent 并且稀疏数组不能包含字符串。
我注意到您已经在使用 pandas
。那么还有一种方法就是使用one-hot encoding。 是您问题的更好答案。我的回答更像是一个扩展评论。
正在准备类似于您的示例数据。
import numpy as np
import pandas as pd
a = np.random.choice(['afr','deu','swe','fi','rus','eng','wu'], 40)
b = np.random.choice(['eu','as'], 40)
df = pd.DataFrame({'a':a, 'b':b})
df.head()
输出
a b
0 rus as
1 eng as
2 fi eu
3 swe eu
4 eng eu
您可以使用 get_dummies
进行单热编码
pd.get_dummies(df, columns=['a'])
输出(剪裁)
b a_afr a_deu a_eng a_fi a_rus a_swe a_wu
0 eu 0 0 0 1 0 0 0
1 eu 0 0 0 0 1 0 0
2 as 0 0 0 0 1 0 0
3 eu 0 0 0 1 0 0 0
4 eu 0 0 0 0 0 0 1
5 as 0 0 0 0 0 1 0
...
我注意到当分类变量列有 6 个或更多类别时,OneHotEncoder 会失败。 例如,我有一个包含两列的 TestData.csv 文件:Geography 和 Continent。 地理的不同值是法国、西班牙、肯尼亚、博茨瓦纳和尼日利亚,而大陆的不同值是欧洲和非洲。 我的目标是使用 OneHotEncoder 对地理列进行编码。我执行以下代码来执行此操作:
import numpy as np
import pandas as pd
#Importing the dataset
dataset = pd.read_csv('TestData.csv')
X = dataset.iloc[:,:].values #X is hence a 2-dimensional numpy.ndarray
#Encoding categorical column Geography
from sklearn.preprocessing import OneHotEncoder
from sklearn.compose import ColumnTransformer
ct = ColumnTransformer(transformers=[('encoder', OneHotEncoder(), [0])], remainder='passthrough') #the 0 is the column index for the categorical column we want to encode, in this case Geography
X = np.array(ct.fit_transform(X))
然后我 print(X)
以确保我得到预期的输出,它看起来像这样 (还要注意 X 的大小):
但是,如果我向 TestData 文件添加一个新国家/地区,假设是比利时。我们现在有 6 个不同的国家。现在 运行 完全相同的代码产生以下内容:
在第
行失败X = np.array(ct.fit_transform(X))
如您所见,X 没有改变,也没有完成编码。我已经多次测试过这个。所以看起来 OneHotEncoder 最多只能处理 5 个不同的类别值。 是否有我可以更改的参数或我可以执行的其他方法来对具有 5 个以上值的分类变量进行编码?
PS - 我知道在编码后删除虚拟变量 ;)
我是运行Python3.7.7
谢谢!
我认为问题出在 ColumnTransformer 中的“sparse_threshold”参数。尝试将其设置为 0,以便所有输出 numpy 数组都是密集的。您的输出密度低于 0.3(默认值),这会提示它尝试切换到稀疏数组,但它仍然包含字符串列 Continent 并且稀疏数组不能包含字符串。
我注意到您已经在使用 pandas
。那么还有一种方法就是使用one-hot encoding。
正在准备类似于您的示例数据。
import numpy as np
import pandas as pd
a = np.random.choice(['afr','deu','swe','fi','rus','eng','wu'], 40)
b = np.random.choice(['eu','as'], 40)
df = pd.DataFrame({'a':a, 'b':b})
df.head()
输出
a b
0 rus as
1 eng as
2 fi eu
3 swe eu
4 eng eu
您可以使用 get_dummies
进行单热编码
pd.get_dummies(df, columns=['a'])
输出(剪裁)
b a_afr a_deu a_eng a_fi a_rus a_swe a_wu
0 eu 0 0 0 1 0 0 0
1 eu 0 0 0 0 1 0 0
2 as 0 0 0 0 1 0 0
3 eu 0 0 0 1 0 0 0
4 eu 0 0 0 0 0 0 1
5 as 0 0 0 0 0 1 0
...