【发布时间】:2016-02-17 04:43:31
【问题描述】:
上下文:我有一个数据框,其中所有分类值都已使用 StringIndexer 进行索引。
val categoricalColumns = df.schema.collect { case StructField(name, StringType, nullable, meta) => name }
val categoryIndexers = categoricalColumns.map {
col => new StringIndexer().setInputCol(col).setOutputCol(s"${col}Indexed")
}
然后我使用 VectorAssembler 对所有特征列(包括索引的分类列)进行向量化。
val assembler = new VectorAssembler()
.setInputCols(dfIndexed.columns.diff(List("label") ++ categoricalColumns))
.setOutputCol("features")
在应用分类器和一些额外的步骤后,我最终得到了一个包含标签、特征和预测的数据框。我想将我的特征向量扩展为单独的列,以便将索引值转换回其原始字符串形式。
val categoryConverters = categoricalColumns.zip(categoryIndexers).map {
colAndIndexer => new IndexToString().setInputCol(s"${colAndIndexer._1}Indexed").setOutputCol(colAndIndexer._1).setLabels(colAndIndexer._2.fit(df).labels)
}
问题:有没有一种简单的方法可以做到这一点,或者是最好的方法以某种方式将预测列附加到测试数据框?
我尝试过的:
val featureSlicers = categoricalColumns.map {
col => new VectorSlicer().setInputCol("features").setOutputCol(s"${col}Indexed").setNames(Array(s"${col}Indexed"))
}
应用这个给了我我想要的列,但它们是矢量形式(正如它的意思)而不是双精度类型。
编辑: 所需的输出是原始数据框(即分类特征作为字符串而不是索引),并带有一个指示预测标签的附加列(在我的例子中是 0 或 1)。
例如,假设我的分类器的输出看起来像这样:
+-----+---------+----------+
|label| features|prediction|
+-----+---------+----------+
| 1.0|[0.0,3.0]| 1.0|
+-----+---------+----------+
通过在每个特征上应用 VectorSlicer,我会得到:
+-----+---------+----------+-------------+-------------+
|label| features|prediction|statusIndexed|artistIndexed|
+-----+---------+----------+-------------+-------------+
| 1.0|[0.0,3.0]| 1.0| [0.0]| [3.0]|
+-----+---------+----------+-------------+-------------+
这很好,但我需要:
+-----+---------+----------+-------------+-------------+
|label| features|prediction|statusIndexed|artistIndexed|
+-----+---------+----------+-------------+-------------+
| 1.0|[0.0,3.0]| 1.0| 0.0 | 3.0 |
+-----+---------+----------+-------------+-------------+
然后才能使用 IndexToString 并将其转换为:
+-----+---------+----------+-------------+-------------+
|label| features|prediction| status | artist |
+-----+---------+----------+-------------+-------------+
| 1.0|[0.0,3.0]| 1.0| good | Pink Floyd |
+-----+---------+----------+-------------+-------------+
甚至:
+-----+----------+-------------+-------------+
|label|prediction| status | artist |
+-----+----------+-------------+-------------+
| 1.0| 1.0| good | Pink Floyd |
+-----+----------+-------------+-------------+
【问题讨论】:
-
我也有类似的问题。我有一个包含数千列或列的数据集,其中一些是分类的,因此我必须使用
StringIndexer和OneHotEncoder将它们“拆分”为更多列。当我试图理解什么代表组合向量的每个特征时,问题就来了。 -
有什么理由首先丢弃输入数据?
-
是的。分类算法需要一个带有“标签”和“特征”列的数据框。其中特征列是向量,不能有字符串。需要明确的是,我仍然拥有包含所有输入数据的原始数据框。
-
如果您有原始数据,为什么要从那里提取此信息而不是矢量?我的意思是,为什么要麻烦一个小的 UDF?
-
好奇心,主要是。此外,将一列从一个数据帧附加到另一个数据帧似乎并不像我预期的那么简单。
标签: scala apache-spark apache-spark-ml