2016-08-23 4 views
5

So habe ich eine Datenrahmen, die einige falsche Informationen enthält, die ich korrigieren möchten:Python Pandas GROUPBY Zurücksetzen Werte auf Index nach

import pandas as pd 
tuples_index = [(1,1990), (2,1999), (2,2002), (3,1992), (3,1994), (3,1996)] 
index = pd.MultiIndex.from_tuples(tuples_index, names=['id', 'FirstYear']) 
df = pd.DataFrame([2007, 2006, 2006, 2000, 2000, 2000], index=index, columns=['LastYear']) 


df 
Out[4]: 
       LastYear 
id FirstYear   
1 1990   2007 
2 1999   2006 
    2002   2006 
3 1992   2000 
    1994   2000 
    1996   2000 

id zu einem Geschäft bezieht und diese Datenrahmen ist ein kleines Beispiel Scheibe ein viel größer, die zeigt, wie sich ein Unternehmen bewegt. Jeder Datensatz ist ein einzigartiger Ort, und ich möchte das erste und letzte Jahr, das es dort war, erfassen. Das aktuelle "LastYear" ist genau für Unternehmen mit nur einem Datensatz und genau für den neuesten Datensatz von Unternehmen für mehr als einen Datensatz. Was die df wie am Ende aussehen soll, ist dies:

   LastYear 
id FirstYear   
1 1990   2007 
2 1999   2002 
    2002   2006 
3 1992   1994 
    1994   1996 
    1996   2000 

Und was ich getan habe, um es dort super klobig:

multirecord = df.groupby(level=0).filter(lambda x: len(x) > 1) 
multirecord_grouped = multirecord.groupby(level=0) 

ls = [] 
for _, group in multirecord_grouped: 
    levels = group.index.get_level_values(level=1).tolist() + [group['LastYear'].iloc[-1]] 
    ls += levels[1:] 

multirecord['LastYear'] = pd.Series(ls, index=multirecord.index.copy()) 
final_joined = pd.concat([df.groupby(level=0).filter(lambda x: len(x) == 1),multirecord]).sort_index() 

Gibt es einen besseren Weg?

Antwort

5
shift_year = lambda df: df.index.get_level_values('FirstYear').to_series().shift(-1) 
df.groupby(level=0).apply(shift_year) \ 
    .combine_first(df.LastYear).astype(int) \ 
    .rename('LastYear').to_frame() 

enter image description here

+0

sonst Wer, aber Sie, das alles mit nur einer Zeile fertig bekommen? – Kartik

+0

Entschuldigung dafür, dass ich das nicht von Anfang an erwähne, aber der Datenrahmen, auf dem dies ausgeführt wird, ist ~ 54 Millionen Zeilen. Dieser Code ist sehr elegant, aber es wird Stunden dauern. Könntest du an etwas denken, das es beschleunigen könnte? – jesseWUT