【spark床头书系列】 import org.apache.spark.sql.functions._ 和 import sparkSession.implicits._区别

spark import org.apache.spark.sql.functions._ 和 import sparkSession.implicits._示例用法源码区别

文章目录

  • spark import org.apache.spark.sql.functions._ 和 import sparkSession.implicits._示例用法源码区别
  • 区别
  • sqlfucntions源码
    • object functions概览
    • 排序函数
    • agg_funcs 聚合函数
    • 窗口函数
    • 非聚合函数
    • 数学函数
    • misc_funcs 杂项函数
    • string_funcs 字符串函数
    • 日期时间函数
    • collection_funcs 集合函数
    • udf函数

区别

import org.apache.spark.sql.functions._import sparkSession.implicits._是Spark中两个不同的导入语句,它们的作用和使用方式也有所不同。

  1. import org.apache.spark.sql.functions._

    • 这个导入语句用于导入org.apache.spark.sql.functions包下的所有函数。functions包含了许多用于对DataFrame进行操作和转换的常用函数,比如聚合函数、窗口函数、日期函数等。
    • 通过导入该包后,就可以直接使用这些函数而不需要在代码中指定完整的包名。
    • 例如,可以直接使用colsumavg等函数,而不需要写成functions.colfunctions.sumfunctions.avg
  2. import sparkSession.implicits._

    • 这个导入语句是针对Spark的SparkSession对象的隐式转换。
    • 通过导入该隐式转换,可以方便地将普通的Scala对象转换为DatasetDataFrame,以便进行Spark SQL的操作。
    • 例如,可以使用toDS()方法将一个SeqList转换为Dataset,而不需要手动创建Encoder和调用createDataset方法。

总结起来,import org.apache.spark.sql.functions._用于导入Spark SQL中的函数库,使得可以直接使用其中的函数;而import sparkSession.implicits._用于导入SparkSession对象的隐式转换,方便地将Scala对象转换为DatasetDataFrame

sqlfucntions源码

object functions概览

/**
 * DataFrame操作中常用的函数。使用这里定义的函数可以提供更多的编译时安全性,以确保函数存在。
 *
 * Spark还包括了一些不太常见的内置函数,这些函数在这里没有定义。您仍然可以使用`functions.expr()` API来访问它们(以及这里定义的所有函数),
 * 并通过SQL表达式字符串来调用它们。您可以在SQL API文档中找到完整的函数列表。
 *
 * 例如,`isnan`是在这里定义的一个函数。您可以使用`isnan(col("myCol"))`来调用`isnan`函数。这样,编程语言的编译器就会确保`isnan`
 * 存在并且具有正确的形式。您也可以使用`expr("isnan(myCol)")`函数来调用相同的函数。在这种情况下,当Spark分析查询时,它自己会确保`isnan`存在。
 *
 * `regr_count`是一个内置函数的示例,但在这里没有定义,因为它不常用。要调用它,请使用`expr("regr_count(yCol, xCol)")`。
 *
 * @groupname udf_funcs UDF函数
 * @groupname agg_funcs 聚合函数
 * @groupname datetime_funcs 日期时间函数
 * @groupname sort_funcs 排序函数
 * @groupname normal_funcs 非聚合函数
 * @groupname math_funcs 数学函数
 * @groupname misc_funcs 杂项函数
 * @groupname window_funcs 窗口函数
 * @groupname string_funcs 字符串函数
 * @groupname collection_funcs 集合函数
 * @groupname Ungrouped DataFrames的支持函数
 * @since 1.3.0
 */
@InterfaceStability.Stable
object functions {
  
  private def withExpr(expr: Expression): Column = Column(expr)

  private def withAggregateFunction(
    func: AggregateFunction,
    isDistinct: Boolean = false): Column = {
    Column(func.toAggregateExpression(isDistinct))
  }   
 

排序函数


  //
  // 排序函数
  //

  /**
   * 返回基于列的升序排序表达式。
   * {{{
   *   df.sort(asc("dept"), desc("age"))
   * }}}
   *
   * @group sort_funcs
   * @since 1.3.0
   */
  def asc(columnName: String): Column = Column(columnName).asc

  /**
   * 返回基于列的升序排序表达式,空值会排在非空值之前。
   * {{{
   *   df.sort(asc_nulls_first("dept"), desc("age"))
   * }}}
   *
   * @group sort_funcs
   * @since 2.1.0
   */
  def asc_nulls_first(columnName: String): Column = Column(columnName).asc_nulls_first

  /**
   * 返回基于列的升序排序表达式,空值会排在非空值之后。
   * {{{
   *   df.sort(asc_nulls_last("dept"), desc("age"))
   * }}}
   *
   * @group sort_funcs
   * @since 2.1.0
   */
  def asc_nulls_last(columnName: String): Column = Column(columnName).asc_nulls_last

  /**
   * 返回基于列的降序排序表达式。
   * {{{
   *   df.sort(asc("dept"), desc("age"))
   * }}}
   *
   * @group sort_funcs
   * @since 1.3.0
   */
  def desc(columnName: String): Column = Column(columnName).desc

  /**
   * 返回基于列的降序排序表达式,空值会排在非空值之前。
   * {{{
   *   df.sort(asc("dept"), desc_nulls_first("age"))
   * }}}
   *
   * @group sort_funcs
   * @since 2.1.0
   */
  def desc_nulls_first(columnName: String): Column = Column(columnName).desc_nulls_first

  /**
   * 返回基于列的降序排序表达式,空值会排在非空值之后。
   * {{{
   *   df.sort(asc("dept"), desc_nulls_last("age"))
   * }}}
   *
   * @group sort_funcs
   * @since 2.1.0
   */
  def desc_nulls_last(columnName: String): Column = Column(columnName).desc_nulls_last

agg_funcs 聚合函数


  //
  // 聚合函数
  //

  /**
   * @group agg_funcs
   * @since 1.3.0
   */
  @deprecated("Use approx_count_distinct", "2.1.0")
  def approxCountDistinct(e: Column): Column = approx_count_distinct(e)

  /**
   * @group agg_funcs
   * @since 1.3.0
   */
  @deprecated("Use approx_count_distinct", "2.1.0")
  def approxCountDistinct(columnName: String): Column = approx_count_distinct(columnName)

  /**
   * @group agg_funcs
   * @since 1.3.0
   */
  @deprecated("Use approx_count_distinct", "2.1.0")
  def approxCountDistinct(e: Column, rsd: Double): Column = approx_count_distinct(e, rsd)

  /**
   * @group agg_funcs
   * @since 1.3.0
   */
  @deprecated("Use approx_count_distinct", "2.1.0")
  def approxCountDistinct(columnName: String, rsd: Double): Column = {
    approx_count_distinct(Column(columnName), rsd)
  }

  /**
   * 聚合函数:返回组中不同项的近似数量。
   *
   * @group agg_funcs
   * @since 2.1.0
   */
  def approx_count_distinct(e: Column): Column = withAggregateFunction {
    HyperLogLogPlusPlus(e.expr)
  }

  /**
   * 聚合函数:返回组中不同项的近似数量。
   *
   * @group agg_funcs
   * @since 2.1.0
   */
  def approx_count_distinct(columnName: String): Column = approx_count_distinct(column(columnName))

  /**
   * 聚合函数:返回组中不同项的近似数量。
   *
   * @param rsd 允许的最大估计误差(默认值 = 0.05)
   *
   * @group agg_funcs
   * @since 2.1.0
   */
  def approx_count_distinct(e: Column, rsd: Double): Column = withAggregateFunction {
    HyperLogLogPlusPlus(e.expr, rsd, 0, 0)
  }

  /**
   * 聚合函数:返回组中不同项的近似数量。
   *
   * @param rsd 允许的最大估计误差(默认值 = 0.05)
   *
   * @group agg_funcs
   * @since 2.1.0
   */
  def approx_count_distinct(columnName: String, rsd: Double): Column = {
    approx_count_distinct(Column(columnName), rsd)
  }

  /**
   * 聚合函数:返回组中值的平均值。
   *
   * @group agg_funcs
   * @since 1.3.0
   */
  def avg(e: Column): Column = withAggregateFunction { Average(e.expr) }

  /**
   * 聚合函数:返回组中值的平均值。
   *
   * @group agg_funcs
   * @since 1.3.0
   */
  def avg(columnName: String): Column = avg(Column(columnName))

  /**
   * 聚合函数:返回一个带有重复值的对象列表。
   *
   * @note 此函数是非确定性的,因为收集结果的顺序取决于行的顺序,在洗牌后可能是非确定性的。
   *
   * @group agg_funcs
   * @since 1.6.0
   */
  def collect_list(e: Column): Column = withAggregateFunction { CollectList(e.expr) }

  /**
   * 聚合函数:返回一个带有重复值的对象列表。
   *
   * @note 此函数是非确定性的,因为收集结果的顺序取决于行的顺序,在洗牌后可能是非确定性的。
   *
   * @group agg_funcs
   * @since 1.6.0
   */
  def collect_list(columnName: String): Column = collect_list(Column(columnName))

  /**
   * 聚合函数:返回一个去除重复元素的对象集合。
   *
   * @note 此函数是非确定性的,因为收集结果的顺序取决于行的顺序,在洗牌后可能是非确定性的。
   *
   * @group agg_funcs
   * @since 1.6.0
   */
  def collect_set(e: Column): Column = withAggregateFunction { CollectSet(e.expr) }

  /**
   * 聚合函数:返回一个去除重复元素的对象集合。
   *
   * @note 此函数是非确定性的,因为收集结果的顺序取决于行的顺序,在洗牌后可能是非确定性的。
   *
   * @group agg_funcs
   * @since 1.6.0
   */
  def collect_set(columnName: String): Column = collect_set(Column(columnName))

  /**
   * 聚合函数:返回两列的皮尔逊相关系数。
   *
   * @group agg_funcs
   * @since 1.6.0
   */
  def corr(column1: Column, column2: Column): Column = withAggregateFunction {
    Corr(column1.expr, column2.expr)
  }

  /**
   * 聚合函数:返回两列的皮尔逊相关系数。
   *
   * @group agg_funcs
   * @since 1.6.0
   */
  def corr(columnName1: String, columnName2: String): Column = {
    corr(Column(columnName1), Column(columnName2))
  }

  /**
   * 聚合函数:返回组中项的数量。
   *
   * @group agg_funcs
   * @since 1.3.0
   */
  def count(e: Column): Column = withAggregateFunction {
    e.expr match {
      // 将count(*)转换为count(1)
      case s: Star => Count(Literal(1))
      case _ => Count(e.expr)
    }
  }

  /**
   * 聚合函数:返回分组中的项目数。
   *
   * @group agg_funcs
   * @since 1.3.0
   */
  def count(columnName: String): TypedColumn[Any, Long] =
    count(Column(columnName)).as(ExpressionEncoder[Long]())

  /**
   * 聚合函数:返回分组中不同项目的数量。
   *
   * @group agg_funcs
   * @since 1.3.0
   */
  @scala.annotation.varargs
  def countDistinct(expr: Column, exprs: Column*): Column = {
    withAggregateFunction(Count.apply((expr +: exprs).map(_.expr)), isDistinct = true)
  }

  /**
   * 聚合函数:返回分组中不同项目的数量。
   *
   * @group agg_funcs
   * @since 1.3.0
   */
  @scala.annotation.varargs
  def countDistinct(columnName: String, columnNames: String*): Column =
    countDistinct(Column(columnName), columnNames.map(Column.apply) : _*)

  /**
   * 聚合函数:返回两列的总体协方差。
   *
   * @group agg_funcs
   * @since 2.0.0
   */
  def covar_pop(column1: Column, column2: Column): Column = withAggregateFunction {
    CovPopulation(column1.expr, column2.expr)
  }

  /**
   * 聚合函数:返回两列的总体协方差。
   *
   * @group agg_funcs
   * @since 2.0.0
   */
  def covar_pop(columnName1: String, columnName2: String): Column = {
    covar_pop(Column(columnName1), Column(columnName2))
  }

  /**
   * 聚合函数:返回两列的样本协方差。
   *
   * @group agg_funcs
   * @since 2.0.0
   */
  def covar_samp(column1: Column, column2: Column): Column = withAggregateFunction {
    CovSample(column1.expr, column2.expr)
  }

  /**
   * 聚合函数:返回两列的样本协方差。
   *
   * @group agg_funcs
   * @since 2.0.0
   */
  def covar_samp(columnName1: String, columnName2: String): Column = {
    covar_samp(Column(columnName1), Column(columnName2))
  }

  /**
   * 聚合函数:返回分组中的第一个值。
   *
   * 默认情况下,该函数返回它看到的第一个值。当 ignoreNulls 设置为 true 时,它将返回它看到的第一个非空值。
   * 如果所有值都为 null,则返回 null。
   *
   * 注意:由于结果取决于行的顺序,所以该函数是不确定性的,在洗牌后可能是不确定性的。
   *
   * @group agg_funcs
   * @since 2.0.0
   */
  def first(e: Column, ignoreNulls: Boolean): Column = withAggregateFunction {
    new First(e.expr, Literal(ignoreNulls))
  }

  /**
   * 聚合函数:返回分组中某列的第一个值。
   *
   * 默认情况下,该函数返回它看到的第一个值。当 ignoreNulls 设置为 true 时,它将返回它看到的第一个非空值。
   * 如果所有值都为 null,则返回 null。
   *
   * 注意:由于结果取决于行的顺序,所以该函数是不确定性的,在洗牌后可能是不确定性的。
   *
   * @group agg_funcs
   * @since 2.0.0
   */
  def first(columnName: String, ignoreNulls: Boolean): Column = {
    first(Column(columnName), ignoreNulls)
  }

  /**
   * 聚合函数:返回分组中的第一个值。
   *
   * 默认情况下,该函数返回它看到的第一个值。当 ignoreNulls 设置为 true 时,它将返回它看到的第一个非空值。
   * 如果所有值都为 null,则返回 null。
   *
   * 注意:由于结果取决于行的顺序,所以该函数是不确定性的,在洗牌后可能是不确定性的。
   *
   * @group agg_funcs
   * @since 1.3.0
   */
  def first(e: Column): Column = first(e, ignoreNulls = false)

  /**
   * 聚合函数:返回分组中某列的第一个值。
   *
   * 默认情况下,该函数返回它看到的第一个值。当 ignoreNulls 设置为 true 时,它将返回它看到的第一个非空值。
   * 如果所有值都为 null,则返回 null。
   *
   * 注意:由于结果取决于行的顺序,所以该函数是不确定性的,在洗牌后可能是不确定性的。
   *
   * @group agg_funcs
   * @since 1.3.0
   */
  def first(columnName: String): Column = first(Column(columnName))

  /**
   * 聚合函数:指示在 GROUP BY 列表中的指定列是否已聚合,
   * 返回结果集中的聚合为 1,未聚合为 0。
   *
   * @group agg_funcs
   * @since 2.0.0
   */
  def grouping(e: Column): Column = Column(Grouping(e.expr))

  /**
   * 聚合函数:指示在 GROUP BY 列表中的指定列是否已聚合,
   * 返回结果集中的聚合为 1,未聚合为 0。
   *
   * @group agg_funcs
   * @since 2.0.0
   */
  def grouping(columnName: String): Column = grouping(Column(columnName))

