簡體   English   中英

如何在Pyspark中使用滑動窗口對時間序列數據進行數據轉換

[英]How to transform data with sliding window over time series data in Pyspark

我試圖基於時間序列數據的滑動窗口提取功能。 在Scala中,似乎有一個基於這篇文章文檔sliding功能

import org.apache.spark.mllib.rdd.RDDFunctions._

sc.parallelize(1 to 100, 10)
  .sliding(3)
  .map(curSlice => (curSlice.sum / curSlice.size))
  .collect()

我的問題是PySpark中有類似的功能嗎? 或者,如果沒有這樣的功能,我們如何實現類似的滑動窗口轉換呢?

據我所知, sliding功能不能從Python獲得, SlidingRDD是私有類,不能在MLlib外部MLlib

如果你在現有的RDD上使用sliding ,你可以像這樣創建窮人sliding

def sliding(rdd, n):
    assert n > 0
    def gen_window(xi, n):
        x, i = xi
        return [(i - offset, (i, x)) for offset in xrange(n)]

    return (
        rdd.
        zipWithIndex(). # Add index
        flatMap(lambda xi: gen_window(xi, n)). # Generate pairs with offset
        groupByKey(). # Group to create windows
        # Sort values to ensure order inside window and drop indices
        mapValues(lambda vals: [x for (i, x) in sorted(vals)]).
        sortByKey(). # Sort to makes sure we keep original order
        values(). # Get values
        filter(lambda x: len(x) == n)) # Drop beginning and end

或者你可以嘗試這樣的東西(在toolz幫助下)

from toolz.itertoolz import sliding_window, concat

def sliding2(rdd, n):
    assert n > 1

    def get_last_el(i, iter):
        """Return last n - 1 elements from the partition"""
        return  [(i, [x for x in iter][(-n + 1):])]

    def slide(i, iter):
        """Prepend previous items and return sliding window"""
        return sliding_window(n, concat([last_items.value[i - 1], iter]))

    def clean_last_items(last_items):
        """Adjust for empty or to small partitions"""
        clean = {-1: [None] * (n - 1)}
        for i in range(rdd.getNumPartitions()):
            clean[i] = (clean[i - 1] + list(last_items[i]))[(-n + 1):]
        return {k: tuple(v) for k, v in clean.items()}

    last_items = sc.broadcast(clean_last_items(
        rdd.mapPartitionsWithIndex(get_last_el).collectAsMap()))

    return rdd.mapPartitionsWithIndex(slide)

為了增加venuktan的答案,這里是如何使用Spark SQL創建一個基於時間的滑動窗口並保留窗口的全部內容,而不是采用它的聚合。 在我將時間序列數據預處理到滑動窗口以輸入Spark ML的用例中需要這樣做。

這種方法的一個限制是我們假設你想隨着時間推移滑動窗口。

首先,您可以創建Spark DataFrame,例如通過讀取CSV文件:

df = spark.read.csv('foo.csv')

我們假設您的CSV文件有兩列:其中一列是unix時間戳,另一列是要從中提取滑動窗口的列。

from pyspark.sql import functions as f

window_duration = '1000 millisecond'
slide_duration = '500 millisecond'

df.withColumn("_c0", f.from_unixtime(f.col("_c0"))) \
    .groupBy(f.window("_c0", window_duration, slide_duration)) \
    .agg(f.collect_list(f.array('_c1'))) \
    .withColumnRenamed('collect_list(array(_c1))', 'sliding_window')

額外:要將此數組列轉換為Spark ML所需的DenseVector格式, 請參閱此處的UDF方法

額外獎勵:要取消嵌套生成的列,以便滑動窗口的每個元素都有自己的列,請在此處嘗試此方法

我希望這有幫助,如果我能澄清任何事情,請告訴我。

spark 1.4具有窗口功能,如下所述: https//databricks.com/blog/2015/07/15/introducing-window-functions-in-spark-sql.html

希望有所幫助,請告訴我。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM