2016-08-23 16 views
5

Więc mam dataframe który zawiera pewną błędną informację, że chcesz naprawić:Python Pandy GroupBy Resetowanie wartości oparte na indeksie

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 odnosi się do biznesu, a to DataFrame jest mały przykład plasterek znacznie większy, który pokazuje, w jaki sposób firma się porusza. Każda płyta jest wyjątkową lokalizacją i chcę uchwycić pierwszy i ostatni rok jej istnienia. Obecny "LastYear" jest dokładny dla firm z tylko jednym rekordem i dokładny dla najnowszych rekordów firm dla więcej niż jednego rekordu. Co df powinna wyglądać w końcu jest to:

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

I co zrobiłem, aby ją tam było super przylegający:

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() 

Czy istnieje lepszy sposób?

Odpowiedz

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

Kto jeszcze, ale może dostać wszystko, co zrobić z tylko jednej linii? – Kartik

+0

Przepraszam, że nie wspomniałem o tym od samego początku, ale ramka danych, na której działa, ma ~ 54 miliony wierszy. Ten kod jest bardzo elegancki, ale potrwa kilka godzin. Czy możesz wymyślić coś, co może przyspieszyć? – jesseWUT

Powiązane problemy