2014-09-18 10 views
13

Jestem nowy w Pythonie i Pandach, więc może być proste rozwiązanie, którego nie widzę.Brakujące dane, wstawianie wierszy w Pandach i wypełnianie NAN

Mam szereg nieciągłych zestawów danych, które wyglądają tak:

ind A B C 
0 0.0 1 3 
1 0.5 4 2 
2 1.0 6 1 
3 3.5 2 0 
4 4.0 4 5 
5 4.5 3 3 

teraz szukać rozwiązania, aby uzyskać następujące:

ind A B C 
0 0.0 1 3 
1 0.5 4 2 
2 1.0 6 1 
3 1.5 NAN NAN 
4 2.0 NAN NAN 
5 2.5 NAN NAN 
6 3.0 NAN NAN 
7 3.5 2 0 
8 4.0 4 5 
9 4.5 3 3 

Problem polega na tym, że luka w A różni się od zestawu danych do zestawu danych w pozycji i długości ...

+0

Witamy StackOverflow. Upewnij się, że pokazujesz swój kod (wysiłek) innym użytkownikom, aby mogli oni dobrze zrozumieć twój problem i móc go usunąć. –

Odpowiedz

15

set_index i reset_index są Twoimi przyjaciółmi.

df = DataFrame({"A":[0,0.5,1.0,3.5,4.0,4.5], "B":[1,4,6,2,4,3], "C":[3,2,1,0,5,3]}) 

pierwsze posunięcie kolumna A do indeksu:

In [64]: df.set_index("A") 
Out[64]: 
    B C 
A   
0.0 1 3 
0.5 4 2 
1.0 6 1 
3.5 2 0 
4.0 4 5 
4.5 3 3 

Następnie reindex z nowym indeksem, tutaj brakuje danych jest wypełniane Nans. Używamy obiektu Index, ponieważ możemy go nazwać; to będzie użyte w następnym kroku.

In [66]: new_index = Index(arange(0,5,0.5), name="A") 
In [67]: df.set_index("A").reindex(new_index) 
Out[67]: 
     B C 
0.0 1 3 
0.5 4 2 
1.0 6 1 
1.5 NaN NaN 
2.0 NaN NaN 
2.5 NaN NaN 
3.0 NaN NaN 
3.5 2 0 
4.0 4 5 
4.5 3 3 

Na koniec przenieś indeks z powrotem do kolumn za pomocą reset_index. Od nazwaliśmy indeksu, to wszystko działa magicznie:

In [69]: df.set_index("A").reindex(new_index).reset_index() 
Out[69]: 
     A B C 
0 0.0 1 3 
1 0.5 4 2 
2 1.0 6 1 
3 1.5 NaN NaN 
4 2.0 NaN NaN 
5 2.5 NaN NaN 
6 3.0 NaN NaN 
7 3.5 2 0 
8 4.0 4 5 
9 4.5 3 3 
+0

Dzięki, to działa idealnie. – mati

1

W tym przypadku nadpisuję kolumnę A nowo wygenerowaną ramką danych i łączę ją z oryginalnym plikiem df, a następnie stosuję to:

In [177]: 

df.merge(how='right', on='A', right = pd.DataFrame({'A':np.arange(df.iloc[0]['A'], df.iloc[-1]['A'] + 0.5, 0.5)})).sort(columns='A').reset_index().drop(['index'], axis=1) 
Out[177]: 
    A B C 
0 0.0 1 3 
1 0.5 4 2 
2 1.0 6 1 
3 1.5 NaN NaN 
4 2.0 NaN NaN 
5 2.5 NaN NaN 
6 3.0 NaN NaN 
7 3.5 2 0 
8 4.0 4 5 
9 4.5 3 3 

Tak w ogólnym przypadku można ustawić funkcję arange która przyjmuje wartość początkową i końcową, trzeba pamiętać, że dodaje się 0,5 do końca jak zakresy są otwarte zamknięte, i przekazać wartość kroku.

bardziej ogólny sposób może być tak:

In [197]: 

df = df.set_index(keys='A', drop=False).reindex(np.arange(df.iloc[0]['A'], df.iloc[-1]['A'] + 0.5, 0.5)) 
df.reset_index(inplace=True) 
df['A'] = df['index'] 
df.drop(['A'], axis=1, inplace=True) 
df.reset_index().drop(['level_0'], axis=1) 
Out[197]: 
    index B C 
0 0.0 1 3 
1 0.5 4 2 
2 1.0 6 1 
3 1.5 NaN NaN 
4 2.0 NaN NaN 
5 2.5 NaN NaN 
6 3.0 NaN NaN 
7 3.5 2 0 
8 4.0 4 5 
9 4.5 3 3 

Tutaj ustawiamy indeks na kolumnie A ale nie upuszczać go, a następnie reindex DF użyciu funkcji arange.

1

Korzystanie odpowiedź przez EdChum powyżej, stworzyłem następującą funkcję

def fill_missing_range(df, field, range_from, range_to, range_step=1, fill_with=0): 
    return df\ 
     .merge(how='right', on=field, 
      right = pd.DataFrame({field:np.arange(range_from, range_to, range_step)}))\ 
     .sort_values(by=field).reset_index().fillna(fill_with).drop(['index'], axis=1) 

Przykład wykorzystania:

fill_missing_range(df, 'A', 0.0, 4.5, 0.5, np.nan) 
Powiązane problemy