簡體   English   中英

如何將 Spark Streaming 數據轉換為 Spark DataFrame

[英]How to convert Spark Streaming data into Spark DataFrame

到目前為止,Spark 還沒有創建用於流式數據的 DataFrame,但是當我在做異常檢測時,使用 DataFrame 進行數據分析更方便、更快捷。 我已經完成了這部分,但是當我嘗試使用流數據進行實時異常檢測時,問題出現了。 我嘗試了幾種方法,仍然無法將DStream轉換為DataFrame,也無法將DStream內部的RDD轉換為DataFrame。

這是我最新版本的代碼的一部分:

import sys
import re

from pyspark import SparkContext
from pyspark.sql.context import SQLContext
from pyspark.sql import Row
from pyspark.streaming import StreamingContext
from pyspark.mllib.clustering import KMeans, KMeansModel, StreamingKMeans
from pyspark.sql.functions import *
from pyspark.sql.types import *
from pyspark.sql.functions import udf
import operator


sc = SparkContext(appName="test")
ssc = StreamingContext(sc, 5)
sqlContext = SQLContext(sc)

model_inputs = sys.argv[1]

def streamrdd_to_df(srdd):
    sdf = sqlContext.createDataFrame(srdd)
    sdf.show(n=2, truncate=False)
    return sdf

def main():
    indata = ssc.socketTextStream(sys.argv[2], int(sys.argv[3]))
    inrdd = indata.map(lambda r: get_tuple(r))
    Features = Row('rawFeatures')
    features_rdd = inrdd.map(lambda r: Features(r))
    features_rdd.pprint(num=3)
    streaming_df = features_rdd.flatMap(streamrdd_to_df)

    ssc.start()
    ssc.awaitTermination()

if __name__ == "__main__":
    main()

正如你在 main() 函數中看到的,當我使用 ssc.socketTextStream() 方法讀取輸入的流數據時,它會生成 DStream,然后我嘗試將 DStream 中的每個個體轉換為 Row,希望可以將數據轉換為DataFrame 稍后。

如果我在這里使用 ppprint() 來打印 features_rdd,它會起作用,這讓我想到, features_rdd 中的每個人都是一批 RDD,而整個 features_rdd 是一個 DStream。

然后我創建了 streamrdd_to_df() 方法並希望將每批 RDD 轉換為數據幀,它給了我錯誤,顯示:

錯誤 StreamingContext:啟動上下文時出錯,將其標記為已停止 java.lang.IllegalArgumentException:要求失敗:未注冊輸出操作,因此無需執行任何操作

有沒有想過如何對 Spark 流數據進行 DataFrame 操作?

Spark 為我們提供了可以解決此類問題的結構化流 它可以生成流數據幀,即連續附加的數據幀。 請檢查以下鏈接

http://spark.apache.org/docs/latest/structured-streaming-programming-guide.html

仔細閱讀錯誤..它說沒有注冊輸出操作 Spark 是懶惰的,只有在它有結果時才執行作業/代碼。 在您的程序中沒有“輸出操作”,Spark 也抱怨同樣的問題。

在 DataFrame 上定義 foreach() 或原始 SQL 查詢,然后打印結果。 它會正常工作。

你為什么不使用這樣的東西:

def socket_streamer(sc): # retruns a streamed dataframe
    streamer = session.readStream\
        .format("socket") \
        .option("host", "localhost") \
        .option("port", 9999) \
        .load()
    return streamer

上面這個函數的輸出本身(或一般的readStream )是一個 DataFrame。 在那里你不需要擔心 df,它已經由 spark 自動創建了。 請參閱Spark 結構化流編程指南

1年后,我開始探索Spark 2.0的流式方法,終於解決了我的異常檢測問題。 這是我在 IPython 中的代碼,您還可以找到我的原始數據輸入的樣子

無需將 DStream 轉換為 RDD。 根據定義,DStream 是 RDD 的集合。 只需使用 DStream 的方法 foreach() 來循環每個 RDD 並采取行動。

val conf = new SparkConf()
  .setAppName("Sample")
val spark = SparkSession.builder.config(conf).getOrCreate()
sampleStream.foreachRDD(rdd => {
    val sampleDataFrame = spark.read.json(rdd)
}

spark 文檔介紹了如何使用 DStream。 基本上,您必須在流對象上使用foreachRDD才能與之交互。

這是一個示例(確保您創建了一個 spark 會話對象):

def process_stream(record, spark):
    if not record.isEmpty():
        df = spark.createDataFrame(record) 
        df.show()


def main():
    sc = SparkContext(appName="PysparkStreaming")
    spark = SparkSession(sc)
    ssc = StreamingContext(sc, 5)
    dstream = ssc.textFileStream(folder_path)
    transformed_dstream = # transformations

    transformed_dstream.foreachRDD(lambda rdd: process_stream(rdd, spark))
    #                   ^^^^^^^^^^
    ssc.start()
    ssc.awaitTermination()

使用 Spark 2.3 / Python 3 / Scala 2.11(使用數據塊),我能夠在 Scala 中使用臨時表和代碼片段(在筆記本中使用魔法):

蟒蛇部分:

ddf.createOrReplaceTempView("TempItems")

然后在一個新單元格上:

%scala
import java.sql.DriverManager
import org.apache.spark.sql.ForeachWriter

// Create the query to be persisted...
val tempItemsDF = spark.sql("SELECT field1, field2, field3 FROM TempItems")

val itemsQuery = tempItemsDF.writeStream.foreach(new ForeachWriter[Row] 
{      
  def open(partitionId: Long, version: Long):Boolean = {
    // Initializing DB connection / etc...
  }

  def process(value: Row): Unit = {
    val field1 = value(0)
    val field2 = value(1)
    val field3 = value(2)

    // Processing values ...
  }

  def close(errorOrNull: Throwable): Unit = {
    // Closing connections etc...
  }
})

val streamingQuery = itemsQuery.start()

暫無
暫無

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

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