2016-07-29 4 views
0

Ich mag den mutual information (MI) zwischen zwei Variablen berechnen x und y, die ich in einem Spark-Datenrahmen habe, die wie folgt aussieht:beiden Vorkommen und cooccurrences in einem DF-Counting

scala> df.show() 
+---+---+ 
| x| y| 
+---+---+ 
| 0| DO| 
| 1| FR| 
| 0| MK| 
| 0| FR| 
| 0| RU| 
| 0| TN| 
| 0| TN| 
| 0| KW| 
| 1| RU| 
| 0| JP| 
| 0| US| 
| 0| CL| 
| 0| ES| 
| 0| KR| 
| 0| US| 
| 0| IT| 
| 0| SE| 
| 0| MX| 
| 0| CN| 
| 1| EE| 
+---+---+ 

In meinem Fall, x passiert, ob ein Ereignis auftritt (x = 1) oder nicht (x = 0), und y ist ein Ländercode, aber diese Variablen könnten alles darstellen. Zur Berechnung des MI zwischen x und y Ich mag den oben Datenrahmen von x, y Paaren mit den folgenden drei zusätzlichen Spalten gruppiert haben:

  • Die Anzahl der Vorkommen von x
  • Die Anzahl der Vorkommen von y
  • die Anzahl der Vorkommen von x, y

In dem kurzen obigen Beispiel wäre es wie

01.235.164 aussehen
x, y, count_x, count_y, count_xy 
0, FR, 17, 2, 1 
1, FR, 3, 2, 1 
... 

Dann müsste ich nur die gegenseitigen Informationen Begriff für jedes Paar x, y berechnen und summieren.

Bisher habe ich von x, y Paaren Gruppe in der Lage gewesen und aggregieren eine count(*) Spalte, aber ich konnte nicht eine effiziente Art und Weise hinzufügen, um die x und y zählt finden. Meine derzeitige Lösung besteht darin, den DF in ein Array zu konvertieren und die Vorkommen und Kookuzenzen manuell zu zählen. Es funktioniert gut, wenn y ein Land ist, aber es dauert ewig, wenn die Kardinalität von y groß wird. Irgendwelche Vorschläge, wie ich es in einer mehr Sparkish Weise tun könnte?

Vielen Dank im Voraus!

Antwort

1

Ich würde mit RDDs gehen, einen Schlüssel für jeden Anwendungsfall generieren, nach Schlüssel zählen und die Ergebnisse beitreten. Auf diese Weise weiß ich genau, was die Stufen sind. Eine andere Option wäre, map partition zu verwenden und einfach an iterables zu arbeiten und die resolutes über Partitionen hinweg zu verschmelzen.

1

Auch neu bei Spark, aber ich habe eine Idee, was zu tun ist. Ich weiß nicht, ob das die perfekte Lösung ist, aber ich dachte, das würde nicht schaden.

Was ich tun würde, ist wahrscheinlich Filter() für den Wert 1 einen Datenrahmen und Filter() für den Wert 0 für einen zweiten Datenrahmen zu erstellen

Sie bekommen würde so etwas wie

erster Datenrahmen

DO 1
FR 1

im nächsten Schritt tun würde i groupBy (y)

So würden Sie für den ersten Datenrahmen erhalten

DO 1 1

FR 1

Als GroupedData https://spark.apache.org/docs/1.4.0/api/java/org/apache/spark/sql/GroupedData.html

Dies auch eine Funktion count() aufweist, die die Zeilen werden Zählen sollte pro Gruppe.Leider habe ich momentan nicht die Zeit, das selbst auszuprobieren, aber ich wollte trotzdem versuchen und helfen.

Edit: Bitte lassen Sie mich wissen, wenn dies geholfen hat, sonst werde ich die Antwort löschen, so dass andere Leute noch einen Blick darauf werfen!

+0

Danke für Ihre Antwort. Diese Lösung ist diejenige, für die ich mich vorübergehend entschieden habe, aber ich bin mir nicht sicher, ob es sich auf den Fall verallgemeinern würde, in dem die Kardinalität von y 3 oder mehr ist. Grob gesagt besteht es darin, ein kartesisches Produkt explizit herzustellen (wobei zu beachten ist, dass "y" nur zwei Werte annehmen kann). Ich denke @ z-star schlägt eine vielseitige Antwort vor. Bitte lösche deine Antwort jedoch nicht, sie funktioniert immer noch und könnte für einige andere Benutzer nützlich sein. Andere Beitragende könnten dir helfen, sie zu verbessern. –

Verwandte Themen