[英]How to convert spark Streaming dataframe column into a Python list
[英]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.