  /**
   * 聚合函数:返回分组级别,等于
   *
   * (grouping(c1) <<; (n-1)) + (grouping(c2) <<; (n-2)) + ... + grouping(cn)
   *
   * 注意:列列表应与分组列完全匹配,或为空(表示所有分组列)。
   *
   * @group agg_funcs
   * @since 2.0.0
   */
  def grouping_id(cols: Column*): Column = Column(GroupingID(cols.map(_.expr)))

  /**
   * 聚合函数:返回分组级别,等于
   *
   * (grouping(c1) <<; (n-1)) + (grouping(c2) <<; (n-2)) + ... + grouping(cn)
   *
   * 注意:列列表应与分组列完全匹配。
   *
   * @group agg_funcs
   * @since 2.0.0
   */
  def grouping_id(colName: String, colNames: String*): Column = {
    grouping_id((Seq(colName) ++ colNames).map(n => Column(n)) : _*)
  }

  /**
   * 聚合函数:返回分组中值的峰度。
   *
   * @group agg_funcs
   * @since 1.6.0
   */
  def kurtosis(e: Column): Column = withAggregateFunction { Kurtosis(e.expr) }

  /**
   * 聚合函数:返回分组中值的峰度。
   *
   * @group agg_funcs
   * @since 1.6.0
   */
  def kurtosis(columnName: String): Column = kurtosis(Column(columnName))

  /**
   * 聚合函数:返回分组中的最后一个值。
   *
   * 默认情况下,该函数返回它看到的最后一个值。当 ignoreNulls 设置为 true 时,它将返回它看到的最后一个非空值。
   * 如果所有值都为 null,则返回 null。
   *
   * 注意:由于结果取决于行的顺序,所以该函数是不确定性的,在洗牌后可能是不确定性的。
   *
   * @group agg_funcs
   * @since 2.0.0
   */
  def last(e: Column, ignoreNulls: Boolean): Column = withAggregateFunction {
    new Last(e.expr, Literal(ignoreNulls))
  }

  /**
   * 聚合函数:返回分组中某列的最后一个值。
   *
   * 默认情况下,该函数返回它看到的最后一个值。当 ignoreNulls 设置为 true 时,它将返回它看到的最后一个非空值。
   * 如果所有值都为 null,则返回 null。
   *
   * 注意:由于结果取决于行的顺序,所以该函数是不确定性的,在洗牌后可能是不确定性的。
   *
   * @group agg_funcs
   * @since 2.0.0
   */
  def last(columnName: String, ignoreNulls: Boolean): Column = {
    last(Column(columnName), ignoreNulls)
  }

  /**
   * 聚合函数:返回分组中的最后一个值。
   *
   * 默认情况下,该函数返回它看到的最后一个值。当 ignoreNulls 设置为 true 时,它将返回它看到的最后一个非空值。
   * 如果所有值都为 null,则返回 null。
   *
   * 注意:由于结果取决于行的顺序,所以该函数是不确定性的,在洗牌后可能是不确定性的。
   *
   * @group agg_funcs
   * @since 1.3.0
   */
  def last(e: Column): Column = last(e, ignoreNulls = false)

  /**
   * 聚合函数:返回分组中某列的最后一个值。
   *
   * 默认情况下,该函数返回它看到的最后一个值。当 ignoreNulls 设置为 true 时,它将返回它看到的最后一个非空值。
   * 如果所有值都为 null,则返回 null。
   *
   * 注意:由于结果取决于行的顺序,所以该函数是不确定性的,在洗牌后可能是不确定性的。
   *
   * @group agg_funcs
   * @since 1.3.0
   */
  def last(columnName: String): Column = last(Column(columnName), ignoreNulls = false)

  /**
   * 聚合函数:返回表达式在分组中的最大值。
   *
   * @group agg_funcs
   * @since 1.3.0
   */
  def max(e: Column): Column = withAggregateFunction { Max(e.expr) }

  /**
   * 聚合函数:返回某列在分组中的最大值。
   *
   * @group agg_funcs
   * @since 1.3.0
   */
  def max(columnName: String): Column = max(Column(columnName))

  /**
   * 聚合函数:返回分组中值的平均值。
   * avg 的别名。
   *
   * @group agg_funcs
   * @since 1.4.0
   */
  def mean(e: Column): Column = avg(e)

  /**
   * 聚合函数:返回分组中某列的平均值。
   * avg 的别名。
   *
   * @group agg_funcs
   * @since 1.4.0
   */
  def mean(columnName: String): Column = avg(columnName)

  /**
   * 聚合函数:返回表达式在分组中的最小值。
   *
   * @group agg_funcs
   * @since 1.3.0
   */
  def min(e: Column): Column = withAggregateFunction { Min(e.expr) }

  /**
   * 聚合函数:返回某列在分组中的最小值。
   *
   * @group agg_funcs
   * @since 1.3.0
   */
  def min(columnName: String): Column = min(Column(columnName))

  /**
   * 聚合函数:返回分组中值的偏度。
   *
   * @group agg_funcs
   * @since 1.6.0
   */
  def skewness(e: Column): Column = withAggregateFunction { Skewness(e.expr) }

  /**
   * 聚合函数:返回分组中值的偏度。
   *
   * @group agg_funcs
   * @since 1.6.0
   */
  def skewness(columnName: String): Column = skewness(Column(columnName))

  /**
   * 聚合函数:`stddev_samp` 的别名。
   *
   * @group agg_funcs
   * @since 1.6.0
   */
  def stddev(e: Column): Column = withAggregateFunction { StddevSamp(e.expr) }

  /**
   * 聚合函数:`stddev_samp` 的别名。
   *
   * @group agg_funcs
   * @since 1.6.0
   */
  def stddev(columnName: String): Column = stddev(Column(columnName))

  /**
   * 聚合函数:返回表达式在分组中的样本标准差。
   *
   * @group agg_funcs
   * @since 1.6.0
   */
  def stddev_samp(e: Column): Column = withAggregateFunction { StddevSamp(e.expr) }

  /**
   * 聚合函数:返回表达式在分组中的样本标准差。
   *
   * @group agg_funcs
   * @since 1.6.0
   */
  def stddev_samp(columnName: String): Column = stddev_samp(Column(columnName))

  /**
   * 聚合函数:返回表达式在分组中的总体标准差。
   *
   * @group agg_funcs
   * @since 1.6.0
   */
  def stddev_pop(e: Column): Column = withAggregateFunction { StddevPop(e.expr) }

  /**
   * 聚合函数:返回表达式在分组中的总体标准差。
   *
   * @group agg_funcs
   * @since 1.6.0
   */
  def stddev_pop(columnName: String): Column = stddev_pop(Column(columnName))

  /**
   * 聚合函数:返回表达式中所有值的总和。
   *
   * @group agg_funcs
   * @since 1.3.0
   */
  def sum(e: Column): Column = withAggregateFunction { Sum(e.expr) }

  /**
   * 聚合函数:返回某列中所有值的总和。
   *
   * @group agg_funcs
   * @since 1.3.0
   */
  def sum(columnName: String): Column = sum(Column(columnName))

  /**
   * 聚合函数:返回表达式中不同值的总和。
   *
   * @group agg_funcs
   * @since 1.3.0
   */
  def sumDistinct(e: Column): Column = withAggregateFunction(Sum(e.expr), isDistinct = true)

  /**
   * 聚合函数:返回某列中不同值的总和。
   *
   * @group agg_funcs
   * @since 1.3.0
   */
  def sumDistinct(columnName: String): Column = sumDistinct(Column(columnName))
 
  /**
   * 聚合函数:别名为 `var_samp`。
   *
   * @group agg_funcs
   * @since 1.6.0
   */
  def variance(e: Column): Column = withAggregateFunction { VarianceSamp(e.expr) }

  /**
   * 聚合函数:别名为 `var_samp`。
   *
   * @group agg_funcs
   * @since 1.6.0
   */
  def variance(columnName: String): Column = variance(Column(columnName))

  /**
   * 聚合函数:返回分组中值的无偏方差。
   *
   * @group agg_funcs
   * @since 1.6.0
   */
  def var_samp(e: Column): Column = withAggregateFunction { VarianceSamp(e.expr) }

  /**
   * 聚合函数:返回分组中值的无偏方差。
   *
   * @group agg_funcs
   * @since 1.6.0
   */
  def var_samp(columnName: String): Column = var_samp(Column(columnName))

  /**
   * 聚合函数:返回分组中值的总体方差。
   *
   * @group agg_funcs
   * @since 1.6.0
   */
  def var_pop(e: Column): Column = withAggregateFunction { VariancePop(e.expr) }

  /**
   * 聚合函数:返回分组中值的总体方差。
   *
   * @group agg_funcs
   * @since 1.6.0
   */
  def var_pop(columnName: String): Column = var_pop(Column(columnName))

窗口函数



  //
  // 窗口函数
  //
  /**
   * 此函数在Spark 2.4中已弃用。有关更多信息,请参见SPARK-25842。
   *
   * @group window_funcs
   * @since 2.3.0
   */
  @deprecated("Use Window.unboundedPreceding", "2.4.0")
  def unboundedPreceding(): Column = Column(UnboundedPreceding)

  /**
   * 此函数在Spark 2.4中已弃用。有关更多信息,请参见SPARK-25842。
   *
   * @group window_funcs
   * @since 2.3.0
   */
  @deprecated("Use Window.unboundedFollowing", "2.4.0")
  def unboundedFollowing(): Column = Column(UnboundedFollowing)

  /**
   * 此函数在Spark 2.4中已弃用。有关更多信息,请参见SPARK-25842。
   *
   * @group window_funcs
   * @since 2.3.0
   */
  @deprecated("Use Window.currentRow", "2.4.0")
  def currentRow(): Column = Column(CurrentRow)

  /**
   * 窗口函数:返回窗口分区内值的累计分布,即当前行之前(包括当前行)的行的比例。
   *
   * {{{
   *   N = 窗口分区中的总行数
   *   cumeDist(x) = 在 x 之前(包括 x)的值的数量 / N
   * }}}
   *
   * @group window_funcs
   * @since 1.6.0
   */
  def cume_dist(): Column = withExpr { new CumeDist }

  /**
   * 窗口函数:返回窗口分区内行的等级,没有间隔。
   *
   * 排名和密集排名之间的区别是,当存在并列时,密集排名不会在排名序列中留下空白。
   * 也就是说,如果使用密集排名对竞争进行排名,并且有三个人并列为第二名,那么所有三个人都将被认为是第二名,
   * 下一个人将被认为是第三名。而排名将给出连续的数字,使得在并列后来的第三名(在并列后)将被标记为第五名。
   *
   * 这相当于SQL中的DENSE_RANK函数。
   *
   * @group window_funcs
   * @since 1.6.0
   */
  def dense_rank(): Column = withExpr { new DenseRank }

  /**
   * 窗口函数:返回当前行之前的 `offset` 行的值,如果当前行之前的行数少于 `offset` 行,则返回 `null`。
   * 例如,`lag(a, b)` 将在窗口分区的任何给定点返回前一行。
   *
   * 这相当于SQL中的LAG函数。
   *
   * @group window_funcs
   * @since 1.4.0
   */
  def lag(e: Column, offset: Int): Column = lag(e, offset, null)

  /**
   * 窗口函数:返回当前行之前的 `offset` 行的值,如果当前行之前的行数少于 `offset` 行,则返回 `null`。
   * 例如,`lag(a, b)` 将在窗口分区的任何给定点返回前一行。
   *
   * 这相当于SQL中的LAG函数。
   *
   * @group window_funcs
   * @since 1.4.0
   */
  def lag(columnName: String, offset: Int): Column = lag(columnName, offset, null)

  /**
   * 窗口函数:返回当前行之前的 `offset` 行的值,如果当前行之前的行数少于 `offset` 行,则返回 `defaultValue`。
   * 例如,`lag(a, b, c)` 将在窗口分区的任何给定点返回前一行。
   *
   * 这相当于SQL中的LAG函数。
   *
   * @group window_funcs
   * @since 1.4.0
   */
  def lag(columnName: String, offset: Int, defaultValue: Any): Column = {
    lag(Column(columnName), offset, defaultValue)
  }

  /**
   * 窗口函数:返回当前行之前的 `offset` 行的值,如果当前行之前的行数少于 `offset` 行,则返回 `defaultValue`。
   * 例如,`lag(a, b, c)` 将在窗口分区的任何给定点返回前一行。
   *
   * 这相当于SQL中的LAG函数。
   *
   * @group window_funcs
   * @since 1.4.0
   */
  def lag(e: Column, offset: Int, defaultValue: Any): Column = withExpr {
    Lag(e.expr, Literal(offset), Literal(defaultValue))
  }

  /**
   * 窗口函数:返回当前行之后的 `offset` 行的值,如果当前行之后的行数少于 `offset` 行,则返回 `null`。
   * 例如,`lead(a, b)` 将在窗口分区的任何给定点返回下一行。
   *
   * 这相当于SQL中的LEAD函数。
   *
   * @group window_funcs
   * @since 1.4.0
   */
  def lead(columnName: String, offset: Int): Column = { lead(columnName, offset, null) }

  /**
   * 窗口函数:返回当前行之后的 `offset` 行的值,如果当前行之后的行数少于 `offset` 行,则返回 `null`。
   * 例如,`lead(a, b)` 将在窗口分区的任何给定点返回下一行。
   *
   * 这相当于SQL中的LEAD函数。
   *
   * @group window_funcs
   * @since 1.4.0
   */
  def lead(e: Column, offset: Int): Column = { lead(e, offset, null) }

  /**
   * 窗口函数:返回当前行之后的 `offset` 行的值,如果当前行之后的行数少于 `offset` 行,则返回 `defaultValue`。
   * 例如,`lead(a, b, c)` 将在窗口分区的任何给定点返回下一行。
   *
   * 这相当于SQL中的LEAD函数。
   *
   * @group window_funcs
   * @since 1.4.0
   */
  def lead(columnName: String, offset: Int, defaultValue: Any): Column = {
    lead(Column(columnName), offset, defaultValue)
  }

  /**
   * 窗口函数:返回当前行之后的 `offset` 行的值,如果当前行之后的行数少于 `offset` 行,则返回 `defaultValue`。
   * 例如,`lead(a, b, c)` 将在窗口分区的任何给定点返回下一行。
   *
   * 这相当于SQL中的LEAD函数。
   *
   * @group window_funcs
   * @since 1.4.0
   */
  def lead(e: Column, offset: Int, defaultValue: Any): Column = withExpr {
    Lead(e.expr, Literal(offset), Literal(defaultValue))
  }

  /**
   * 窗口函数:返回一个NTILE组ID(从1到 `n`)在有序窗口分区内。
   * 例如,如果 `n` 是4,第一四分位数将得到值1,第二四分位数将得到值2,第三四分位数将得到值3,
   * 最后四分位数将得到值4。
   *
   * 这相当于SQL中的NTILE函数。
   *
   * @group window_funcs
   * @since 1.4.0
   */
  def ntile(n: Int): Column = withExpr { new NTile(Literal(n)) }

  /**
   * 窗口函数:返回行在窗口分区内的相对排名(即百分位数)。
   *
   * 计算方法为:
   * {{{
   *   (窗口分区中的行的排名 - 1)/ (窗口分区中的行数 - 1)
   * }}}
   *
   * 这相当于SQL中的PERCENT_RANK函数。
   *
   * @group window_funcs
   * @since 1.6.0
   */
  def percent_rank(): Column = withExpr { new PercentRank }

