【问题标题】:Spark SQL - Check for a value in multiple columnsSpark SQL - 检查多列中的值
【发布时间】:2020-08-28 14:20:26
【问题描述】:

我有一个 status 数据集,如下所示:

我想从该数据集中选择在这 5 个状态列中的任何一个中具有“FAILURE”的所有行。

因此,我希望结果仅包含 ID 1、2、4,因为它们在其中一个状态列中有 FAILURE。

我想在 SQL 中我们可以做如下的事情:

SELECT * FROM status WHERE "FAILURE" IN (Status1, Status2, Status3, Status4, Status5);

在 spark 中,我知道我可以通过将每个状态列与“FAILURE”进行比较来进行过滤

status.filter(s => {s.Status1.equals(FAILURE) || s.Status2.equals(FAILURE) ... and so on..})

但我想知道在 Spark SQL 中是否有更聪明的方法。

提前致谢!

【问题讨论】:

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


【解决方案1】:

如果要检查的列很多,请考虑在第一次匹配时短路的递归函数,如下所示:

val df = Seq(
  (1, "T", "F", "T", "F"),
  (2, "T", "T", "T", "T"),
  (3, "T", "T", "F", "T")
).toDF("id", "c1", "c2", "c3", "c4")

import org.apache.spark.sql.Column

def checkFor(elem: Column, cols: List[Column]): Column = cols match {
  case Nil =>
    lit(true)
  case h :: tail =>
    when(h === elem, lit(false)).otherwise(checkFor(elem, tail))
}

val cols = df.columns.filter(_.startsWith("c")).map(col).toList

df.where(checkFor(lit("F"), cols)).show

// +---+---+---+---+---+
// | id| c1| c2| c3| c4|
// +---+---+---+---+---+
// |  2|  T|  T|  T|  T|
// +---+---+---+---+---+

【讨论】:

  • 懒人存在不也是短路吗?
  • 相当肯定 Scala 的 exists 实现将在遍历集合时利用短路(尽管我有点不愿意使用 asInstanceOf[A])。
【解决方案2】:

您可以修改和过滤添加的新列的类似示例。我把它留给你,在这里检查除第一列之外的零:

import org.apache.spark.sql.functions._
import spark.implicits._

val df = sc.parallelize(Seq(
    ("r1", 0.0, 0.0, 0.0, 0.0),
    ("r2", 6.4, 4.9, 6.3, 7.1),
    ("r3", 4.2, 0.0, 7.2, 8.4),
    ("r4", 1.0, 2.0, 0.0, 0.0)
)).toDF("ID", "a", "b", "c", "d")

val count_some_val = df.columns.tail.map(x => when(col(x) === 0.0, 1).otherwise(0)).reduce(_ + _)     

val df2 = df.withColumn("some_val_count", count_some_val)
df2.filter(col("some_val_count") > 0).show(false)

当第一场比赛很容易找到时,Afaik 不可能停下来,但我确实记得有一个比我自己更聪明的人向我展示了这种 lazy exists 的方法,我认为它确实会停下来比赛的第一次相遇。像这样,但我喜欢不同的方法:

import org.apache.spark.sql.functions._
import spark.implicits._

val df = sc.parallelize(Seq(
    ("r1", 0.0, 0.0, 0.0, 0.0),
    ("r2", 6.0, 4.9, 6.3, 7.1),
    ("r3", 4.2, 0.0, 7.2, 8.4),
    ("r4", 1.0, 2.0, 0.0, 0.0)
)).toDF("ID", "a", "b", "c", "d")

df.map{r => (r.getString(0),r.toSeq.tail.exists(c => 
             c.asInstanceOf[Double]==0))}
  .toDF("ID","ones")
  .show() 

【讨论】:

    【解决方案3】:
            scala> import org.apache.spark.sql.functions._
            import org.apache.spark.sql.functions._
    
            scala> import spark.implicits._
            import spark.implicits._
    
            scala> val df = Seq(
                 |     ("Prop1", "SUCCESS", "SUCCESS", "SUCCESS", "FAILURE" ,"SUCCESS"),
                 |     ("Prop2", "SUCCESS", "FAILURE", "SUCCESS", "FAILURE", "SUCCESS"),
                 |     ("Prop3", "SUCCESS", "SUCCESS", "SUCCESS", "SUCCESS", "SUCCESS" ),
                 |     ("Prop4", "SUCCESS", "FAILURE", "SUCCESS", "FAILURE", "SUCCESS"),
                 |     ("Prop5", "SUCCESS", "SUCCESS", "SUCCESS", "SUCCESS","SUCCESS")
                 |    ).toDF("Name", "Status1", "Status2", "Status3", "Status4","Status5")
            df: org.apache.spark.sql.DataFrame = [Name: string, Status1: string ... 4 more fields]
    
    
            scala> df.show
            +-----+-------+-------+-------+-------+-------+
            | Name|Status1|Status2|Status3|Status4|Status5|
            +-----+-------+-------+-------+-------+-------+
            |Prop1|SUCCESS|SUCCESS|SUCCESS|FAILURE|SUCCESS|
            |Prop2|SUCCESS|FAILURE|SUCCESS|FAILURE|SUCCESS|
            |Prop3|SUCCESS|SUCCESS|SUCCESS|SUCCESS|SUCCESS|
            |Prop4|SUCCESS|FAILURE|SUCCESS|FAILURE|SUCCESS|
            |Prop5|SUCCESS|SUCCESS|SUCCESS|SUCCESS|SUCCESS|
            +-----+-------+-------+-------+-------+-------+
    
    
            scala> df.where($"Name".isin("Prop1","Prop4") and $"Status1".isin("SUCCESS","FAILURE")).show
            +-----+-------+-------+-------+-------+-------+
            | Name|Status1|Status2|Status3|Status4|Status5|
            +-----+-------+-------+-------+-------+-------+
            |Prop1|SUCCESS|SUCCESS|SUCCESS|FAILURE|SUCCESS|
            |Prop4|SUCCESS|FAILURE|SUCCESS|FAILURE|SUCCESS|
            +-----+-------+-------+-------+-------+-------+
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-04-09
      • 1970-01-01
      • 2016-10-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多