it-swarm.com.de

Spark: Wie man count (distinct (value)) in Dataframe-APIs übersetzt

Ich versuche, verschiedene Arten der Aggregation meiner Daten zu vergleichen.

Dies sind meine Eingabedaten mit 2 Elementen (Seite, Besucher):

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

Arbeiten mit einem SQL-Befehl in Spark SQL mit diesem 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)

Ich bekomme diese Ausgabe:

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

Jetzt möchte ich mit Dataframes und der thiers-API das gleiche Ergebnis erzielen, kann aber nicht die gleiche Ausgabe erzielen:

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)

In der Tat ist es das, was ich als Ausgabe bekomme:

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

Es ist wahrscheinlich etwas dummes, aber ich kann es gerade nicht sehen.

Danke im Voraus!

FF

26
Fabio Fantoni

Was Sie brauchen, ist die DataFrame-Aggregationsfunktion 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

Sie können dazu den Befehl groupBy von dataframe zweimal verwenden. Hier, df1 ist Ihre ursprüngliche Eingabe.

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

Dieser Befehl würde das folgende Ergebnis erzeugen:

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

Verwenden Sie dann den Befehl groupBy erneut, um das endgültige Ergebnis zu erhalten.

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

Endgültige Ausgabe:

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