  /**
   * 窗口函数:返回行在窗口分区内的排名。
   *
   * 排名和密集排名之间的区别是,当存在并列时,密集排名不会在排名序列中留下空白。
   * 也就是说,如果使用密集排名对竞争进行排名,并且有三个人并列为第二名,那么所有三个人都将被认为是第二名,
   * 下一个人将被认为是第三名。而排名将给出连续的数字,使得在并列后来的第三名(在并列后)将被标记为第五名。
   *
   * 这相当于SQL中的RANK函数。
   *
   * @group window_funcs
   * @since 1.4.0
   */
  def rank(): Column = withExpr { new Rank }

  /**
   * 窗口函数:在窗口分区内创建一个从1开始的顺序号。
   *
   * @group window_funcs
   * @since 1.6.0
   */
  def row_number(): Column = withExpr { RowNumber() }

非聚合函数


  //
  // 非聚合函数
  //
/**
   * 根据给定的列名返回一个基于该列名的[[Column]]。
   *
   * @group normal_funcs
   * @since 1.3.0
   */
  def col(colName: String): Column = Column(colName)

  /**
   * 根据给定的列名返回一个基于该列名的[[Column]]。[[col]]的别名。
   *
   * @group normal_funcs
   * @since 1.3.0
   */
  def column(colName: String): Column = Column(colName)

  /**
   * 创建一个表示字面值的[[Column]]。
   *
   * 如果传入的对象已经是一个[[Column]],则直接返回该对象。如果对象是一个Scala Symbol,则也将其转换为[[Column]]。
   * 否则,将创建一个新的[[Column]]来表示字面值。
   *
   * @group normal_funcs
   * @since 1.3.0
   */
  def lit(literal: Any): Column = typedLit(literal)

  /**
   * 创建一个表示字面值的[[Column]]。
   *
   * 如果传入的对象已经是一个[[Column]],则直接返回该对象。如果对象是一个Scala Symbol,则也将其转换为[[Column]]。
   * 否则,将创建一个新的[[Column]]来表示字面值。与[[lit]]函数的区别在于,此函数可以处理参数化的scala类型,例如:List、Seq和Map。
   *
   * @group normal_funcs
   * @since 2.2.0
   */
  def typedLit[T : TypeTag](literal: T): Column = literal match {
    case c: Column => c
    case s: Symbol => new ColumnName(s.name)
    case _ => Column(Literal.create(literal))
  }


  /**
   * 创建一个新的数组列。输入列必须具有相同的数据类型。
   *
   * @group normal_funcs
   * @since 1.4.0
   */
  @scala.annotation.varargs
  def array(cols: Column*): Column = withExpr { CreateArray(cols.map(_.expr)) }

  /**
   * 创建一个新的数组列。输入列必须具有相同的数据类型。
   *
   * @group normal_funcs
   * @since 1.4.0
   */
  @scala.annotation.varargs
  def array(colName: String, colNames: String*): Column = {
    array((colName +: colNames).map(col) : _*)
  }

  /**
   * 创建一个新的映射列。输入列必须按键值对进行分组,例如(key1,value1,key2,value2,...)。
   * 键列必须具有相同的数据类型,并且不能为 null。值列必须具有相同的数据类型。
   *
   * @group normal_funcs
   * @since 2.0
   */
  @scala.annotation.varargs
  def map(cols: Column*): Column = withExpr { CreateMap(cols.map(_.expr)) }

  /**
   * 创建一个新的映射列。第一列中的数组用作键。第二列中的数组用作值。键中的所有元素都不应为 null。
   *
   * @group normal_funcs
   * @since 2.4
   */
  def map_from_arrays(keys: Column, values: Column): Column = withExpr {
    MapFromArrays(keys.expr, values.expr)
  }

  /**
   * 将一个DataFrame标记为在广播连接中可用的小型数据集。
   *
   * 下面的示例使用 `joinKey` 将右侧的DataFrame标记为广播哈希连接。
   * {{{
   *   // left和right是DataFrames
   *   left.join(broadcast(right), "joinKey")
   * }}}
   *
   * @group normal_funcs
   * @since 1.5.0
   */
  def broadcast[T](df: Dataset[T]): Dataset[T] = {
    Dataset[T](df.sparkSession,
      ResolvedHint(df.logicalPlan, HintInfo(broadcast = true)))(df.exprEnc)
  }

  /**
   * 返回第一个非空的列,如果所有输入都为null,则返回null。
   *
   * 例如,`coalesce(a, b, c)` 如果a不为null,则返回a,
   * 如果a为null且b不为null,则返回b,如果a和b都为null但c不为null,则返回c。
   *
   * @group normal_funcs
   * @since 1.3.0
   */
  @scala.annotation.varargs
  def coalesce(e: Column*): Column = withExpr { Coalesce(e.map(_.expr)) }

  /**
   * 创建一个表示当前Spark任务的文件名的字符串列。
   *
   * @group normal_funcs
   * @since 1.6.0
   */
  def input_file_name(): Column = withExpr { InputFileName() }

  /**
   * 如果列为NaN,则返回true。
   *
   * @group normal_funcs
   * @since 1.6.0
   */
  def isnan(e: Column): Column = withExpr { IsNaN(e.expr) }

  /**
   * 如果列为空,则返回true。
   *
   * @group normal_funcs
   * @since 1.6.0
   */
  def isnull(e: Column): Column = withExpr { IsNull(e.expr) }

  /**
   * 生成单调递增的64位整数的列表达式。
   *
   * 生成的ID保证是单调递增且唯一的,但不是连续的。
   * 当前实现将分区ID放在高31位中,并将每个分区中的记录编号放在低33位中。
   * 假设数据框具有少于10亿个分区,并且每个分区具有小于80亿条记录。
   *
   * 例如,考虑一个包含两个分区的DataFrame,每个分区有3条记录。
   * 此表达式将返回以下ID:
   *
   * {{{
   * 0, 1, 2, 8589934592 (1L << 33), 8589934593, 8589934594.
   * }}}
   *
   * @group normal_funcs
   * @since 1.4.0
   */
  @deprecated("Use monotonically_increasing_id()", "2.0.0")
  def monotonicallyIncreasingId(): Column = monotonically_increasing_id()

  /**
   * 返回一个生成单调递增的64位整数的列表达式。
   *
   * 生成的ID保证是单调递增且唯一的,但不是连续的。
   * 当前实现将分区ID放在高31位中,并将每个分区中的记录编号放在低33位中。
   * 假设数据框具有少于10亿个分区,并且每个分区具有小于80亿条记录。
   *
   * 例如,考虑一个包含两个分区的DataFrame,每个分区有3条记录。
   * 此表达式将返回以下ID:
   *
   * {{{
   * 0, 1, 2, 8589934592 (1L << 33), 8589934593, 8589934594.
   * }}}
   *
   * @group normal_funcs
   * @since 1.6.0
   */
  def monotonically_increasing_id(): Column = withExpr { MonotonicallyIncreasingID() }

  /**
   * 如果列1不为NaN,则返回列1,否则返回列2。
   *
   * 输入列应为浮点列(DoubleType或FloatType)。
   *
   * @group normal_funcs
   * @since 1.5.0
   */
  def nanvl(col1: Column, col2: Column): Column = withExpr { NaNvl(col1.expr, col2.expr) }

  /**
   * 一元减号,即对表达式取反。
   * {{{
   *   // 选择amount列并对所有值取反。
   *   // Scala:
   *   df.select(-df("amount"))
   *
   *   // Java:
   *   df.select(negate(df.col("amount")));
   * }}}
   *
   * @group normal_funcs
   * @since 1.3.0
   */
  def negate(e: Column): Column = -e

  /**
   * 布尔表达式的取反,即 NOT。
   * {{{
   *   // Scala:选择不活动的行(isActive === false)
   *   df.filter(!df("isActive"))
   *
   *   // Java:
   *   df.filter(not(df.col("isActive")));
   * }}}
   *
   * @group normal_funcs
   * @since 1.3.0
   */
  def not(e: Column): Column = !e

  /**
   * 生成一个具有独立且来自U[0.0, 1.0]的i.i.d.样本的随机列。
   *
   * @note 一般情况下,该函数是非确定性的。
   *
   * @group normal_funcs
   * @since 1.4.0
   */
  def rand(seed: Long): Column = withExpr { Rand(seed) }

  /**
   * 生成一个具有独立且来自U[0.0, 1.0]的i.i.d.样本的随机列。
   *
   * @note 一般情况下,该函数是非确定性的。
   *
   * @group normal_funcs
   * @since 1.4.0
   */
  def rand(): Column = rand(Utils.random.nextLong)

  /**
   * 生成一个具有独立且来自标准正态分布的i.i.d.样本的随机列。
   *
   * @note 一般情况下,该函数是非确定性的。
   *
   * @group normal_funcs
   * @since 1.4.0
   */
  def randn(seed: Long): Column = withExpr { Randn(seed) }

  /**
   * 生成一个具有独立且来自标准正态分布的i.i.d.样本的随机列。
   *
   * @note 一般情况下,该函数是非确定性的。
   *
   * @group normal_funcs
   * @since 1.4.0
   */
  def randn(): Column = randn(Utils.random.nextLong)

  /**
   * 分区ID。
   *
   * @note 由于它取决于数据分区和任务调度,因此这是非确定性的。
   *
   * @group normal_funcs
   * @since 1.6.0
   */
  def spark_partition_id(): Column = withExpr { SparkPartitionID() }

  /**
   * 创建一个新的结构列。
   * 如果输入列是`DataFrame`中的列,或者是已命名的导出列表达式,
   * 则它的名称将保留为StructField的名称;
   * 否则,新生成的StructField的名称将自动生成为`col`加上后缀`index + 1`,
   * 即col1、col2、col3等。
   *
   * @group normal_funcs
   * @since 1.4.0
   */
  @scala.annotation.varargs
  def struct(cols: Column*): Column = withExpr { CreateStruct(cols.map(_.expr)) }

  /**
   * 创建一个新的结构列,由多个输入列组成。
   *
   * @group normal_funcs
   * @since 1.4.0
   */
  @scala.annotation.varargs
  def struct(colName: String, colNames: String*): Column = {
    struct((colName +: colNames).map(col) : _*)
  }

  /**
   * 计算一系列条件,并返回多个可能结果表达式之一。
   * 如果最后没有定义otherwise,则对于未匹配的条件返回null。
   *
   * {{{
   *   // 示例:将性别字符串列编码为整数。
   *
   *   // Scala:
   *   people.select(when(people("gender") === "male", 0)
   *     .when(people("gender") === "female", 1)
   *     .otherwise(2))
   *
   *   // Java:
   *   people.select(when(col("gender").equalTo("male"), 0)
   *     .when(col("gender").equalTo("female"), 1)
   *     .otherwise(2))
   * }}}
   *
   * @group normal_funcs
   * @since 1.4.0
   */
  def when(condition: Column, value: Any): Column = withExpr {
    CaseWhen(Seq((condition.expr, lit(value).expr)))
  }

  /**
   * 计算一个数的按位取反(~)。
   *
   * @group normal_funcs
   * @since 1.4.0
   */
  def bitwiseNOT(e: Column): Column = withExpr { BitwiseNot(e.expr) }

  /**
   * 将表达式字符串解析为表示其列的列,类似于[[Dataset#selectExpr]]。
   * {{{
   *   // 获取每个长度的单词数
   *   df.groupBy(expr("length(word)")).count()
   * }}}
   *
   * @group normal_funcs
   */
  def expr(expr: String): Column = {
    val parser = SparkSession.getActiveSession.map(_.sessionState.sqlParser).getOrElse {
      new SparkSqlParser(new SQLConf)
    }
    Column(parser.parseExpression(expr))
  }

数学函数




  /**
   * 计算给定值的平方根。
   *
   * @group math_funcs
   * @since 1.3.0
   */
  def sqrt(e: Column): Column = withExpr { Sqrt(e.expr) }

  /**
   * 计算给定值的平方根。
   *
   * @group math_funcs
   * @since 1.5.0
   */
  def sqrt(colName: String): Column = sqrt(Column(colName))



  //
  // Math Functions
  //

  /**
   * 计算数值的绝对值。
   *
   * @group math_funcs
   * @since 1.3.0
   */
  def abs(e: Column): Column = withExpr { Abs(e.expr) }

  /**
   * @return 返回`e`的反余弦值(以弧度为单位),如同通过`java.lang.Math.acos`计算得到的那样
   *
   * @group math_funcs
   * @since 1.4.0
   */
  def acos(e: Column): Column = withExpr { Acos(e.expr) }

  /**
   * @return 返回`columnName`的反余弦值,如同通过`java.lang.Math.acos`计算得到的那样
   *
   * @group math_funcs
   * @since 1.4.0
   */
  def acos(columnName: String): Column = acos(Column(columnName))

  /**
   * @return 返回`e`的反正弦值(以弧度为单位),如同通过`java.lang.Math.asin`计算得到的那样
   *
   * @group math_funcs
   * @since 1.4.0
   */
  def asin(e: Column): Column = withExpr { Asin(e.expr) }

  /**
   * @return 返回`columnName`的反正弦值,如同通过`java.lang.Math.asin`计算得到的那样
   *
   * @group math_funcs
   * @since 1.4.0
   */
  def asin(columnName: String): Column = asin(Column(columnName))

  /**
   * @return 返回`e`的反正切值,如同通过`java.lang.Math.atan`计算得到的那样
   *
   * @group math_funcs
   * @since 1.4.0
   */
  def atan(e: Column): Column = withExpr { Atan(e.expr) }

  /**
   * @return 返回`columnName`的反正切值,如同通过`java.lang.Math.atan`计算得到的那样
   *
   * @group math_funcs
   * @since 1.4.0
   */
  def atan(columnName: String): Column = atan(Column(columnName))

  /**
   * @param y y轴上的坐标
   * @param x x轴上的坐标
   * @return 对应于笛卡尔坐标中的点(x,y)的极坐标中的组件的<θ>值,
   *         如同通过`java.lang.Math.atan2`计算得到的那样
   *
   * @group math_funcs
   * @since 1.4.0
   */
  def atan2(y: Column, x: Column): Column = withExpr { Atan2(y.expr, x.expr) }

  /**
   * @param y y轴上的坐标
   * @param xName x轴上的坐标
   * @return 对应于笛卡尔坐标中的点(x,y)的极坐标中的组件的<θ>值,
   *         如同通过`java.lang.Math.atan2`计算得到的那样
   *
   * @group math_funcs
   * @since 1.4.0
   */
  def atan2(y: Column, xName: String): Column = atan2(y, Column(xName))

  /**
   * @param yName y轴上的坐标
   * @param x x轴上的坐标
   * @return 对应于笛卡尔坐标中的点(x,y)的极坐标中的组件的<θ>值,
   *         如同通过`java.lang.Math.atan2`计算得到的那样
   *
   * @group math_funcs
   * @since 1.4.0
   */
  def atan2(yName: String, x: Column): Column = atan2(Column(yName), x)

  /**
   * @param yName y轴上的坐标
   * @param xName x轴上的坐标
   * @return 对应于笛卡尔坐标中的点(x,y)的极坐标中的组件的<θ>值,
   *         如同通过`java.lang.Math.atan2`计算得到的那样
   *
   * @group math_funcs
   * @since 1.4.0
   */
  def atan2(yName: String, xName: String): Column =
    atan2(Column(yName), Column(xName))

