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()
那么,这是一种期望的行为,一个错误还是一种规范的方式?
谢谢,亚历克斯
答案 0 :(得分:37)
将字符串传递给filter
函数时,该字符串将被解释为SQL。 Count是一个SQL关键字,使用count
作为变量会混淆解析器。这是一个小错误(如果您愿意,可以提交JIRA票证。)
您可以通过使用列表达式而不是字符串来轻松避免这种情况:
df.groupBy("x").count()
.filter($"count" >= 2)
.show()
答案 1 :(得分:18)
那么,这是一种期待的行为,一个错误
说实话,我不确定。看起来解析器将count
解释为不是列名而是函数,并且需要使用括号。看起来像是一个错误或至少是解析器的严重限制。
有规范的方法吗?
Herman和mattinbits已经提到了一些选项,所以这里有更多的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