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:
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()
:
my_summary()
funktioniert, aber wie Sie sehen können, ist seine Implementierung nicht die schönste. Hier sind die wichtigsten Punkte:
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.) 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:
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. @ 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% 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%