5、Spark DataFrame理解和使用之不同数据类型的操作(二)

数据类型:

Dates and Timestamps 日期和时间戳

Handling Null 空值

Complex Types 复杂类型

User Defined Functions 用户自定义函数

布尔型、数值型、字符型数据操作见前博文 4、Spark DataFrame理解和使用之不同数据类型的操作(一) 

Dates and Timestamps 日期和时间戳

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()

 

NULL 处理缺失值

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()

Complex Types 处理复杂类型数据

1、Struct

2、Array

3、Map

JSON型数据处理

1、get_json_object(), json_tuple()

2、from_json(), to_json()

UDF用户自定义函数

1、注册函数

//定义一个df
val udfExampleDF = spark.range(5).toDF("num")
//定义一个函数
def power3(number:Double):Double = number * number * number
//测试一下函数功能
power3(2.0)
  • 注册成DataFrame函数。只能用作DataFrame的函数。
//注册udf函数
import org.apache.spark.sql.functions.udf
val power3udf = udf(power3(_:Double):Double)

//调用注册的udf函数
udfExampleDF.select(power3udf(col("num"))).show()
  • 注册成SparkSql函数。这样可以在DataFrame中使用表达式调用,也可以在Sql中调用。
//注册成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
    })
  • 注册成HIVE语法的函数

你可能感兴趣的:(Spark权威指南,spark,spark)