如何添加天数(作为列的值)到目前为止?

时间:2018-04-12 15:15:25

标签: scala apache-spark apache-spark-sql

我在Spark中将日期(数字)添加到日期格式列时遇到问题。我知道有一个函数date_add带有两个参数 - 日期列和整数:

date_add(date startdate, tinyint/smallint/int days)

我想使用整数类型的列值(不是整数本身)。

说我有以下数据框:

val data = Seq(
    (0, "2016-01-1"),
    (1, "2016-02-2"),
    (2, "2016-03-22"),
    (3, "2016-04-25"),
    (4, "2016-05-21"),
    (5, "2016-06-1"),
    (6, "2016-03-21"))
).toDF("id", "date")

我可以简单地将整数添加到日期:

val date_add_fun = 
data.select(
    $"id",
    $"date",
    date_add($"date", 1)
)

但是我不能使用包含值的列表达式:

val date_add_fun = 
data.select(
    $"id",
    $"date",
    date_add($"date", $"id")
)

它给出错误:

<console>:60: error: type mismatch;
 found   : org.apache.spark.sql.ColumnName
 required: Int
           date_add($"date", $"id")

有谁知道是否可以使用列是date_add函数?或者解决方法是什么?

4 个答案:

答案 0 :(得分:6)

您可以使用expr

import org.apache.spark.sql.functions.expr

data.withColumn("future", expr("date_add(date, id)")).show
// +---+----------+----------+
// | id|      date|    future|
// +---+----------+----------+
// |  0| 2016-01-1|2016-01-01|
// |  1| 2016-02-2|2016-02-03|
// |  2|2016-03-22|2016-03-24|
// |  3|2016-04-25|2016-04-28|
// |  4|2016-05-21|2016-05-25|
// |  5| 2016-06-1|2016-06-06|
// |  6|2016-03-21|2016-03-27|
// +---+----------+----------+

selectExpr可以以类似的方式使用:

data.selectExpr("*", "date_add(date, id) as future").show

答案 1 :(得分:1)

您可以将sql表达式用作

data.createOrReplaceTempView("table")
sqlContext.sql("select id, date, date_add(`date`, `id`) as added_date from table").show(false)

会给你

+---+----------+----------+
|id |date      |added_date|
+---+----------+----------+
|0  |2016-01-1 |2016-01-01|
|1  |2016-02-2 |2016-02-03|
|2  |2016-03-22|2016-03-24|
|3  |2016-04-25|2016-04-28|
|4  |2016-05-21|2016-05-25|
|5  |2016-06-1 |2016-06-06|
|6  |2016-03-21|2016-03-27|
+---+----------+----------+

答案 2 :(得分:0)

其他答案有效,但不能代替现有的date_add函数。  我遇到了expr对我不起作用的情况,因此这是一个替代品:

def date_add(date: Column, days: Column) = {
    new Column(DateAdd(date.expr, days.expr))
}

基本上,Spark中已经存在所有机制来执行此操作,date_add的函数签名只是强制将其作为文字。

答案 3 :(得分:0)

对于这里的 Python 开发人员,您可以简单地使用 + 将一个数据列添加到另一个列中:

import pyspark.sql.functions as F

new_df = df.withColumn("new_date", F.col("date") + F.col("offset"))

请确保偏移列是 int/smallint/tinyint。