spark:scala-正则表达式作为udf的参数

时间:2018-10-31 16:59:28

标签: regex scala apache-spark dataframe user-defined-functions

我正在尝试使用udf和一个表示实际正则表达式的附加参数来对照正则表达式检查scala数据帧的一列。 但是,似乎不允许将正则表达式放入lit()语句中引发以下错误

  

java.lang.RuntimeException:不支持的文字类型类   scala.util.matching.Regex

使用下面的示例代码。我希望带有布尔条目的附加列“ DMY”。

import org.apache.spark.sql.SparkSession
import org.apache.spark.sql.functions._
import scala.util.matching._


def dateDMY_regex(): Regex = """^[0-3]?[0-9][-/.][0-1]?[0-9][-/.](19|20)?\d{2}$""".r

def date_match(value: String, dateEx: Regex): Boolean = {
  return dateEx.unapplySeq(value).isDefined
}

val spark = SparkSession.builder().getOrCreate()

var df = spark.createDataFrame(Seq(
  (0, "31/10/2018"),
  (1, "01/11/2018"),
  (2, "02/11/2018"))).toDF("Id", "col_1")

// to test the function
// print(date_match("31/10/2018", dateDMY_regex()))

val date_match_udf = udf(date_match _)   //, lit("c")
df = df.withColumn( "DMY", date_match_udf( $"col_1", lit(dateDMY_regex()) ) )

df.show()

2 个答案:

答案 0 :(得分:1)

您可以通过在UDF中进行计数来提供非列参数(即dateEx的值),如下所示:

import org.apache.spark.sql.functions._
import scala.util.matching._

val df = spark.createDataFrame(Seq(
  (0, "31/10/2018"),
  (1, "999/11/2018"),
  (2, "02/11/2018"))
).toDF("Id", "col_1")

val dateEx = """^[0-3]?[0-9][-/.][0-1]?[0-9][-/.](19|20)?\d{2}$""".r

def date_match_udf(dateEx: Regex) = udf(
  (value: String) => dateEx.unapplySeq(value).isDefined
)

df.withColumn("DMY", date_match_udf(dateEx)($"col_1")).
  show
// +---+-----------+-----+
// | Id|      col_1|  DMY|
// +---+-----------+-----+
// |  0| 31/10/2018| true|
// |  1|999/11/2018|false|
// |  2| 02/11/2018| true|
// +---+-----------+-----+

但是,为满足您的需求,我建议您使用通常性能更好的Spark内置函数而不是UDF。以下是使用regexp_extract的一种方法:

val dateExStr = """^([0-3]?[0-9][-/.][0-1]?[0-9][-/.](19|20)?\d{2})$"""

df.withColumn("DMY", $"col_1" === regexp_extract($"col_1", dateExStr, 1)).
  show

答案 1 :(得分:0)

我仍然无法通过正则表达式。现在,我的解决方法是通过字符串并在函数中进行编译。如下:

import org.apache.spark.sql.SparkSession
import org.apache.spark.sql.functions._
import scala.util.matching._


def dateDMY_regex(): String = """^[0-3]?[0-9][-/.][0-1]?[0-9][-/.](19|20)?\d{2}$"""

def date_match(value: String, dateEx: String): Boolean = {
  return dateEx.r.unapplySeq(value).isDefined
}

val spark = SparkSession.builder().getOrCreate()

var df = spark.createDataFrame(Seq(
  (0, "31/10/2018"),
  (1, "01/11/2018"),
  (2, "02/11/2018"))).toDF("Id", "col_1")

// to test the function
// print(date_match("31/10/2018", dateDMY_regex()))

val date_match_udf = udf(date_match _)   //, lit("c")
df = df.withColumn( "DMY", date_match_udf( $"col_1", lit(dateDMY_regex()) ) )

df.show()
相关问题