如何在Scala中找到特定字段的平均值

时间:2017-12-01 04:47:37

标签: scala apache-spark apache-spark-sql

我正在Apache Spark中尝试Scala shell。 我有一个包含值列表的文本文件,我想查找特定列的平均值。我的input.txt文件如下所示。 (这不是整个文件,而是一个示例。)

<!DOCTYPE html>
<html>
<head>
<script>
function newEl(tag){return document.createElement(tag);}

window.addEventListener('load', mInit, false);

var filenames = ['blueBomb.svg','cpBob.svg'];

function ajaxGet(url, onLoad, onError)
{
    var ajax = new XMLHttpRequest();
    ajax.onload = function(){onLoad(this);}
    ajax.onerror = function(){console.log("ajax request failed to: "+url);onError(this);}
    ajax.open("GET",url,true);
    ajax.send();
}

function mInit()
{
    filenames.forEach( loadImage );
}

function loadImage(filename)
{
    ajaxGet(filename, onLoaded, onFailed);
}

function onLoaded(ajax)
{
    var div = newEl('div');
    div.innerHTML = ajax.responseText;
    document.body.appendChild(div);
}

function onFailed(ajax)
{
    console.log('bugger!');
}
</script>
<style>
</style>
</head>
<body>
</body>
</html>

我想在第1列中找到每列第5列的平均值。例如,假设这些是学生ID和标记的集合。对于每个学生ID,我想找到最后一个主题的标记。另请注意,最后一栏中缺少一些值。

这是我到目前为止尝试过的代码。

1   12.4   12.5   18.9   19.9
2   1.7    1.9
3   11.99  1.9    8.9    12.90978933
2   89.987  7.99         12.898980800000
1   12.8    1.88  1.8
2   1.9     1.8   1.8979  1.808888

我想获得最后一列并找到平均值。 作为第一步,我想到了最后一列中的所有值。

val text = sc.textFile("/neerja/input.txt")
val data = text.flatMap(line => line.split("\\t")).map(word => (word,1).reduceByKey(_ + _);

但这给了我val fourth = text.map(_.split("\\t")(4)).collect 。我怀疑它发生是因为最后一列中缺少某些值。请帮我查一下最后一栏的平均值。任何帮助将受到高度赞赏。

2 个答案:

答案 0 :(得分:0)

您可以执行以下操作

val text = sc.textFile("/neerja/input.txt")

val fourth = text.map(line => line.split("\\t"))
      .map(arr => Try(arr(4).toDouble) getOrElse(0.0)).mean()

println(fourth)

你应该得到第5栏主题的平均值

<强>更新

如果需要所有主题列的平均值,我建议您创建dataframeDataframe已经过优化RDD,许多内置函数可用于计算。

要为给定的数据创建dataframe,您需要schema

import org.apache.spark.sql.types.{DoubleType, IntegerType, StructField, StructType}
val schema = StructType(Seq(
  StructField("Sn", IntegerType, true),
  StructField("subject1", DoubleType, true),
  StructField("subject2", DoubleType, true),
  StructField("subject3", DoubleType, true),
  StructField("subject4", DoubleType, true)
))

RDD[Row]需要创建为

val data = text.map(line => line.split("\\t"))
  .map(arr => Row.fromSeq(Seq(arr(0).toInt, Try(arr(1).asInstanceOf[DoubleType]) getOrElse(0.0),Try(arr(2).toDouble) getOrElse(0.0),Try(arr(3).toDouble) getOrElse(0.0),Try(arr(4).toDouble) getOrElse(0.0))))

最后创建了数据框

val df = sqlContext.createDataFrame(data, schema)
可以使用mean函数

计算每列的

平均值

df.select(mean("subject1").as("averageOFS1"),mean("subject2").as("averageOFS2"),mean("subject3").as("averageOFS3"),mean("subject4").as("averageOFS4")).show(false)

应该给你dataframe

+------------------+-----------------+-----------+-----------------+
|averageOFS1       |averageOFS2      |averageOFS3|averageOFS4      |
+------------------+-----------------+-----------+-----------------+
|21.796166666666668|4.661666666666666|5.24965    |7.919609688333335|
+------------------+-----------------+-----------+-----------------+

答案 1 :(得分:0)

如果你想尝试一种结构方法,你也可以使用Dataframes来实现这个目标:

object average extends App{

  val sparkSession = SparkSession.builder
    .master("local")
    .appName("example")
    .getOrCreate()

  import sparkSession.implicits._


      val x = sparkSession.read
        .option("header", "false")
        .option("delimiter", "\\t")
        .option("mode", "FAILFAST")
        .csv("...Spark-2.x/src/main/resources/tab_data.csv")

x.printSchema()
x.show(truncate = false)
 val df: DataFrame =  x.select('_c0 as "id",
'_c1 as "sub1",'_c2 as "sub2",'_c3 as "sub3",'_c4 as "sub4")

  df.groupBy('id).agg(avg('sub4)).show()
}