Scala:如何获得矩阵的均值、方差和协方差?
Scala: how to get the mean and variance and covariance of a matrix?
我是 scala 的新手,我迫切需要一些关于以下问题的指导:
我有一个如下所示的数据框(某些元素可能为 NULL)
val dfDouble = Seq(
(1.0, 1.0, 1.0, 3.0),
(1.0, 2.0, 0.0, 0.0),
(1.0, 3.0, 1.0, 1.0),
(1.0, 4.0, 0.0, 2.0)).toDF("m1", "m2", "m3", "m4")
dfDouble.show
+---+---+---+---+
| m1| m2| m3| m4|
+---+---+---+---+
|1.0|1.0|1.0|3.0|
|1.0|2.0|0.0|0.0|
|1.0|3.0|1.0|1.0|
|1.0|4.0|0.0|2.0|
+---+---+---+---+
我需要从此数据框中获取以下统计信息:
- 包含每列平均值的向量(某些元素可能为 NULL,我想仅使用非 NULL 元素计算平均值);我还想按名称引用向量的每个元素,例如,vec_mean["m1_mean"] 会 return 第一个元素
vec_mean: Vector(m1_mean, m2_mean, m3_mean, m4_mean)
一个方差协方差矩阵,即(4 x 4),其中对角线是var(m1), var(m2),...,
,非对角线是cov(m1,m2), cov(m1,m3) ...
在这里,我还想仅在方差-协方差计算中使用非 NULL 元素
包含每列非空数的向量
vec_n: Vector(m1_n, m2_n, m3_n, m4_n)
- 包含每列标准差的向量
vec_stdev: Vector(m1_stde, m2_stde, m3_stde, m4_stde)
在 R 中,我会将所有内容都转换为矩阵,然后剩下的就很简单了。但是在 scala 中,我不熟悉矩阵,而且显然有多种类型的矩阵,令人困惑(DenseMatrix、IndexedMatrix 等)
已编辑:显然,数据帧的内容是 Double 还是 Int 会有所不同。将元素修改为 double
根据建议的答案使用以下命令并且有效!
val rdd = dfDouble0.rdd.map {
case a: Row => (0 until a.length).foldRight(Array[Double]())((b, acc) =>
{ val k = a.getAs[Double](b)
if(k == null)
acc.+:(0.0)
else acc.+:(k)}).map(_.toDouble)
}
你可以使用 Spark RowMatrix。它具有此类操作,例如使用每一行作为观察值、均值、方差等来计算协方差矩阵……您唯一需要知道的是如何从 Dataframe 构建它。
事实证明,Spark 中的 Dataframe 包含一个 schema,表示可以存储在其中的信息类型,而不仅仅是浮点数数组。所以第一件事就是将这个 DF 转换为向量的 RDD(在本例中为密集向量)。
拥有这个 DF:
val df = Seq(
(1, 1, 1, 3),
(1, 2, 0, 0),
(1, 3, 1, 1),
(1, 4, 0, 2),
(1, 5, 0, 1),
(2, 1, 1, 3),
(2, 2, 1, 1),
(2, 3, 0, 0)).toDF("m1", "m2", "m3", "m4")
将其转换为 RDD Row[DenseVector] 表示。一定有几十种方法可以做到这一点。一个可能是:
val rdd = df.rdd.map {
case a: Row =>
(0 until a.length).foldRight(Array[Int]())((b, acc) => {
val k = a.getAs[Int](b)
if(k == null) acc.+:(0) else acc.+:(k)
}).map(_.toDouble)
}
如您在 IDE 中所见,推断类型为 RDD[Array[Float]。现在将其转换为 RDD[DenseVector]。就这么简单:
val rowsRdd = rdd.map(Vectors.dense(_))
现在您可以构建矩阵了:
val mat: RowMatrix = new RowMatrix(rowsRdd)
获得矩阵后,您可以轻松计算每列的不同矩阵:
println("Mean: " + mat.computeColumnSummaryStatistics().mean)
println("Variance: " + mat.computeColumnSummaryStatistics().variance)
它给出:
Mean: [1.375,2.625,0.5,1.375]
Variance:
[0.26785714285714285,1.9821428571428572,0.2857142857142857,1.4107142857142858]
您可以在文档中阅读有关 Spark 和这些分布式类型的功能的更多信息:https://spark.apache.org/docs/latest/mllib-data-types.html#data-types-rdd-based-api
您还可以计算协方差矩阵,执行 SVD 等...
我是 scala 的新手,我迫切需要一些关于以下问题的指导:
我有一个如下所示的数据框(某些元素可能为 NULL)
val dfDouble = Seq(
(1.0, 1.0, 1.0, 3.0),
(1.0, 2.0, 0.0, 0.0),
(1.0, 3.0, 1.0, 1.0),
(1.0, 4.0, 0.0, 2.0)).toDF("m1", "m2", "m3", "m4")
dfDouble.show
+---+---+---+---+
| m1| m2| m3| m4|
+---+---+---+---+
|1.0|1.0|1.0|3.0|
|1.0|2.0|0.0|0.0|
|1.0|3.0|1.0|1.0|
|1.0|4.0|0.0|2.0|
+---+---+---+---+
我需要从此数据框中获取以下统计信息:
- 包含每列平均值的向量(某些元素可能为 NULL,我想仅使用非 NULL 元素计算平均值);我还想按名称引用向量的每个元素,例如,vec_mean["m1_mean"] 会 return 第一个元素
vec_mean: Vector(m1_mean, m2_mean, m3_mean, m4_mean)
一个方差协方差矩阵,即(4 x 4),其中对角线是
var(m1), var(m2),...,
,非对角线是cov(m1,m2), cov(m1,m3) ...
在这里,我还想仅在方差-协方差计算中使用非 NULL 元素包含每列非空数的向量
vec_n: Vector(m1_n, m2_n, m3_n, m4_n)
- 包含每列标准差的向量
vec_stdev: Vector(m1_stde, m2_stde, m3_stde, m4_stde)
在 R 中,我会将所有内容都转换为矩阵,然后剩下的就很简单了。但是在 scala 中,我不熟悉矩阵,而且显然有多种类型的矩阵,令人困惑(DenseMatrix、IndexedMatrix 等)
已编辑:显然,数据帧的内容是 Double 还是 Int 会有所不同。将元素修改为 double
根据建议的答案使用以下命令并且有效!
val rdd = dfDouble0.rdd.map {
case a: Row => (0 until a.length).foldRight(Array[Double]())((b, acc) =>
{ val k = a.getAs[Double](b)
if(k == null)
acc.+:(0.0)
else acc.+:(k)}).map(_.toDouble)
}
你可以使用 Spark RowMatrix。它具有此类操作,例如使用每一行作为观察值、均值、方差等来计算协方差矩阵……您唯一需要知道的是如何从 Dataframe 构建它。
事实证明,Spark 中的 Dataframe 包含一个 schema,表示可以存储在其中的信息类型,而不仅仅是浮点数数组。所以第一件事就是将这个 DF 转换为向量的 RDD(在本例中为密集向量)。
拥有这个 DF:
val df = Seq(
(1, 1, 1, 3),
(1, 2, 0, 0),
(1, 3, 1, 1),
(1, 4, 0, 2),
(1, 5, 0, 1),
(2, 1, 1, 3),
(2, 2, 1, 1),
(2, 3, 0, 0)).toDF("m1", "m2", "m3", "m4")
将其转换为 RDD Row[DenseVector] 表示。一定有几十种方法可以做到这一点。一个可能是:
val rdd = df.rdd.map {
case a: Row =>
(0 until a.length).foldRight(Array[Int]())((b, acc) => {
val k = a.getAs[Int](b)
if(k == null) acc.+:(0) else acc.+:(k)
}).map(_.toDouble)
}
如您在 IDE 中所见,推断类型为 RDD[Array[Float]。现在将其转换为 RDD[DenseVector]。就这么简单:
val rowsRdd = rdd.map(Vectors.dense(_))
现在您可以构建矩阵了:
val mat: RowMatrix = new RowMatrix(rowsRdd)
获得矩阵后,您可以轻松计算每列的不同矩阵:
println("Mean: " + mat.computeColumnSummaryStatistics().mean)
println("Variance: " + mat.computeColumnSummaryStatistics().variance)
它给出:
Mean: [1.375,2.625,0.5,1.375]
Variance:
[0.26785714285714285,1.9821428571428572,0.2857142857142857,1.4107142857142858]
您可以在文档中阅读有关 Spark 和这些分布式类型的功能的更多信息:https://spark.apache.org/docs/latest/mllib-data-types.html#data-types-rdd-based-api
您还可以计算协方差矩阵,执行 SVD 等...