2016-07-12 11 views
2

Ich habe einen Datenrahmen, df, die wie folgt aussieht:Eine schnelle Methode zum Vergleichen eines Wertes in einer Panda-Reihe mit einem anderen in einer vorherigen Reihe?

ID |   TERM  | DISC_1 
1  |   2003-10  | ECON 
1  |   2002-01  | ECON 
1  |   2002-10  | ECON 
2  |   2003-10  | CHEM 
2  |   2004-01  | CHEM 
2  |   2004-10  | ENGN 
2  |   2005-01  | ENGN 
3  |   2001-01  | HISTR 
3  |   2002-10  | HISTR 
3  |   2002-10  | HISTR 

ID ist ein Student ID, TERM ist ein akademischer Begriff, und DISC_1 ist die Disziplin ihrer wichtigsten. Für jeden Schüler möchte ich den TERM identifizieren, wenn (und wenn) er DISC_1 geändert hat, und dann einen neuen Datenrahmen erstellen, der wann meldet. Null gibt an, dass sie sich nicht geändert haben. Die Ausgabe sieht so aus:

ID |  Change 
1  |   0  
2  |   2004-01  
3  |   0  

Mein Code unten funktioniert, aber es ist sehr langsam. Ich versuchte dies mit Groupby zu tun, konnte es aber nicht. Könnte jemand erklären, wie ich diese Aufgabe effizienter erledigen könnte?

df = df.sort_values(by = ['PIDM', 'TERM']) 
c = 0 
last_PIDM = 0 
last_DISC_1 = 0 
change = [ ] 
for index, row in df.iterrows(): 
    c = c + 1 
    if c > 1: 
     row['change'] = np.where((row['PIDM'] == last_PIDM) & (row['DISC_1'] != last_DISC_1),  row['TERM'], 0) 
     last_PIDM = row['PIDM'] 
     last_DISC_1 = row['DISC_1'] 

    else: 
     row['change'] = 0 
    change.append(row['change']) 

df['change'] = change   
change_terms = df.groupby('PIDM')['change'].max() 
+0

Ich bin etwas verwirrt über die 'TERM'-Werte. Ist 'YYYY-10' vor' YYYY-01'? Ihre erwartete Ausgabe scheint dies anzuzeigen, andernfalls hätte ID 2 mehrere Switches. Ihr Arbeitscode wird jedoch nach "TERM" sortiert, was innerhalb von Jahren die umgekehrte Reihenfolge ergibt. – root

+0

@root ja das war ein Fehler. In letzter Minute habe ich die Daten geändert, um klarzustellen, warum ich die Spalte sortieren musste. Ich habe die Tabelle korrigiert, ID 2 hat nur einen Schalter. Vielen Dank! –

Antwort

4

Hier ist ein Anfang:

df = df.sort_values(['ID', 'TERM']) 
gb = df.groupby('ID').DISC_1 
df['Change'] = df.TERM[gb.apply(lambda x: x != x.shift().bfill())] 
df.Change = df.Change.fillna(0) 
2

Ich habe noch nie ein großer Pandas Benutzer gewesen, so wäre meine Lösung Spucken beinhaltet, die als csv df aus, und über jede Reihe laufen, während der Halt vorherige Reihe. Wenn es richtig sortiert ist (zuerst nach ID, dann nach Term-Datum), schreibe ich vielleicht so etwas ...

import csv 

with open('inputDF.csv', 'rb') as infile: 
    with open('outputDF.csv', 'wb') as outfile: 
     reader = csv.reader(infile) 
     writer = csv.writer(outfile) 

     previousline = reader.next() #grab the first row to compare to the second 
     termChange = 0 
     for line in reader: 
      if line[0] != previousline[0]: #new ID means print and move on to next person 
       writer.writerow([previousline[0], termChange]) #print to file ID, termChange date 
       termChange = 0 
      elif line[2] != previousline[2]: #new discipline 
       termChange = line[1] #set term changed date 
       #termChange = previousline[1] #in case you want to rather retain the last date they were in the old dicipline 

      previousline = line #store current line as previous and continue loop 
+0

Ich möchte auch darauf hinweisen, dass die Lese- und Schreibobjekte jedes iterierbare Objekt und nicht nur Dateiobjekte verwenden. Dies bedeutet, dass das tatsächliche Lesen und Schreiben von Dateien nicht stattfinden muss, und dies könnte einfach im Speicher liegen. Wenn Sie dies tun würden, müssten Sie wahrscheinlich das Schlüsselwort 'dialect =' sowohl im Reader- als auch im Writer-Konstruktor angeben. – Aaron

+0

Soße: [CSV - Lesen und Schreiben von CSV-Dateien] (https://docs.python.org/2/ Bibliothek/csv.html # Beispiele) – Aaron

Verwandte Themen