Erstellen eines partiellen SAS PROC SUMMARY-Ersatzes in Python / Pandas

9

Wir arbeiten daran, von SAS auf Python / Pandas zu kommen. Eine Sache, mit der wir Probleme haben, ist jedoch, einen Ersatz für PROC SUMMARY (AKA PROC MEANS ) zu schaffen, der die Flexibilität der SAS-Routine hat. Für Nicht-SAS-Benutzer: PROC SUMMARY ist nur eine Routine, die eine Tabelle mit "deskriptiven Statistiken für Variablen über alle Beobachtungen oder innerhalb von Gruppen von Beobachtungen" in einem Datensatz erstellt, um die SAS-Dokumentation zu paraphrasieren. Unsere Anforderungen sind nur eine kleine Teilmenge der vollen Funktionalität - Ausgabe einer Tabelle, wo wir haben:

  • Möglichkeit, verschiedene Statistiken auf verschiedene Spalten anzuwenden (für jetzt nur zählen, Summe, Mittelwert, gewichtetes Mittel)
  • Fähigkeit, null bis viele Gruppierungsvariablen zu behandeln
  • Möglichkeit, eine Gewichtungsvariable für das gewichtete Mittel
  • anzugeben

Wir versuchen nicht, irgendetwas anderes zu tun (irgendetwas grafisches usw.)

Folgendes haben wir bisher:

%Vor%

Hier ist ein Beispielaufruf für die Funktion my_summary() :

%Vor%

my_summary() funktioniert, aber wie Sie sehen können, ist seine Implementierung nicht die schönste. Hier sind die wichtigsten Punkte:

  • Zwei verschiedene Codepfade abhängig von gruppierten oder nicht gruppierten - dies ergibt sich vollständig aus der Tatsache, dass DataFrame und DataFrameGroupBy unterschiedliche Möglichkeiten haben, eine programmgesteuert ausgewählte reduzierende Funktion auf eine einzelne Spalte anzuwenden. Für DataFrame ist der einzige Weg, den ich gefunden habe, direkt func(data[var_name_in]) aufzurufen. data[var_name_in].apply(func) funktioniert nicht, weil apply() für Series nicht reduziert wird (im Gegensatz zu apply() für DataFrame ). Auf der anderen Seite muss ich für DataFrameGroupBy genau diesen Ansatz verwenden: grouped[var_name_in].apply(func) . Das liegt daran, dass etwas wie func(grouped[var_name_in]) nicht funktioniert (kein Grund sollte es sein.)
  • Spezielle Behandlung für gewichtetes Mittel - das ist so, weil es im Gegensatz zu allen anderen Berechnungen, die nur auf einer basieren, auf zwei Spalten arbeitet; Ich weiß nicht, ob das helfen kann.
  • Zwei verschiedene gewichtete Mittelfunktionen - dies ist eine Konsequenz des ersten Problems. Die nicht gruppierte Funktion hat Series -Typ-Parameter und benötigt dot() , um sie zu multiplizieren und zu reduzieren; Die gruppierte Funktion behandelt schließlich SeriesGroupBy -Objekte und muss den Operator * verwenden (Bestätigungen für die Antwort auf diesen SO-Post für den gewichteten Durchschnittsfunktionscode.)

Meine Fragen sind also:

  • Gibt es etwas, das den Pandas eigen ist, die all dies tun können (d. h. das oben genannte wegwerfen und stattdessen verwenden)?
  • Falls nicht, gibt es irgendwelche Korrekturen zu den oben genannten Problemen?
  • Gibt es zufällig eine Möglichkeit, nach nichts zu gruppieren - das heißt, ein DataFrameGroupBy -Objekt von einem DataFrame zu erhalten, ohne eine Variable zu gruppieren? Dann würden die Code-Pfade reduziert werden, da wir ausschließlich mit der DataFrameGroupBy -Schnittstelle arbeiten würden.

Aktualisierung / Aktuelle Lösung

@ JohnEs Antwort bietet eine Möglichkeit, nach nichts zu gruppieren: groupby(lambda x: True) . Dies ist ein Workaround, den er entdeckt hat in diesem SO-Beitrag (der übrigens eine Antwort von Wes selbst enthält, der von der Notwendigkeit eines DataFrame.agg() spricht, das dem gleichen Zweck dienen würde). @ JohnEs exzellente Lösung erlaubt uns, ausschließlich mit Objekten vom Typ DataFrameGroupBy zu arbeiten und reduziert die meisten Code-Pfade sofort. Ich war in der Lage, mit einigen funktionellen Spielereien, die jetzt möglich sind, weiter zu reduzieren, da wir nur DataFrameGroupBy Instanzen haben. Grundsätzlich werden alle Funktionen nach Bedarf generiert - die "Generatoren" (in Anführungszeichen, um nicht mit Python-Generatorausdrücken verwechselt zu werden) haben zwei Parameter: Wert Spaltenname und Gewicht Spaltenname, von denen der zweite in allen Fällen ignoriert wird %Code%. Die generierten Funktionen werden immer auf das gesamte wmean angewendet, wie es ursprünglich nur mit DataFrameGroupBy der Fall war, wobei die Parameter die korrekten Spaltennamen sind. Ich habe auch alle wmean -Implementierungen durch Pandas-Berechnungen ersetzt, um besser mit np.* -Werten umgehen zu können.

Wenn es Pandas nicht etwas gibt, das das kann, ist dies unsere Lösung:

%Vor%     
sparc_spread 28.04.2015, 18:14
quelle

1 Antwort

4

Nun, hier ist ein Quickie, der zwei Probleme hat (aber immer noch eine andere Funktion für den gewichteten Mittelwert benötigt). Meistens verwendet es den Trick hier (Guthaben für @DSM), um deine leere Gruppe zu umgehen, indem du groupby(lamda x: True) machst. Es wäre toll, wenn es einen Kwarg für "Gewichte" auf Sachen wie Mittel gäbe, aber meines Wissens nicht. Anscheinend gibt es ein Paket für gewichtete Quantile hier basierend auf numpy, aber ich don 't Ich weiß nichts darüber. Tolles Projekt übrigens!

(Beachten Sie, dass die Namen meistens die gleichen sind wie Ihre, ich habe gerade eine '2' zu wmean_grouped und my_summary hinzugefügt, ansonsten können Sie dieselbe Aufrufschnittstelle verwenden)

%Vor%     
JohnE 28.04.2015, 19:12
quelle

Tags und Links