Как добавить схему в набор данных в Spark?

98
14

Я пытаюсь загрузить файл в искру. Если я загружаю обычный 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")

Результатом является dataframe с готовой схемой:

pfile: org.apache.spark.sql.DataFrame = [address: struct<city: string, state: string>, age: bigint ... 1 more field]

В файлах Json/parquet/orc есть схема. Поэтому я могу понять, что это особенность версии Spark: 2x, что упростило ситуацию, поскольку мы напрямую получаем DataFrame в этом случае, а для обычного текстового файла вы получаете набор данных, где нет никакой схемы, которая имеет смысл. Я хотел бы знать, как я могу добавить схему в набор данных, который является результатом загрузки textFile в искру. Для RDD существует опция case/StructType для добавления схемы и преобразования ее в DataFrame. Может ли кто-нибудь дать мне знать, как я могу это сделать?

спросил(а) 2021-01-19T14:19:45+03:00 2 месяца, 3 недели назад
1
Решение
106

Когда вы используете 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")

Кроме того, вы можете определить класс case, который будет представлять окончательную схему для вашего 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)

ответил(а) 2021-01-19T14:19:45+03:00 2 месяца, 3 недели назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема