【问题标题】:Spark SQL case sensitive filter on pattern for column列模式上的 Spark SQL 区分大小写过滤器
【发布时间】:2019-02-24 03:47:41
【问题描述】:

如何使用 spark sql 过滤器作为模式的列基础上区分大小写的过滤器。

例如,我有一个模式:

'啊啊啊'

我的专栏有这样的数据:

adaz
LssA ss 
Leds ST 
Pear QA 
Lear QA

关于字母大小写,我想检索具有“Aaaa AA”模式的行。这意味着所需的行将是“Leds ST”、“Pear QA”、“Lear QA”。

"Aaaa AA" => 'Leds ST' , 'Pear QA', 'Lear QA'
"AaaA aa" => 'LssA ss'
"aaaa" => 'adaz'

如何使用 spark sql 获得此结果? 或者我们可以为此结果编写任何正则表达式 sql 查询吗?

【问题讨论】:

  • 动态模式匹配,有趣。模式也暗示了长度?

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


【解决方案1】:

我们可以使用 Spark SQL 函数 translate() 为您的字符串创建分组列。

使用 PySpark:

用于测试的示例数据框

from pyspark.sql.types import StringType

df = spark.createDataFrame(["adaz", "LssA ss", "Leds ST", "Pear QA","Lear QA"], StringType())

实际转型

from pyspark.sql.functions import translate, collect_list, col
import string

lowercases = string.ascii_lowercase
uppercases = string.ascii_uppercase
length_alphabet = len(uppercases)

ones = "1" * length_alphabet
zeroes = "0" * length_alphabet

old = uppercases + lowercases
new = ones + zeroes

df.withColumn("group", translate(df.value, old, new)) \
  .groupBy(col("group")).agg(collect_list(df.value).alias("strings")) \
  .show(truncate = False)

结果:

+-------+---------------------------+
|group  |strings                    |
+-------+---------------------------+
|1000 11|[Leds ST, Pear QA, Lear QA]|
|0000   |[adaz]                     |
|1001 00|[LssA ss]                  |
+-------+---------------------------+

使用 Scala Spark:

import org.apache.spark.sql.functions.{translate, col, collect_list}

val lower = 'a' to 'z'
val upper = 'A' to 'Z'
val length_alphabet = upper.size

val lowercases = lower.mkString("")
val uppercases = upper.mkString("")

val ones = "1" * length_alphabet
val zeroes = "0" * length_alphabet

val old = uppercases + lowercases
val news = ones + zeroes

df.withColumn("group", translate($"value", old, news)) 
  .groupBy(col("group")).agg(collect_list($"value").alias("strings")) 
  .show(truncate = false)

【讨论】:

    【解决方案2】:

    使用“regexp_extract”:

    val df=List(
    "adaz",
    "LssA ss",
      "Leds ST",
      "Pear QA",
      "Lear QA"
    ).toDF("value")
    df.filter(regexp_extract($"value","^[A-Z][a-z]{3} [A-Z]{2}$",0)=!=lit("")).show(false)
    

    输出:

    +-------+
    |value  |
    +-------+
    |Leds ST|
    |Pear QA|
    |Lear QA|
    +-------+
    

    【讨论】:

    • 此解决方案可能会部分解决问题。
    【解决方案3】:

    我正在扩展 @pasha701。

    scala> val df=List(
         | "adaz",
         | "LssA ss",
         |   "Leds ST",
         |   "Pear QA",
         |   "Lear QA"
         | ).toDF("value")
    df: org.apache.spark.sql.DataFrame = [value: string]
    
    scala> val df2= df.withColumn("reg1", regexp_extract($"value","^[A-Z][a-z]{3} [A-Z]{2}$",0)=!=lit("")).withColumn("reg2",regexp_extract($"value","^[a-z]{4}$",0)=!=lit("")).withColumn("reg3", regexp_extract($"value","^[A-Z][a-z]{2}[A-Z] [a-z]{2}$",0)=!=lit(""))
    df2: org.apache.spark.sql.DataFrame = [value: string, reg1: boolean ... 2 more fields]
    
    scala> val df3=df2.withColumn("reg_patt", when('reg1,"1000 11").when('reg2,"0000").when('reg3,"1001 00").otherwise("9"))
    df3: org.apache.spark.sql.DataFrame = [value: string, reg1: boolean ... 3 more fields]
    
    scala> df3.groupBy("reg_patt").agg(collect_list('value) as "newval").show(false)
    +--------+---------------------------+
    |reg_patt|newval                     |
    +--------+---------------------------+
    |1000 11 |[Leds ST, Pear QA, Lear QA]|
    |0000    |[adaz]                     |
    |1001 00 |[LssA ss]                  |
    +--------+---------------------------+
    
    
    scala>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-03-15
      • 2013-08-07
      • 1970-01-01
      • 2023-04-01
      • 1970-01-01
      • 2018-07-10
      • 2017-12-10
      相关资源
      最近更新 更多