代码之家  ›  专栏  ›  技术社区  ›  Georg Heiler

spark filter string column by包含字符串列表之一

  •  0
  • Georg Heiler  · 技术社区  · 7 年前

    我需要实现类似的目标: Checking if values in List is part of String 在火花中。也就是说,有一个数据框架:

    abcd_some long strings
    goo bar baz
    

    以及一系列想要的单词,比如 ["some", "bar"] .

    使用此代码的UDF可以很好地工作,但是,我希望有更有效的方法。有没有办法表达 FILTER my_col CONTAINS ONE OF [items] 使用SQL DSL?也许通过动态构造regex?

    注意:它不是一个exat匹配,而是一个常规的“contains”(包含)/如“%thing%”。也就是说,不完全匹配。否则 isIn 接线员会工作的。

    编辑

    可能动态生成一些SQL代码是最有效的方法。

    def orFilterGeneratorMultiContains(filterPredicates:Seq[String], column:String):Column = {
    
        col(column).contains(filterPredicates(0)) or col(column).contains(filterPredicates(1)) // TODO iterate
      }
      def filterToDesiredApps(filterPredicates:Seq[String], column:String)(df:DataFrame):DataFrame={
          df.filter(orFilterGeneratorMultiContains(filterPredicates, column))
      }
    

    所以仍然需要弄清楚如何正确地迭代表达式。

    编辑2

    然而,这有点棘手:

    import org.apache.spark.sql.functions.col
    
    val column = col("foo")
    val interstingTHings = Seq("bar", "baz", "thing3")
    
    interstingTHings.foldLeft(column) { (filteredOrColumnExpression, predicateItem) =>
      // TODO how to properly nest the OR operator?
      // filteredOrColumnExpression.contains(predicateItem) // generates: Contains(Contains(Contains('foo, bar), baz), thing3)
      filteredOrColumnExpression or filteredOrColumnExpression.contains(predicateItem) // generates: ((('foo || Contains('foo, bar)) || Contains(('foo || Contains('foo, bar)), baz)) || Contains((('foo || Contains('foo, bar)) || Contains(('foo || Contains('foo, bar)), baz)), thing3)) 
      //     TODO but what y really would need is:
      //      col(column).contains("bar") or col(column).contains("baz") or col(column).contains("thing3")
    }.explain(true)
    

    因为它不能产生正确的 OR 嵌套的筛选条件。

    1 回复  |  直到 7 年前
        1
  •  1
  •   Bi Rico    7 年前

    你的想法是对的,但我认为你想用 || or . 类似:

    def orFilterGeneratorMultiContains(filterPredicates:Seq[String], column:String): Column = {
      val coi = col(column)
      filterPredicates.map(coi.contains).reduce(_ || _)
    }
    
    推荐文章