首先啰嗦一句,Spark SQL Dataset中主要分为Transformation和Action两种API(这个特性沿用了Spark RDD的特性,其中的Transformation也有懒计算的猥琐特性)
下面主要通过对比SQL语句的方式来记录下如何从一个DataFrame中获取某个字段
首先有个DataFrame,如下
personDf.show()
|age| name| sex|
±–±----±-----+
| 32| Brad| male|
| 31| Anne|female|
| 4|Eason| male|
我们知道,如果是通过SQL语句(把上面的personDf比喻成一个表)选择其中的name列,只要简单的
SELECT name FROM personDf
即可
而在DataFrame中,同样有select这样的API,要完成上面的name这一列的展示也只是
personDf.select("name").show()
一行代码即可,感觉比SQL更简单了,有木有?
那么如何查看一个表的所有的列信息呢,有如下几种方法
personDf.printSchema
上述展示结果比较好看,有点类似于SQL中的
desc personDf;
2.PersonDf.columns
结果如下:
Array[String] = Array(age, name, sex)
此时看不到列的属性
3.personDf.schema
结果如下:
org.apache.spark.sql.types.StructType = StructType(StructField(age,LongType,true), StructField(name,StringType,true), StructField(sex,StringType,true))
这个结果虽然也能看到列的属性,但是不大好看
下面讲述一下和select这个API相关的一些操作
首先,上述的select(“name”)在底层会将字符串“name”转换为Column类,而select实际上是接收Column类,如下操作等同之前的personDf.select(“name”).show()
val nameColumn = personDf.col("name")
单独构建一个Column类,返回结果如下:
org.apache.spark.sql.Column = name
然后再select
personDf.select(nameColumn).show()
而构建Column类有很多种方法,比如
val nameColumn = personDf("name")
val nameColumn = personDf.apply("name")
val nameColumn = personDf.col("name")
val nameColumn = personDf.column("name")
上述四种方法等同
select除了接收Column类型外,还接收ColumnName类型,可以首先将spark的隐式转换导入,
import spark.implicits._
然后使用$符合加""定义一个ColumnName类型,比如
$"name"
返回的就是
org.apache.spark.sql.ColumnName = name
其次,在SQL操作中,可以重命名以及选择常量或者计算某一列的表达式,还是以上述personDf为例,SQL执行如下操作
SELECT age + 10 as new_age
,"constant" as cons
FROM personDf
上述涉及到
使用dataset来操作则是
personDf.select(expr("age + 10"),lit("constant")).toDF("new_age","cons").show()
其中expr是用来计算列,里面可以使用列名称加运算符
,lit()是定义常量,后面的toDF可以重命名。
注意,上面的expr只接受String类型,如果把之前定义的Column或者ColumnName类型的变量传入则会报错,
personDf.select(expr(ageCol)).show
:36: error: type mismatch;
found : org.apache.spark.sql.ColumnName
required: String
personDf.select(expr(ageCol)).show
给DF增加新的一列或者重命名可以使用如下命令,
personDf.withColumn("new_age_column",$"age" + 18).withColumnRenamed("age","old_age").show()
+-------+-----+------+--------------+
|old_age| name| sex|new_age_column|
+-------+-----+------+--------------+
| 32| Brad| male| 50|
| 31| Anne|female| 49|
| 4|Eason| male| 22|
+-------+-----+------+--------------+
其中withColumn是在原有DF的基础上新增加一列new_age_column,而withColumnRenamed是将原有的age列重命名为old_age