从Spark中嵌套的其他DF / RDD(嵌套Json)创建DF / RDD

时间:2015-11-05 07:23:06

标签: json scala apache-spark rdd

我是Spark& Scala的新手,如果有人可以向我解释这一点,那就太好了。 我们采取以下JSON

let userDefaults = NSUserDefaults.standardUserDefaults();
if let userDefaults.objectForKey("username"){
    if let userDefaults.objectForKey("password"){
        // do login process
        // if user id and password are valid then
        let nextViewController = YourViewController();
        self.presentViewController(nextViewController, animated: true, completion: nil);
    }
}
// else alert some message and stay in loginViewController

我通过sc.parralelize(file.json)将此Json加载到RDD,并通过sqlContext.sql.load.json(file.json)加载到DF。到目前为止这很好,这给了我提到的Json的RDD和DF(带有模式),但我想从现有的RDD / DF中创建另一个包含所有不同的"爱好"记录。我怎么能这样做? 我从我的操作中得到的唯一的东西是多个业余爱好WrappedArrays但我不能更深入,也不能将它们分配给DF / RDD。

我到目前为止的SqlContext代码

    {
    "id": 1,
    "persons": [{
        "name": "n1",
        "lastname": "l1",
        "hobbies": [{
            "name": "h1",
            "activity": "a1"
        },
        {
            "name": "h2",
            "activity": "a2"
        }]
    },
    {
        "name": "n2",
        "lastname": "l2",
        "hobbies": [{
            "name": "h3",
            "activity": "a3"
        },
        {
            "name": "h4",
            "activity": "a4"
        }]
    }]
    }

离开了我

    val jsonData = sqlContext.read.json("path/file.json")
    jsonData.registerTempTable("jsonData") //I receive schema for whole file
    val hobbies = sqlContext.sql("SELECT persons.hobbies FROM jasonData") //subschema for hobbies
    hobbies.show()

我的期望更像是:

    +--------------------+
    |             hobbies|
    +--------------------+
    |[WrappedArray([a1...|
    +--------------------+

1 个答案:

答案 0 :(得分:1)

我将您的示例加载到数据框hobbies中,与您一样,并使用它。您可以运行以下内容:

val distinctHobbies = hobbies.rdd.flatMap {row => row.getSeq[List[Row]](0).flatten}.map(row => (row.getString(0), row.getString(1))).distinct
val dhDF = distinctHobbies.toDF("activity", "name")

这基本上会使你的爱好结构变平,将其转换为元组,并在返回的元组上运行一个独特的元素。然后我们将其转回到正确列别名下的数据框中。因为我们通过底层RDD这样做,所以可能还有一种更有效的方法来使用DataFrame API来完成它。

无论如何,当我运行你的例子时,我看到:

scala> val distinctHobbies = hobbies.rdd.flatMap {row => row.getSeq[List[Row]](0).flatten}.map(row => (row.getString(0), row.getString(1))).distinct
distinctHobbies: org.apache.spark.rdd.RDD[(String, String)] = MapPartitionsRDD[121] at distinct at <console>:24

scala> val dhDF = distinctHobbies.toDF("activity", "name")
dhDF: org.apache.spark.sql.DataFrame = [activity: string, name: string]

scala> dhDF.show
...
+--------+----+
|activity|name|
+--------+----+
|      a2|  h2|
|      a1|  h1|
|      a3|  h3|
|      a4|  h4|
+--------+----+