dataframe:如何groupBy / count然后过滤Scala中的count

时间:2015-08-20 13:42:39

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

Spark 1.4.1

我遇到了一种情况,即按数据框进行分组,然后对“计数”进行计数和过滤。列引发了以下异常

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

case class Paf(x:Int)
val myData = Seq(Paf(2), Paf(1), Paf(2))
val df = sc.parallelize(myData, 2).toDF()

然后分组和过滤:

df.groupBy("x").count()
  .filter("count >= 2")
  .show()

引发异常:

java.lang.RuntimeException: [1.7] failure: ``('' expected but `>=' found count >= 2

解决方案:

重命名列会使问题消失(因为我怀疑与插值'计数功能没有冲突'

df.groupBy("x").count()
  .withColumnRenamed("count", "n")
  .filter("n >= 2")
  .show()

那么,这是一种期望的行为,一个错误还是一种规范的方式?

谢谢,亚历克斯

3 个答案:

答案 0 :(得分:37)

将字符串传递给filter函数时,该字符串将被解释为SQL。 Count是一个SQL关键字,使用count作为变量会混淆解析器。这是一个小错误(如果您愿意,可以提交JIRA票证。)

您可以通过使用列表达式而不是字符串来轻松避免这种情况:

df.groupBy("x").count()
  .filter($"count" >= 2)
  .show()

答案 1 :(得分:18)

  

那么,这是一种期待的行为,一个错误

说实话,我不确定。看起来解析器将count解释为不是列名而是函数,并且需要使用括号。看起来像是一个错误或至少是解析器的严重限制。

  

有规范的方法吗?

Hermanmattinbits已经提到了一些选项,所以这里有更多的SQLish方法:

import org.apache.spark.sql.functions.count

df.groupBy("x").agg(count("*").alias("cnt")).where($"cnt"  > 2)

答案 2 :(得分:10)

我认为解决方案是将计数放在后面的滴答中

respondLeftOnce :: Monad m => Pipe (Either e a) (Value a) m ()
respondLeftOnce = go
    where
        go = do
            ea <- await
            case ea of
                Right a -> yield (Value a) >> go                    
                Left  _ -> yield Exhausted       -- The upstream proxy is exhausted; do something else  

http://mail-archives.us.apache.org/mod_mbox/spark-user/201507.mbox/%3C8E43A71610EAA94A9171F8AFCC44E351B48EDF@fmsmsx124.amr.corp.intel.com%3E