cat department
dept_id,dept_name
1,acc
2,finance
3,sales
4,marketing
为什么在df.show()和rdd.toDF.show()中使用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>
答案 0 :(得分:1)
问题在这里
val mappedDpt = dept.map(p => Department( p(0).toInt,p(1).toString))
p
是一个字符串,而不是行 (您可能会想到)。为了更精确一点,p
是文本文件的每一行,您可以确认已读过scaladoc。
“ 返回文本文件行的RDD”。
因此,当您应用apply
方法((0)
)时,您正在按行上的位置访问字符。
这就是为什么从第一个字符的"49, ','"
到toInt
49结束的原因,该字符返回该行的字符的ascii值,并从该行的第二个字符返回','
。 >
如果您需要重现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 ,则上述代码将引发异常。
答案 1 :(得分:0)
始终使用spark.read。*变体,因为它可以为您提供数据框,并且您也可以推断模式。
针对您的问题,在RDD版本中,您必须过滤第一行,然后使用逗号分隔符将行分开,然后可以将其映射到案例类Department。
一旦将其映射到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|
+-------+---------+