如何将我的JSON字符串的RDD转换为DataFrame

时间:2017-05-12 15:15:00

标签: json scala apache-spark dataframe rdd

我创建了RDD[String],其中每个String元素包含多个JSON字符串,但所有这些JSON字符串在整个RDD上具有相同的方案。

例如:

名为RDD{String]

rdd包含以下条目: 字符串1:

{"data":"abc", "field1":"def"}
{"data":"123", "field1":"degf"}
{"data":"87j", "field1":"hzc"}
{"data":"efs", "field1":"ssaf"}

字符串2:

{"data":"fsg", "field1":"agas"}
{"data":"sgs", "field1":"agg"}
{"data":"sdg", "field1":"agads"}

我的目标是将此RDD[String]转换为DataFrame。如果我这样做:

val df = rdd.toDF()

...,然后它无法正常工作。实际上df.count()为我提供2,而不是7用于上述示例,因为JSON字符串是批处理的,无法单独识别。

如何创建DataFrame以便每行对应特定的JSON字符串?

2 个答案:

答案 0 :(得分:2)

我现在无法检查,但我认为这应该有效:

// split each string by newline character
val splitted: RDD[Array[String]] = rdd.map(_.split("\n"))

// flatten
val jsonRdd: RDD[String] = splitted.flatMap(identity)

答案 1 :(得分:1)

通过关注您在问题中提供的信息,以下内容可以作为您的解决方案:

import sqlContext.implicits._
val str1 = "{\"data\":\"abc\", \"field1\":\"def\"}\n{\"data\":\"123\", \"field1\":\"degf\"}\n{\"data\":\"87j\", \"field1\":\"hzc\"}\n{\"data\":\"efs\", \"field1\":\"ssaf\"}"
val str2 = "{\"data\":\"fsg\", \"field1\":\"agas\"}\n{\"data\":\"sgs\", \"field1\":\"agg\"}\n{\"data\":\"sdg\", \"field1\":\"agads\"}"
val input = Seq(str1, str2)

val rddData = sc.parallelize(input).flatMap(_.split("\n"))
  .map(line => line.split(","))
  .map(array => (array(0).split(":")(1).trim.replaceAll("\\W", ""), array(1).split(":")(1).trim.replaceAll("\\W", "")))
rddData.toDF("data", "field1").show


被修改
您可以排除fieldNames并使用.toDF(),但这会从您的数据中提供default column names(例如_1 _2col_1 col_2等)
相反,您可以创建schema来创建dataframe,如下所示(您可以添加更多字段)

val rddData = sc.parallelize(input).flatMap(_.split("\n"))
  .map(line => line.split(","))
  .map(array => Row.fromSeq(Seq(array(0).split(":")(1).trim.replaceAll("\\W", ""), array(1).split(":")(1).trim.replaceAll("\\W", ""))))

val schema = StructType(Array(StructField("data", StringType, true),
  StructField("field1", StringType, true)))

sqlContext.createDataFrame(rddData, schema).show

或者
您可以直接创建dataset,但需要case class(您可以添加更多字段),如下所示

val dataSet = sc.parallelize(input).flatMap(_.split("\n"))
  .map(line => line.split(","))
  .map(array => Dinasaurius(array(0).split(":")(1).trim.replaceAll("\\W", ""),
    array(1).split(":")(1).trim.replaceAll("\\W", ""))).toDS

dataSet.show

以上case class的{​​{1}}是

dataset

我希望我回答你所有的问题