2017-06-03 1 views
1

Ich arbeite mit einer großen Reihe von 1 und muss systematisch Nullen aus Abschnitten des Arrays entfernen. Das große Array besteht aus vielen kleineren Arrays, für jedes kleinere Array muss ich seine oberen und unteren Dreiecke systematisch durch 0 ersetzen. Zum Beispiel haben wir ein Array mit 5 Subarrays durch den Indexwert angegeben (alle Unterfelder die gleiche Anzahl von Spalten haben):Iterating und Modifizierung von Datenrahmen mit Pandas groupby

 0 1 2 
0 1.0 1.0 1.0 
1 1.0 1.0 1.0 
1 1.0 1.0 1.0 
2 1.0 1.0 1.0 
2 1.0 1.0 1.0 
2 1.0 1.0 1.0 
3 1.0 1.0 1.0 
3 1.0 1.0 1.0 
3 1.0 1.0 1.0 
3 1.0 1.0 1.0 
4 1.0 1.0 1.0 
4 1.0 1.0 1.0 
4 1.0 1.0 1.0 
4 1.0 1.0 1.0 
4 1.0 1.0 1.0 

Ich mag jede Zeilengruppe in ihrem oberen und unteren Dreieck modifiziert werden ich verwende nur numpy dieses resultierende Array zu erreichen, aber ich denke, ich es

 0 1 2 
0 1.0 1.0 1.0 
1 1.0 1.0 0.0 
1 0.0 1.0 1.0 
2 1.0 0.0 0.0 
2 0.0 1.0 0.0 
2 0.0 0.0 1.0 
3 1.0 0.0 0.0 
3 1.0 1.0 0.0 
3 0.0 1.0 1.0 
3 0.0 0.0 1.0 
4 1.0 0.0 0.0 
4 1.0 1.0 0.0 
4 1.0 1.0 1.0 
4 0.0 1.0 1.0 
4 0.0 0.0 1.0 

im Moment beschleunigen kann Pandas Gruppierung mit bis: so dass die resultierenden Matrix ist. In Wirklichkeit ist mein Datensatz sehr groß, fast 500.000 Zeilen lang. Der numpy Code ist unten:

import numpy as np 

candidateLengths = np.array([1,2,3,4,5]) 
centroidLength =3 

smallPaths = [min(l,centroidLength) for l in candidateLengths] 

# This is the k_values of zeros to delete. To be used in np.tri 
k_vals = list(map(lambda smallPath: centroidLength - (smallPath), smallPaths)) 
maskArray = np.ones((np.sum(candidateLengths), centroidLength)) 

startPos = 0 
endPos = 0 
for canNo, canLen in enumerate(candidateLengths): 
    a = np.ones((canLen, centroidLength)) 
    a *= np.tri(*a.shape, dtype=np.bool, k=k_vals[canNo]) 
    b = np.fliplr(np.flipud(a)) 
    c = a*b 

    endPos = startPos + canLen 

    maskArray[startPos:endPos, :] = c 

    startPos = endPos 

print(maskArray) 

Als ich dieser Datensatz auf meinem realen führen Sie es fast 5-7secs auszuführen nimmt. Ich denke, das liegt an dieser massiven for-Schleife. Wie kann ich Pandas-Gruppierungen verwenden, um eine höhere Geschwindigkeit zu erreichen? Dank

Antwort

1

Neue Antwort

def tris(n, m): 
    if n < m: 
     a = np.tri(m, n, dtype=int).T 
    else: 
     a = np.tri(n, m, dtype=int) 
    return a * a[::-1, ::-1] 

idx = np.append(df.index.values, -1) 
w = np.append(-1, np.flatnonzero(idx[:-1] != idx[1:])) 
c = np.diff(w) 
df * np.vstack([tris(n, 3) for n in c]) 

    0 1 2 
0 1.0 1.0 1.0 
1 1.0 1.0 0.0 
1 0.0 1.0 1.0 
2 1.0 0.0 0.0 
2 0.0 1.0 0.0 
2 0.0 0.0 1.0 
3 1.0 0.0 0.0 
3 1.0 1.0 0.0 
3 0.0 1.0 1.0 
3 0.0 0.0 1.0 
4 1.0 0.0 0.0 
4 1.0 1.0 0.0 
4 1.0 1.0 1.0 
4 0.0 1.0 1.0 
4 0.0 0.0 1.0 

Alte Antwort

definiere ich einige Hilfsfunktionen Dreieck

def tris(n, m): 
    if n < m: 
     a = np.tri(m, n, dtype=int).T 
    else: 
     a = np.tri(n, m, dtype=int) 
    return a * a[::-1, ::-1] 

def tris_df(df): 
    n, m = df.shape 
    return pd.DataFrame(tris(n, m), df.index, df.columns) 

Dann

df * df.groupby(level=0, group_keys=False).apply(tris_df) 

    0 1 2 
0 1.0 1.0 1.0 
1 1.0 1.0 0.0 
1 0.0 1.0 1.0 
2 1.0 0.0 0.0 
2 0.0 1.0 0.0 
2 0.0 0.0 1.0 
3 1.0 0.0 0.0 
3 1.0 1.0 0.0 
3 0.0 1.0 1.0 
3 0.0 0.0 1.0 
4 1.0 0.0 0.0 
4 1.0 1.0 0.0 
4 1.0 1.0 1.0 
4 0.0 1.0 1.0 
4 0.0 0.0 1.0 
+0

Hallo @piRSquared danke, dafür. Ich denke, dass die von Ihnen zur Verfügung gestellte Lösung im Vergleich zu der for-Schleife, die ich ursprünglich geschrieben habe, langsam ist. Ich denke, unter der Haube läuft man fast wie eine For-Schleife durch. Wenn Sie es mit candidateLengths = np.random.randint (1,7, size = 300000) versuchen, finde ich, dass mein Code in 6 Sekunden ausgeführt wird. Vielen Dank! – kPow989

+0

@ user3063482 versuchen Sie das. – piRSquared

+0

Hallo, danke ich habe es zeitlich abgestimmt und deine neue Funktion kehrt in 3.74s zurück während meine in 5.34s! Das funktioniert ziemlich gut. Schätze die Hilfe! – kPow989