  /**
   * @param y y轴上的坐标
   * @param xValue x轴上的坐标
   * @return 对应于笛卡尔坐标中的点(x,y)的极坐标中的组件的<θ>值,
   *         如同通过`java.lang.Math.atan2`计算得到的那样
   *
   * @group math_funcs
   * @since 1.4.0
   */
  def atan2(y: Column, xValue: Double): Column = atan2(y, lit(xValue))

  /**
   * @param yName y轴上的坐标
   * @param xValue x轴上的坐标
   * @return 对应于笛卡尔坐标中的点(x,y)的极坐标中的组件的<θ>值,
   *         如同通过`java.lang.Math.atan2`计算得到的那样
   *
   * @group math_funcs
   * @since 1.4.0
   */
  def atan2(yName: String, xValue: Double): Column = atan2(Column(yName), xValue)

  /**
   * @param yValue y轴上的坐标
   * @param x x轴上的坐标
   * @return 对应于笛卡尔坐标中的点(x,y)的极坐标中的组件的<θ>值,
   *         如同通过`java.lang.Math.atan2`计算得到的那样
   *
   * @group math_funcs
   * @since 1.4.0
   */
  def atan2(yValue: Double, x: Column): Column = atan2(lit(yValue), x)

  /**
   * @param yValue y轴上的坐标
   * @param xName x轴上的坐标
   * @return 对应于笛卡尔坐标中的点(x,y)的极坐标中的组件的<θ>值,
   *         如同通过`java.lang.Math.atan2`计算得到的那样
   *
   * @group math_funcs
   * @since 1.4.0
   */
  def atan2(yValue: Double, xName: String): Column = atan2(yValue, Column(xName))

  /**
   * 返回具有给定长整型列的二进制值的字符串表示形式。
   * 例如,bin("12")返回"1100"。
   *
   * @group math_funcs
   * @since 1.5.0
   */
  def bin(e: Column): Column = withExpr { Bin(e.expr) }

  /**
   * 返回具有给定长整型列的二进制值的字符串表示形式。
   * 例如,bin("12")返回"1100"。
   *
   * @group math_funcs
   * @since 1.5.0
   */
  def bin(columnName: String): Column = bin(Column(columnName))

  /**
   * 计算给定值的立方根。
   *
   * @group math_funcs
   * @since 1.4.0
   */
  def cbrt(e: Column): Column = withExpr { Cbrt(e.expr) }

  /**
   * 计算给定列的立方根。
   *
   * @group math_funcs
   * @since 1.4.0
   */
  def cbrt(columnName: String): Column = cbrt(Column(columnName))

  /**
   * 计算给定值的上限。
   *
   * @group math_funcs
   * @since 1.4.0
   */
  def ceil(e: Column): Column = withExpr { Ceil(e.expr) }

  /**
   * 计算给定列的上限。
   *
   * @group math_funcs
   * @since 1.4.0
   */
  def ceil(columnName: String): Column = ceil(Column(columnName))

  /**
   * 将一个字符串列中的数字从一种进制转换为另一种进制。
   *
   * @group math_funcs
   * @since 1.5.0
   */
  def conv(num: Column, fromBase: Int, toBase: Int): Column = withExpr {
    Conv(num.expr, lit(fromBase).expr, lit(toBase).expr)
  }

  /**
   * 返回角度的余弦值,类似于`java.lang.Math.cos`计算得到的值。
   *
   * @group math_funcs
   * @since 1.4.0
   */
  def cos(e: Column): Column = withExpr { Cos(e.expr) }

  /**
   * 返回角度的余弦值,类似于`java.lang.Math.cos`计算得到的值。
   *
   * @group math_funcs
   * @since 1.4.0
   */
  def cos(columnName: String): Column = cos(Column(columnName))

  /**
   * 返回给定值的双曲余弦值,类似于`java.lang.Math.cosh`计算得到的值。
   *
   * @group math_funcs
   * @since 1.4.0
   */
  def cosh(e: Column): Column = withExpr { Cosh(e.expr) }

  /**
   * 返回给定值的双曲余弦值,类似于`java.lang.Math.cosh`计算得到的值。
   *
   * @group math_funcs
   * @since 1.4.0
   */
  def cosh(columnName: String): Column = cosh(Column(columnName))

  /**
   * 计算给定值的指数。
   *
   * @group math_funcs
   * @since 1.4.0
   */
  def exp(e: Column): Column = withExpr { Exp(e.expr) }

  /**
   * 计算给定列的指数。
   *
   * @group math_funcs
   * @since 1.4.0
   */
  def exp(columnName: String): Column = exp(Column(columnName))

  /**
   * 计算给定值减一的指数。
   *
   * @group math_funcs
   * @since 1.4.0
   */
  def expm1(e: Column): Column = withExpr { Expm1(e.expr) }

  /**
   * 计算给定列减一的指数。
   *
   * @group math_funcs
   * @since 1.4.0
   */
  def expm1(columnName: String): Column = expm1(Column(columnName))

  /**
   * 计算给定值的阶乘。
   *
   * @group math_funcs
   * @since 1.5.0
   */
  def factorial(e: Column): Column = withExpr { Factorial(e.expr) }

  /**
   * 计算给定值的下舍整数。
   *
   * @group math_funcs
   * @since 1.4.0
   */
  def floor(e: Column): Column = withExpr { Floor(e.expr) }

  /**
   * 计算给定列的下舍整数。
   *
   * @group math_funcs
   * @since 1.4.0
   */
  def floor(columnName: String): Column = floor(Column(columnName))

  /**
   * 返回值列表中的最大值,跳过null值。该函数至少需要2个参数。当所有参数都为null时返回null。
   *
   * @group normal_funcs
   * @since 1.5.0
   */
  @scala.annotation.varargs
  def greatest(exprs: Column*): Column = withExpr { Greatest(exprs.map(_.expr)) }

  /**
   * 返回列名列表中的最大值,跳过null值。该函数至少需要2个参数。当所有参数都为null时返回null。
   *
   * @group normal_funcs
   * @since 1.5.0
   */
  @scala.annotation.varargs
  def greatest(columnName: String, columnNames: String*): Column = {
    greatest((columnName +: columnNames).map(Column.apply): _*)
  }

  /**
   * 计算给定列的十六进制值。
   *
   * @group math_funcs
   * @since 1.5.0
   */
  def hex(column: Column): Column = withExpr { Hex(column.expr) }

  /**
   * 对十六进制值进行解码。将每对字符解释为一个十六进制数字,并转换为相应的字节表示形式。
   *
   * @group math_funcs
   * @since 1.5.0
   */
  def unhex(column: Column): Column = withExpr { Unhex(column.expr) }

  /**
   * 计算 `sqrt(a^2^ + b^2^)` ,避免溢出或下溢。
   *
   * @group math_funcs
   * @since 1.4.0
   */
  def hypot(l: Column, r: Column): Column = withExpr { Hypot(l.expr, r.expr) }

  /**
   * 计算 `sqrt(a^2^ + b^2^)` ,避免溢出或下溢。
   *
   * @group math_funcs
   * @since 1.4.0
   */
  def hypot(l: Column, rightName: String): Column = hypot(l, Column(rightName))

  /**
   * 计算 `sqrt(a^2^ + b^2^)` ,避免溢出或下溢。
   *
   * @group math_funcs
   * @since 1.4.0
   */
  def hypot(leftName: String, r: Column): Column = hypot(Column(leftName), r)

  /**
   * 计算 `sqrt(a^2^ + b^2^)` ,避免溢出或下溢。
   *
   * @group math_funcs
   * @since 1.4.0
   */
  def hypot(leftName: String, rightName: String): Column =
    hypot(Column(leftName), Column(rightName))

  /**
   * 计算 `sqrt(a^2^ + b^2^)` ,避免溢出或下溢。
   *
   * @group math_funcs
   * @since 1.4.0
   */
  def hypot(l: Column, r: Double): Column = hypot(l, lit(r))

  /**
   * 计算 `sqrt(a^2^ + b^2^)` ,避免溢出或下溢。
   *
   * @group math_funcs
   * @since 1.4.0
   */
  def hypot(leftName: String, r: Double): Column = hypot(Column(leftName), r)

  /**
   * 计算 `sqrt(a^2^ + b^2^)` ,避免溢出或下溢。
   *
   * @group math_funcs
   * @since 1.4.0
   */
  def hypot(l: Double, r: Column): Column = hypot(lit(l), r)

  /**
   * 计算 `sqrt(a^2^ + b^2^)` ,避免溢出或下溢。
   *
   * @group math_funcs
   * @since 1.4.0
   */
  def hypot(l: Double, rightName: String): Column = hypot(l, Column(rightName))

  /**
   * 返回值列表中的最小值,跳过null值。该函数至少需要2个参数。当所有参数都为null时返回null。
   *
   * @group normal_funcs
   * @since 1.5.0
   */
  @scala.annotation.varargs
  def least(exprs: Column*): Column = withExpr { Least(exprs.map(_.expr)) }

  /**
   * 返回列名列表中的最小值,跳过null值。该函数至少需要2个参数。当所有参数都为null时返回null。
   *
   * @group normal_funcs
   * @since 1.5.0
   */
  @scala.annotation.varargs
  def least(columnName: String, columnNames: String*): Column = {
    least((columnName +: columnNames).map(Column.apply): _*)
  }

  /**
   * 计算给定值的自然对数。
   *
   * @group math_funcs
   * @since 1.4.0
   */
  def log(e: Column): Column = withExpr { Log(e.expr) }

  /**
   * 计算给定列的自然对数。
   *
   * @group math_funcs
   * @since 1.4.0
   */
  def log(columnName: String): Column = log(Column(columnName))

  /**
   * 返回以给定底数为基的对数值。
   *
   * @group math_funcs
   * @since 1.4.0
   */
  def log(base: Double, a: Column): Column = withExpr { Logarithm(lit(base).expr, a.expr) }

  /**
   * 返回以给定底数为基的对数值。
   *
   * @group math_funcs
   * @since 1.4.0
   */
  def log(base: Double, columnName: String): Column = log(base, Column(columnName))

  /**
   * 计算给定值的以10为底的对数。
   *
   * @group math_funcs
   * @since 1.4.0
   */
  def log10(e: Column): Column = withExpr { Log10(e.expr) }

  /**
   * 计算给定列的以10为底的对数。
   *
   * @group math_funcs
   * @since 1.4.0
   */
  def log10(columnName: String): Column = log10(Column(columnName))

  /**
   * 计算给定值加一的自然对数。
   *
   * @group math_funcs
   * @since 1.4.0
   */
  def log1p(e: Column): Column = withExpr { Log1p(e.expr) }

  /**
   * 计算给定列加一的自然对数。
   *
   * @group math_funcs
   * @since 1.4.0
   */
  def log1p(columnName: String): Column = log1p(Column(columnName))

  /**
   * 计算给定列的以2为底的对数。
   *
   * @group math_funcs
   * @since 1.5.0
   */
  def log2(expr: Column): Column = withExpr { Log2(expr.expr) }

  /**
   * 计算给定值的以2为底的对数。
   *
   * @group math_funcs
   * @since 1.5.0
   */
  def log2(columnName: String): Column = log2(Column(columnName))

  /**
   * 返回第一个参数的第二个参数次幂的值。
   *
   * @group math_funcs
   * @since 1.4.0
   */
  def pow(l: Column, r: Column): Column = withExpr { Pow(l.expr, r.expr) }

  /**
   * 返回第一个参数的第二个参数次幂的值。
   *
   * @group math_funcs
   * @since 1.4.0
   */
  def pow(l: Column, rightName: String): Column = pow(l, Column(rightName))

  /**
   * 返回第一个参数的第二个参数次幂的值。
   *
   * @group math_funcs
   * @since 1.4.0
   */
  def pow(leftName: String, r: Column): Column = pow(Column(leftName), r)

  /**
   * 返回第一个参数的第二个参数次幂的值。
   *
   * @group math_funcs
   * @since 1.4.0
   */
  def pow(leftName: String, rightName: String): Column = pow(Column(leftName), Column(rightName))

  /**
   * 返回第一个参数的第二个参数次幂的值。
   *
   * @group math_funcs
   * @since 1.4.0
   */
  def pow(l: Column, r: Double): Column = pow(l, lit(r))

  /**
   * 返回第一个参数的第二个参数次幂的值。
   *
   * @group math_funcs
   * @since 1.4.0
   */
  def pow(leftName: String, r: Double): Column = pow(Column(leftName), r)

  /**
   * 返回第一个参数的第二个参数次幂的值。
   *
   * @group math_funcs
   * @since 1.4.0
   */
  def pow(l: Double, r: Column): Column = pow(lit(l), r)

  /**
   * 返回第一个参数的第二个参数次幂的值。
   *
   * @group math_funcs
   * @since 1.4.0
   */
  def pow(l: Double, rightName: String): Column = pow(l, Column(rightName))

  /**
   * 返回除法中的正数被除数模除除数的正数余数。
   *
   * @group math_funcs
   * @since 1.5.0
   */
  def pmod(dividend: Column, divisor: Column): Column = withExpr {
    Pmod(dividend.expr, divisor.expr)
  }

  /**
   * 返回最接近参数的整数,四舍五入到最接近的整数。
   *
   * @group math_funcs
   * @since 1.4.0
   */
  def rint(e: Column): Column = withExpr { Rint(e.expr) }

  /**
   * 返回最接近参数的整数,四舍五入到最接近的整数。
   *
   * @group math_funcs
   * @since 1.4.0
   */
  def rint(columnName: String): Column = rint(Column(columnName))

  /**
   * 返回列 `e` 的值向0舍入到0位小数的结果,使用HALF_UP舍入模式。
   *
   * @group math_funcs
   * @since 1.5.0
   */
  def round(e: Column): Column = round(e, 0)

  /**
   * 将列 `e` 的值舍入到 `scale` 位小数,使用HALF_UP舍入模式,
   * 如果 `scale` 大于等于0或者在 `scale` 小于0时取整数部分。
   *
   * @group math_funcs
   * @since 1.5.0
   */
  def round(e: Column, scale: Int): Column = withExpr { Round(e.expr, Literal(scale)) }

  /**
   * 返回列 `e` 的值向0舍入到0位小数的结果,使用HALF_EVEN舍入模式。
   *
   * @group math_funcs
   * @since 2.0.0
   */
  def bround(e: Column): Column = bround(e, 0)

  /**
   * 将列 `e` 的值舍入到 `scale` 位小数,使用HALF_EVEN舍入模式,
   * 如果 `scale` 大于等于0或者在 `scale` 小于0时取整数部分。
   *
   * @group math_funcs
   * @since 2.0.0
   */
  def bround(e: Column, scale: Int): Column = withExpr { BRound(e.expr, Literal(scale)) }

  /**
   * 将给定值向左移动 `numBits` 位。如果给定值是long类型,则返回long类型,否则返回整型。
   *
   * @group math_funcs
   * @since 1.5.0
   */
  def shiftLeft(e: Column, numBits: Int): Column = withExpr { ShiftLeft(e.expr, lit(numBits).expr) }

  /**
   * (有符号)将给定值向右移动 `numBits` 位。如果给定值是long类型,则返回long类型,否则返回整型。
   *
   * @group math_funcs
   * @since 1.5.0
   */
  def shiftRight(e: Column, numBits: Int): Column = withExpr {
    ShiftRight(e.expr, lit(numBits).expr)
  }

  /**
   * 无符号地将给定值向右移动 `numBits` 位。如果给定值是long类型,则返回long类型,否则返回整型。
   *
   * @group math_funcs
   * @since 1.5.0
   */
  def shiftRightUnsigned(e: Column, numBits: Int): Column = withExpr {
    ShiftRightUnsigned(e.expr, lit(numBits).expr)
  }

