Apache spark Spark窗口功能:为范围引用不同的列

Apache spark Spark窗口功能:为范围引用不同的列,apache-spark,pyspark,spark-dataframe,window-functions,pyspark-sql,Apache Spark,Pyspark,Spark Dataframe,Window Functions,Pyspark Sql,我有一个数据框,其中列为start\u time和end\u time。我想设置窗口,每个观察的窗口在结束时间之前是它前面的两行,限制为在该观察的开始时间之前有一个end\u时间的数据 示例数据: data = [('a', 10, 12, 5),('b', 20, 25, 10),('c', 30, 60, 15),('d', 40, 45, 20),('e', 50, 70, 25)] df = sqlContext.createDataFrame(data, ['name', 'start

我有一个数据框,其中列为
start\u time
end\u time
。我想设置窗口,每个观察的窗口在结束时间之前是它前面的两行,限制为在该观察的开始时间之前有一个
end\u时间的数据

示例数据:

data = [('a', 10, 12, 5),('b', 20, 25, 10),('c', 30, 60, 15),('d', 40, 45, 20),('e', 50, 70, 25)]
df = sqlContext.createDataFrame(data, ['name', 'start_time', 'end_time', 'resource'])
+----+----------+--------+--------+
|name|start_time|end_time|resource|
+----+----------+--------+--------+
|   a|        10|      12|       5|
|   b|        20|      25|      10|
|   c|        30|      60|      15|
|   d|        40|      45|      20|
|   e|        50|      70|      25|
+----+----------+--------+--------+
因此,“e”的窗口应该包括“b”和“d”,而不是“c”

没有结束时间<开始时间的限制,我可以使用

from pyspark.sql import Window        
from pyspark.sql import functions as func
window = Window.orderBy("name").rowsBetween(-2, -1)
df.select('*', func.avg("resource").over(window).alias("avg")).show()
我查看了
rangeBetween()
,但我找不到引用当前行的
start\u time
的方法,或者我想通过其他行的
end\u time
来限制它。有
Window.currentRow
,但在本例中,它只会引用
resource

这可以使用Windows来完成吗?我应该完全尝试别的吗


编辑:如果有必要,可以使用Spark 2.1.1和Python 2.7+。

您实际上可以使用groupBy函数对不同分区进行聚合,然后在同一公共键上使用输出数据帧之间的内部联接。Partition by或window函数在spark中需要花费大量时间,因此如果可以,最好使用groupby。

您实际上可以使用groupby函数对不同的分区进行聚合,然后通过相同的公共键使用输出数据帧之间的内部联接。分区依据或窗口函数在spark中需要花费大量时间,因此如果可以,最好使用groupby。

我认为纯粹使用windows是不可能的。从给定的行开始,您需要能够按照与前面的行相反的排序顺序工作,直到有两个满足条件的点击

您可以使用一个窗口函数来创建一个列表,其中列出了每一行之前遇到的所有值,然后使用一个带有纯scala/python的UDF来确定总和,从而说明排除情况

在scala中:

val window = Window.partitionBy(???).orderBy("end_time").rowsBetween(Long.MinValue, -1)

val udfWithSelectionLogic = udf { values: Seq[Row] => INSERT_LOGIC_HERE_TO_CALCULATE_AGGREGATE }

val dataPlus = data.withColumn("combined", struct($"start_time", $"end_time", $"resource"))
        .withColumn("collected", collect_list($"combined") over window)
        .withColumn("result", udfWithSelectionLogic($"collected"))

这并不理想,但可能会有所帮助。

我认为纯粹使用windows不可能做到这一点。从给定的行开始,您需要能够按照与前面的行相反的排序顺序工作,直到有两个满足条件的点击

您可以使用一个窗口函数来创建一个列表,其中列出了每一行之前遇到的所有值,然后使用一个带有纯scala/python的UDF来确定总和,从而说明排除情况

在scala中:

val window = Window.partitionBy(???).orderBy("end_time").rowsBetween(Long.MinValue, -1)

val udfWithSelectionLogic = udf { values: Seq[Row] => INSERT_LOGIC_HERE_TO_CALCULATE_AGGREGATE }

val dataPlus = data.withColumn("combined", struct($"start_time", $"end_time", $"resource"))
        .withColumn("collected", collect_list($"combined") over window)
        .withColumn("result", udfWithSelectionLogic($"collected"))

这并不理想,但可能会有所帮助。

分区依据是什么?没有它,所有的行都会在同一个分区中,在一个执行器上,这会用大数据集杀死它。是的,我的实际数据非常大,所以我有一个
partitionBy
,它似乎工作得很好-
name
的组,每个组都有一个a,b,c,等等。当我运行代码时,没有只考虑结束时间<当前行开始时间的数据的限制,它似乎没有任何问题。我只是在集成此限制时遇到问题。
分区依据是什么?没有它,所有的行都会在同一个分区中,在一个执行器上,这会用大数据集杀死它。是的,我的实际数据非常大,所以我有一个
partitionBy
,它似乎工作得很好-
name
的组,每个组都有一个a,b,c,等等。当我运行代码时,没有只考虑结束时间<当前行开始时间的数据的限制,它似乎没有任何问题。我只是在整合这个限制时遇到了问题。