如何在使用Spark ML时以另一种方式索引分类特征

3
Spark中的VectorIndexer根据变量频率对分类特征进行索引。 但我想以不同的方式对分类特征进行索引。
例如,对于以下数据集,“a”、“b”和“c”将被索引为0、1、2,如果使用Spark中的VectorIndexer。但是我想根据标签对它们进行索引。有4行数据,它们被索引为1,其中3行具有'a'特征,1行具有'c'特征。因此,在这里,我将'a'索引为0,'c'索引为1,'b'索引为2。
是否有方便的方法来实现这一点?
 label|feature
-----------------
    1 | a
    1 | c
    0 | a
    0 | b
    1 | a
    0 | b
    0 | b
    0 | c
    1 | a
1个回答

1
如果我正确理解您的问题,您希望在分组数据上复制StringIndexer()的行为。为了在pySpark中实现这一点,我们首先定义一个操作List列的udf,该列包含每个组的所有值。请注意,具有相等计数的元素将被任意排序。
from collections import Counter
from pyspark.sql.types import ArrayType, IntegerType

def encoder(col):

  # Generate count per letter
  x = Counter(col)

  # Create a dictionary, mapping each letter to its rank
  ranking = {pair[0]: rank 
           for rank, pair in enumerate(x.most_common())}

  # Use dictionary to replace letters by rank
  new_list = [ranking[i] for i in col]

  return(new_list)

encoder_udf = udf(encoder, ArrayType(IntegerType()))

现在我们可以使用collect_list()feature列按照label列分组成列表,并逐行应用我们的udf
from pyspark.sql.functions import collect_list, explode

df1 = (df.groupBy("label")
       .agg(collect_list("feature")
            .alias("features"))
       .withColumn("index", 
                   encoder_udf("features")))

因此,您可以将index列展开以获取编码值而不是字母:
df1.select("label", explode(df1.index).alias("index")).show()
+-----+-----+
|label|index|
+-----+-----+
|    0|    1|
|    0|    0|
|    0|    0|
|    0|    0|
|    0|    2|
|    1|    0|
|    1|    1|
|    1|    0|
|    1|    0|
+-----+-----+

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接