更改BlockMatrix的对角元素

时间:2018-07-10 06:53:55

标签: apache-spark matrix pyspark apache-spark-mllib diagonal

我有一个大小为4 * 4的块矩阵

Blockmatrix = 
    0.0  2.0  1.0  2.0
    2.0  0.0  2.0  4.0
    1.0  2.0  0.0  3.0
    2.0  4.0  3.0  0.0

在键入此矩阵的类型时,

显示

<class 'pyspark.mllib.linalg.distributed.BlockMatrix'>

我只想将对角线元素更改为 1.0

当我尝试这段代码时,

diagonal_matrix = DenseMatrix(dataframe_item.numRows,dataframe_item.numCols,dataframe_item.toLocalMatrix().rowIter().zipWithIndex().flatMap(lambda x:(x[1].toArray(x[2]),x[1].toArray())).toArray())

它抛出以下错误,

AttributeError: 'DenseMatrix' object has no attribute 'rowIter'

任何人都可以帮助解决此错误吗? 还是有更好的方法来更改Pyspark中BlockMatrix的对角线值?

1 个答案:

答案 0 :(得分:0)

尝试一下

from pyspark.mllib.linalg.distributed import *

rdd = sc.parallelize([
    (0, 0.0 , 2.0 , 1.0,  2.0),
    (1, 2.0 , 0.0 , 2.0 , 4.0),
    (2, 1.0 , 2.0 , 0.0 , 3.0),
    (3, 2.0 , 4.0  ,3.0  ,0.0)
    ])

Blockmatrix = IndexedRowMatrix(rdd.map(lambda x: IndexedRow(x[0],x[1:]))).toBlockMatrix()

这给了我们Blockmatrix

现在,要用1.0替换对角线元素,我们使用行索引。因此,我们将BlockMatrix转换为IndexedRowMatrix,然后转换为rdd。因此,我们有索引和行。

然后我们使用索引将所有对角元素更改为1.0,然后将其转换回IndexedRowMatrix,然后再转换为BlockMatrix

Blockmatrix_new = IndexedRowMatrix(Blockmatrix.toIndexedRowMatrix().rows\
                 .map(lambda x: IndexedRow(x.index, [1.0 if i == x.index else v for i,v in enumerate(x.vector)])))\
                 .toBlockMatrix()

Blockmatrix_new是所需的矩阵。要查看内容,我们将其转换为局部矩阵。但是请记住,这将导致矩阵被收集。

print Blockmatrix_new.toLocalMatrix()

DenseMatrix([[1., 2., 1., 2.],
             [2., 1., 2., 4.],
             [1., 2., 1., 3.],
             [2., 4., 3., 1.]])