2015-08-20 7 views
16

Spark 1.4.1dataframe: come groupby/contare poi filtrata su conteggio Scala

I incontrano una situazione in cui il raggruppamento per un dataframe, quindi contando e filtraggio nella colonna 'conteggio' genera l'eccezione sotto

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

Poi raggruppamento e filtraggio:

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

genera un'eccezione:

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

Soluzione:

Rinominare la colonna rende il problema Vanish (come sospetto non v'è alcun conflitto con la funzione di interpolato 'count''

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

Quindi, è che un comportamento aspettarsi , un bug o c'è un modo canonico per andare in giro?

grazie, alex

risposta

16

Quando si passa una stringa alla funzione filter, la stringa viene interpretato come SQL. Count è una parola chiave SQL e utilizza count come una variabile che confonde il parser. Questo è un piccolo bug (puoi inserire un biglietto JIRA se lo desideri).

Si può facilmente evitare questo utilizzando un'espressione di colonna al posto di una stringa:

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

Quindi, è che un comportamento aspettarsi, un bug

A dire il vero io sono non. Sembra che il parser stia interpretando count non come un nome di colonna ma come una funzione e si aspetta che seguano le parentesi. Sembra un bug o almeno una seria limitazione del parser.

c'è un modo canonico per andare in giro?

Alcune opzioni sono state già menzionato da Herman e mattinbits ecco più SQLish approccio da me:

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

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