我正在尝试将文件加载到spark中。 如果我将正常的textFile加载到Spark中,如下所示:
val partFile = spark.read.textFile("hdfs://quickstart:8020/user/cloudera/partfile")
结果是:
partFile: org.apache.spark.sql.Dataset[String] = [value: string]
我可以在输出中看到数据集。但是如果我加载一个Json文件:
val pfile = spark.read.json("hdfs://quickstart:8020/user/cloudera/pjson")
结果是一个带有现成模式的数据框:
pfile: org.apache.spark.sql.DataFrame = [address: struct<city: string, state: string>, age: bigint ... 1 more field]
Json / parquet / orc文件有架构。所以我可以理解这是Spark版本的一个特性:2x,这使得事情变得更容易,因为我们在这种情况下直接获得DataFrame,而对于普通的textFile,你得到的数据集中没有任何架构是有意义的。 我想知道的是如何将模式添加到数据集中,该数据集是将textFile加载到spark中的结果。对于RDD,有一个case类/ StructType选项来添加模式并将其转换为DataFrame。 谁能告诉我怎么办呢?
答案 0 :(得分:7)
使用textFile
时,文件的每一行都是数据集中的字符串行。要使用架构转换为DataFrame,您可以使用toDF
:
val partFile = spark.read.textFile("hdfs://quickstart:8020/user/cloudera/partfile")
import sqlContext.implicits._
val df = partFile.toDF("string_column")
在这种情况下,DataFrame将具有StringType类型的单个列的模式。
如果您的文件包含更复杂的架构,您可以使用csv阅读器(如果文件采用结构化的csv格式):
val partFile = spark.read.option("header", "true").option("delimiter", ";").csv("hdfs://quickstart:8020/user/cloudera/partfile")
或者您可以使用地图处理数据集,然后使用toDF
转换为DataFrame。例如,假设您希望一列成为该行的第一个字符(作为Int)而另一列成为第四个字符(也作为Int):
val partFile = spark.read.textFile("hdfs://quickstart:8020/user/cloudera/partfile")
val processedDataset: Dataset[(Int, Int)] = partFile.map {
line: String => (line(0).toInt, line(3).toInt)
}
import sqlContext.implicits._
val df = processedDataset.toDF("value0", "value3")
此外,您可以定义一个案例类,它将代表DataFrame的最终架构:
case class MyRow(value0: Int, value3: Int)
val partFile = spark.read.textFile("hdfs://quickstart:8020/user/cloudera/partfile")
val processedDataset: Dataset[MyRow] = partFile.map {
line: String => MyRow(line(0).toInt, line(3).toInt)
}
import sqlContext.implicits._
val df = processedDataset.toDF
在上述两种情况下,调用df.printSchema
都会显示:
root
|-- value0: integer (nullable = true)
|-- value3: integer (nullable = true)