  /**
   * 计算给定值的符号。
   *
   * @group math_funcs
   * @since 1.4.0
   */
  def signum(e: Column): Column = withExpr { Signum(e.expr) }

  /**
   * 计算给定列的符号。
   *
   * @group math_funcs
   * @since 1.4.0
   */
  def signum(columnName: String): Column = signum(Column(columnName))

  /**
   * 返回角度的正弦值,类似于`java.lang.Math.sin`计算得到的值。
   *
   * @group math_funcs
   * @since 1.4.0
   */
  def sin(e: Column): Column = withExpr { Sin(e.expr) }

  /**
   * 返回角度的正弦值,类似于`java.lang.Math.sin`计算得到的值。
   *
   * @group math_funcs
   * @since 1.4.0
   */
  def sin(columnName: String): Column = sin(Column(columnName))

  /**
   * 返回给定值的双曲正弦值,类似于`java.lang.Math.sinh`计算得到的值。
   *
   * @group math_funcs
   * @since 1.4.0
   */
  def sinh(e: Column): Column = withExpr { Sinh(e.expr) }

/**
 * 返回给定值的双曲正弦值,类似于`java.lang.Math.sinh`计算得到的值。
 *
 * @param columnName 双曲角
 * @return 给定值的双曲正弦值,类似于`java.lang.Math.sinh`计算得到的值。
 *
 * @group math_funcs
 * @since 1.4.0
 */
def sinh(columnName: String): Column = sinh(Column(columnName))

/**
 * 返回角度的正切值,类似于`java.lang.Math.tan`计算得到的值。
 *
 * @param e 弧度角
 * @return 角度的正切值,类似于`java.lang.Math.tan`计算得到的值。
 *
 * @group math_funcs
 * @since 1.4.0
 */
def tan(e: Column): Column = withExpr { Tan(e.expr) }

/**
 * 返回角度的正切值,类似于`java.lang.Math.tan`计算得到的值。
 *
 * @param columnName 弧度角
 * @return 角度的正切值,类似于`java.lang.Math.tan`计算得到的值。
 *
 * @group math_funcs
 * @since 1.4.0
 */
def tan(columnName: String): Column = tan(Column(columnName))

/**
 * 返回给定值的双曲正切值,类似于`java.lang.Math.tanh`计算得到的值。
 *
 * @param e 双曲角
 * @return 给定值的双曲正切值,类似于`java.lang.Math.tanh`计算得到的值。
 *
 * @group math_funcs
 * @since 1.4.0
 */
def tanh(e: Column): Column = withExpr { Tanh(e.expr) }

/**
 * 返回给定值的双曲正切值,类似于`java.lang.Math.tanh`计算得到的值。
 *
 * @param columnName 双曲角
 * @return 给定值的双曲正切值,类似于`java.lang.Math.tanh`计算得到的值。
 *
 * @group math_funcs
 * @since 1.4.0
 */
def tanh(columnName: String): Column = tanh(Column(columnName))

/**
 * @group math_funcs
 * @since 1.4.0
 * @deprecated("Use degrees", "2.1.0")
 * 将弧度转换为度数。
 */
def toDegrees(e: Column): Column = degrees(e)

/**
 * @group math_funcs
 * @since 1.4.0
 * @deprecated("Use degrees", "2.1.0")
 * 将弧度转换为度数。
 */
def toDegrees(columnName: String): Column = degrees(Column(columnName))

/**
 * 将以弧度表示的角度转换为大致相等的以度数表示的角度。
 *
 * @param e 弧度角
 * @return 以度数表示的角度,类似于`java.lang.Math.toDegrees`
 *
 * @group math_funcs
 * @since 2.1.0
 */
def degrees(e: Column): Column = withExpr { ToDegrees(e.expr) }

/**
 * 将以弧度表示的角度转换为大致相等的以度数表示的角度。
 *
 * @param columnName 弧度角
 * @return 以度数表示的角度,类似于`java.lang.Math.toDegrees`
 *
 * @group math_funcs
 * @since 2.1.0
 */
def degrees(columnName: String): Column = degrees(Column(columnName))

/**
 * @group math_funcs
 * @since 1.4.0
 * @deprecated("Use radians", "2.1.0")
 * 将度数转换为弧度。
 */
def toRadians(e: Column): Column = radians(e)

/**
 * @group math_funcs
 * @since 1.4.0
 * @deprecated("Use radians", "2.1.0")
 * 将度数转换为弧度。
 */
def toRadians(columnName: String): Column = radians(Column(columnName))

/**
 * 将以度数表示的角度转换为大致相等的以弧度表示的角度。
 *
 * @param e 度数角
 * @return 以弧度表示的角度,类似于`java.lang.Math.toRadians`
 *
 * @group math_funcs
 * @since 2.1.0
 */
def radians(e: Column): Column = withExpr { ToRadians(e.expr) }

/**
 * 将以度数表示的角度转换为大致相等的以弧度表示的角度。
 *
 * @param columnName 度数角
 * @return 以弧度表示的角度,类似于`java.lang.Math.toRadians`
 *
 * @group math_funcs
 * @since 2.1.0
 */
def radians(columnName: String): Column = radians(Column(columnName))

misc_funcs 杂项函数

//
// Misc functions
//

/**
 * 计算二进制列的MD5摘要,并将结果作为32个字符的十六进制字符串返回。
 *
 * @group misc_funcs
 * @since 1.5.0
 */
def md5(e: Column): Column = withExpr { Md5(e.expr) }

/**
 * 计算二进制列的SHA-1摘要,并将结果作为40个字符的十六进制字符串返回。
 *
 * @group misc_funcs
 * @since 1.5.0
 */
def sha1(e: Column): Column = withExpr { Sha1(e.expr) }

/**
 * 计算二进制列的SHA-2系列散列函数,并将结果作为十六进制字符串返回。
 *
 * @param e 要计算SHA-2的列
 * @param numBits 224、256、384或512中的一个
 *
 * @group misc_funcs
 * @since 1.5.0
 */
def sha2(e: Column, numBits: Int): Column = {
  require(Seq(0, 224, 256, 384, 512).contains(numBits),
    s"numBits $numBits is not in the permitted values (0, 224, 256, 384, 512)")
  withExpr { Sha2(e.expr, lit(numBits).expr) }
}

/**
 * 计算二进制列的循环冗余校验值(CRC32),并将结果作为bigint返回。
 *
 * @group misc_funcs
 * @since 1.5.0
 */
def crc32(e: Column): Column = withExpr { Crc32(e.expr) }

/**
 * 计算给定列的哈希码,并将结果作为int列返回。
 *
 * @group misc_funcs
 * @since 2.0.0
 */
@scala.annotation.varargs
def hash(cols: Column*): Column = withExpr {
  new Murmur3Hash(cols.map(_.expr))
}


string_funcs 字符串函数

//
// String functions
//

/**
 * 计算字符串列第一个字符的数字值,并将结果作为int列返回。
 *
 * @group string_funcs
 * @since 1.5.0
 */
def ascii(e: Column): Column = withExpr { Ascii(e.expr) }

/**
 * 计算二进制列的BASE64编码,并将结果作为字符串列返回。
 * 这是unbase64的反操作。
 *
 * @group string_funcs
 * @since 1.5.0
 */
def base64(e: Column): Column = withExpr { Base64(e.expr) }

/**
 * 将多个输入字符串列连接成单个字符串列,使用给定的分隔符。
 *
 * @group string_funcs
 * @since 1.5.0
 */
@scala.annotation.varargs
def concat_ws(sep: String, exprs: Column*): Column = withExpr {
  ConcatWs(Literal.create(sep, StringType) +: exprs.map(_.expr))
}

/**
 * 使用提供的字符集('US-ASCII', 'ISO-8859-1', 'UTF-8', 'UTF-16BE', 'UTF-16LE', 'UTF-16'之一)
 * 将第一个参数解码为字符串。如果任一参数为空,则结果也为空。
 *
 * @group string_funcs
 * @since 1.5.0
 */
def decode(value: Column, charset: String): Column = withExpr {
  Decode(value.expr, lit(charset).expr)
}

/**
 * 使用提供的字符集('US-ASCII', 'ISO-8859-1', 'UTF-8', 'UTF-16BE', 'UTF-16LE', 'UTF-16'之一)
 * 将第一个参数编码为二进制。如果任一参数为空,则结果也为空。
 *
 * @group string_funcs
 * @since 1.5.0
 */
def encode(value: Column, charset: String): Column = withExpr {
  Encode(value.expr, lit(charset).expr)
}

/**
 * 格式化数字列x为类似于'#,###,###.##'的格式,四舍五入到d位小数,
 * 使用HALF_EVEN舍入模式,并将结果作为字符串列返回。
 *
 * 如果d为0,则结果没有小数点或小数部分。
 * 如果d小于0,则结果将为空。
 *
 * @group string_funcs
 * @since 1.5.0
 */
def format_number(x: Column, d: Int): Column = withExpr {
  FormatNumber(x.expr, lit(d).expr)
}

/**
 * 使用printf样式格式化参数,并将结果作为字符串列返回。
 *
 * @group string_funcs
 * @since 1.5.0
 */
@scala.annotation.varargs
def format_string(format: String, arguments: Column*): Column = withExpr {
  FormatString((lit(format) +: arguments).map(_.expr): _*)
}

/**
 * 返回一个新的字符串列,其中每个单词的首字母转换为大写。
 * 单词由空格分隔。
 *
 * 例如,"hello world"将变为"Hello World"。
 *
 * @group string_funcs
 * @since 1.5.0
 */
def initcap(e: Column): Column = withExpr { InitCap(e.expr) }

/**
 * 定位给定字符串中子字符串的第一个出现位置。
 * 如果任一参数为空,则返回null。
 *
 * 注意:位置不是从零开始,而是从1开始的索引。如果在str中找不到substr,则返回0。
 *
 * @group string_funcs
 * @since 1.5.0
 */
def instr(str: Column, substring: String): Column = withExpr {
  StringInstr(str.expr, lit(substring).expr)
}

/**
 * 计算给定字符串的字符长度或给定二进制字符串的字节数。
 * 字符串的长度包括尾部的空格。二进制字符串的长度包括二进制零。
 *
 * @group string_funcs
 * @since 1.5.0
 */
def length(e: Column): Column = withExpr { Length(e.expr) }

/**
 * 将字符串列转换为小写。
 *
 * @group string_funcs
 * @since 1.3.0
 */
def lower(e: Column): Column = withExpr { Lower(e.expr) }

/**
 * 计算两个给定字符串列的Levenshtein距离。
 * @group string_funcs
 * @since 1.5.0
 */
def levenshtein(l: Column, r: Column): Column = withExpr { Levenshtein(l.expr, r.expr) }

/**
 * 在给定字符串中定位子字符串的第一个出现位置。
 *
 * 注意:位置不是从零开始,而是从1开始的索引。如果在str中找不到substr,则返回0。
 *
 * @group string_funcs
 * @since 1.5.0
 */
def locate(substr: String, str: Column): Column = withExpr {
  new StringLocate(lit(substr).expr, str.expr)
}

/**
 * 在给定字符串中定位子字符串的第一个出现位置,位置从pos开始。
 *
 * 注意:位置不是从零开始,而是从1开始的索引。如果在str中找不到substr,则返回0。
 *
 * @group string_funcs
 * @since 1.5.0
 */
def locate(substr: String, str: Column, pos: Int): Column = withExpr {
  StringLocate(lit(substr).expr, str.expr, lit(pos).expr)
}

/**
 * 使用pad右填充字符串列,使其长度达到len。如果字符串列超过len,则返回值将被截断为len个字符。
 *
 * @group string_funcs
 * @since 1.5.0
 */
def lpad(str: Column, len: Int, pad: String): Column = withExpr {
  StringLPad(str.expr, lit(len).expr, lit(pad).expr)
}

/**
 * 从指定字符串值的左端删除空格。
 *
 * @group string_funcs
 * @since 1.5.0
 */
def ltrim(e: Column): Column = withExpr {StringTrimLeft(e.expr) }

/**
 * 从指定字符串列的左端删除指定的字符字符串。
 * @group string_funcs
 * @since 2.3.0
 */
def ltrim(e: Column, trimString: String): Column = withExpr {
  StringTrimLeft(e.expr, Literal(trimString))
}

/**
 * 从指定字符串表达式中提取与Java正则表达式匹配的特定组。如果正则表达式未匹配或指定的组未匹配,则返回空字符串。
 *
 * @group string_funcs
 * @since 1.5.0
 */
def regexp_extract(e: Column, exp: String, groupIdx: Int): Column = withExpr {
  RegExpExtract(e.expr, lit(exp).expr, lit(groupIdx).expr)
}

/**
 * 使用rep替换指定字符串值的所有子字符串。
 *
 * @group string_funcs
 * @since 1.5.0
 */
def regexp_replace(e: Column, pattern: String, replacement: String): Column = withExpr {
  RegExpReplace(e.expr, lit(pattern).expr, lit(replacement).expr)
}

/**
 * 使用rep替换指定字符串值的所有子字符串。
 *
 * @group string_funcs
 * @since 2.1.0
 */
def regexp_replace(e: Column, pattern: Column, replacement: Column): Column = withExpr {
  RegExpReplace(e.expr, pattern.expr, replacement.expr)
}

/**
 * 解码一个BASE64编码的字符串列,并将其作为二进制列返回。
 * 这是base64的反操作。
 *
 * @group string_funcs
 * @since 1.5.0
 */
def unbase64(e: Column): Column = withExpr { UnBase64(e.expr) }

/**
 * 使用pad右填充字符串列,使其长度达到len。如果字符串列超过len,则返回值将被截断为len个字符。
 *
 * @group string_funcs
 * @since 1.5.0
 */
def rpad(str: Column, len: Int, pad: String): Column = withExpr {
  StringRPad(str.expr, lit(len).expr, lit(pad).expr)
}

/**
 * 将字符串列重复n次,并将其作为新的字符串列返回。
 *
 * @group string_funcs
 * @since 1.5.0
 */
def repeat(str: Column, n: Int): Column = withExpr {
  StringRepeat(str.expr, lit(n).expr)
}

/**
 * 从指定字符串值的右端删除空格。
 *
 * @group string_funcs
 * @since 1.5.0
 */
def rtrim(e: Column): Column = withExpr { StringTrimRight(e.expr) }

/**
 * 从指定字符串列的右端删除指定的字符字符串。
 * @group string_funcs
 * @since 2.3.0
 */
def rtrim(e: Column, trimString: String): Column = withExpr {
  StringTrimRight(e.expr, Literal(trimString))
}

/**
 * 返回指定表达式的Soundex代码。
 *
 * @group string_funcs
 * @since 1.5.0
 */
def soundex(e: Column): Column = withExpr { SoundEx(e.expr) }

/**
 * 使用pattern(pattern是一个正则表达式)在str周围拆分。
 *
 * 注意:pattern是正则表达式的字符串表示形式。
 *
 * @group string_funcs
 * @since 1.5.0
 */
def split(str: Column, pattern: String): Column = withExpr {
  StringSplit(str.expr, lit(pattern).expr)
}

/**
 * 返回字符串列的子串,子串从`pos`开始,长度为`len`
 * 当str是String类型时,或者返回二进制数组的切片,该切片从`pos`开始,长度为`len`,当str是Binary类型时。
 *
 * @note 位置不是基于0的,而是基于1的索引。
 *
 * @group string_funcs
 * @since 1.5.0
 */
def substring(str: Column, pos: Int, len: Int): Column = withExpr {
  Substring(str.expr, lit(pos).expr, lit(len).expr)
}

/**
 * 返回给定字符串中出现分隔符delim之前的子字符串。
 * 如果count是正数,则返回分隔符的左侧部分(从左开始计数)。
 * 如果count是负数,则返回分隔符的右侧部分(从右开始计数)。
 * substring_index在搜索delim时执行区分大小写的匹配。
 *
 * @group string_funcs
 */
def substring_index(str: Column, delim: String, count: Int): Column = withExpr {
  SubstringIndex(str.expr, lit(delim).expr, lit(count).expr)
}

/**
 * 将源字符串中的任何字符替换为replaceString中的字符。
 * replaceString中的字符与matchingString中的字符相对应。
 * 当源字符串中的字符与matchingString中的字符匹配时,将进行替换。
 *
 * @group string_funcs
 * @since 1.5.0
 */
def translate(src: Column, matchingString: String, replaceString: String): Column = withExpr {
  StringTranslate(src.expr, lit(matchingString).expr, lit(replaceString).expr)
}

/**
 * 去掉字符串列两端的空格。
 *
 * @group string_funcs
 * @since 1.5.0
 */
def trim(e: Column): Column = withExpr { StringTrim(e.expr) }

/**
 * 去掉指定字符串列两端的指定字符。
 * @group string_funcs
 * @since 2.3.0
 */
def trim(e: Column, trimString: String): Column = withExpr {
  StringTrim(e.expr, Literal(trimString))
}

/**
 * 将字符串列转换为大写。
 *
 * @group string_funcs
 * @since 1.3.0
 */
def upper(e: Column): Column = withExpr { Upper(e.expr) }

日期时间函数

//
// DateTime functions
//

/**
 * 返回`startDate`之后`numMonths`个月的日期。
 *
 * @param startDate 一个日期、时间戳或字符串。如果是字符串,则数据必须以可以转换为日期的格式,例如`yyyy-MM-dd`或`yyyy-MM-dd HH:mm:ss.SSSS`
 * @param numMonths 要添加到`startDate`的月数,可以为负数以减去月数
 * @return 一个日期,如果`startDate`是无法转换为日期的字符串,则返回null
 * @group datetime_funcs
 * @since 1.5.0
 */
def add_months(startDate: Column, numMonths: Int): Column = withExpr {
  AddMonths(startDate.expr, Literal(numMonths))
}

/**
 * 返回当前日期作为日期列。
 *
 * @group datetime_funcs
 * @since 1.5.0
 */
def current_date(): Column = withExpr { CurrentDate() }

/**
 * 返回当前时间戳作为时间戳列。
 *
 * @group datetime_funcs
 * @since 1.5.0
 */
def current_timestamp(): Column = withExpr { CurrentTimestamp() }

/**
 * 将日期/时间戳/字符串转换为指定格式的字符串值。
 *
 * 有关有效日期和时间格式模式,请参见[[java.text.SimpleDateFormat]]
 *
 * @param dateExpr 日期、时间戳或字符串。如果是字符串,则数据必须以可以转换为时间戳的格式,例如`yyyy-MM-dd`或`yyyy-MM-dd HH:mm:ss.SSSS`
 * @param format 模式 `dd.MM.yyyy`将返回如`18.03.1993`的字符串
 * @return 一个字符串,如果`dateExpr`是无法转换为时间戳的字符串,则返回null
 * @note 尽可能使用专用函数(例如[[year]]),因为它们能从特殊实现中受益。
 * @throws IllegalArgumentException 如果`format`模式无效
 * @group datetime_funcs
 * @since 1.5.0
 */
def date_format(dateExpr: Column, format: String): Column = withExpr {
  DateFormatClass(dateExpr.expr, Literal(format))
}

/**
 * 返回`start`之后`days`天的日期。
 *
 * @param start 一个日期、时间戳或字符串。如果是字符串,则数据必须以可以转换为日期的格式,例如`yyyy-MM-dd`或`yyyy-MM-dd HH:mm:ss.SSSS`
 * @param days 要添加到`start`的天数,可以为负数以减去天数
 * @return 一个日期,如果`start`是无法转换为日期的字符串,则返回null
 * @group datetime_funcs
 * @since 1.5.0
 */
def date_add(start: Column, days: Int): Column = withExpr { DateAdd(start.expr, Literal(days)) }

/**
 * 返回`start`之前`days`天的日期。
 *
 * @param start 一个日期、时间戳或字符串。如果是字符串,则数据必须以可以转换为日期的格式,例如`yyyy-MM-dd`或`yyyy-MM-dd HH:mm:ss.SSSS`
 * @param days 要减去`start`的天数,可以为负数以添加天数
 * @return 一个日期,如果`start`是无法转换为日期的字符串,则返回null
 * @group datetime_funcs
 * @since 1.5.0
 */
def date_sub(start: Column, days: Int): Column = withExpr { DateSub(start.expr, Literal(days)) }

/**
 * 返回从`start`到`end`的天数。
 *
 * 只考虑输入的日期部分。例如:
 * {{{
 * dateddiff("2018-01-10 00:00:00", "2018-01-09 23:59:59")
 * // 返回1
 * }}}
 *
 * @param end 一个日期、时间戳或字符串。如果是字符串,则数据必须以可以转换为日期的格式,例如`yyyy-MM-dd`或`yyyy-MM-dd HH:mm:ss.SSSS`
 * @param start 一个日期、时间戳或字符串。如果是字符串,则数据必须以可以转换为日期的格式,例如`yyyy-MM-dd`或`yyyy-MM-dd HH:mm:ss.SSSS`
 * @return 一个整数,如果`end`或`start`是无法转换为日期的字符串,则返回null。如果`end`在`start`之前,则返回负数
 * @group datetime_funcs
 * @since 1.5.0
 */
def datediff(end: Column, start: Column): Column = withExpr { DateDiff(end.expr, start.expr) }

/**
 * 从给定日期/时间戳/字符串中提取年份作为整数。
 * @return 一个整数,如果输入是无法转换为日期的字符串,则返回null
 * @group datetime_funcs
 * @since 1.5.0
 */
def year(e: Column): Column = withExpr { Year(e.expr) }

/**
 * 从给定日期/时间戳/字符串中提取季度作为整数。
 * @return 一个整数,如果输入是无法转换为日期的字符串,则返回null
 * @group datetime_funcs
 * @since 1.5.0
 */
def quarter(e: Column): Column = withExpr { Quarter(e.expr) }

/**
 * 从给定日期/时间戳/字符串中提取月份作为整数。
 * @return 一个整数,如果输入是无法转换为日期的字符串,则返回null
 * @group datetime_funcs
 * @since 1.5.0
 */
def month(e: Column): Column = withExpr { Month(e.expr) }

/**
 * 从给定日期/时间戳/字符串中提取星期几作为整数。
 * 从星期天到星期六分别为1到7。
 * @return 一个整数,如果输入是无法转换为日期的字符串,则返回null
 * @group datetime_funcs
 * @since 2.3.0
 */
def dayofweek(e: Column): Column = withExpr { DayOfWeek(e.expr) }

/**
 * 从给定日期/时间戳/字符串中提取月份中的某天作为整数。
 * @return 一个整数,如果输入是无法转换为日期的字符串,则返回null
 * @group datetime_funcs
 * @since 1.5.0
 */
def dayofmonth(e: Column): Column = withExpr { DayOfMonth(e.expr) }

/**
 * 从给定日期/时间戳/字符串中提取年份中的某天作为整数。
 * @return 一个整数,如果输入是无法转换为日期的字符串,则返回null
 * @group datetime_funcs
 * @since 1.5.0
 */
def dayofyear(e: Column): Column = withExpr { DayOfYear(e.expr) }

/**
 * 从给定日期/时间戳/字符串中提取小时作为整数。
 * @return 一个整数,如果输入是无法转换为日期的字符串,则返回null
 * @group datetime_funcs
 * @since 1.5.0
 */
def hour(e: Column): Column = withExpr { Hour(e.expr) }

/**
 * 返回给定日期所在月份的最后一天。
 * 例如,输入"2015-07-27"返回"2015-07-31",因为7月31日是2015年7月的最后一天。
 *
 * @param e 一个日期、时间戳或字符串。如果是字符串,则数据必须以可以转换为日期的格式,例如`yyyy-MM-dd`或`yyyy-MM-dd HH:mm:ss.SSSS`
 * @return 一个日期,如果输入是无法转换为日期的字符串,则返回null
 * @group datetime_funcs
 * @since 1.5.0
 */
def last_day(e: Column): Column = withExpr { LastDay(e.expr) }

/**
 * 从给定日期/时间戳/字符串中提取分钟作为整数。
 * @return 一个整数,如果输入是无法转换为日期的字符串,则返回null
 * @group datetime_funcs
 * @since 1.5.0
 */
def minute(e: Column): Column = withExpr { Minute(e.expr) }

/**
 * 返回`start`和`end`之间的月份数。
 *
 * 如果两个输入具有相同的日期,或者两者都是各自月份的最后一天,将返回一个整数。
 * 否则,假设每个月有31天,计算差异。
 *
 * 例如:
 * {{{
 * months_between("2017-11-14", "2017-07-14")  // 返回4.0
 * months_between("2017-01-01", "2017-01-10")  // 返回0.29032258
 * months_between("2017-06-01", "2017-06-16 12:00:00")  // 返回-0.5
 * }}}
 *
 * @param end 一个日期、时间戳或字符串。如果是字符串,则数据必须以可以转换为时间戳的格式,例如`yyyy-MM-dd`或`yyyy-MM-dd HH:mm:ss.SSSS`
 * @param start 一个日期、时间戳或字符串。如果是字符串,则数据必须以可以转换为时间戳的格式,例如`yyyy-MM-dd`或`yyyy-MM-dd HH:mm:ss.SSSS`
 * @return 一个双精度浮点数,如果`end`或`start`是无法转换为时间戳的字符串,则返回null。如果`end`在`start`之前,则返回负数
 * @group datetime_funcs
 * @since 1.5.0
 */
def months_between(end: Column, start: Column): Column = withExpr {
  new MonthsBetween(end.expr, start.expr)
}

/**
 * 返回`start`和`end`之间的月份数。如果将`roundOff`设置为true,则结果将四舍五入到8位小数;否则不进行四舍五入。
 * @group datetime_funcs
 * @since 2.4.0
 */
def months_between(end: Column, start: Column, roundOff: Boolean): Column = withExpr {
  MonthsBetween(end.expr, start.expr, lit(roundOff).expr)
}

/**
 * 返回给定日期的下一个星期几之后的日期。
 *
 * 例如,`next_day('2015-07-27', "Sunday")`返回2015-08-02,因为这是2015年7月27日之后的第一个星期日。
 *
 * @param date 一个日期、时间戳或字符串。如果是字符串,则数据必须以可以转换为日期的格式,例如`yyyy-MM-dd`或`yyyy-MM-dd HH:mm:ss.SSSS`
 * @param dayOfWeek 不区分大小写,接受:"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"
 * @return 一个日期,如果`date`是无法转换为日期的字符串或`dayOfWeek`是无效值,则返回null
 * @group datetime_funcs
 * @since 1.5.0
 */
def next_day(date: Column, dayOfWeek: String): Column = withExpr {
  NextDay(date.expr, lit(dayOfWeek).expr)
}

/**
 * 从给定日期/时间戳/字符串中提取秒数作为整数。
 * @return 一个整数,如果输入是无法转换为时间戳的字符串,则返回null
 * @group datetime_funcs
 * @since 1.5.0
 */
def second(e: Column): Column = withExpr { Second(e.expr) }

/**
 * 从给定日期/时间戳/字符串中提取年份中的某周作为整数。
 *
 * 周被认为从星期一开始,第1周是具有大于3天的第一周,这是ISO 8601定义的
 *
 * @return 一个整数,如果输入是无法转换为日期的字符串,则返回null
 * @group datetime_funcs
 * @since 1.5.0
 */
def weekofyear(e: Column): Column = withExpr { WeekOfYear(e.expr) }

/**
 * 将从Unix纪元(1970-01-01 00:00:00 UTC)到的秒数转换为表示该时刻的时间戳的字符串,
 * 该时刻是在当前系统时区中的`yyyy-MM-dd HH:mm:ss`格式。
 *
 * @param ut 可以转换为long类型的数字,例如字符串或整数。可以为负数以表示Unix纪元之前的时间戳
 * @return 一个字符串,如果输入是无法转换为long的字符串,则返回null
 * @group datetime_funcs
 * @since 1.5.0
 */
def from_unixtime(ut: Column): Column = withExpr {
  FromUnixTime(ut.expr, Literal("yyyy-MM-dd HH:mm:ss"))
}
/**
 * 将给定的秒数从Unix纪元(1970-01-01 00:00:00 UTC)转换为表示该时刻的时间戳的字符串,
 * 该时刻是在当前系统时区中的给定格式。
 *
 * 可参考[[java.text.SimpleDateFormat]]获取有效的日期和时间格式模式
 *
 * @param ut 可以转换为long类型的数字,例如字符串或整数。可以为负数以表示Unix纪元之前的时间戳
 * @param f 日期时间格式模式,用于将输入格式化为字符串
 * @return 一个字符串,如果`ut`是无法转换为long的字符串,则返回null,或者`f`是无效的日期时间格式模式
 * @group datetime_funcs
 * @since 1.5.0
 */
def from_unixtime(ut: Column, f: String): Column = withExpr {
  FromUnixTime(ut.expr, Literal(f))
}

/**
 * 返回当前Unix时间戳(以秒为单位)作为长整型。
 *
 * @note 在同一查询中,所有`unix_timestamp`的调用返回相同的值
 * (即当前时间戳是在查询评估开始时计算的)。
 *
 * @group datetime_funcs
 * @since 1.5.0
 */
def unix_timestamp(): Column = withExpr {
  UnixTimestamp(CurrentTimestamp(), Literal("yyyy-MM-dd HH:mm:ss"))
}

/**
 * 将格式为`yyyy-MM-dd HH:mm:ss`的时间字符串转换为Unix时间戳(以秒为单位),
 * 使用默认时区和默认区域设置。
 *
 * @param s 一个日期、时间戳或字符串。如果是字符串,则数据必须以可以转换为时间戳的格式,例如`yyyy-MM-dd`或`yyyy-MM-dd HH:mm:ss.SSSS`
 * @return 一个长整型,如果输入是无法转换为正确格式的字符串,则返回null
 * @group datetime_funcs
 * @since 1.5.0
 */
def unix_timestamp(s: Column): Column = withExpr {
  UnixTimestamp(s.expr, Literal("yyyy-MM-dd HH:mm:ss"))
}

/**
 * 将给定日期/时间戳/字符串按照给定模式转换为Unix时间戳(以秒为单位)。
 *
 * 可参考[[java.text.SimpleDateFormat]]获取有效的日期和时间格式模式
 *
 * @param s 一个日期、时间戳或字符串。如果是字符串,则数据必须以可以转换为时间戳的格式,例如`yyyy-MM-dd`或`yyyy-MM-dd HH:mm:ss.SSSS`
 * @param p 字符串格式详细说明`s`在`s`是字符串时的格式
 * @return 一个长整型,如果`s`是无法转换为时间戳的字符串,则返回null。或者`p`是无效的格式
 * @group datetime_funcs
 * @since 1.5.0
 */
def unix_timestamp(s: Column, p: String): Column = withExpr { UnixTimestamp(s.expr, Literal(p)) }

/**
 * 根据`TimestampType`将列转换为时间戳。
 *
 * @param s 一个日期、时间戳或字符串。如果是字符串,则数据必须以可以转换为时间戳的格式,例如`yyyy-MM-dd`或`yyyy-MM-dd HH:mm:ss.SSSS`
 * @return 一个时间戳,如果输入是无法转换为时间戳的字符串,则返回null
 * @group datetime_funcs
 * @since 2.2.0
 */
def to_timestamp(s: Column): Column = withExpr {
  new ParseToTimestamp(s.expr)
}

/**
 * 将给定格式的时间字符串转换为时间戳。
 *
 * 可参考[[java.text.SimpleDateFormat]]获取有效的日期和时间格式模式
 *
 * @param s 一个日期、时间戳或字符串。如果是字符串,则数据必须以可以转换为时间戳的格式,例如`yyyy-MM-dd`或`yyyy-MM-dd HH:mm:ss.SSSS`
 * @param fmt 字符串格式详细说明`s`在`s`是字符串时的格式
 * @return 一个时间戳,如果`s`是无法转换为时间戳的字符串,则返回null,或者`fmt`是无效的格式
 * @group datetime_funcs
 * @since 2.2.0
 */
def to_timestamp(s: Column, fmt: String): Column = withExpr {
  new ParseToTimestamp(s.expr, Literal(fmt))
}

/**
 * 根据`DateType`将列转换为`DateType`。
 *
 * @group datetime_funcs
 * @since 1.5.0
 */
def to_date(e: Column): Column = withExpr { new ParseToDate(e.expr) }

/**
 * 将列转换为指定格式的`DateType`
 *
 * 可参考[[java.text.SimpleDateFormat]]获取有效的日期和时间格式模式
 *
 * @param e 一个日期、时间戳或字符串。如果是字符串,则数据必须以可以转换为日期的格式,例如`yyyy-MM-dd`或`yyyy-MM-dd HH:mm:ss.SSSS`
 * @param fmt 字符串格式详细说明`e`在`e`是字符串时的格式
 * @return 一个日期,如果`e`是无法转换为日期的字符串,则返回null,或者`fmt`是无效的格式
 * @group datetime_funcs
 * @since 2.2.0
 */
def to_date(e: Column, fmt: String): Column = withExpr {
  new ParseToDate(e.expr, Literal(fmt))
}

/**
 * 将日期按照给定格式截断到指定单位。
 *
 * 例如,`trunc("2018-11-19 12:01:19", "year")`返回2018-01-01
 *
 * @param date 一个日期、时间戳或字符串。如果是字符串,则数据必须以可以转换为日期的格式,例如`yyyy-MM-dd`或`yyyy-MM-dd HH:mm:ss.SSSS`
 * @param format: 'year', 'yyyy', 'yy' 表示按年截断,
 *               或 'month', 'mon', 'mm' 表示按月截断
 * @return 一个日期,如果`date`是无法转换为日期的字符串,则返回null,或者`format`是无效的值
 * @group datetime_funcs
 * @since 1.5.0
 */
def trunc(date: Column, format: String): Column = withExpr {
  TruncDate(date.expr, Literal(format))
}

/**
 * 将时间戳按照给定格式截断到指定单位。
 *
 * 例如,`date_tunc("2018-11-19 12:01:19", "year")`返回2018-01-01 00:00:00
 *
 * @param format: 'year', 'yyyy', 'yy' 表示按年截断,
 *                'month', 'mon', 'mm' 表示按月截断,
 *                'day', 'dd' 表示按日截断,
 *                其他选项为:'second', 'minute', 'hour', 'week', 'month', 'quarter'
 * @param timestamp 一个日期、时间戳或字符串。如果是字符串,则数据必须以可以转换为时间戳的格式,例如`yyyy-MM-dd`或`yyyy-MM-dd HH:mm:ss.SSSS`
 * @return 一个时间戳,如果`timestamp`是无法转换为时间戳的字符串,则返回null,或者`format`是无效的值
 * @group datetime_funcs
 * @since 2.3.0
 */
def date_trunc(format: String, timestamp: Column): Column = withExpr {
  TruncTimestamp(Literal(format), timestamp.expr)
}

/**
 * 给定一个类似于'2017-07-14 02:40:00.0'的时间戳,在UTC中解释它,并将该时间作为给定时区中的时间戳呈现。
 * 例如,'GMT+1'将产生'2017-07-14 03:40:00.0'。
 *
 * @param ts 一个日期、时间戳或字符串。如果是字符串,则数据必须以可以转换为时间戳的格式,例如`yyyy-MM-dd`或`yyyy-MM-dd HH:mm:ss.SSSS`
 * @param tz 详细说明输入应调整为的时区的字符串,例如`Europe/London`、`PST`或`GMT+5`
 * @return 一个时间戳,如果`ts`是无法转换为时间戳的字符串,则返回null,或者`tz`是无效的值
 * @group datetime_funcs
 * @since 1.5.0
 */
def from_utc_timestamp(ts: Column, tz: String): Column = withExpr {
  FromUTCTimestamp(ts.expr, Literal(tz))
}

/**
 * 给定一个类似于'2017-07-14 02:40:00.0'的时间戳,在UTC中解释它,并将该时间作为给定时区中的时间戳呈现。
 * 例如,'GMT+1'将产生'2017-07-14 03:40:00.0'。
 * @group datetime_funcs
 * @since 2.4.0
 */
def from_utc_timestamp(ts: Column, tz: Column): Column = withExpr {
  FromUTCTimestamp(ts.expr, tz.expr)
}

/**
 * 给定一个类似于'2017-07-14 02:40:00.0'的时间戳,在给定时区中解释它,并将该时间作为UTC中的时间戳呈现。
 * 例如,'GMT+1'将产生'2017-07-14 01:40:00.0'。
 *
 * @param ts 一个日期、时间戳或字符串。如果是字符串,则数据必须以可以转换为时间戳的格式,例如`yyyy-MM-dd`或`yyyy-MM-dd HH:mm:ss.SSSS`
 * @param tz 详细说明输入所属的时区的字符串,例如`Europe/London`、`PST`或`GMT+5`
 * @return 一个时间戳,如果`ts`是无法转换为时间戳的字符串,则返回null,或者`tz`是无效的值
 * @group datetime_funcs
 * @since 1.5.0
 */
def to_utc_timestamp(ts: Column, tz: String): Column = withExpr {
  ToUTCTimestamp(ts.expr, Literal(tz))
}

/**
 * 给定一个类似于'2017-07-14 02:40:00.0'的时间戳,在给定时区中解释它,并将该时间作为UTC中的时间戳呈现。
 * 例如,'GMT+1'将产生'2017-07-14 01:40:00.0'。
 * @group datetime_funcs
 * @since 2.4.0
 */
def to_utc_timestamp(ts: Column, tz: Column): Column = withExpr {
  ToUTCTimestamp(ts.expr, tz.expr)
}

/**
 * 将行按照给定时间戳列分桶到一个或多个时间窗口中。窗口的起始时间是包含的,但窗口的结束时间是不包含的,
 * 例如12:05将在窗口[12:05,12:10)中,但不在[12:00,12:05)中。窗口可以支持微秒精度。不支持按月份的窗口。
 *
 * 下面的示例将每10秒开始于整点后5秒的一个一分钟窗口的平均股票价格:
 *
 * {{{
 *   val df = ... // schema => timestamp: TimestampType, stockId: StringType, price: DoubleType
 *   df.groupBy(window($"time", "1 minute", "10 seconds", "5 seconds"), $"stockId")
 *     .agg(mean("price"))
 * }}}
 *
 * 窗口将会如下所示:
 *
 * {{{
 *   09:00:05-09:01:05
 *   09:00:15-09:01:15
 *   09:00:25-09:01:25 ...
 * }}}
 *
 * 对于流式查询,可以使用函数`current_timestamp`在处理时间上生成窗口。
 *
 * @param timeColumn 时间戳列或表达式,用于按时间进行窗口化。时间列必须是TimestampType类型。
 * @param windowDuration 字符串,指定窗口的宽度,例如`10 minutes`、`1 second`。请检查`org.apache.spark.unsafe.types.CalendarInterval`以获取有效的持续时间标识符。注意,持续时间是固定的时间长度,并且不随时间变化(根据日历)而变化。例如,`1 day`始终表示86,400,000毫秒,而不是日历天。
 * @param slideDuration 字符串,指定窗口的滑动间隔,例如`1 minute`。每个`slideDuration`将生成一个新的窗口。必须小于或等于`windowDuration`。请检查`org.apache.spark.unsafe.types.CalendarInterval`以获取有效的持续时间标识符。此持续时间同样是绝对的,并且不随时间变化(根据日历)而变化。
 * @param startTime 与1970-01-01 00:00:00 UTC相对偏移量,用于开始窗口间隔。例如,为了使小时滚动窗口从整点后15分钟开始,例如12:15-13:15、13:15-14:15...提供`startTime`作为`15 minutes`。
 *
 * @group datetime_funcs
 * @since 2.0.0
 */
def window(
    timeColumn: Column,
    windowDuration: String,
    slideDuration: String,
    startTime: String): Column = {
  withExpr {
    TimeWindow(timeColumn.expr, windowDuration, slideDuration, startTime)
  }.as("window")
}
/**
 * 将行按照给定时间戳列分桶到一个或多个时间窗口中。窗口的起始时间是包含的,但窗口的结束时间是不包含的,
 * 例如12:05将在窗口[12:05,12:10)中,但不在[12:00,12:05)中。窗口可以支持微秒精度。不支持按月份的窗口。
 * 窗口的开始时间从1970-01-01 00:00:00 UTC开始。
 * 下面的示例将每10秒生成一个一分钟窗口的平均股票价格:
 *
 * {{{
 *   val df = ... // schema => timestamp: TimestampType, stockId: StringType, price: DoubleType
 *   df.groupBy(window($"time", "1 minute", "10 seconds"), $"stockId")
 *     .agg(mean("price"))
 * }}}
 *
 * 窗口将会如下所示:
 *
 * {{{
 *   09:00:00-09:01:00
 *   09:00:10-09:01:10
 *   09:00:20-09:01:20 ...
 * }}}
 *
 * 对于流式查询,可以使用函数`current_timestamp`根据处理时间生成窗口。
 *
 * @param timeColumn 时间戳列或表达式,用于按时间进行窗口化。时间列必须是TimestampType类型。
 * @param windowDuration 字符串,指定窗口的宽度,例如`10 minutes`、`1 second`。请检查`org.apache.spark.unsafe.types.CalendarInterval`以获取有效的持续时间标识符。注意,持续时间是固定的时间长度,并且不随时间变化(根据日历)而变化。例如,`1 day`始终表示86,400,000毫秒,而不是日历天。
 * @param slideDuration 字符串,指定窗口的滑动间隔,例如`1 minute`。每个`slideDuration`将生成一个新的窗口。必须小于或等于`windowDuration`。请检查`org.apache.spark.unsafe.types.CalendarInterval`以获取有效的持续时间标识符。此持续时间同样是绝对的,并且不随时间变化(根据日历)而变化。
 *
 * @group datetime_funcs
 * @since 2.0.0
 */
def window(timeColumn: Column, windowDuration: String, slideDuration: String): Column = {
  window(timeColumn, windowDuration, slideDuration, "0 second")
}

/**
 * 给定一个时间戳列,生成滚动窗口。窗口的起始时间是包含的,但窗口的结束时间是不包含的,
 * 例如12:05将在窗口[12:05,12:10)中,但不在[12:00,12:05)中。窗口可以支持微秒精度。不支持按月份的窗口。
 * 窗口的开始时间从1970-01-01 00:00:00 UTC开始。
 * 下面的示例将每一分钟生成一个平均股票价格的滚动窗口:
 *
 * {{{
 *   val df = ... // schema => timestamp: TimestampType, stockId: StringType, price: DoubleType
 *   df.groupBy(window($"time", "1 minute"), $"stockId")
 *     .agg(mean("price"))
 * }}}
 *
 * 窗口将会如下所示:
 *
 * {{{
 *   09:00:00-09:01:00
 *   09:01:00-09:02:00
 *   09:02:00-09:03:00 ...
 * }}}
 *
 * 对于流式查询,可以使用函数`current_timestamp`根据处理时间生成窗口。
 *
 * @param timeColumn 时间戳列或表达式,用于按时间进行窗口化。时间列必须是TimestampType类型。
 * @param windowDuration 字符串,指定窗口的宽度,例如`10 minutes`、`1 second`。请检查`org.apache.spark.unsafe.types.CalendarInterval`以获取有效的持续时间标识符。
 *
 * @group datetime_funcs
 * @since 2.0.0
 */
def window(timeColumn: Column, windowDuration: String): Column = {
  window(timeColumn, windowDuration, windowDuration, "0 second")
}

collection_funcs 集合函数

//
// 集合函数
//

/**
 * 如果数组为null,则返回null;如果数组包含`value`,则返回true;否则返回false。
 *
 * @param column 数组列
 * @param value 值
 * @group collection_funcs
 * @since 1.5.0
 */
def array_contains(column: Column, value: Any): Column = withExpr {
  ArrayContains(column.expr, lit(value).expr)
}

/**
 * 如果`a1`和`a2`至少有一个非空元素,则返回`true`。如果两个数组都非空且其中任何一个包含`null`,则返回`null`。否则返回`false`。
 *
 * @param a1 数组列1
 * @param a2 数组列2
 * @group collection_funcs
 * @since 2.4.0
 */
def arrays_overlap(a1: Column, a2: Column): Column = withExpr {
  ArraysOverlap(a1.expr, a2.expr)
}

/**
 * 返回包含`x`从索引`start`开始(如果`start`为负数,则从末尾开始)的指定长度`length`的所有元素的数组。
 *
 * @param x 列
 * @param start 起始位置
 * @param length 长度
 * @group collection_funcs
 * @since 2.4.0
 */
def slice(x: Column, start: Int, length: Int): Column = withExpr {
  Slice(x.expr, Literal(start), Literal(length))
}

/**
 * 使用`delimiter`将`column`的元素连接起来。将null值替换为`nullReplacement`。
 *
 * @param column 列
 * @param delimiter 分隔符
 * @param nullReplacement 空值替换
 * @group collection_funcs
 * @since 2.4.0
 */
def array_join(column: Column, delimiter: String, nullReplacement: String): Column = withExpr {
  ArrayJoin(column.expr, Literal(delimiter), Some(Literal(nullReplacement)))
}

/**
 * 使用`delimiter`将`column`的元素连接起来。
 *
 * @param column 列
 * @param delimiter 分隔符
 * @group collection_funcs
 * @since 2.4.0
 */
def array_join(column: Column, delimiter: String): Column = withExpr {
  ArrayJoin(column.expr, Literal(delimiter), None)
}

/**
 * 将多个输入列连接成一个单独的列。函数适用于字符串、二进制和兼容的数组列。
 *
 * @param exprs 输入列
 * @group collection_funcs
 * @since 1.5.0
 */
@scala.annotation.varargs
def concat(exprs: Column*): Column = withExpr { Concat(exprs.map(_.expr)) }

/**
 * 返回在给定数组中找到的第一个值的位置(作为长整型)。如果任一参数为null,则返回null。
 *
 * 注意:位置不是基于0的索引,而是从1开始的索引。如果在数组中找不到值,则返回0。
 *
 * @param column 数组列
 * @param value 值
 * @group collection_funcs
 * @since 2.4.0
 */
def array_position(column: Column, value: Any): Column = withExpr {
  ArrayPosition(column.expr, lit(value).expr)
}

/**
 * 如果列是数组,则返回数组中给定索引处的元素。如果列是映射,则返回映射中给定键的值。
 *
 * @param column 列
 * @param value 索引或键的值
 * @group collection_funcs
 * @since 2.4.0
 */
def element_at(column: Column, value: Any): Column = withExpr {
  ElementAt(column.expr, lit(value).expr)
}

/**
 * 按升序对输入数组进行排序。输入数组的元素必须是可排序的。将null元素放在返回的数组的末尾。
 *
 * @param e 数组列
 * @group collection_funcs
 * @since 2.4.0
 */
def array_sort(e: Column): Column = withExpr { ArraySort(e.expr) }

/**
 * 从给定数组中删除等于element的所有元素。
 *
 * @param column 数组列
 * @param element 要删除的元素
 * @group collection_funcs
 * @since 2.4.0
 */
def array_remove(column: Column, element: Any): Column = withExpr {
  ArrayRemove(column.expr, lit(element).expr)
}

/**
 * 从数组中删除重复的值。
 *
 * @param e 数组列
 * @group collection_funcs
 * @since 2.4.0
 */
def array_distinct(e: Column): Column = withExpr { ArrayDistinct(e.expr) }

/**
 * 返回两个数组的交集(不包含重复的元素)。
 *
 * @param col1 数组列1
 * @param col2 数组列2
 * @group collection_funcs
 * @since 2.4.0
 */
def array_intersect(col1: Column, col2: Column): Column = withExpr {
  ArrayIntersect(col1.expr, col2.expr)
}

/**
 * 返回两个数组的并集(不包含重复的元素)。
 *
 * @param col1 数组列1
 * @param col2 数组列2
 * @group collection_funcs
 * @since 2.4.0
 */
def array_union(col1: Column, col2: Column): Column = withExpr {
  ArrayUnion(col1.expr, col2.expr)
}

/**
 * 返回第一个数组中但不在第二个数组中的元素(不包含重复的元素)。结果中元素的顺序不确定。
 *
 * @param col1 数组列1
 * @param col2 数组列2
 * @group collection_funcs
 * @since 2.4.0
 */
def array_except(col1: Column, col2: Column): Column = withExpr {
  ArrayExcept(col1.expr, col2.expr)
}

/**
 * 根据给定的数组或映射列,为每个元素创建一个新行。
 *
 * @param e 数组或映射列
 * @group collection_funcs
 * @since 1.3.0
 */
def explode(e: Column): Column = withExpr { Explode(e.expr) }

/**
 * 根据给定的数组或映射列,为每个元素创建一个新行。如果数组或映射为null或空,则返回null。
 *
 * @param e 数组或映射列
 * @group collection_funcs
 * @since 2.2.0
 */
def explode_outer(e: Column): Column = withExpr { GeneratorOuter(Explode(e.expr)) }

/**
 * 根据给定的数组或映射列和元素的位置,为每个元素创建一个新行。
 *
 * @param e 数组或映射列
 * @group collection_funcs
 * @since 2.1.0
 */
def posexplode(e: Column): Column = withExpr { PosExplode(e.expr) }

/**
 * 根据给定的数组或映射列和元素的位置,为每个元素创建一个新行。如果数组或映射为null或空,则返回(null, null)。
 *
 * @param e 数组或映射列
 * @group collection_funcs
 * @since 2.2.0
 */
def posexplode_outer(e: Column): Column = withExpr { GeneratorOuter(PosExplode(e.expr)) }

/**
 * 根据指定的json path从json字符串中提取json对象,并返回提取后的json字符串。
 * 如果输入的json字符串无效,则返回null。
 *
 * @param e json列
 * @param path json path
 * @group collection_funcs
 * @since 1.6.0
 */
def get_json_object(e: Column, path: String): Column = withExpr {
  GetJsonObject(e.expr, lit(path).expr)
}

/**
 * 根据给定字段名称为JSON列创建一个新的行。
 *
 * @param json 包含JSON数据的列
 * @param fields 字段名称
 * @group collection_funcs
 * @since 1.6.0
 */
@scala.annotation.varargs
def json_tuple(json: Column, fields: String*): Column = withExpr {
  require(fields.nonEmpty, "至少需要一个字段名称。")
  JsonTuple(json.expr +: fields.map(Literal.apply))
}

/**
 * (仅适用于Scala)将包含JSON字符串的列解析为具有指定模式的`StructType`。
 * 如果无法解析字符串,则返回null。
 *
 * @param e 包含JSON数据的字符串列
 * @param schema 解析json字符串时使用的模式
 * @param options 控制如何解析json的选项。接受与json数据源相同的选项。
 *
 * @group collection_funcs
 * @since 2.1.0
 */
def from_json(e: Column, schema: StructType, options: Map[String, String]): Column =
  from_json(e, schema.asInstanceOf[DataType], options)

/**
 * (仅适用于Java)将包含JSON字符串的列解析为具有指定模式的`StructType`。
 * 如果无法解析字符串,则返回null。
 *
 * @param e 包含JSON数据的字符串列
 * @param schema 解析json字符串时使用的模式
 * @param options 控制如何解析json的选项。接受与json数据源相同的选项。
 *
 * @group collection_funcs
 * @since 2.1.0
 */
def from_json(e: Column, schema: StructType, options: java.util.Map[String, String]): Column =
  from_json(e, schema, options.asScala.toMap)

/**
 * (仅适用于Scala)将包含JSON字符串的列解析为`MapType`,键类型为`StringType`,
 * 值类型为指定模式的`StructType`或`ArrayType`。
 * 如果无法解析字符串,则返回null。
 *
 * @param e 包含JSON数据的字符串列
 * @param schema 解析json字符串时使用的模式
 * @param options 控制如何解析json的选项。接受与json数据源相同的选项。
 *
 * @group collection_funcs
 * @since 2.2.0
 */
def from_json(e: Column, schema: DataType, options: Map[String, String]): Column = withExpr {
  JsonToStructs(schema, options, e.expr)
}

/**
 * (仅适用于Java)将包含JSON字符串的列解析为`MapType`,键类型为`StringType`,
 * 值类型为指定模式的`StructType`或`ArrayType`。
 * 如果无法解析字符串,则返回null。
 *
 * @param e 包含JSON数据的字符串列
 * @param schema 解析json字符串时使用的模式
 * @param options 控制如何解析json的选项。接受与json数据源相同的选项。
 *
 * @group collection_funcs
 * @since 2.2.0
 */
def from_json(e: Column, schema: DataType, options: java.util.Map[String, String]): Column =
  from_json(e, schema, options.asScala.toMap)

/**
 * 将包含JSON字符串的列解析为具有指定模式的`StructType`。
 * 如果无法解析字符串,则返回null。
 *
 * @param e 包含JSON数据的字符串列
 * @param schema 解析json字符串时使用的模式
 *
 * @group collection_funcs
 * @since 2.1.0
 */
def from_json(e: Column, schema: StructType): Column =
  from_json(e, schema, Map.empty[String, String])

/**
 * (仅适用于Java)将包含JSON字符串的列解析为具有指定模式的`StructType`。
 * 如果无法解析字符串,则返回null。
 *
 * @param e 包含JSON数据的字符串列
 * @param schema 解析json字符串时使用的模式
 *
 * @group collection_funcs
 * @since 2.1.0
 */
def from_json(e: Column, schema: DataType): Column =
  from_json(e, schema, Map.empty[String, String])

/**
 * 将包含JSON字符串的列解析为具有指定模式的`MapType`,键类型为`StringType`,
 * 值类型为指定模式的`StructType`或`ArrayType`。
 * 如果无法解析字符串,则返回null。
 *
 * @param e 包含JSON数据的字符串列
 * @param schema 解析json字符串时使用的模式
 *
 * @group collection_funcs
 * @since 2.4.0
 */
def from_json(e: Column, schema: Column): Column = {
  from_json(e, schema, Map.empty[String, String].asJava)
}

/**
 * 解析JSON字符串并推断其DDL格式的模式。
 *
 * @param json JSON字符串
 *
 * @group collection_funcs
 * @since 2.4.0
 */
def schema_of_json(json: String): Column = schema_of_json(lit(json))

/**
 * 解析JSON字符串并推断其DDL格式的模式。
 *
 * @param json 包含JSON字符串的列
 *
 * @group collection_funcs
 * @since 2.4.0
 */
def schema_of_json(json: Column): Column = withExpr(new SchemaOfJson(json.expr))

/**
 * (仅适用于Scala)将包含`StructType`、`ArrayType`或`MapType`的列转换为具有指定模式的JSON字符串。
 * 在不支持的类型的情况下抛出异常。
 *
 * @param e 包含结构体、数组或映射的列
 * @param options 控制如何将结构列转换为JSON字符串的选项。接受与json数据源相同的选项。
 *
 * @group collection_funcs
 * @since 2.1.0
 */
def to_json(e: Column, options: Map[String, String]): Column = withExpr {
  StructsToJson(options, e.expr)
}

