对窗口函数求平均会导致StackOverflowError

时间:2016-01-14 15:57:11

标签: apache-spark pyspark apache-spark-sql pyspark-sql

我试图通过使用窗口函数来确定Dataframe列中日期之间的平均时间跨度。然而,实现Dataframe会引发Java异常。

考虑以下示例:

from pyspark import SparkContext
from pyspark.sql import HiveContext, Window, functions
from datetime import datetime

sc = SparkContext()
sq = HiveContext(sc)

data = [
    [datetime(2014,1,1)],
    [datetime(2014,2,1)],
    [datetime(2014,3,1)],
    [datetime(2014,3,6)],
    [datetime(2014,8,23)],
    [datetime(2014,10,1)],
]
df = sq.createDataFrame(data, schema=['ts'])

ts = functions.col('ts')

w = Window.orderBy(ts)
diff = functions.datediff(
    ts,
    functions.lag(ts, count=1).over(w)
)

avg_diff = functions.avg(diff)

df.select(diff.alias('diff')).show()正确呈现为

+----+
|diff|
+----+
|null|
|  31|
|  28|
|   5|
| 170|
|  39|
+----+

执行df.select(avg_diff).show()会得到java.lang.StackOverflowError

我认为这应该有用吗?如果是这样,我做错了什么,我该怎么办呢?

我在Spark 1.6上使用Python API

当我执行df2 = df.select(diff.alias('diff'))然后执行

df2.select(functions.avg('diff'))

没有错误。不幸的是,这不是我当前设置中的一个选项。

1 个答案:

答案 0 :(得分:1)

它看起来像Catalyst中的一个错误但是。链接方法应该可以正常工作:

df.select(diff.alias('diff')).agg(functions.avg('diff'))

不过我在这里要小心。不应使用窗口函数来执行全局(没有PARTITION BY子句)操作。这些将所有数据移动到单个分区并执行顺序扫描。在这里使用RDD可能是更好的选择。