Отображение класса дела в CSV - PullRequest
0 голосов
/ 28 ноября 2018
cat department 
dept_id,dept_name
1,acc
2,finance
3,sales
4,marketing

Почему существует разница в выводе show () при использовании в df.show () и rdd.toDF.show ().Может кто-нибудь, пожалуйста, помогите?

scala> case class Department (dept_id: Int, dept_name: String)
defined class Department

scala> val dept = sc.textFile("/home/sam/Projects/department")

scala> val mappedDpt = dept.map(p => Department( p(0).toInt,p(1).toString))

scala> mappedDpt.toDF.show()
+-------+---------+
|dept_id|dept_name|
+-------+---------+
|     49|        ,|
|     50|        ,|
|     51|        ,|
|     52|        ,|
+-------+---------+


scala> 

  val dept_df = spark.read
  .format("csv")
  .option("header","true")
  .option("inferSchema","true")
  .option("mode","permissive")
  .load("/home/sam/Projects/department")

  scala> dept_df.show()
+-------+---------+
|dept_id|dept_name|
+-------+---------+
|      1|      acc|
|      2|  finance|
|      3|    sales|
|      4|marketing|
+-------+---------+


scala> 

Ответы [ 2 ]

0 голосов
/ 28 ноября 2018

Всегда используйте варианты spark.read. *, Так как это дает вам фрейм данных, и вы также можете вывести схему.

Что касается вашей проблемы, то в вашей версии СДР вам необходимо отфильтровать первую строку, а затем разбить строки, используя разделитель запятых, а затем сопоставить его с классом дел Department.

Как только высопоставьте его с отделом, обратите внимание, что вы создаете типизированный фрейм данных .. так что это набор данных.Поэтому вы должны использовать createDataset

У меня работает следующий код:

import org.apache.log4j.{Level, Logger}
import org.apache.spark.sql.SparkSession

object RDDSample {

  case class Department(dept_id: Int, dept_name: String)

  def main(args: Array[String]) {
    Logger.getLogger("org").setLevel(Level.ERROR)
    val spark = SparkSession.builder().appName("Spark_processing").master("local[*]").getOrCreate()

    import spark.implicits._

    val dept = spark.sparkContext.textFile("in/department.txt")
    val mappedDpt = dept.filter(line => !line.contains("dept_id")).map(p => {
      val y = p.split(","); Department(y(0).toInt, y(1).toString)
    })

    spark.createDataset(mappedDpt).show
  }
}

Результаты:

+-------+---------+
|dept_id|dept_name|
+-------+---------+
|      1|      acc|
|      2|  finance|
|      3|    sales|
|      4|marketing|
+-------+---------+
0 голосов
/ 28 ноября 2018

Проблема здесь

val mappedDpt = dept.map(p => Department( p(0).toInt,p(1).toString))

p здесь есть строка , а не строка (как вы, возможно, думаете) ,Чтобы быть более точным здесь p - это каждая строка текстового файла, вы можете подтвердить, что чтение scaladoc .

" возвращает RDD строктекстового файла ".

Итак, когда вы применяете метод apply ((0)) , вы получаете доступ к символу по позиции в строке.
Вот почему вы получаете "49, ','" 49 от toInt первого символа, который возвращает значение ascii символа, и ',' от второго символа в строке.

Edit

Если вам нужно воспроизвести метод read, вы можете сделать следующее:

object Department {
  /** The Option here is to handle errors. */
  def fromRawArray(data: Array[String]): Option[Department] = data match {
    case Array(raw_dept_id, dept_name) => Some(Department(raw_dept_id.toInt, dept_name))
    case _ => None
  }
}

// We use flatMap instead of map, to unwrap the values from the Option, the Nones get removed.
val mappedDpt = dept.flatMap(line => Department.fromRawArray(line.split(",")))

Однако я надеюсь, что это только для обучения.В производственном коде вы всегда должны использовать версию read.Так как он будет более устойчивым (обработка пропущенных значений, более качественное приведение типов и т. Д.) .
Например, приведенный выше код вызовет исключение, если первое значение не может быть приведено к Int .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...