В Spark нет встроенной функции для SparseVectors.С объектами DenseVector
можно разобраться, превратив их в массивы, но для SparseVector
это может быть убийцей памяти.Вы можете интерпретировать SparseVectors как карту, а затем «добавить» карты вместе.
import org.apache.spark.mllib.linalg.{SparseVector, Vectors, Vector}
def addVecCols(v1: SparseVector, v2: SparseVector): Vector = {
val map1: Map[Int, Double] = (v1.indices zip v1.values).toMap
Vectors.sparse(v1. size,
(map1 ++ (v2.indices zip v2.values).toMap)
.map{ case (k, v) => k -> (v + map1.getOrElse(k, 0d))}
.toList
)
val addVecUDF = udf((v1: SparseVector, v2: SparseVector) => addVecCols(v1, v2))
Обратите внимание, что в Spark 1.6 тип возвращаемого значения Vectors.sparse
равен Vector
, в то время как в Spark 2.X - SparseVector
, поэтому соответствующим образом измените тип возвращаемого значения addVecCols
,Кроме того, в 2.X вы можете использовать библиотеку ml
вместо библиотеки mllib
.
Использование этого в кадре данных будет
val outDF = inDF.withColumn("added", addVecUDF(col("one_vector"), col("other_vector")))