  /**
   * (仅适用于Java)将包含`StructType`、`ArrayType`或`MapType`的列转换为具有指定模式的JSON字符串。
   * 在不支持的类型的情况下抛出异常。
   *
   * @param e 包含结构体、数组或映射的列
   * @param options 控制如何将结构列转换为JSON字符串的选项。接受与json数据源相同的选项。
   *
   * @group collection_funcs
   * @since 2.1.0
   */
  def to_json(e: Column, options: java.util.Map[String, String]): Column =
    to_json(e, options.asScala.toMap)

  /**
   * 将包含`StructType`、`ArrayType`或`MapType`的列转换为具有指定模式的JSON字符串。
   * 在不支持的类型的情况下抛出异常。
   *
   * @param e 包含结构体、数组或映射的列
   *
   * @group collection_funcs
   * @since 2.1.0
   */
  def to_json(e: Column): Column =
    to_json(e, Map.empty[String, String])

  /**
   * 返回数组或映射的长度。
   *
   * @group collection_funcs
   * @since 1.5.0
   */
  def size(e: Column): Column = withExpr { Size(e.expr) }

  /**
   * 按升序对给定列中的数组进行排序,根据数组元素的自然顺序。
   * null元素将放在返回的数组的开头。
   *
   * @group collection_funcs
   * @since 1.5.0
   */
  def sort_array(e: Column): Column = sort_array(e, asc = true)

