【问题标题】:How can I add scaled catergorical data back to orginal dataset?如何将比例分类数据添加回原始数据集?
【发布时间】:2020-07-10 04:55:54
【问题描述】:

我对转换和反向转换不同类型的数据有点困惑。我有一个带有数字和分类列的数据框。

  1. 获取数据框并将分类值转换为数值
  2. 获取新数据框并对其进行缩放。
  3. 在上面运行我的模型。
  4. 尝试将其转换回(未缩放 + 将数字分类数据转换回字符串)

问题是我得到了第 1-3 步的工作,但我不确定如何将分类数据转换回来。我可以转换数据框,使其不再缩放(反转步骤 2),但不确定如何重新添加列名。

这是一个例子,原始数据:

     totalRevenue Exchange  costOfRevenue
0    2.601740e+11   NASDAQ   1.617820e+11
1    2.601740e+11   NASDAQ   1.617820e+11
2    2.655950e+11   NASDAQ   1.637560e+11
3    2.655950e+11   NASDAQ   1.637560e+11

转换和转换回来后,我有

[[2.60174e+11 0.00000e+00 1.61782e+11]
 [2.60174e+11 0.00000e+00 1.61782e+11]
 [2.65595e+11 0.00000e+00 1.63756e+11]
 [2.65595e+11 0.00000e+00 1.63756e+11]

这是我的代码:

catergoryEncoder = OrdinalEncoder()
cleanData['Exchange'] = catergoryEncoder.fit_transform(X_train['Exchange'].values.reshape(-1, 1))

scaler = MinMaxScaler()
scaled = scaler.fit_transform(X_train)
unscaled = scaler.inverse_transform(scaled)

未缩放的输出只是输出我上面显示的内容。我认为我面临的一些挑战是,我从 pandas 数据框开始,但在转换后,我有一个 NumPy 数组,我不清楚如何将“exchange”列转换回来。

我知道将分类数据转换回来的命令,它是:catergoryEncoder.inverse_transform(np.asarray(unscaled.Exchange).reshape(-1, 1)),但我收到以下错误(我怀疑是因为在缩放/取消缩放时列名丢失了):

AttributeError: 'numpy.ndarray' object has no attribute 'Exchange'

我可以做些什么来轻松地来回转换?我也以正确的方式接近这个吗?

【问题讨论】:

  • 嘿,您是否尝试在未缩放的数据上使用 OrdinalEncoder 的 inverse transform function
  • @BruceSwain 谢谢布鲁斯。我不确定如何应用它。我应该提一下,我知道可以使用的命令-categoryEncoder.inverse_transform(np.asarray(unscaled.Exchange).reshape(-1, 1)) 但我怀疑它不起作用,因为它位于没有概念的 np 框架上原始标题。我想。

标签: python pandas numpy scikit-learn


【解决方案1】:

回答您问题的第一部分:为什么会出现此错误?您的 OrdinalEncoder 已使用从 pandas Serie 的值获得的 numpy 数组进行了训练。

正如您所评论的,(这里真的需要重塑吗?)(np.asarray 应该不是必需的,因为fit_transform 已经给了您一个 numpy 数组)

catergoryEncoder.inverse_transform(np.asarray(unscaled.Exchange))

将导致错误,因为 numpy 数组没有列名的概念。相反,您应该做的是通过index 取回您的 Exchange 数据:

catergoryEncoder.inverse_transform(unscaled[:,1])

1 是您要选择的列的索引。这应该会返回您的原始数据。

现在,在实现此类事情的正确/干净的方式上,Pipelines 风格是要走的路 (example)。

PS:使用One Hot Encoding 应该无需缩放数据,因为所有值都在 0 和 1 之间编码。

编辑

要回答您的 cmets,请参阅下面的完整示例:

让我们从一个数据框开始:

df = pd.DataFrame({'Numeric':[0,1,2,3,4,5],'Categorial1':['A','A','A','B','B','B'],'Categorial2':['A','C','A','C','B','C']})
   Numeric Categorial1 Categorial2
0        0           A           A
1        1           A           C
2        2           A           A
3        3           B           C
4        4           B           B
5        5           B           C

现在,应用您的编码器:

from sklearn.preprocessing import OrdinalEncoder
encoder = OrdinalEncoder()
#dtype 'O' mean that columns is of type object, this will get all your non numeric data
categorial_column = [col for col in df.columns if df[col].dtype == 'O'] 
df[categorial_column] = encoder.fit_transform(df[categorial_column])

请注意,如果您想使用 numpy 数组而不是 DataFrame 进行操作,您可以使用以下命令“保存”分类列的索引:

categorial_index = np.where(df.columns.isin(categorial_column))
n_categorial = len(categorial_column)
df.values[:,categorial_index].reshape(-1,n_categorial)

为您提供以下内容(带有完整的数据框):

   Numeric  Categorial1  Categorial2
0        0          0.0          0.0
1        1          0.0          2.0
2        2          0.0          0.0
3        3          1.0          2.0
4        4          1.0          1.0
5        5          1.0          2.0

然后是你已经完成的缩放:

from sklearn.preprocessing import MinMaxScaler
scaler = MinMaxScaler()
scaled = scaler.fit_transform(df)
unscaled = scaler.inverse_transform(scaled)

然后回到DataFrame:

df = pd.DataFrame(unscaled, columns=df.columns)
df[categorial_column] = encoder.inverse_transform(df[categorial_column])

还给你:

   Numeric Categorial1 Categorial2
0      0.0           A           A
1      1.0           A           C
2      2.0           A           A
3      3.0           B           C
4      4.0           B           B
5      5.0           B           C

现在您可以将所有预处理步骤放入某个函数或 sklearn 管道中并完成!

【讨论】:

  • 非常感谢布鲁斯!当我运行您的示例时,出现此错误 - ValueError: Expected 2D array, got 1D array instead: array=[ 3. 3. 3. ... 10. 10. 10.]。如果您的数据具有单个特征,则使用 array.reshape(-1, 1) 重塑您的数据,如果数据包含单个样本,则使用 array.reshape(1, -1)。
  • 另外,当有一个类别时,这有效,当有更多时,我应该手动选择列吗?我希望有一种更动态的方式来做到这一点(我是新手,所以不确定它是否存在)。
  • 这似乎有效,categoryEncoder.inverse_transform(unscaled[:,1].reshape(-1,1)) 但我仍然需要将其转换回熊猫数据框
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-11-18
  • 2023-01-16
  • 1970-01-01
  • 2019-09-10
  • 1970-01-01
  • 1970-01-01
  • 2017-11-13
相关资源
最近更新 更多