Spark -- LabelEncoder,使用StringIndexer对多列编码

  由于业务需求,需要对多列进行LabelEncoder编码,SparkML中是通过StringIndexer来实现LabelEncoder的,而StringIndexer是对单列操作的,而如果循环对每列进行编码,不符合Spark的设计,效率是十分低下的,对于这样的需求,我们使用Pipeline来解决这个问题。
在这里插入图片描述
  通过map操作为每一组创建StringIndexer特征,然后通过pipeline一次性对所有列进行转换。代码如下:

  /**
    * @Author: TheBigBlue
    * @Description: 2.4版本未支持多列编码,使用pipeline对多列编码
    * @Date: 2019/2/13
    * @param spark     :
    * @param inputDF   :
    * @param configMap :
    * @Return:
    **/
  def invokeLabelEncoder(spark: SparkSession, inputDF: DataFrame, configMap: Map[String, Any]): (DataFrame, DataFrame) = {
    val disColsList: List[String] = configMap.getOrElse(OneHotEncoder.DIS_COLS, null).asInstanceOf[List[String]]
    if (disColsList == null || disColsList.size == 0) throw new Exception("离散列为空!")
    //用户选择的需要转换的离散列
    val userSelectCols = disColsList.toArray
    inputDF.cache()
    //校验空值
    val nullValueCount = NullValueCheck.countNullValue(inputDF, userSelectCols)
    if (nullValueCount > 0) {
      throw new Exception("输入数据有" + nullValueCount + "条存在空值!")
    }
    //使用pipeline一次转换
    val indexers = userSelectCols.map(col => {
      new StringIndexer().setInputCol(col).setOutputCol(col + "_indexed")
    })
    //转换后数据
    val finalDF = new Pipeline().setStages(indexers).fit(inputDF).transform(inputDF).cache()
    println(finalDF.count())
    //生成字典DF
    val colNames = finalDF.schema.fieldNames
    val dictRDD: RDD[(String, String, Double)] = finalDF.rdd.flatMap(row => {
      colNames.filter(_.indexOf("_indexed") > 0).map(colName => {
        val originalCol = colName.substring(0, colName.lastIndexOf("_indexed"))
        (originalCol, row.getAs(originalCol).toString, row.getAs[Double](colName))
      })
    })
    val dictDF = spark.createDataFrame(dictRDD)
      .toDF("columns", "properties", "labels")
      .dropDuplicates("columns", "properties", "labels")
      .orderBy("columns", "labels")
    (dictDF, finalDF)
  }
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值