StringIndexerapache
StringIndexer将一串字符串标签编码为一列标签索引。这些索引范围是[0, numLabels)按照标签频率排序,所以最频繁的标签得到索引0。若是用户选择保留它们,那么看不见的标签将被放在索引numLabels处。若是输入列是数字,咱们将其转换为字符串值并将为其建索引。当下游管道组件(例如Estimator或 Transformer使用此字符串索引标签)时,必须将组件的输入列设置为此字符串索引列名称。在许多状况下,您能够使用设置输入列setInputCol。ide
例1, 假如咱们有下面的DataFrame,带有id和category列:编码
Idspa |
category翻译 |
0orm |
a排序 |
1索引 |
bip |
2字符串 |
c |
3 |
a |
4 |
a |
5 |
c |
对着个Dataframe使用StringIndexer,输入列式category,categoryIndex做为输出列,获得以下值:
Id |
Category |
CategoryIndex |
0 |
a |
0.0 |
1 |
b |
2.0 |
2 |
c |
1.0 |
3 |
a |
0.0 |
4 |
a |
0.0 |
5 |
c |
1.0 |
字符a,索引值是0,缘由是a出现的频率最高,接着就是c:1,b:2。
另外,对于不可见的标签,StringIndexer有是三种处理策略:
1, 抛出异常,这是默认行为
2, 跳过不可见的标签
3, 把不可见的标签,标记为numLabels(这个是无用的)。
还用上面的例子,数据以下:
Id |
Category |
0 |
a |
1 |
b |
2 |
c |
3 |
a |
4 |
a |
5 |
c |
6 |
d |
7 |
e |
若是你没有设置StringIndexer如何处理这些不可见的词,或者设置为了error,他将会抛出一个异常。然而,你若是设置setHandleInvalid("skip"),将会获得以下结果:
Id |
Category |
CategoryIndex |
0 |
a |
0.0 |
1 |
b |
2.0 |
2 |
c |
1.0 |
注意,包含d,e的行并无出现。
若是,调用setHandleInvalid("keep"),会获得下面的结果:
Id |
Category |
CategoryIndex |
0 |
a |
0.0 |
1 |
b |
2.0 |
2 |
c |
1.0 |
3 |
d |
3.0 |
4 |
e |
3.0 |
注意,d,e得到的索引值是3.0
代码用例以下:
import org.apache.spark.ml.feature.StringIndexer
val df = spark.createDataFrame(
Seq((0, "a"), (1, "b"), (2, "c"), (3, "a"), (4, "a"), (5, "c"))
).toDF("id", "category")
val indexer = new StringIndexer()
.setInputCol("category")
.setOutputCol("categoryIndex")
val indexed = indexer.fit(df).transform(df)
indexed.show()
IndexToString
对称地StringIndexer,IndexToString将一列标签索引映射回包含做为字符串的原始标签的列。一个常见的用例是从标签生成索引StringIndexer,用这些索引对模型进行训练,并从预测索引列中检索原始标签IndexToString。可是,您能够自由提供本身的标签。
例如,假如咱们有dataframe格式以下:
Id |
CategoryIndex |
0 |
0.0 |
1 |
2.0 |
2 |
1.0 |
3 |
0.0 |
4 |
0.0 |
5 |
1.0 |
使用IndexToString 而且使用categoryIndex做为输入列,originalCategory做为输出列,能够检索到原始标签以下:
Id |
originalCategory |
CategoryIndex |
0 |
a |
0.0 |
1 |
b |
2.0 |
2 |
c |
1.0 |
3 |
a |
0.0 |
4 |
a |
0.0 |
5 |
c |
1.0 |
代码案例以下:
import org.apache.spark.ml.attribute.Attribute
import org.apache.spark.ml.feature.{IndexToString, StringIndexer}
val df = spark.createDataFrame(Seq(
(0, "a"),
(1, "b"),
(2, "c"),
(3, "a"),
(4, "a"),
(5, "c")
)).toDF("id", "category")
val indexer = new StringIndexer()
.setInputCol("category")
.setOutputCol("categoryIndex")
.fit(df)
val indexed = indexer.transform(df)
println(s"Transformed string column '${indexer.getInputCol}' " +
s"to indexed column '${indexer.getOutputCol}'")
indexed.show()
val inputColSchema = indexed.schema(indexer.getOutputCol)
println(s"StringIndexer will store labels in output column metadata: " +
s"${Attribute.fromStructField(inputColSchema).toString} ")
val converter = new IndexToString()
.setInputCol("categoryIndex")
.setOutputCol("originalCategory")
val converted = converter.transform(indexed)
println(s"Transformed indexed column '${converter.getInputCol}' back to original string " +
s"column '${converter.getOutputCol}' using labels in metadata")
converted.select("id", "categoryIndex", "originalCategory").show()
本文主要参考翻译整理自Spark官网,打原创标签纯属为了保证,翻译劳动成果,谢谢你们谅解。