数据类型:
Dates and Timestamps 日期和时间戳
Handling Null 空值
Complex Types 复杂类型
User Defined Functions 用户自定义函数
布尔型、数值型、字符型数据操作见前博文 4、Spark DataFrame理解和使用之不同数据类型的操作(一)
1、当前时间current_date()、当前时间戳, current_timestamp()
import org.apache.spark.sql.functions.{current_date, current_timestamp}
val dateDF = spark.range(10)
.withColumn("today", current_date())
.withColumn("now", current_timestamp())
2、加减几天获得新日期 date_sub(), date_add()
// in Scala
import org.apache.spark.sql.functions.{date_add, date_sub}
dateDF.select(date_sub(col("today"), 5), date_add(col("today"), 5)).show(1)
3、查看两个日期之间天数差datediff("$start_date","$end_date") 返回$start - $end 天数、月数months_between("$start_date","$end_date"),返回($start -$end)/月数
// in Scala
import org.apache.spark.sql.functions.{datediff, months_between, to_date}
dateDF.withColumn("week_ago", date_sub(col("today"), 7)).select(datediff(col("week_ago"), col("today"))).show(1)
dateDF.select(
to_date(lit("2016-01-01")).alias("start"),
to_date(lit("2017-05-22")).alias("end"))
.select(months_between(col("start"), col("end"))).show(1)
4、string类型转日期类型,to_date()\ to_timestamp()函数
to_date($date,"$date_type")函数 | |||
date日期输入 | date_type输入日期类型 | to_date标准输出日期类型 | 输出值 |
"2020-12-31" | “yyyy-MM-dd” | "yyyy-MM-dd" | "2020-12-31" |
"2020-31-12" | “yyyy-dd-MM” | "yyyy-MM-dd" | "2020-12-31" |
to_timestamp()函数 | |||
date日期输入 | date_type输入日期类型 | to_timestamp标准输出日期类型 | 输出值 |
"2020-12-31" | “yyyy-MM-dd” | "yyyy-MM-dd HH:mm:SS" | "2020-12-31 00:00:00" |
"2020-31-12" | “yyyy-dd-MM” | "yyyy-MM-dd HH:mm:SS" | "2020-12-31 00:00:00" |
// in Scala
import org.apache.spark.sql.functions.to_date
val cleanDateDF = spark.range(1).select(
to_date(lit("2017-12-11"), "yyyy-MM-dd").alias("date"),
to_date(lit("2017-20-12"), "yyyy-dd-MM").alias("date2"))
import org.apache.spark.sql.functions.to_timestamp
cleanDateDF.select(to_timestamp(col("date"), "yyyy-dd-MM")).show()
5、比较时间大小。保证是 "yyyy-MM-dd"类型,系统会自动解读成日期类型
//yyyy-MM-dd
cleanDateDF.filter(col("date2") > lit("2017-12-12")).show()
//yyyy-MM-dd string类型
cleanDateDF.filter(col("date2") > "'2017-12-12'").show()
DataFrame中,与null值交互的主要方式是在DataFrame上使用.na子包。默认的缺失值标示是null 、 NaN。
处理缺失值时,比起隐式处理,更推荐使用显式的处理方式。显式的删除、填充缺失值(全局或按行)
1、在数据列中选出第一个非null值的列 coalesce()函数
// in Scala
import org.apache.spark.sql.functions.coalesce
df.select(coalesce(col("Description"), col("CustomerId"))).show()
2、SQL的方法判断是否是缺失值,如果是返回值是什么。 ifnull(), nullIf(), nvl(), nvl2() 函数
SELECT
ifnull(null, 'return_value'),
nullif('value', 'value'),nvl(null, 'return_value'),
nvl2('not_null', 'return_value', "else_value")
FROM dfTable LIMIT 1
3、删除含有null值的列drop(),参数"any","all"
//drop函数默认参数any,即行中存在任一个null值都要删除此行
df.na.drop()
df.na.drop("any")
//参数all, 此行所有值都是null才删除此行
df.na.drop("all")
//只指定某些列进行空值的删除操作
df.na.drop("all",Seq("colname1","colname2"))
4、填充函数fill()
//用string填充所有空值
df.na.fill("All Null values become this string")
//用整数5填充制定列的空值
df.na.fill(5, Seq("StockCode", "InvoiceNo"))
df.na.fill(5:Double, Seq("StockCode", "InvoiceNo"))
//用Map,key->value的形式来给每列指定一个填充值。Map函数的Key是列名,value是填充值。
val fillColValues = Map("StockCode" -> 5, "Description" -> "No Value")
df.na.fill(fillColValues)
5、替换函数replace(),不仅可以处理空值,还可以用来处理非空的值。要求替换词和被替换词是相同的数据类型。
//第一列参数:列名,Map函数的key是被替换词,value是替换词
df.na.replace("Description", Map("" -> "UNKNOWN"))
6、排序函数: 升序null在前函数asc_nulls_first(), 降序null在前函数desc_nulls_first(), 升序null在后函数asc_nulls_last(), 降序null在后函数desc_nulls_last()
1、Struct
2、Array
3、Map
1、get_json_object(), json_tuple()
2、from_json(), to_json()
1、注册函数
//定义一个df
val udfExampleDF = spark.range(5).toDF("num")
//定义一个函数
def power3(number:Double):Double = number * number * number
//测试一下函数功能
power3(2.0)
//注册udf函数
import org.apache.spark.sql.functions.udf
val power3udf = udf(power3(_:Double):Double)
//调用注册的udf函数
udfExampleDF.select(power3udf(col("num"))).show()
//注册成sparkSql函数
spark.udf.register("power3", power3(_:Double):Double)
udfExampleDF.selectExpr("power3(num)").show(2)
另外一个注册UDF的例子:
spark.udf.register("tmValidOrNot", (val_time_limit: Int, valid_end_tm: String, activity_end_tm: String, dt: String) => {
var result = false
if (val_time_limit == 0 & dt <= valid_end_tm) {
result = true
}
else if (val_time_limit == 1 & dt <= activity_end_tm) {
result = true
}
else {}
result
})