如何在Spark中创建一个空的dataFrame

时间:2018-05-30 13:53:47

标签: scala apache-spark apache-spark-sql avro spark-avro

我有一组基于Avro的配置单元表,我需要从中读取数据。由于Spark-SQL使用hive serdes从HDFS读取数据,因此它比直接读取HDFS慢得多。所以我使用数据块Spark-Avro jar从底层HDFS目录中读取Avro文件。

除非表格为空,否则一切正常。我已经设法使用以下命令从hive表的.avsc文件中获取模式但是我收到错误" 找不到Avro文件"

val schemaFile = FileSystem.get(sc.hadoopConfiguration).open(new Path("hdfs://myfile.avsc"));

val schema = new Schema.Parser().parse(schemaFile);

spark.read.format("com.databricks.spark.avro").option("avroSchema", schema.toString).load("/tmp/myoutput.avro").show()

解决方法:

我在该目录中放置了一个空文件,同样的工作正常。

还有其他方法可以实现同样的目标吗?喜欢conf设置还是什么?

4 个答案:

答案 0 :(得分:2)

创建一个空的DataFrame:

val my_schema = StructType(Seq(
    StructField("field1", StringType, nullable = false),
    StructField("field2", StringType, nullable = false)
  ))

val empty: DataFrame = spark.createDataFrame(spark.sparkContext.emptyRDD[Row], my_schema)

也许这可能会有所帮助

答案 1 :(得分:1)

与EmiCareOfCell44的答案类似,只是更加优雅和“空”

val emptySchema = StructType(Seq())
val emptyDF = spark.createDataFrame(spark.sparkContext.emptyRDD[Row],
                emptySchema)

答案 2 :(得分:0)

根据您的Spark版本,您可以使用反射方式。SchemaConverters中有一个私有方法可以将Schema转换为StructType ...(不知道为什么它是私有的)老实说,在其他情况下它会非常有用)。使用scala反射,您应该能够以下列方式执行此操作

import scala.reflect.runtime.{universe => ru}
import org.apache.avro.Schema
import org.apache.spark.sql.Row
import org.apache.spark.sql.types.{StructType, StructField, StringType, IntegerType}

var schemaStr = "{\n \"type\": \"record\",\n \"namespace\": \"com.example\",\n \"name\": \"FullName\",\n \"fields\": [\n { \"name\": \"first\", \"type\": \"string\" },\n      { \"name\": \"last\", \"type\": \"string\" }\n  ]\n }"
val schema = new Schema.Parser().parse(schemaStr);

val m = ru.runtimeMirror(getClass.getClassLoader)
val module = m.staticModule("com.databricks.spark.avro.SchemaConverters")
val im = m.reflectModule(module)
val method = im.symbol.info.decl(ru.TermName("toSqlType")).asMethod

val objMirror = m.reflect(im.instance)
val structure = objMirror.reflectMethod(method)(schema).asInstanceOf[com.databricks.spark.avro.SchemaConverters.SchemaType]
val sqlSchema = structure.dataType.asInstanceOf[StructType]
val empty = spark.createDataFrame(spark.sparkContext.emptyRDD[Row], sqlSchema)

empty.printSchema

答案 3 :(得分:0)

您不需要使用emptyRDD。这是PySpark 2.4对我有用的东西:

empty_df = spark.createDataFrame([], schema) # spark is the Spark Session

如果您已经具有另一个数据框的架构,则可以执行以下操作:

schema = some_other_df.schema

如果不这样做,则手动创建空数据框的架构,例如:

schema = StructType([StructField("col_1", StringType(), True),
                     StructField("col_2", DateType(), True),
                     StructField("col_3", StringType(), True),
                     StructField("col_4", IntegerType(), False)]
                     )

我希望这会有所帮助。