Scala - Как разбить столбец вероятности (столбец векторов), который мы получаем, когда мы подходим к модели GMM к данным в два отдельных столбца?

80
8

Я пытаюсь сделать следующее:

+-----+-------------------------+----------+-------------------------------------------+
|label|features |prediction|probability |
+-----+-------------------------+----------+-------------------------------------------+
|0.0 |(3,[],[]) |0 |[0.9999999999999979,2.093996169658831E-15] |
|1.0 |(3,[0,1,2],[0.1,0.1,0.1])|0 |[0.999999999999999,9.891337521299582E-16] |
|2.0 |(3,[0,1,2],[0.2,0.2,0.2])|0 |[0.9999999999999979,2.0939961696578572E-15]|
|3.0 |(3,[0,1,2],[9.0,9.0,9.0])|1 |[2.093996169659668E-15,0.9999999999999979] |
|4.0 |(3,[0,1,2],[9.1,9.1,9.1])|1 |[9.89133752128275E-16,0.999999999999999] |
|5.0 |(3,[0,1,2],[9.2,9.2,9.2])|1 |[2.0939961696605603E-15,0.9999999999999979]|
+-----+-------------------------+----------+-------------------------------------------+

Преобразуйте вышеуказанный блок данных, чтобы иметь еще два столбца: prob1 & prob2 Каждый столбец имеет соответствующие значения, присутствующие в столбце probability.

Я нашел похожие вопросы - один в pyspark, а другой в scala. Я не знаю, как перевести код pyspark, и я получаю сообщение об ошибке с кодом Scala.

Код PySpark:

split1_udf = udf(lambda value: value[0].item(), FloatType())
split2_udf = udf(lambda value: value[1].item(), FloatType())

output2 = randomforestoutput.select(split1_udf('probability').alias('c1'), split2_udf('probability').alias('c2'))

Или добавить эти столбцы в исходный фреймворк:

randomforestoutput.withColumn('c1', split1_udf('probability')).withColumn('c2', split2_udf('probability'))

Scala Код:

import org.apache.spark.sql.functions.udf

val getPOne = udf((v: org.apache.spark.mllib.linalg.Vector) => v(1))
model.transform(testDf).select(getPOne($"probability"))

При запуске кода Scala появляется следующая ошибка:

scala> predictions.select(getPOne(col("probability"))).show(false)
org.apache.spark.sql.AnalysisException: cannot resolve 'UDF(probability)' due to data type mismatch: argument 1 requires vector type, however, ''probability'' is of vector type.;;
'Project [UDF(probability#39) AS UDF(probability)#135]
+- Project [label#0, features#1, prediction#34, UDF(features#1) AS probability#39]
+- Project [label#0, features#1, UDF(features#1) AS prediction#34]
+- Relation[label#0,features#1] libsvm

В настоящее время я использую Scala 2.11.11 и Spark 2.1.1

спросил(а) 2017-06-14T00:29:00+03:00 3 года, 3 месяца назад
1
Решение
88

Насколько я понимаю из вашего вопроса, вы пытаетесь split столбцы probability на два столбца prob1 и prob2. Если то случай, то простой array функциональность с withColumn должна решить проблему.

predictions
.withColumn("prob1", $"probability"(0))
.withColumn("prob2", $"probability"(1))
.drop("probability")

Вы можете найти больше функций, которые могут помочь вам в будущем применяться к dataframes.

отредактированный

Я создал временный dataframe temp, соответствующий вашему column как

val predictions = Seq(Array(1.0,2.0), Array(2.0939961696605603E-15,0.9999999999999979), Array(Double.NaN,Double.NaN)).toDF("probability")
+--------------------------------------------+
|probability |
+--------------------------------------------+
|[1.0, 2.0] |
|[2.0939961696605603E-15, 0.9999999999999979]|
|[NaN, NaN] |
+--------------------------------------------+

И я применил вышеупомянутое с помощью withColumns которые привели

+----------------------+------------------+
|prob1 |prob2 |
+----------------------+------------------+
|1.0 |2.0 |
|2.0939961696605603E-15|0.9999999999999979|
|NaN |NaN |
+----------------------+------------------+

Несоответствие схемы

Теперь, поскольку Vector schema вашего столбца probability не совпадает с приведенным выше решением schema arrayType, выше решение не должно работать в вашем состоянии. Пожалуйста, используйте следующее решение.

Вам нужно будет создать функции udf и вернуть значение, как ожидалось, как

   val first = udf((v: Vector) => v.toArray(0))
val second = udf((v: Vector) => v.toArray(1))
predictions
.withColumn("prob1", first($"probability"))
.withColumn("prob2", second($"probability"))
.drop("probability")

Надеюсь, вы получите желаемый результат.

ответил(а) 2017-06-14T05:47:00+03:00 3 года, 3 месяца назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема