文本文件Spark的数据框

时间:2017-12-07 14:14:27

标签: scala apache-spark dataframe

我正在尝试在文本文件上创建数据框。对于示例输入( Input1 )  在代码下工作正常

输入1

1,5

2,6

3,7

4,8

输出1

+---+----+
| id|name|
+---+----+
|  1|   5|
|  2|   6|
|  3|   7|
|  4|   8|
+---+----+

然而,当我更改输入( Input2 )时,我没有得到任何输出。

输入2

1,"a,b,c"

2,"d,e,f"

3,"a,b,c"

4,"a,d,f"

输出2

+---+----+
| id|name|
+---+----+
+---+----+

代码

    {
        val input = sc.textFile(inputFile).map(x=>x.split(",")).collect {
                            case Array(id,name) => Record(id.toInt, name)
                    }
                    input.toDF().show()
    }
case class Record(id: Int, name: String)

Input2的预期输出格式

+---+-----+------+-----+
| id|name1| name2|name3|
+---+-----+------+-----+
|  1|    a|     b|    c|
|  2|    d|     e|    d|    
|  3|    a|     b|    c|
|  4|    a|     d|    f|
+---+-----+------+-----+

我应该对代码和案例类进行更改,以便编译器理解 Input2 的数据格式,但我没有得到我需要做的更改。请指教。

3 个答案:

答案 0 :(得分:1)

假设您使用的是Spark2,您只需执行

即可
val df = spark.read.csv(inputFile)

您可以按照以下步骤拆分第二列。

目前,您正在尝试读取包含多个逗号的整行,并且仅匹配两个元素的数组

答案 1 :(得分:1)

您正在尝试将第一个数字设为id列,其余的逗号分隔的字符在反转的逗号中作为name列。为此,你必须改变一点你的逻辑,你应该没事,如下

val input = sc.textFile(inputFile).map(x=>x.split(",")).map(x => Record(x.head.toInt, x.tail.mkString(",")))
input.toDF().show()

当然case class就像你一样

case class Record(id: Int, name: String)

您应该关注dataframe

+---+-------+
| id|   name|
+---+-------+
|  1|"a,b,c"|
|  2|"d,e,f"|
|  3|"a,b,c"|
|  4|"a,d,f"|
+---+-------+

如果您不想要倒置的逗号,可以添加replace api

val input = sc.textFile(inputFile).map(x=>x.replace("\"", "").split(",")).map(x => Record(x.head.toInt, x.tail.mkString(",")))
input.toDF().show()
你应该

+---+-----+
| id| name|
+---+-----+
|  1|a,b,c|
|  2|d,e,f|
|  3|a,b,c|
|  4|a,d,f|
+---+-----+

我希望答案很有帮助。

顺便说一句,最好使用sqlContext来读取你想忽略引号内逗号的文件。

sqlContext.read.format(inputFile).toDF("id", "name").show(false)

你应该有以上输出数据框

答案 2 :(得分:0)

我尝试使用以下代码并根据需要获得输出。

    {
        val input = sc.textFile(inputFile).map(x=>x.replaceAll("\"","")) 
        val input1 = input.map(x=>x.split(",")).collect { case Array(id,name,name1, name2) => Record(id.toInt, name, name1, name2) }
    }
    case class Record(id: Int, name: String, name1 : String, name2 : String)