Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/apache-spark/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Apache spark Spark SQL dataframe:跨行对计算的最佳方法_Apache Spark_Dataframe_Apache Spark Sql - Fatal编程技术网

Apache spark Spark SQL dataframe:跨行对计算的最佳方法

Apache spark Spark SQL dataframe:跨行对计算的最佳方法,apache-spark,dataframe,apache-spark-sql,Apache Spark,Dataframe,Apache Spark Sql,我有一个Spark数据帧“deviceDF”,如下所示: ID date_time state a 2015-12-11 4:30:00 up a 2015-12-11 5:00:00 down a 2015-12-11 5:15:00 up b 2015-12-12 4:00:00 down b 2015-12-12 4:20:00 up a 2015-1

我有一个Spark数据帧“deviceDF”,如下所示:

ID    date_time            state  
a     2015-12-11 4:30:00     up  
a     2015-12-11 5:00:00     down  
a     2015-12-11 5:15:00     up  
b     2015-12-12 4:00:00     down  
b     2015-12-12 4:20:00     up  
a     2015-12-12 10:15:00    down  
a     2015-12-12 10:20:00    up  
b     2015-12-14 15:30:00    down  
我试图计算每个ID的停机时间。我从简单开始,根据id分组,分别计算所有正常运行时间和停机时间的总和。然后计算正常运行时间和停机时间之差

val downtimeDF=deviceDF.filter($“state”=“down”)
.groupBy(“ID”)
.agg(总和(unix时间戳($“日期时间”)为“停机时间”)
val uptimeDF=deviceDF.filter($“state”=“up”)
.groupBy(“ID”)
.agg(总和(unix\u时间戳($“日期\u时间”)为“up\u时间”)
val updownjoinDF=uptimeDF.join(downtimeDF,“ID”)
val difftimeDF=向上向下连接DF
.withColumn(“差异时间”,“上升时间”-$“下降时间”)
但是,很少有情况会导致错误,例如设备停机但从未恢复,在这种情况下,停机时间是当前停机时间和上次停机时间之间的差值


此外,如果特定设备的第一个条目以“up”开头,则down_时间是第一个_条目与分析开始时的时间之差,例如2015-12-11 00:00:00。使用dataframe处理这些边界条件的最佳方法是什么?是否需要编写自定义UDAF?

您可以尝试的第一件事是使用窗口函数。虽然这通常不是最快的解决方案,但它简洁且极具表现力。以您的数据为例:

import org.apache.spark.sql.functions.unix\u时间戳
val df=sc.parallelize(数组(
(“a”,“2015-12-11 04:30:00”,“上升”),(“a”,“2015-12-11 05:00:00”,“下降”),
(“a”,“2015-12-11 05:15:00”,“上升”),(“b”,“2015-12-12 04:00:00”,“下降”),
(“b”,“2015-12-12 04:20:00”,“向上”),(“a”,“2015-12-12 10:15:00”,“向下”),
(“a”,“2015-12-12 10:20:00”,“上升”),(“b”,“2015-12-14 15:30:00”,“下降”))
.toDF(“ID”、“日期时间”、“状态”)
.withColumn(“时间戳”,unix\u时间戳($“日期\u时间”))
让我们定义示例窗口:

import org.apache.spark.sql.expressions.Window
import org.apache.spark.sql.functions.{coalesce, lag, when, sum}

val w = Window.partitionBy($"ID").orderBy($"timestamp")
一些辅助列

val-previousTimestamp=coalesce(滞后($“timestamp”,1).over(w),$“timestamp”)
val previousState=合并(滞后($“状态”,1)。超过(w),$“状态”)
val停机时间=何时(
previousState==“向下”,
$“时间戳”-以前的时间戳
).否则(0).别名(“停机”)
val正常运行时间=何时(
previousState==“向上”,
$“时间戳”-以前的时间戳
).否则(0).别名(“正常运行时间”)
最后是一个基本查询:

val upsAndDowns=df.选择($“*”,正常运行时间,停机时间)
上上下下的表演
// +---+-------------------+-----+----------+------+--------+
//| ID |日期|时间|状态|时间戳|正常运行时间|停机时间|
// +---+-------------------+-----+----------+------+--------+
//| a | 2015-12-11 04:30:00 |向上| 1449804600 | 0 | 0|
//| a | 2015-12-11 05:00:00 |下降| 1449806400 | 1800 | 0|
//| a | 2015-12-11 05:15:00向上| 1449807300 | 0 | 900|
//| a | 2015-12-12 10:15:00 |下降| 1449911700 | 104400 | 0|
//| a | 2015-12-12 10:20:00向上| 1449912000 | 0 | 300|
//| b | 2015-12-12 04:00:00 |向下| 1449889200 | 0 | 0|
//| b | 2015-12-12 04:20:00向上| 1449890400 | 0 | 1200|
//| b | 2015-12-14 15:30:00 |下降| 1450103400 | 213000 | 0|
// +---+-------------------+-----+----------+------+--------+
以类似的方式,您可以向前看,如果组中没有更多记录,您可以使用当前时间戳调整总的
正常运行时间
/
停机时间

窗口函数提供了一些其他有用的功能,如窗口定义,其中包含
行在
之间和
范围在
子句之间

另一种可能的解决方案是将数据移动到RDD,并使用
RangePartitioner
mapPartitions
和滑动窗口的低级操作。对于基本内容,您甚至可以
groupBy
。这需要付出更多的努力,但也更加灵活

最后是Cloudera的一个包。文档几乎不存在,但测试足够全面,可以让您了解如何使用它


关于自定义UDAFs,我不会乐观。UDAFAPI相当具体,并不完全灵活

谢谢,我不知道窗口的功能