web-dev-qa-db-fra.com

dataframe: comment grouper / compter puis filtrer sur compter dans Scala

Spark 1.4.1

Je rencontre une situation où le regroupement par une structure de données, puis le comptage et le filtrage sur la colonne 'nombre' lève l'exception ci-dessous

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()

Puis regroupement et filtrage:

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

Lève une exception:

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

Solution:

Renommer la colonne fait disparaître le problème (car je soupçonne qu’il n’ya pas de conflit avec la fonction interpolée 'count'

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

Alors, est-ce un comportement à prévoir, un bogue ou y a-t-il un moyen canonique de s'y prendre?

merci alex

35
user3646671

Lorsque vous passez une chaîne à la fonction filter, la chaîne est interprétée en tant que SQL. Count est un mot clé SQL et l'utilisation de count en tant que variable perturbe l'analyseur. Ceci est un petit bug (vous pouvez déposer un ticket JIRA si vous le souhaitez).

Vous pouvez facilement éviter cela en utilisant une expression de colonne au lieu d'une chaîne:

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

Alors, est-ce un comportement à attendre, un bug

À vrai dire, je ne suis pas sûr. Il semble que l'analyseur interprète count non pas comme un nom de colonne mais comme une fonction et attend les parenthèses suivantes. Cela ressemble à un bogue ou au moins à une limitation sérieuse de l'analyseur.

y a-t-il un moyen canonique de faire le tour?

Certaines options ont déjà été mentionnées par Herman et mattinbits alors voici une approche plus SQLish de ma part:

import org.Apache.spark.sql.functions.count

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