  /**
   * 根据给定列中的数组按升序或降序排序,根据数组元素的自然顺序。
   * null元素将按升序放在返回的数组的开头,按降序放在末尾。
   *
   * @group collection_funcs
   * @since 1.5.0
   */
  def sort_array(e: Column, asc: Boolean): Column = withExpr { SortArray(e.expr, lit(asc).expr) }

  /**
   * 返回数组中的最小值。
   *
   * @group collection_funcs
   * @since 2.4.0
   */
  def array_min(e: Column): Column = withExpr { ArrayMin(e.expr) }

  /**
   * 返回数组中的最大值。
   *
   * @group collection_funcs
   * @since 2.4.0
   */
  def array_max(e: Column): Column = withExpr { ArrayMax(e.expr) }

  /**
   * 返回给定数组的随机排列。
   *
   * 注意:该函数是非确定性的。
   *
   * @group collection_funcs
   * @since 2.4.0
   */
  def shuffle(e: Column): Column = withExpr { Shuffle(e.expr) }

  /**
   * 返回一个反转的字符串或数组,或者元素顺序相反的数组。
   * @group collection_funcs
   * @since 1.5.0
   */
  def reverse(e: Column): Column = withExpr { Reverse(e.expr) }

  /**
   * 从数组的数组中创建一个单一的数组。如果嵌套数组的结构深度大于两级,则仅删除一级嵌套。
   * @group collection_funcs
   * @since 2.4.0
   */
  def flatten(e: Column): Column = withExpr { Flatten(e.expr) }

