Apache spark 如何计算数据帧中的移动中值?

Apache spark 如何计算数据帧中的移动中值?,apache-spark,apache-spark-sql,Apache Spark,Apache Spark Sql,是否有方法计算spark DataFrame中属性的移动中值 我希望可以使用窗口函数(通过使用(0,10)之间的行定义窗口)来计算移动中值,但没有计算它的功能(类似于平均值或平均值)。我认为您在这里几乎没有选择 前向窗函数 我认为ntile(2)(在一个行窗口上)会给你两个“段”,你可以用它们来计算窗口上的中值 引述: ntile(n:Int)窗口函数:返回有序窗口分区中的ntile组id(从1到n,包括1到n)。例如,如果n为4,则第一季度的行将获得值1,第二季度将获得值2,第三季度将获得值3

是否有方法计算spark DataFrame中属性的移动中值

我希望可以使用窗口函数(通过使用(0,10)之间的
行定义窗口)来计算移动中值,但没有计算它的功能(类似于
平均值
平均值
)。

我认为您在这里几乎没有选择

前向窗函数 我认为
ntile(2)
(在一个行窗口上)会给你两个“段”,你可以用它们来计算窗口上的中值

引述:

ntile(n:Int)窗口函数:返回有序窗口分区中的ntile组id(从1到n,包括1到n)。例如,如果n为4,则第一季度的行将获得值1,第二季度将获得值2,第三季度将获得值3,最后一季度将获得值4

这相当于SQL中的NTILE函数

如果一个组中的行数大于另一个组中的行数,请从较大的组中选择最大的行数

如果组中的行数为偶数,则取每组中的最大行数和最小行数,然后计算中位数

我发现它在中描述得很好

百分比秩窗口函数 我认为,
percent\u rank
也可能是计算行窗口中位数的一个选项

引述:

percent\u rank()窗口函数:返回窗口分区内行的相对排名(即百分位)

计算方法如下:

(其分区中的行的排名-1)/(分区中的行数-1)

这相当于SQL中的PERCENT_RANK函数

用户定义聚合函数(UDAF) 您可以编写一个用户定义的聚合函数(UDAF)来计算窗口上的中值

UDAF扩展为(引用scaladoc):

用于实现用户定义的聚合函数(UDAF)的基类


幸运的是,示例中有一个自定义UDAF的示例实现。

下面是一个类I扩展的UserDefinedAggregateFunction,用于获取移动中值

class MyMedian extends org.apache.spark.sql.expressions.UserDefinedAggregateFunction {
  def inputSchema: org.apache.spark.sql.types.StructType =
    org.apache.spark.sql.types.StructType(org.apache.spark.sql.types.StructField("value", org.apache.spark.sql.types.DoubleType) :: Nil)

  def bufferSchema: org.apache.spark.sql.types.StructType = org.apache.spark.sql.types.StructType(
    org.apache.spark.sql.types.StructField("window_list", org.apache.spark.sql.types.ArrayType(org.apache.spark.sql.types.DoubleType, false)) :: Nil
  )
  def dataType: org.apache.spark.sql.types.DataType = org.apache.spark.sql.types.DoubleType
  def deterministic: Boolean = true
  def initialize(buffer: org.apache.spark.sql.expressions.MutableAggregationBuffer): Unit = {
    buffer(0) = new scala.collection.mutable.ArrayBuffer[Double]()
  }
  def update(buffer: org.apache.spark.sql.expressions.MutableAggregationBuffer,input: org.apache.spark.sql.Row): Unit = {
    var bufferVal=buffer.getAs[scala.collection.mutable.WrappedArray[Double]](0).toBuffer
    bufferVal+=input.getAs[Double](0)
    buffer(0) = bufferVal
  }
  def merge(buffer1: org.apache.spark.sql.expressions.MutableAggregationBuffer, buffer2: org.apache.spark.sql.Row): Unit = {
    buffer1(0) = buffer1.getAs[scala.collection.mutable.ArrayBuffer[Double]](0) ++ buffer2.getAs[scala.collection.mutable.ArrayBuffer[Double]](0)
  }
  def evaluate(buffer: org.apache.spark.sql.Row): Any = {
      var sortedWindow=buffer.getAs[scala.collection.mutable.WrappedArray[Double]](0).sorted.toBuffer
      var windowSize=sortedWindow.size
      if(windowSize%2==0){
          var index=windowSize/2
          (sortedWindow(index) + sortedWindow(index-1))/2
      }else{
          var index=(windowSize+1)/2 - 1
          sortedWindow(index)
      }
  }
}
使用上述UDAF示例:

// Create an instance of UDAF MyMedian.
val mm = new MyMedian

var movingMedianDS = dataSet.withColumn("MovingMedian", mm(col("value")).over( Window.partitionBy("GroupId").rowsBetween(-10,10)) )

如何注册UDAF并在Spark应用程序中使用它?@Jacek//create mymedia object var winMed=new mymedia//Define window val wSpec1=window.partitionBy//在窗口df上应用中间值,带列(,winMed(col())。超过(wSpec1))