Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
向数据帧添加新列时出现问题-spark/scala_Scala_Apache Spark_Dataframe_Apache Spark Sql_User Defined Functions - Fatal编程技术网

向数据帧添加新列时出现问题-spark/scala

向数据帧添加新列时出现问题-spark/scala,scala,apache-spark,dataframe,apache-spark-sql,user-defined-functions,Scala,Apache Spark,Dataframe,Apache Spark Sql,User Defined Functions,我是spark/scala的新手。我正在尝试将配置单元表中的一些数据读取到spark数据帧,然后根据某些条件添加一列。这是我的密码: val DF = hiveContext.sql("select * from (select * from test_table where partition_date='2017-11-22') a JOIN (select max(id) as bid from test_table where partition_date='2017-11-22' gr

我是spark/scala的新手。我正在尝试将配置单元表中的一些数据读取到spark数据帧,然后根据某些条件添加一列。这是我的密码:

val DF = hiveContext.sql("select * from (select * from test_table where partition_date='2017-11-22') a JOIN (select max(id) as bid from test_table where partition_date='2017-11-22' group by at_id) b ON a.id=b.bid")

def dateDiff(partition_date: org.apache.spark.sql.Column, item_due_date: org.apache.spark.sql.Column): Long ={
      ChronoUnit.DAYS.between(LocalDate.parse(partition_date.toString()), LocalDate.parse(item_due_date.toString))
    }

val finalDF = DF.withColumn("status", 
                   when(col("past_due").equalTo(1) && !(col("item_due_date").equalTo(null) || col("item_due_date").equalTo("NULL") || col("item_due_date").equalTo("null")) && (dateDiff(col("partition_date"),col("item_due_date")) < 0) && !(col("item_decision").equalTo(null) || col("item_decision").equalTo("NULL") || col("item_decision").equalTo("null")), "approved")
                  .when(col("past_due").equalTo(1) && !(col("item_due_date").equalTo(null) || col("item_due_date").equalTo("NULL") || col("item_due_date").equalTo("null")) && (dateDiff(col("partition_date"),col("item_due_date")) < 0) && (col("item_decision").equalTo(null) || col("item_decision").equalTo("NULL") || col("item_decision").equalTo("null")), "pending")
                  .when(col("past_due").equalTo(1) && !(col("item_due_date").equalTo(null) || col("item_due_date").equalTo("NULL") || col("item_due_date").equalTo("null")) && (dateDiff(col("partition_date"),col("item_due_date")) >= 0), "expired")
                  .otherwise("null"))
我使用的列的数据示例来自
DF

 |-- item_due_date: string (nullable = true)
 |-- past_due: integer (nullable = true)
 |-- item_decision: string (nullable = true)
 |-- partition_date: string (nullable = true)
+--------+-------------+-------------+--------------+
|past_due|item_due_date|item_decision|partition_date|
+--------+-------------+-------------+--------------+
|       1|   0001-01-14|         null|    2017-11-22|
|       1|   0001-01-14|     Mitigate|    2017-11-22|
|       1|   0001-01-14|     Mitigate|    2017-11-22|
|       1|   0001-01-14|     Mitigate|    2017-11-22|
|       0|   2018-03-18|         null|    2017-11-22|
|       1|   2016-11-30|         null|    2017-11-22|
+--------+-------------+-------------+--------------+
我还尝试使用自定义自定义自定义项:

  def status(past_due: Int, item_decision: String, maxPartitionDate: String, item_due_date: String): String = {
      if (past_due == 1 && item_due_date != "NULL") {
        if (ChronoUnit.DAYS.between(LocalDate.parse(maxPartitionDate.trim), LocalDate.parse(item_due_date.trim)) < 0) {
          if (item_decision != "NULL") "pending"
          else "approved"
        } else "expired"
      } else "NULL"
    }

val statusUDF = sqlContext.udf.register("statusUDF", status _)

val DF2 = DF.withColumn("status", statusUDF(DF("past_due"),DF("item_decision"),DF("partition_date"),DF("item_due_date")))
DF2.show()

任何帮助都将不胜感激。谢谢大家!

您只需使用
datediff
内置函数检查两列之间的天数差异。您不需要编写函数或
udf
函数。当函数也被修改时

import org.apache.spark.sql.functions._
val finalDF = DF.withColumn("status",
  when(col("past_due").equalTo(1) && col("item_due_date").isNotNull && !(lower(col("item_due_date")).equalTo("null")) && (datediff(col("partition_date"),col("item_due_date")) < 0) && col("item_decision").isNotNull && !(lower(col("item_decision")).equalTo("null")), "approved")
    .otherwise(when(col("past_due").equalTo(1) && col("item_due_date").isNotNull && !(lower(col("item_due_date")).equalTo("null")) && (datediff(col("partition_date"),col("item_due_date")) < 0) && (col("item_decision").isNull || lower(col("item_decision")).equalTo("null")), "pending")
      .otherwise(when(col("past_due").equalTo(1) && col("item_due_date").isNotNull && !(lower(col("item_due_date")).equalTo("null")) && (datediff(col("partition_date"),col("item_due_date")) >= 0), "expired")
    .otherwise("null"))))
添加
状态
列作为

+--------+-------------+-------------+--------------+--------+
|past_due|item_due_date|item_decision|partition_date|status  |
+--------+-------------+-------------+--------------+--------+
|1       |2017-12-14   |null         |2017-11-22    |pending |
|1       |2017-12-14   |Mitigate     |2017-11-22    |approved|
|1       |0001-01-14   |Mitigate     |2017-11-22    |expired |
|1       |0001-01-14   |Mitigate     |2017-11-22    |expired |
|0       |2018-03-18   |null         |2017-11-22    |null    |
|1       |2016-11-30   |null         |2017-11-22    |expired |
+--------+-------------+-------------+--------------+--------+

我希望答案是有帮助的

您可以简单地使用
datediff
内置函数来检查两列之间的天数差异。您不需要编写函数或
udf
函数。当函数也被修改时

import org.apache.spark.sql.functions._
val finalDF = DF.withColumn("status",
  when(col("past_due").equalTo(1) && col("item_due_date").isNotNull && !(lower(col("item_due_date")).equalTo("null")) && (datediff(col("partition_date"),col("item_due_date")) < 0) && col("item_decision").isNotNull && !(lower(col("item_decision")).equalTo("null")), "approved")
    .otherwise(when(col("past_due").equalTo(1) && col("item_due_date").isNotNull && !(lower(col("item_due_date")).equalTo("null")) && (datediff(col("partition_date"),col("item_due_date")) < 0) && (col("item_decision").isNull || lower(col("item_decision")).equalTo("null")), "pending")
      .otherwise(when(col("past_due").equalTo(1) && col("item_due_date").isNotNull && !(lower(col("item_due_date")).equalTo("null")) && (datediff(col("partition_date"),col("item_due_date")) >= 0), "expired")
    .otherwise("null"))))
添加
状态
列作为

+--------+-------------+-------------+--------------+--------+
|past_due|item_due_date|item_decision|partition_date|status  |
+--------+-------------+-------------+--------------+--------+
|1       |2017-12-14   |null         |2017-11-22    |pending |
|1       |2017-12-14   |Mitigate     |2017-11-22    |approved|
|1       |0001-01-14   |Mitigate     |2017-11-22    |expired |
|1       |0001-01-14   |Mitigate     |2017-11-22    |expired |
|0       |2018-03-18   |null         |2017-11-22    |null    |
|1       |2016-11-30   |null         |2017-11-22    |expired |
+--------+-------------+-------------+--------------+--------+


我希望答案有帮助

您的函数是基于列的。因此,如果任何函数满足您的需求,您都可以使用它。否则,如果要在基本数据类型中进行操作,则必须使用udf函数。我尝试在和时使用udf而不是
,否则
,但在显示/保存数据帧时遇到错误。所以我转向了这种方法。有什么方法可以解决这种方法中的错误吗?您必须使用示例数据帧和数据帧的模式更新您的问题。这将帮助你得到答案quickly@Hemanth您编写的函数不是
udf
,您应该仔细阅读如何编写适当的
udf
。我知道它不是
udf
。这是一个普通的scala函数,用于获取日期差异@提示如何使其工作的想法?您的函数是基于列的。因此,如果任何函数满足您的需求,您都可以使用它。否则,如果要在基本数据类型中进行操作,则必须使用udf函数。我尝试在和时使用udf而不是
,否则
,但在显示/保存数据帧时遇到错误。所以我转向了这种方法。有什么方法可以解决这种方法中的错误吗?您必须使用示例数据帧和数据帧的模式更新您的问题。这将帮助你得到答案quickly@Hemanth您编写的函数不是
udf
,您应该仔细阅读如何编写适当的
udf
。我知道它不是
udf
。这是一个普通的scala函数,用于获取日期差异@你有什么办法让它发挥作用吗?你是救世主!非常感谢!:)程序运行时没有任何问题,但我在
状态
列中只看到
过期
值。逻辑上有问题吗?你的约会应该是这样的。请核对日期。:)似乎是这样。还有,我的“何时”状态也应该很好,对吧?我想知道是否有任何不同。不,当你的逻辑也有一些缺陷。我的意思是你写它的方式,因为一切都在状态栏中生成null。你可以自己试试看。调试和改进。我想你能做到你是救世主!非常感谢!:)程序运行时没有任何问题,但我在
状态
列中只看到
过期
值。逻辑上有问题吗?你的约会应该是这样的。请核对日期。:)似乎是这样。还有,我的“何时”状态也应该很好,对吧?我想知道是否有任何不同。不,当你的逻辑也有一些缺陷。我的意思是你写它的方式,因为一切都在状态栏中生成null。你可以自己试试看。调试和改进。我想你能做到