web-dev-qa-db-fra.com

Spark: Comment traduire le nombre (distinct (valeur)) dans les API Dataframe

J'essaie de comparer différentes façons d'agréger mes données.

Voici mes données d'entrée avec 2 éléments (page, visiteur):

(PAG1,V1)
(PAG1,V1)
(PAG2,V1)
(PAG2,V2)
(PAG2,V1)
(PAG1,V1)
(PAG1,V2)
(PAG1,V1)
(PAG1,V2)
(PAG1,V1)
(PAG2,V2)
(PAG1,V3)

Travailler avec une commande SQL dans Spark SQL avec ce code:

import sqlContext.implicits._
case class Log(page: String, visitor: String)
val logs = data.map(p => Log(p._1,p._2)).toDF()
logs.registerTempTable("logs")
val sqlResult= sqlContext.sql(
                              """select page
                                       ,count(distinct visitor) as visitor
                                   from logs
                               group by page
                              """)
val result = sqlResult.map(x=>(x(0).toString,x(1).toString))
result.foreach(println)

J'obtiens cette sortie:

(PAG1,3) // PAG1 has been visited by 3 different visitors
(PAG2,2) // PAG2 has been visited by 2 different visitors

Maintenant, je voudrais obtenir le même résultat en utilisant Dataframes et leur API, mais je ne peux pas obtenir la même sortie:

import sqlContext.implicits._
case class Log(page: String, visitor: String)
val logs = data.map(p => Coppia(p._1,p._2)).toDF()
val result = log.select("page","visitor").groupBy("page").count().distinct
result.foreach(println)

En fait, c'est ce que j'obtiens en sortie:

[PAG1,8]  // just the simple page count for every page
[PAG2,4]

C'est probablement quelque chose de stupide, mais je ne le vois pas pour le moment.

Merci d'avance!

FF

26
Fabio Fantoni

Ce dont vous avez besoin est la fonction d'agrégation DataFrame countDistinct:

import sqlContext.implicits._
import org.Apache.spark.sql.functions._

case class Log(page: String, visitor: String)

val logs = data.map(p => Log(p._1,p._2))
            .toDF()

val result = logs.select("page","visitor")
            .groupBy('page)
            .agg('page, countDistinct('visitor))

result.foreach(println)
49
yjshen

Pour ce faire, vous pouvez utiliser la commande groupBy de dataframe deux fois. Ici, df1 est votre entrée d'origine.

val df2 = df1.groupBy($"page",$"visitor").agg(count($"visitor").as("count"))

Cette commande produirait le résultat suivant:

page  visitor  count
----  ------   ----
PAG2    V2       2
PAG1    V3       1
PAG1    V1       5
PAG1    V2       2
PAG2    V1       2

Ensuite, utilisez à nouveau la commande groupBy pour obtenir le résultat final.

 df2.groupBy($"page").agg(count($"visitor").as("count"))

Sortie finale:

page   count
----   ----
PAG1    3
PAG2    2
2
Abu Shoeb