Python 如何将Spark流数据转换为Spark数据帧

Python 如何将Spark流数据转换为Spark数据帧,python,pyspark,spark-streaming,Python,Pyspark,Spark Streaming,到目前为止,Spark还没有为流式数据创建DataFrame,但是当我进行异常检测时,使用DataFrame进行数据分析更方便、更快。我已经完成了这一部分,但是当我尝试使用流数据进行实时异常检测时,问题出现了。我尝试了几种方法,但仍然无法将数据流转换为数据帧,也无法将数据流内部的RDD转换为数据帧 以下是我最新版本代码的一部分: import sys import re from pyspark import SparkContext from pyspark.sql.context impo

到目前为止,Spark还没有为流式数据创建DataFrame,但是当我进行异常检测时,使用DataFrame进行数据分析更方便、更快。我已经完成了这一部分,但是当我尝试使用流数据进行实时异常检测时,问题出现了。我尝试了几种方法,但仍然无法将数据流转换为数据帧,也无法将数据流内部的RDD转换为数据帧

以下是我最新版本代码的一部分:

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.socketextstream()方法读取输入流数据时,它会生成数据流,然后我尝试将数据流中的每个个体转换为行,希望以后可以将数据转换为数据帧

如果我在这里使用ppprint()打印出features\u rdd,它会起作用,这让我想到,features\u rdd中的每个单独部分都是一批rdd,而整个features\u rdd是一个数据流

然后我创建了streamrdd_to_df()方法,希望将每批RDD转换为dataframe,它给出了错误,显示:

ERROR StreamingContext:启动上下文时出错,将其标记为已停止 java.lang.IllegalArgumentException:需求失败:未注册任何输出操作,因此无法执行任何操作


有没有想过如何对Spark streaming data执行数据帧操作?

仔细阅读错误。它说没有注册输出操作。Spark是懒惰的,只有当它有结果时才执行作业/cod。在您的程序中没有“输出操作”,Spark也在抱怨这一点


在数据帧上定义foreach()或原始SQL查询,然后打印结果。它会很好地工作。

Spark为我们提供了结构化流媒体,可以解决这些问题。它可以生成流数据帧,即连续追加的数据帧。请查看下面的链接


为什么不使用这样的东西:

def socket_streamer(sc): # retruns a streamed dataframe
    streamer = session.readStream\
        .format("socket") \
        .option("host", "localhost") \
        .option("port", 9999) \
        .load()
    return streamer
上面这个函数的输出本身(或者通常是
readStream
)是一个数据帧。在这里,您不需要担心df,它已经由spark自动创建。
参见

1年后,我开始探索Spark 2.0流媒体方法,并最终解决了异常检测问题,您还可以在Spark 2.3/Python 3/Scala 2.11(使用databricks)中找到

,我可以在Scala中使用临时表和代码片段(在笔记本中使用magic):

Python部分:

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()

不需要将数据流转换为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会话对象):


谢谢@Sumit,我确实试过输出结果。在streamrdd_to_df()函数中,我使用
sdf.show(n=2,truncate=False)
打印结果,但它无法……我执行了代码,它对我有效。我所做的唯一更改是用
tuple
替换
get\u tuple
,并删除
pyspark.mllib…
import。虽然输出没有意义,但没有错误。这个错误还有其他原因吗?你能粘贴完整的堆栈跟踪吗?我刚刚读到,他们在Spark 2.0中添加了它,这可能是解决这个问题的方法。我使用的是Spark 1.5,它现在比发布时有了很大的改进。
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()