  /**
   * 从start到stop生成一个整数序列,步长为step。
   *
   * @group collection_funcs
   * @since 2.4.0
   */
  def sequence(start: Column, stop: Column, step: Column): Column = withExpr {
    new Sequence(start.expr, stop.expr, step.expr)
  }

  /**
   * 从start到stop生成一个整数序列,
   * 如果start小于等于stop,则步长为1;否则为-1。
   *
   * @group collection_funcs
   * @since 2.4.0
   */
  def sequence(start: Column, stop: Column): Column = withExpr {
    new Sequence(start.expr, stop.expr)
  }

  /**
   * 创建一个包含左参数重复右参数次数的数组。
   *
   * @group collection_funcs
   * @since 2.4.0
   */
  def array_repeat(left: Column, right: Column): Column = withExpr {
    ArrayRepeat(left.expr, right.expr)
  }

  /**
   * 创建一个包含左参数重复右参数次数的数组。
   *
   * @group collection_funcs
   * @since 2.4.0
   */
  def array_repeat(e: Column, count: Int): Column = array_repeat(e, lit(count))

  /**
   * 返回包含映射键的无序数组。
   * @group collection_funcs
   * @since 2.3.0
   */
  def map_keys(e: Column): Column = withExpr { MapKeys(e.expr) }

  /**
   * 返回包含映射值的无序数组。
   * @group collection_funcs
   * @since 2.3.0
   */
  def map_values(e: Column): Column = withExpr { MapValues(e.expr) }

  /**
   * 从给定的条目数组创建一个map。
   * @group collection_funcs
   * @since 2.4.0
   */
  def map_from_entries(e: Column): Column = withExpr { MapFromEntries(e.expr) }

  /**
   * 返回合并所有给定映射的结果。
   * @group collection_funcs
   * @since 2.4.0
   */
  def map_concat(cols: Column*): Column = withExpr { MapConcat(cols.map(_.expr)) }

udf函数

  // scalastyle:off line.size.limit
  // scalastyle:off parameter.number

  /* 使用以下代码生成:

  (0 to 10).foreach { x =>
    val types = (1 to x).foldRight("RT")((i, s) => {s"A$i, $s"})
    val typeTags = (1 to x).map(i => s"A$i: TypeTag").foldLeft("RT: TypeTag")(_ + ", " + _)
    val inputSchemas = (1 to x).foldRight("Nil")((i, s) => {s"Try(ScalaReflection.schemaFor(typeTag[A$i])).toOption :: $s"})
    println(s"""
      |/**
      | * 将具有$x个参数的Scala闭包定义为用户定义的函数(UDF)。
      | * 数据类型根据Scala闭包的签名自动推断。默认情况下,返回的UDF是确定性的。
      | * 要将其更改为不确定性,请调用API `UserDefinedFunction.asNondeterministic()`。
      | *
      | * @group udf_funcs
      | * @since 1.3.0
      | */
      |def udf[$typeTags](f: Function$x[$types]): UserDefinedFunction = {
      |  val ScalaReflection.Schema(dataType, nullable) = ScalaReflection.schemaFor[RT]
      |  val inputSchemas = $inputSchemas
      |  val udf = SparkUserDefinedFunction.create(f, dataType, inputSchemas)
      |  if (nullable) udf else udf.asNonNullable()
      |}""".stripMargin)
  }  

# sparkSession.implicits源码

你可能感兴趣的:(spark,spark,大数据,分布式)