Spark - 使用正则表达式从字母数字字符串中提取数值
Spark - extracting numeric values from an alphanumeric string using regex
我有一个名为 "Result" 的字母数字列,我想将其解析为 4 个不同的列:前缀、后缀、值和 pure_text。
我想使用 Spark SQL 使用 RLIKE 和 REGEX 解决这个问题,但也想 PySpark/Scala
pure_text:仅包含字母(或)如果存在数字,则它们应具有特殊字符“-”或多个小数(即 9.9 .0) 或数字后跟字母,然后再是数字(即 3x4u)
prefix:任何不能归类到"pure_text"的都会被考虑。需要提取第一个数字 [0-9] 之前的任何字符。
后缀: 任何不能归类到"pure_text"的都会被考虑。需要提取最后一位 [0-9] 之后的任何字符。
值:任何不能归类到"pure_text"的都会被考虑。提取所有数值,包括小数点。
Result
11 H
111L
<.004
>= 0.78
val<=0.6
xyz 100 abc
1-9
aaa 100.3.4
a1q1
预期输出:
Result Prefix Suffix Value Pure_Text
11 H H 11
111L L 111
.9 0.9
<.004 < 0.004
>= 0.78 >= 0.78
val<=0.6 val<= 0.6
xyz 100 abc xyz abc 100
1-9 1-9
aaa 100.3.4 aaa 100.3.4
a1q1 a1q1
这是一种使用 UDF 的方法,它应用模式匹配将字符串内容提取到一个案例中 class。模式匹配以数字 value
为中心,正则表达式模式 [+-]?(?:\d*\.)?\d+
提取第一次出现的数字,如“1.23”、“.99”、“-100”等。随后检查数字suffix
中捕获的剩余子串判断原字符串中的数字子串是否合法
import org.apache.spark.sql.functions._
import spark.implicits._
case class RegexRes(prefix: String, suffix: String, value: Option[Double], pure_text: String)
val regexExtract = udf{ (s: String) =>
val pattern = """(.*?)([+-]?(?:\d*\.)?\d+)(.*)""".r
s match {
case pattern(pfx, num, sfx) =>
if (sfx.exists(_.isDigit))
RegexRes("", "", None, s)
else
RegexRes(pfx, sfx, Some(num.toDouble), "")
case _ =>
RegexRes("", "", None, s)
}
}
val df = Seq(
"11 H", "111L", ".9", "<.004", ">= 0.78", "val<=0.6", "xyz 100 abc", "1-9", "aaa 100.3.4", "a1q1"
).toDF("result")
df.
withColumn("regex_res", regexExtract($"result")).
select($"result", $"regex_res.prefix", $"regex_res.suffix", $"regex_res.value", $"regex_res.pure_text").
show
// +-----------+------+------+-----+-----------+
// | result|prefix|suffix|value| pure_text|
// +-----------+------+------+-----+-----------+
// | 11 H| | H| 11.0| |
// | 111L| | L|111.0| |
// | .9| | | 0.9| |
// | <.004| <| |0.004| |
// | >= 0.78| >= | | 0.78| |
// | val<=0.6| val<=| | 0.6| |
// |xyz 100 abc| xyz | abc|100.0| |
// | 1-9| | | null| 1-9|
// |aaa 100.3.4| | | null|aaa 100.3.4|
// | a1q1| | | null| a1q1|
// +-----------+------+------+-----+-----------+
我有一个名为 "Result" 的字母数字列,我想将其解析为 4 个不同的列:前缀、后缀、值和 pure_text。
我想使用 Spark SQL 使用 RLIKE 和 REGEX 解决这个问题,但也想 PySpark/Scala
pure_text:仅包含字母(或)如果存在数字,则它们应具有特殊字符“-”或多个小数(即 9.9 .0) 或数字后跟字母,然后再是数字(即 3x4u)
prefix:任何不能归类到"pure_text"的都会被考虑。需要提取第一个数字 [0-9] 之前的任何字符。
后缀: 任何不能归类到"pure_text"的都会被考虑。需要提取最后一位 [0-9] 之后的任何字符。
值:任何不能归类到"pure_text"的都会被考虑。提取所有数值,包括小数点。
Result
11 H
111L
<.004
>= 0.78
val<=0.6
xyz 100 abc
1-9
aaa 100.3.4
a1q1
预期输出:
Result Prefix Suffix Value Pure_Text
11 H H 11
111L L 111
.9 0.9
<.004 < 0.004
>= 0.78 >= 0.78
val<=0.6 val<= 0.6
xyz 100 abc xyz abc 100
1-9 1-9
aaa 100.3.4 aaa 100.3.4
a1q1 a1q1
这是一种使用 UDF 的方法,它应用模式匹配将字符串内容提取到一个案例中 class。模式匹配以数字 value
为中心,正则表达式模式 [+-]?(?:\d*\.)?\d+
提取第一次出现的数字,如“1.23”、“.99”、“-100”等。随后检查数字suffix
中捕获的剩余子串判断原字符串中的数字子串是否合法
import org.apache.spark.sql.functions._
import spark.implicits._
case class RegexRes(prefix: String, suffix: String, value: Option[Double], pure_text: String)
val regexExtract = udf{ (s: String) =>
val pattern = """(.*?)([+-]?(?:\d*\.)?\d+)(.*)""".r
s match {
case pattern(pfx, num, sfx) =>
if (sfx.exists(_.isDigit))
RegexRes("", "", None, s)
else
RegexRes(pfx, sfx, Some(num.toDouble), "")
case _ =>
RegexRes("", "", None, s)
}
}
val df = Seq(
"11 H", "111L", ".9", "<.004", ">= 0.78", "val<=0.6", "xyz 100 abc", "1-9", "aaa 100.3.4", "a1q1"
).toDF("result")
df.
withColumn("regex_res", regexExtract($"result")).
select($"result", $"regex_res.prefix", $"regex_res.suffix", $"regex_res.value", $"regex_res.pure_text").
show
// +-----------+------+------+-----+-----------+
// | result|prefix|suffix|value| pure_text|
// +-----------+------+------+-----+-----------+
// | 11 H| | H| 11.0| |
// | 111L| | L|111.0| |
// | .9| | | 0.9| |
// | <.004| <| |0.004| |
// | >= 0.78| >= | | 0.78| |
// | val<=0.6| val<=| | 0.6| |
// |xyz 100 abc| xyz | abc|100.0| |
// | 1-9| | | null| 1-9|
// |aaa 100.3.4| | | null|aaa 100.3.4|
// | a1q1| | | null| a1q1|
// +-----------+------+------+-----+-----------+