集群中的spark执行器如何使用scala中声明的变量

集群中的spark执行器如何使用scala中声明的变量,scala,apache-spark,Scala,Apache Spark,我正在学习scala和spark,我有一个要求,我对为满足要求而实施的方法有些怀疑。 首先,我将告诉您我的数据帧的外观以及我希望在数据帧上执行的操作。 看起来怎么样 +-----------------+----------------------------+ | Street|Total Passing Vehicle Volume| +-----------------+----------------------------+ | Kimball Ave|

我正在学习scala和spark,我有一个要求,我对为满足要求而实施的方法有些怀疑。 首先,我将告诉您我的数据帧的外观以及我希望在数据帧上执行的操作。 看起来怎么样

+-----------------+----------------------------+
|           Street|Total Passing Vehicle Volume|
+-----------------+----------------------------+
|      Kimball Ave|                       100  |
|      Ashland Ave|                       50   |
|         State St|                       110  |
|      Kimball Ave|                       40   |
|     Diversey Ave|                       60   |
|      Ashland Ave|                       70   |
正如你所看到的,有一些重复的街道名称。因此,要求将通过每条街道的车辆总数相加,并用计算出的总和添加一个新列 应该是这样的

+-----------------+----------------------------+-------------+
|           Street|Total Passing Vehicle Volume|Total Vehicle|
+-----------------+----------------------------+-------------+
|      Kimball Ave|                       100  |       140   |
|      Ashland Ave|                       50   |       120   |
|         State St|                       110  |       110   |
|      Kimball Ave|                       40   |       140   |
|     Diversey Ave|                       60   |       60    |
|      Ashland Ave|                       70   |       120   |
我正在得到我想要的,但在读了一些文章后,我发现我的方法并不好,因为它在ceratin的情况下会失败。 我的方法

如您所见,我已经公布了一张地图,并迭代了街道和总超车量列,检查街道列单个记录是否存在于地图中。通过将前一个值与当前值相加来更新该值,否则只需插入该值即可。 但是在阅读了一些文章之后,我认为当它部署到集群时,它将失败,因为这个执行将在多个执行者之间进行划分,并且执行者将不会有Map实例,因此在最后Map甚至不会被填充。 然后我读了闭包,它使用了一个自由变量,而这个自由变量不是函数的一部分。但是我所声明的地图也是一个自由变量,我想。 在这里,我将添加具有值的列:

var func = udf( (s:String) => {
    val d= map.get(s);     //getting the the value from map for each record in Street column
    d
  } )

val newTrafficFd= trafficDf.select($"Street",$"Total Passing Vehicle Volume",func($"Street").as("Total Vehicle"))
  newTrafficFd.show(20); 

有什么改进或建议吗?它会像我预期的那样工作吗

Stone,您不需要为此使用rdd或udf。它可以通过如下窗口聚合实现:

val trafficDf = Seq(
      ("Kimball Ave", 100),
      ("Ashland Ave", 50),
      ("State St", 110),
      ("Kimball Ave", 40),
      ("Diversey Ave", 60),
      ("Ashland Ave", 70)
    ).toDF("Street", "Total Passing Vehicle Volume")

trafficDf.withColumn("Total Vehicle", sum($"Total Passing Vehicle Volume").over(Window.partitionBy("Street")))
      .show()
输出:

+------------+----------------------------+-------------+
|      Street|Total Passing Vehicle Volume|Total Vehicle|
+------------+----------------------------+-------------+
| Ashland Ave|                          50|          120|
| Ashland Ave|                          70|          120|
|Diversey Ave|                          60|           60|
| Kimball Ave|                         100|          140|
| Kimball Ave|                          40|          140|
|    State St|                         110|          110|
+------------+----------------------------+-------------+
说明:

窗口/分析函数是一种ANSI SQL功能,允许基于行组计算额外的聚合

Spark实现了这一功能,因此可以轻松地在其DSL中使用

此功能允许我将车辆总列计算为与每个街道值相关联的车辆总通过量的总和

您可以在此处了解有关窗口的更多信息:

或专门针对Spark:


哦,我的天哪,这是什么请告诉我你做了什么基本上我来自java背景,所以我试图以逻辑的方式解决这个问题,就像我们所做的一样,但是这些东西每天都是全新的,我遇到关于spark的新事物。你能解释一下你做了什么吗?好的,我会在几分钟后给你的答案加上解释;我通过互联网文章学习spark,但大多数网站都没有关于spark的完整内容,因为你是spark开发者,你能给我推荐任何资源吗?除了付费内容,我可以尽可能多地探索内容。不幸的是,StackOverflow中禁止一般资源推荐。我在回答中添加了特定链接,以帮助您打开窗口。您可以在此文档页面中检索更多Spark SQL功能:
+------------+----------------------------+-------------+
|      Street|Total Passing Vehicle Volume|Total Vehicle|
+------------+----------------------------+-------------+
| Ashland Ave|                          50|          120|
| Ashland Ave|                          70|          120|
|Diversey Ave|                          60|           60|
| Kimball Ave|                         100|          140|
| Kimball Ave|                          40|          140|
|    State St|                         110|          110|
+------------+----------------------------+-------------+