spark: scala - регулярное выражение в качестве аргумента для udf - PullRequest
0 голосов
/ 31 октября 2018

Я пытаюсь проверить столбец фрейма данных scala по регулярному выражению, используя udf с дополнительным аргументом, представляющим фактическое регулярное выражение. Однако помещение регулярного выражения в оператор 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 голосов
/ 31 октября 2018

Вы можете предоставить свой параметр, отличный от столбца (то есть значение dateEx), через каррирование в UDF, как показано ниже:

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|
// +---+-----------+-----+

Однако для того, что вам нужно, вместо UDF я бы порекомендовал использовать встроенные функции Spark, которые обычно работают лучше. Ниже приведен один подход с использованием 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
0 голосов
/ 31 октября 2018

Я до сих пор не достиг, чтобы пройти через регулярное выражение. Моя работа теперь состоит в том, чтобы пройти через строку и выполнить компиляцию внутри функции. Следующим образом:

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()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...