(Массив/вектор ML/вектор MLlib) RDD в столбец векторного фрейма данных ML

Мне нужно преобразовать RDD в один столбец o.a.s.ml.linalg.Vector DataFrame, чтобы использовать алгоритмы ML, в частности K-Means для этого случая. Это мой РДД:

val parsedData = sc.textFile("/digits480x.csv").map(s => Row(org.apache.spark.mllib.linalg.Vectors.dense(s.split(',').slice(0,64).map(_.toDouble))))

Я попытался сделать то, что -column">этот ответ предполагает неудачу, я полагаю, потому что вы в конечном итоге получаете вектор MLlib, он выдает ошибку несоответствия при запуске алгоритма. Теперь, если я изменю это:

import org.apache.spark.mllib.linalg.{Vectors, VectorUDT}

val schema = new StructType()
  .add("features", new VectorUDT())

к этому:

import org.apache.spark.ml.linalg.{Vectors, VectorUDT}

val parsedData = sc.textFile("/digits480x.csv").map(s => Row(org.apache.spark.ml.linalg.Vectors.dense(s.split(',').slice(0,64).map(_.toDouble))))

val schema = new StructType()
  .add("features", new VectorUDT())

Я бы получил сообщение об ошибке, потому что ML VectorUDT является частным.

Я также попытался преобразовать RDD в виде массива двойников в Dataframe и получить плотный вектор ML следующим образом:

var parsedData = sc.textFile("/home/pililo/Documents/Mi_Memoria/Codigo/Datasets/Digits/digits480x.csv").map(s => Row(s.split(',').slice(0,64).map(_.toDouble)))

parsedData: org.apache.spark.rdd.RDD[org.apache.spark.sql.Row]

val schema2 = new StructType().add("features", ArrayType(DoubleType))

schema2: org.apache.spark.sql.types.StructType = StructType(StructField(features,ArrayType(DoubleType,true),true))

val df = spark.createDataFrame(parsedData, schema2)

df: org.apache.spark.sql.DataFrame = [features: array<double>]

val df2 = df.map{ case Row(features: Array[Double]) => Row(org.apache.spark.ml.linalg.Vectors.dense(features)) }

Что вызывает следующую ошибку, хотя spark.implicits._ импортируется:

error: Unable to find encoder for type stored in a Dataset.  Primitive types (Int, String, etc) and Product types (case classes) are supported by importing spark.implicits._  Support for serializing other types will be added in future releases.

Любая помощь приветствуется, спасибо!


person Pilailou    schedule 02.09.2016    source источник


Ответы (1)


Вылетело у меня из головы:

  1. Используйте csv источник и VectorAssembler:

    import scala.util.Try
    import org.apache.spark.ml.linalg._
    import org.apache.spark.ml.feature.VectorAssembler
    
    val path: String = ???
    
    val n: Int = ???
    val m:Int = ???
    
    val raw = spark.read.csv(path)
    val featureCols = raw.columns.slice(n, m)
    
    val exprs = featureCols.map(c => col(c).cast("double"))
    val assembler = new VectorAssembler()
      .setInputCols(featureCols)
      .setOutputCol("features")
    
    assembler.transform(raw.select(exprs: _*)).select($"features")
    
  2. Используйте text источник и UDF:

    def parse_(n: Int, m: Int)(s: String) = Try(
      Vectors.dense(s.split(',').slice(n, m).map(_.toDouble))
    ).toOption
    
    def parse(n: Int, m: Int) = udf(parse_(n, m) _)
    
    val raw = spark.read.text(path)
    
    raw.select(parse(n, m)(col(raw.columns.head)).alias("features"))
    
  3. Используйте text исходный код и обертку Row

    spark.read.text(path).as[String].map(parse_(n, m)).toDF
    
person zero323    schedule 02.09.2016
comment
Вау, спасибо за ответ, я попробую их. Есть идеи, если 1) будет наиболее эффективным? Я действительно хотел сделать что-то подобное, но мне не хватало способа нарезать столбцы для входных столбцов, поскольку их 64. Также я был бы очень признателен, если бы вы могли объяснить эту часть в 1), если вы можете: exprs: _ *. Это как выбрать все столбцы? Большое спасибо! - person Pilailou; 02.09.2016
comment
2 и 3 могут быть немного быстрее, потому что в них не используется синтаксический анализ csv, но я бы не стал заострять на этом внимание. 1. можно улучшить, предоставив читателю схему. Наконец, _* — это varargs. Он принимает последовательность и распаковывает ее в качестве аргументов для выбора. - person zero323; 02.09.2016