2016-06-12 9 views
2

Ich habe den folgenden minimalen Code, der zu langsam ist. Für die 1000 Zeilen, die ich brauche, dauert es ca. 2 min. Ich brauche es schneller zu laufen.Python: schnelle Subsetting und Looping Datenrahmen

import numpy as np 
import pandas as pd 

df = pd.DataFrame(np.random.randint(0,1000,size=(1000, 4)), columns=list('ABCD')) 
start_algorithm = time.time() 
myunique = df['D'].unique() 
for i in myunique: 
    itemp = df[df['D'] == i] 
    for j in myunique: 
     jtemp = df[df['D'] == j] 

Ich weiß, dass numpy kann es viel schneller laufen, aber bedenken Sie, dass ich einen Teil des ursprünglichen Datenrahmens (oder Array in numpy) für bestimmte Werte der Spalte ‚D‘ halten wollen. Wie kann ich die Leistung verbessern?

+0

immer versuchen, einen [Minimal, vollständige, und prüfbare Beispiel] (http://stackoverflow.com/help/mcve) wenn man Fragen stellt. Im Falle von _pandas_ Fragen geben Sie bitte Beispiel _input_ und _output_ data sets (5-7 Zeilen im CSV/dict/JSON/Python-Code-Format _als Text_, so könnte man es verwenden, wenn Sie eine Antwort für Sie kodieren). Dies wird dazu beitragen, _situations_ zu vermeiden: 'Ihr Code funktioniert nicht für mich' oder' er funktioniert nicht mit meinen Daten', etc. – MaxU

+1

Es ist nicht klar, was Sie tun möchten ... – MaxU

+0

ich nicht möchte eine einfache Schleife durch Zeilen von Datenrahmen. Sonst könnte ich es einfach in numpy implementieren. Ich brauche die Schleife durch eindeutige Werte von olumn 'D', die Teilmengen des ursprünglichen Datenrahmens erzeugen. Mit numpy sollte ich alle Elemente eines 2d-Arrays durchlaufen und die Zeilen mit demselben Wert in der Spalte 'D' speichern.Es gibt keine wirklichen Daten, an denen gearbeitet werden kann, und deshalb habe ich dem Datenrahmen zufällige Werte gegeben. – ilias

Antwort

3

Vermeiden Sie es, den Sub-DataFrame df[df['D'] == i] mehr als einmal zu berechnen. Der Originalcode berechnet diese len(myunique)**2 mal. Stattdessen können Sie dies einmal pro i (also len(myunique) mal insgesamt) berechnen, speichern Sie die Ergebnisse und dann später zusammen. Zum Beispiel

groups = [grp for di, grp in df.groupby('D')] 
    for itemp, jtemp in IT.product(groups, repeat=2): 
     pass 

import pandas as pd 
import itertools as IT 
df = pd.DataFrame(np.random.randint(0,1000,size=(1000, 4)), columns=list('ABCD')) 

def using_orig(): 
    myunique = df['D'].unique() 
    for i in myunique: 
     itemp = df[df['D'] == i] 
     for j in myunique: 
      jtemp = df[df['D'] == j] 

def using_groupby(): 
    groups = [grp for di, grp in df.groupby('D')] 
    for itemp, jtemp in IT.product(groups, repeat=2): 
     pass 

In [28]: %timeit using_groupby() 
10 loops, best of 3: 63.8 ms per loop 
In [31]: %timeit using_orig() 
1 loop, best of 3: 2min 22s per loop 

In Bezug auf den Kommentar:

ich iTEMP leicht ersetzen kann und jtemp mit a = 1 oder print „Hallo "So ignorieren Sie das

Die obige Antwort behandelt die effizientere Berechnung von itemp und jtemp. Wenn itemp und jtemp sind nicht zentral für Ihre echte Berechnung, dann müssten wir besser verstehen, , was Sie wirklich berechnen möchten, um (wenn möglich) einen Weg, um es schneller zu berechnen vorschlagen.

+0

Ich wünschte, ich hätte Ihre magische Kristallkugel ...;) – MaxU

+1

Mein Kommentar über itemp und jtemp sollte betonen, dass (wie ich zu der Zeit dachte) das Problem war mit einzigartig. Wie ich jetzt anhand der erstaunlichen Antwort von unutbu sehen kann, lag ich eindeutig falsch und entschuldige mich bei den Kollegen von stackoverflow, weil ich sie etwas irregeführt habe. Ihre Antwort funktioniert gut und ich danke Ihnen allen für Ihre Zeit und Ihren Beitrag. – ilias

0

Hier ist eine vektorisierte Ansatz, um die Gruppen aus "D" Spalte basierend auf einzigartige Elemente zu bilden, -

# Sort the dataframe based on the sorted indices of column 'D' 
df_sorted = df.iloc[df['D'].argsort()] 

# In the sorted dataframe's 'D' column find the shift/cut indces 
# (places where elements change values, indicating change of groups). 
# Cut the dataframe at those indices for the final groups with NumPy Split. 
cut_idx = np.where(np.diff(df_sorted['D'])>0)[0]+1 
df_split = np.split(df_sorted,cut_idx) 

Probentest

1] Form einer Probe Datenrahmen mit zufälligen Elementen:

>>> df = pd.DataFrame(np.random.randint(0,100,size=(5, 4)), columns=list('ABCD')) 
>>> df 
    A B C D 
0 68 68 90 39 
1 53 99 20 85 
2 64 76 21 19 
3 90 91 32 36 
4 24 9 89 19 

2] Führen Sie den Originalcode aus und drucken Sie die Ergebnisse aus:

>>> myunique = df['D'].unique() 
>>> for i in myunique: 
...  itemp = df[df['D'] == i] 
...  print itemp 
... 
    A B C D 
0 68 68 90 39 
    A B C D 
1 53 99 20 85 
    A B C D 
2 64 76 21 19 
4 24 9 89 19 
    A B C D 
3 90 91 32 36 

3] Führen Sie den vorgeschlagenen Code und drucken Sie die Ergebnisse:

>>> df_sorted = df.iloc[df['D'].argsort()] 
>>> cut_idx = np.where(np.diff(df_sorted['D'])>0)[0]+1 
>>> df_split = np.split(df_sorted,cut_idx) 
>>> for split in df_split: 
...  print split 
... 
    A B C D 
2 64 76 21 19 
4 24 9 89 19 
    A B C D 
3 90 91 32 36 
    A B C D 
0 68 68 90 39 
    A B C D 
1 53 99 20 85