Matrix中的矩阵转置在Spark中的RowMatrix上

Cha*_*dan 13 apache-spark

假设我有一个RowMatrix.

  1. 我怎样才能转置它.API文档似乎没有转置方法.
  2. Matrix具有transpose()方法.但它没有分发.如果我有一个大的矩阵,那么内存怎么能转置呢?
  3. 我已将RowMatrix转换为DenseMatrix,如下所示

    DenseMatrix Mat = new DenseMatrix(m,n,MatArr);
    
    Run Code Online (Sandbox Code Playgroud)

    这需要将RowMatrix转换为JavaRDD并将JavaRDD转换为数组.

有没有其他方便的方法来进行转换?

提前致谢

ars*_*ars 17

如果有人感兴趣,我已经实现了@javadba提出的分布式版本.

  def transposeRowMatrix(m: RowMatrix): RowMatrix = {
    val transposedRowsRDD = m.rows.zipWithIndex.map{case (row, rowIndex) => rowToTransposedTriplet(row, rowIndex)}
      .flatMap(x => x) // now we have triplets (newRowIndex, (newColIndex, value))
      .groupByKey
      .sortByKey().map(_._2) // sort rows and remove row indexes
      .map(buildRow) // restore order of elements in each row and remove column indexes
    new RowMatrix(transposedRowsRDD)
  }


  def rowToTransposedTriplet(row: Vector, rowIndex: Long): Array[(Long, (Long, Double))] = {
    val indexedRow = row.toArray.zipWithIndex
    indexedRow.map{case (value, colIndex) => (colIndex.toLong, (rowIndex, value))}
  }

  def buildRow(rowWithIndexes: Iterable[(Long, Double)]): Vector = {
    val resArr = new Array[Double](rowWithIndexes.size)
    rowWithIndexes.foreach{case (index, value) =>
        resArr(index.toInt) = value
    }
    Vectors.dense(resArr)
  } 
Run Code Online (Sandbox Code Playgroud)


ale*_*ool 6

您可以使用BlockMatrix,它可以从IndexedRowMatrix创建:

BlockMatrix matA = (new IndexedRowMatrix(...).toBlockMatrix().cache();
matA.validate();

BlockMatrix matB = matA.transpose();
Run Code Online (Sandbox Code Playgroud)

然后,可以轻松地将其作为IndexedRowMatrix.这在spark文档中有描述.


jav*_*dba 5

您是对的:没有

 RowMatrix.transpose()
Run Code Online (Sandbox Code Playgroud)

方法。您将需要手动执行此操作。

是非分布式/本地矩阵版本:

def transpose(m: Array[Array[Double]]): Array[Array[Double]] = {
    (for {
      c <- m(0).indices
    } yield m.map(_(c)) ).toArray
}
Run Code Online (Sandbox Code Playgroud)

分布式版本将大致如下:

    origMatRdd.rows.zipWithIndex.map{ case (rvect, i) =>
        rvect.zipWithIndex.map{ case (ax, j) => ((j,(i,ax))
    }.groupByKey
    .sortBy{ case (i, ax) => i }
    .foldByKey(new DenseVector(origMatRdd.numRows())) { case (dv, (ix,ax))  =>
              dv(ix) = ax
     }
Run Code Online (Sandbox Code Playgroud)

警告:我没有测试上面的:这有错误。但是基本方法是有效的-类似于我过去为小型SparkLinAlg库所做的工作。

  • AFAIK是的,就是这种情况。例如,4月份通过大型矩阵转至Spark用户列表的电子邮件未收到任何回复。 (2认同)