首页 > 解决方案 > 如何在 Breeze 中为 SparseVector 的每个元素添加一个?

问题描述

给定一个 BreezeSparseVector对象:

scala>  val sv = new SparseVector[Double](Array(0, 4, 5), Array(1.5, 3.6, 0.4), 8)
sv: breeze.linalg.SparseVector[Double] = SparseVector(8)((0,1.5), (4,3.6), (5,0.4))

取值 + 1 的对数的最佳方法是什么?

这是一种有效的方法:

scala>  new SparseVector(sv.index, log(sv.data.map(_ + 1)), sv.length)
res11: breeze.linalg.SparseVector[Double] = SparseVector(8)((0,0.9162907318741551), (4,1.5260563034950492), (5,0.3364722366212129))

我不喜欢这个,因为它并没有真正利用微风来做加法。我们正在使用微风 UFunc 来获取 Array[Double] 的日志,但这并不多。我担心在具有大型 SparseVectors 的分布式应用程序中,这会很慢。

标签: scalascala-breeze

解决方案


火花 1.6.3

您可以定义一些 UDF 来在 Spark 中进行任意矢量化加法。首先,您需要设置将 Spark 向量转换为 Breeze 向量的能力;这样做的一个例子是here。一旦你有了隐式转换,你就有几个选择。

要添加任何两列,您可以使用:

def addVectors(v1Col: String, v2Col: String, outputCol: String): DataFrame => DataFrame = {
      // Error checking column names here
  df: DataFrame => {
    def add(v1: SparkVector, v2: SparkVector): SparkVector =
      (v1.asBreeze + v2.asBreeze).fromBreeze
    val func = udf((v1: SparkVector, v2: SparkVector) => add(v1, v2))
    df.withColumn(outputCol, func(col(v1Col), col(v2Col)))
  }
} 

请注意,在上面链接的问题中建立了asBreezeand的使用fromBreeze(以及 的别名SparkVector)。一个可能的解决方案是通过

df.withColumn(colName, lit(1))

然后添加列。

更复杂的数学函数的替代方法是:

def applyMath(func: BreezeVector[Double] => BreezeVector[Double], 
                 inColName: String, outColName: String): DataFrame => DataFrame = {
  df: DataFrame => df.withColumn(outColName, 
    udf((v1: SparkVector) => func(v1.asBreeze).fromBreeze).apply(col(inColName)))
}

您也可以在 Breeze 向量参数中将其设为通用。


推荐阅读