如何让Spark中的onehotencoder像Pandas中的onehotencoder一样工作?

Moh*_*him 4 apache-spark pyspark one-hot-encoding

当我在Spark中使用onehotencoder时,我将得到第四列中的结果,这是一个稀疏向量.

// +---+--------+-------------+-------------+
// | id|category|categoryIndex|  categoryVec|
// +---+--------+-------------+-------------+
// |  0|       a|          0.0|(3,[0],[1.0])|
// |  1|       b|          2.0|(3,[2],[1.0])|
// |  2|       c|          1.0|(3,[1],[1.0])|
// |  3|      NA|          3.0|    (3,[],[])|
// |  4|       a|          0.0|(3,[0],[1.0])|
// |  5|       c|          1.0|(3,[1],[1.0])|
// +---+--------+-------------+-------------+
Run Code Online (Sandbox Code Playgroud)

但是,我想要的是为类别生成3列,就像它在pandas中的工作方式一样.

>>> import pandas as pd
>>> s = pd.Series(list('abca'))
>>> pd.get_dummies(s)
   a  b  c
0  1  0  0
1  0  1  0
2  0  0  1
3  1  0  0
Run Code Online (Sandbox Code Playgroud)

ark*_*296 11

Spark的OneHotEncoder创建一个稀疏矢量列.要创建类似于pandas OneHotEncoder的输出列,我们需要为每个类别创建一个单独的列.我们可以withColumn通过将udf 作为参数传递,借助pyspark数据帧的功能来实现.对于前 -

from pyspark.sql.functions import udf,col
from pyspark.sql.types import IntegerType


df = sqlContext.createDataFrame(sc.parallelize(
        [(0,'a'),(1,'b'),(2,'c'),(3,'d')]), ('col1','col2'))

categories = df.select('col2').distinct().rdd.flatMap(lambda x : x).collect()
categories.sort()
for category in categories:
    function = udf(lambda item: 1 if item == category else 0, IntegerType())
    new_column_name = 'col2'+'_'+category
    df = df.withColumn(new_column_name, function(col('col2')))

print df.show()
Run Code Online (Sandbox Code Playgroud)

输出 -

+----+----+------+------+------+------+                                         
|col1|col2|col2_a|col2_b|col2_c|col2_d|
+----+----+------+------+------+------+
|   0|   a|     1|     0|     0|     0|
|   1|   b|     0|     1|     0|     0|
|   2|   c|     0|     0|     1|     0|
|   3|   d|     0|     0|     0|     1|
+----+----+------+------+------+------+
Run Code Online (Sandbox Code Playgroud)

我希望这有帮助.