编码分类变量后如何跟踪列?
How to keep track of columns after encoding categorical variables?
我想知道在对数据集执行数据预处理后如何跟踪数据集的原始列?
在下面的代码中 df_columns
会告诉我 df_array
中的列 0
是 A
,列 1
是 B
并且等等...
然而,一旦我对分类列 B
进行编码,df_columns
就不再有效跟踪 df_dummies
import pandas as pd
import numpy as np
animal = ['dog','cat','horse']
df = pd.DataFrame({'A': np.random.rand(9),
'B': [animal[np.random.randint(3)] for i in range(9)],
'C': np.random.rand(9),
'D': np.random.rand(9)})
df_array = df.values
df_columns = df.columns
from sklearn.preprocessing import OneHotEncoder
from sklearn.compose import ColumnTransformer
ct = ColumnTransformer([('encoder', OneHotEncoder(), [1])], remainder='passthrough')
df_dummies = np.array(ct.fit_transform(df_array), dtype=np.float)
解决方案应该与分类列的位置无关...可以是 A
、B
、C
或 D
。我可以做繁重的工作并不断更新 df_columns
词典...但这不会很优雅或 "pythonic"
此外...解决方案如何跟踪分类的含义? {0,0,1} 是猫,{0,1,0} 是狗等等?
PS - 我知道虚拟变量陷阱,当我实际使用它来训练我的模型时会使用 df_dummies[:,1:]
。
您能否确认未来的数据集是否会继续具有相同的列名?如果我答对了你的问题,你需要做的就是从原始数据框中保存 df_columns
并使用它重新索引你的新数据框。
new_df_reindexed = new_df[df_columns]
要回答您的其他问题,您可以使用 pandas 中的 get_dummies()
对数据进行单热编码。使用 drop_first
参数删除生成的列值之一并避免虚拟变量陷阱。另外,保存one-hot-encoded数据框的列列表。
为确保您的新/测试/坚持数据集与模型训练中使用的列定义相同,
- 首先使用
get_dummies()
对新数据集进行one-hot-encode。
- 使用 pandas
reindex
将新数据框放入与模型训练中使用的相同结构 - df.reindex(columns=train_one_hot_encode_col_list, axis="columns")
。
- 以上将为训练数据集中的分类列值创建虚拟变量列,这些列值不存在于新数据集的分类列中。
- 最后,使用上述方法删除旧数据集中不存在的新数据集中的任何列 -
test_df_reindexed = test_df_onehotencode[train_one_hot_encode_col_list]
如果按照这些步骤操作,您可以完全依赖原始列名列表,而无需跟踪列位置或分类值定义。
我还建议您阅读以下内容以供进一步参考:
pandas - https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.get_dummies.html 中的单热编码
列重新索引 - https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.reindex.html
我想知道在对数据集执行数据预处理后如何跟踪数据集的原始列?
在下面的代码中 df_columns
会告诉我 df_array
中的列 0
是 A
,列 1
是 B
并且等等...
然而,一旦我对分类列 B
进行编码,df_columns
就不再有效跟踪 df_dummies
import pandas as pd
import numpy as np
animal = ['dog','cat','horse']
df = pd.DataFrame({'A': np.random.rand(9),
'B': [animal[np.random.randint(3)] for i in range(9)],
'C': np.random.rand(9),
'D': np.random.rand(9)})
df_array = df.values
df_columns = df.columns
from sklearn.preprocessing import OneHotEncoder
from sklearn.compose import ColumnTransformer
ct = ColumnTransformer([('encoder', OneHotEncoder(), [1])], remainder='passthrough')
df_dummies = np.array(ct.fit_transform(df_array), dtype=np.float)
解决方案应该与分类列的位置无关...可以是 A
、B
、C
或 D
。我可以做繁重的工作并不断更新 df_columns
词典...但这不会很优雅或 "pythonic"
此外...解决方案如何跟踪分类的含义? {0,0,1} 是猫,{0,1,0} 是狗等等?
PS - 我知道虚拟变量陷阱,当我实际使用它来训练我的模型时会使用 df_dummies[:,1:]
。
您能否确认未来的数据集是否会继续具有相同的列名?如果我答对了你的问题,你需要做的就是从原始数据框中保存 df_columns
并使用它重新索引你的新数据框。
new_df_reindexed = new_df[df_columns]
要回答您的其他问题,您可以使用 pandas 中的 get_dummies()
对数据进行单热编码。使用 drop_first
参数删除生成的列值之一并避免虚拟变量陷阱。另外,保存one-hot-encoded数据框的列列表。
为确保您的新/测试/坚持数据集与模型训练中使用的列定义相同,
- 首先使用
get_dummies()
对新数据集进行one-hot-encode。 - 使用 pandas
reindex
将新数据框放入与模型训练中使用的相同结构 -df.reindex(columns=train_one_hot_encode_col_list, axis="columns")
。 - 以上将为训练数据集中的分类列值创建虚拟变量列,这些列值不存在于新数据集的分类列中。
- 最后,使用上述方法删除旧数据集中不存在的新数据集中的任何列 -
test_df_reindexed = test_df_onehotencode[train_one_hot_encode_col_list]
如果按照这些步骤操作,您可以完全依赖原始列名列表,而无需跟踪列位置或分类值定义。
我还建议您阅读以下内容以供进一步参考: pandas - https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.get_dummies.html 中的单热编码 列重新索引 - https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.reindex.html