我是Scala的新手,我想了解一些基本的东西。
首先,我需要计算DataFrame的某个列的平均值,并将结果用作double类型变量。
经过一些互联网研究,我能够计算平均值,同时通过使用以下命令将其传递给List类型Any:
val avgX_List = mainDataFrame.groupBy().agg(mean("_c1")).collect().map(_(0)).toList
其中“_c1”是我的数据帧的第二列。这行代码返回List类型为List [Any]的List。
要将结果传递给变量,我使用以下命令:
var avgX = avgX_List(0)
希望var avgX会自动输入double类型但显然不会发生。
所以现在让问题开始:
map(_(0)) do
是什么?我知道map()
变换的基本定义,但我无法用这个确切的论证找到解释.toList
方法,我的结果将是一个类型为Any
的List。有没有办法我可以将其更改为包含类型Double
元素的List?甚至转换这个总结一下,我需要计算一个Dataframe的某一列的平均值,并将结果作为double类型变量。
请注意:我是希腊语,我发现有时候很难理解一些英语编码“俚语”。
map(_(0))
是map( (r: Row) => r(0) )
的捷径,而map( (r: Row) => r.apply(0) )
又是apply
的捷径。 Any
方法返回map(_.getAs[Double](0))
,因此您正在丢失正确的类型。尝试使用map(_.getDouble(0))
或collect(...).toList
代替。
收集列的所有条目然后计算平均值将极具反作用,因为您必须向主节点发送大量数据,然后在此单个中心节点上执行所有计算。这与Spark有利的完全相反。
你也不需要Array
,因为你可以直接访问第0个条目(无论你是从List
还是从Row
获得它都没关系)。既然你将所有东西都折叠成一个map
,你可以完全通过重新排序方法来摆脱val avgX = mainDataFrame.groupBy().agg(mean("_c1")).collect()(0).getDouble(0)
步骤:
first
使用val avgX = mainDataFrame.groupBy().agg(mean("_c1")).first().getDouble(0)
方法可以写得更短:
#Any dataType in Scala can't be directly converted to Double.
#Use toString & then toDouble on final captured result.
#Eg-
#scala> x
#res22: Any = 1.0
#scala> x.toString.toDouble
#res23: Double = 1.0
#Note- Instead of using map().toList() directly use (0)(0) to get the final value from your resultset.
#TestSample(Scala)-
val wa = Array("one","two","two")
val wrdd = sc.parallelize(wa,3).map(x=>(x,1))
val wdf = wrdd.toDF("col1","col2")
val x = wdf.groupBy().agg(mean("col2")).collect()(0)(0).toString.toDouble
#O/p-
#scala> val x = wdf.groupBy().agg(mean("col2")).collect()(0)(0).toString.toDouble
#x: Double = 1.0
qazxswpoi