2017-05-19 2 views
3
import numpy as np 
import pandas as pd 
dummies = np.array(pd.get_dummies(list('abdccadab'))) #categorical IV 
groupIDs = np.array([10,10,10,10,20,20,30,30,30]) #groups(/strata) 
_,idx,tags = np.unique(groupIDs, return_index=1, return_inverse=1) 

Ich weiß, wir können Summen, Multiplikationen etc pro Gruppe, pro Spalte, z.Verwenden von NumPy reduceat zur Berechnung von gruppenbasierten Durchschnitten

np.multiply.reduceat(dummies,idx)[tags] 

aber gibt es eine Möglichkeit, die Mittel dieser Behälter zu berechnen?

np.mean.reduceatnp.average.reduceat und funktionieren nicht, da

AttributeError: 'function' object has no attribute 'reduceat' 
+1

Nur 'ufunc' haben' reduceat'. 'mean' und' average' sind nicht diese Art von Funktion. – hpaulj

+1

Aus Neugier, gibt es einen Grund, warum Sie versuchen, dies mit reinem numpy (im Gegensatz zu einer Pandas Groupby) tun? – DSM

+0

Kein anderer Grund als ich bin weniger vertraut mit Pandas als numpy und wusste nicht einmal, dass es auch in Pandas getan werden konnte – Tony

Antwort

2

Verwenden np.add.reduceatdummies pro Spalte Summierungen von Datenanordnung zu erhalten, basierend auf dem Intervall verschieben idx und dann dividieren durch die Intervalllängen berechnet mit np.bincount -

np.add.reduceat(dummies, idx, axis=0)/np.bincount(tags)[:,None] 

Eine andere Möglichkeit zur Berechnung der Intervalllängen wäre die direkte Verwendung von idx -

np.diff(np.r_[idx,dummies.shape[0]]) 

Auch hier können wir die Verwendung von np.unique vermeiden idx zu bekommen, wie so -

idx = np.r_[0,np.flatnonzero(groupIDs[1:] > groupIDs[:-1])+1] 
+0

Danke nochmal! Und wie würden wir die Ausgabe von 'np.add.reduceat (Dummies, idx, axis = 0) /np.bincount (Tags) [:, None]' auf die gleichen Dimensionen wie die Dummies setzen? -i.e. was wir in 'np.multiply.reduceat (Dummies, idx) 'erreichen würden, mit der Hinzufügung von' [tags] 'am Ende. – Tony

+1

@Tony Ich bin nicht klar bei der Abfrage von 'Tags'. Ich habe hier "Tags" mit "np.bincount" verwendet, um die Anzahl der einzelnen Intervalle zu ermitteln und somit Durchschnittswerte zu berechnen. Nicht sicher, wie Sie es mit 'np.multiply.reduceat' verwenden möchten. Könnten Sie das ausarbeiten oder umformulieren? – Divakar

+0

Entschuldigung für den Mangel an Klarheit. Wenn man irgendeine der "sum", "multiply" usw. auf jede Weise aufruft, wie im Beispiel im ursprünglichen Beitrag, dh nicht geteilt durch "np.bincount", um den Mittelwert zu erhalten, dann ist das zurückgegebene Array dasselbe Form wie unsere ursprüngliche. Meine aktuelle Frage ist also, wie man die Ausgabe von 'np.add.reduceat (Dummies, idx, axis = 0) /np.bincount (Tags) [:, None]' so umformt, dass sie dieselben Dimensionen wie das ursprüngliche Array haben. In diesem Beispiel wären die ersten 4 Elemente der ersten Zeile 0,25, die beiden folgenden wären 0,5 usw. Ich bearbeite meine Frage mit der gewünschten Ausgabe. – Tony

1

Das numpy_indexed Paket (Disclaimer: Ich bin sein Autor) bietet diese Art von Funktionalität als Single- line statement:

Für diesen Fall (bereits sortierte Schlüssel) bietet es lineare und vektorisierte Leistung; obwohl mit mehr Overhead als die spezialisierte Lösung von Divakar, die diese Annahme bereits gebacken hat. Je nachdem, wie Sie Wartbarkeit, Selbstdokumentation und Allgemeingültigkeit gewichten, könnte dies eine bevorzugte Alternative sein.

Verwandte Themen