我正在尝试使用scala将数据帧转换为微风密集矩阵。我找不到任何内置函数来执行此操作,所以这就是我正在执行的操作。
import scala.util.Random
import breeze.linalg.DenseMatrix
val featuresDF = (1 to 10)
.map(_ => (
Random.nextDouble,Random.nextDouble,Random.nextDouble))
.toDF("F1", "F2", "F3")
var FeatureArray: Array[Array[Double]] = Array.empty
val features = featuresDF.columns
for(i <- features.indices){
FeatureArray = FeatureArray :+ featuresDF.select(features(i)).collect.map(_(0).toString).map(_.toDouble)
}
val desnseMat = DenseMatrix(FeatureArray: _*).t
这确实工作正常,我得到了我想要的。但是,这在我的环境中导致OOM异常。有没有更好的方法来执行此转换。我的最终目标是使用密集矩阵计算特征的特征值和特征向量。
import breeze.stats.covmat
import breeze.linalg.eig
val covariance = covmat(desnseMat)
val eigen = eig(covariance)
因此,如果有直接方法可以从数据帧中获取特征值和特征向量,那就更好了。 spark ml中的PCA必须使用功能列进行此计算。是否可以通过PCA访问特征值?
答案 0 :(得分:0)
首先,尝试增加RAM。
第二,使用Spark中的DenseMatrix尝试这些功能之一。 这两个功能在我的计算机上使用相同数量的RAM。
我获得了1.34秒的时间来解析一个DataFrame中的201238行,其中1列分别包含几个Double值:
import org.apache.spark.mllib.linalg.DenseMatrix
import org.apache.spark.ml.linalg.DenseVector
import org.apache.spark.sql.DataFrame
def getDenseMatrixFromDF(featuresDF:DataFrame):DenseMatrix = {
val featuresTrain = featuresDF.columns
val rows = featuresDF.count().toInt
val newFeatureArray:Array[Double] = featuresTrain
.indices
.flatMap(i => featuresDF
.select(featuresTrain(i))
.collect())
.map(r => r.toSeq.toArray).toArray.flatten.flatMap(_.asInstanceOf[org.apache.spark.ml.linalg.DenseVector].values)
val newCols = newFeatureArray.length / rows
val denseMat:DenseMatrix = new DenseMatrix(rows, newCols, newFeatureArray, isTransposed=false)
denseMat
}
如果我想从一个仅包含一个Double值的列的DataFrame中获取DenseVector,对于相同数量的数据,我将获得0.8秒的时间:
import org.apache.spark.mllib.linalg.DenseVector
import org.apache.spark.ml.linalg.DenseVector
import org.apache.spark.sql.DataFrame
def getDenseVectorFromDF(featuresDF:DataFrame):DenseVector = {
val featuresTrain = featuresDF.columns
val cols = featuresDF.columns.length
cols match {
case i if i>1 => throw new IllegalArgumentException
case _ => {
def addArray(acc:Array[Array[Double]],cur:Array[Double]):Array[Array[Double]] = {
acc :+ cur
}
val newFeatureArray:Array[Double] = featuresTrain
.indices
.flatMap(i => featuresDF
.select(featuresTrain(i))
.collect())
.map(r => r.toSeq.toArray.map(e => e.asInstanceOf[Double])).toArray.flatten
val denseVec:DenseVector = new DenseVector(newFeatureArray)
denseVec
}
}
要计算特征值/特征向量,只需检查this link和this API link
要计算协方差矩阵chek this link和this API link
答案 1 :(得分:0)
def getDenseMatrixFromDF(featuresDF:DataFrame):BDM[Double] = {
val featuresTrain = featuresDF.columns
val cols = featuresTrain.length
val rows = featuresDF.count().toInt
val denseMat: BDM[Double] = BDM.tabulate(rows,cols)((i, j)=>{
featuresDF.collect().apply(i).getAs[Double](j)
})
denseMat
}