我在Spark / Scala中编写一个应用程序,我需要计算列的指数移动平均值。
EMA_t = (price_t * 0.4) + (EMA_t-1 * 0.6)
我面临的问题是我需要先前计算的同一列的值(EMA_t-1)。通过mySQL可以通过使用MODEL或创建一个EMA列来实现,然后你可以每行更新一行,但是我已经尝试了这个并且不能使用Spark SQL或Hive Context ...有什么方法我可以访问此EMA_t-1?
我的数据如下:
timestamp price
15:31 132.3
15:32 132.48
15:33 132.76
15:34 132.66
15:35 132.71
15:36 132.52
15:37 132.63
15:38 132.575
15:39 132.57
所以我需要添加一个新列,其中我的第一个值只是第一行的价格,然后我需要使用前一个值:EMA_t =(price_t * 0.4)+(EMA_t-1 * 0.6)计算该列中的以下行。 我的EMA专栏必须是:
EMA
132.3
132.372
132.5272
132.58032
132.632192
132.5873152
132.6043891
132.5926335
132.5835801
我目前正在尝试使用Spark SQL和Hive,但如果可以通过其他方式实现,那么这将是受欢迎的!我也想知道如何用Spark Streaming做到这一点。我的数据在数据框中,我使用的是Spark 1.4.1。
非常感谢您提供的任何帮助!
答案 0 :(得分:0)
要回答您的问题:
我面临的问题是我需要同一列的先前计算出的值(EMA_t-1)
我认为您需要两个功能:Window和Lag。 (为方便起见,在计算EMA时,我也将null值设为零)
my_window = Window.orderBy("timestamp")
df.withColumn("price_lag_1",when(lag(col("price"),1).over(my_window).isNull,lit(0)).otherwise(lag(col("price"),1).over(my_window)))
我也是Spark Scala的新手,并且正在尝试查看是否可以定义UDF进行指数平均。但目前来看,一个明显的解决方法是手动将所有滞后列加起来(0.4 * lag0 + 0.4 * 0.6 * lag1 + 0.4 * 0.6 ^ 2 * lag2 ...)
df.withColumn("ema_price",
price * lit(0.4) * Math.pow(0.6,0) +
lag(col("price"),1).over(my_window) * 0.4 * Math.pow(0.6,1) +
lag(col("price"),2).over(my_window) * 0.4 * Math.pow(0.6,2) + .... )
我忽略了when.other,以使其更加清晰。这种方法现在对我有用。
----更新----
def emaFunc (y: org.apache.spark.sql.Column, group: org.apache.spark.sql.Column, order: org.apache.spark.sql.Column, beta: Double, lookBack: Int) : org.apache.spark.sql.Column = {
val ema_window = Window.partitionBy(group).orderBy(order)
var i = 1
var result = y
while (i < lookBack){
result = result + lit(1) * ( when(lag(y,i).over(ema_window).isNull,lit(0)).otherwise(lag(y,i).over(ema_window)) * beta * Math.pow((1-beta),i)
- when(lag(y,i).over(ema_window).isNull,lit(0)).otherwise(y * beta * Math.pow((1-beta),i)) )
i = i + 1
}
return result }
通过使用此功能,您应该能够获得价格类似的EMA。
df.withColumn("one",lit(1))
.withColumn("ema_price", emaFunc('price,'one,'timestamp,0.1,10)
这将回溯10天,并计算beta = 0.1的估算EMA。列“一个”只是一个占位符,因为您没有分组列。
答案 1 :(得分:-1)
您应该可以使用1.4中引入的Spark Window函数执行此操作:https://databricks.com/blog/2015/07/15/introducing-window-functions-in-spark-sql.html
w = Window()。partitionBy()。orderBy(col(“timestamp”)) df.select(“*”,lag(“price”)。over(w).alias(“ema”))
这将为您选择最后一个价格,以便您可以对其进行计算