2012-10-15 12 views
7

Jestem nowy w pandach i próbuję odczytać dziwny sformatowany plik w DataFrame. Oryginalny plik wygląda tak:Skutecznie rozwiń linie z pand DataFrame

; No Time Date MoistAve MatTemp TDRConduct TDRAve DeltaCount tpAve Moist1 Moist2 Moist3 Moist4 TDR1 TDR2 TDR3 TDR4 
1 11:38:17 11.07.2012 11.37 48.20 5.15 88.87 15 344.50 11.84 11.35 11.59 15.25 89.0 89.0 89.0 88.0 
2 11:38:18 11.07.2012 11.44 48.20 5.13 88.88 2 346.22 12.08 11.83 -1.00 -1.00 89.0 89.0 -1.0 -1.0 
3 11:38:19 11.07.2012 11.10 48.20 4.96 89.00 3 337.84 11.83 11.59 10.62 -1.00 89.0 89.0 89.0 -1.0 
4 11:38:19 11.07.2012 11.82 48.20 5.54 88.60 3 355.92 11.10 13.54 12.32 -1.00 89.0 88.0 88.0 -1.0 

udało mi się uzyskać równie uporządkowanego DataFrame z:

In [42]: date_spec = {'FetchTime': [1, 2]} 

In [43]: df = pd.read_csv('MeasureCK32450-20120711114050.mck', header=7, sep='\s\s+', 
          parse_dates=date_spec, na_values=['-1.0', '-1.00']) 

In [44]: df 
Out[52]: 
       FetchTime ; No MoistAve MatTemp TDRConduct TDRAve DeltaCount tpAve Moist1 Moist2 Moist3 Moist4 TDR1 TDR2 TDR3 TDR4 
0 2012-11-07 11:38:17  1  11.37  48.2  5.15 88.87   15 344.50 11.84 11.35 11.59 15.25 89 89 89 88 
1 2012-11-07 11:38:18  2  11.44  48.2  5.13 88.88   2 346.22 12.08 11.83  NaN  NaN 89 89 NaN NaN 
2 2012-11-07 11:38:19  3  11.10  48.2  4.96 89.00   3 337.84 11.83 11.59 10.62  NaN 89 89 89 NaN 
3 2012-11-07 11:38:19  4  11.82  48.2  5.54 88.60   3 355.92 11.10 13.54 12.32  NaN 89 88 88 NaN 

Ale teraz muszę rozwinąć każdą linię tego DataFrame

.... Moist1 Moist2 Moist3 Moist4 TDR1 TDR2 TDR3 TDR4 
1 .... 11.84 11.35 11.59 15.25 89 89 89 88 
2 .... 12.08 11.83  NaN  NaN 89 89 NaN NaN 

na cztery linie (z trzema indeksami Nie, FetchTime i MeasureNo):

        .... Moist TDR 
No   FetchTime MeasureNo 
0 2012-11-07 11:38:17   1 .... 11.84 89 # from line 1, Moist1 and TDR1 
1        2 .... 11.35 89 # from line 1, Moist2 and TDR2 
2        3 .... 11.59 89 # from line 1, Moist3 and TDR3 
3        4 .... 15.25 88 # from line 1, Moist4 and TDR4 
4 2012-11-07 11:38:18   1 .... 12.08 89 # from line 2, Moist1 and TDR1 
5        2 .... 11.83 89 # from line 2, Moist2 and TDR2 
6        3 .... NaN NaN # from line 2, Moist3 and TDR3 
7        4 .... NaN NaN # from line 2, Moist4 and TDR4 

zachowując pozostałe kolumny i MOST ważne, zachowując kolejność wpisów. I wiem, że mogę iterować przez każdą linię z for row in df.iterrows(): ..., ale czytam, że jest to niezbyt szybkie. Moje pierwsze podejście było takie:

In [54]: data = [] 
In [55]: for d in range(1,5): 
....:  temp = df.ix[:, ['FetchTime', 'MoistAve', 'MatTemp', 'TDRConduct', 'TDRAve', 'DeltaCount', 'tpAve', 'Moist%d' % d, 'TDR%d' % d]] 
....:  temp.columns = ['FetchTime', 'MoistAve', 'MatTemp', 'TDRConduct', 'TDRAve', 'DeltaCount', 'tpAve', 'RawMoist', 'RawTDR'] 
....:  temp['MeasureNo'] = d 
....:  data.append(temp) 
....:  
In [56]: test = pd.concat(data, ignore_index=True) 
In [62]: test.head() 
Out[62]: 
      FetchTime MoistAve MatTemp TDRConduct TDRAve DeltaCount tpAve RawMoist RawTDR MeasureNo 
0 2012-11-07 11:38:17  11.37  48.2  5.15 88.87   15 344.50  11.84  89   1 
1 2012-11-07 11:38:18  11.44  48.2  5.13 88.88   2 346.22  12.08  89   1 
2 2012-11-07 11:38:19  11.10  48.2  4.96 89.00   3 337.84  11.83  89   1 
3 2012-11-07 11:38:19  11.82  48.2  5.54 88.60   3 355.92  11.10  89   1 
4 2012-11-07 11:38:20  12.61  48.2  5.87 88.38   3 375.72  12.80  89   1 

Ale nie widzę sposobu wpływania na konkatenacji dostać rozkaz muszę ... Czy jest jakiś inny sposób, aby uzyskać wynikowy DataFrame muszę?

+0

można załadować 2 odrębnych ramek danych i czy dołączyć/groupby na datetime? – reptilicus

+0

Zobacz także http://stackoverflow.com/questions/11795992/pandas-efficiently-splitting-entries –

Odpowiedz

0

Daje każdy daje czwarty wiersz w teście zaczynając od „I”

test.ix[i::4] 

Stosując tę ​​samą podstawową pętlę jak wyżej, tylko dołączyć komplet każdy czwartym rzędzie, zaczynając od 0 do 3 po uruchomić kod powyżej.

data = []  
for i in range(0,3:):  
    temp = test.ix[i::4] 
    data.append(temp) 
test2 = pd.concat(data,ignore_index=True) 

Aktualizacja: teraz zdaję sobie sprawę, że to, co tylko chcesz, nie jest co czwarty rząd, ale każdy wiersz mth, więc to będzie tylko sugestie pętli powyżej. Przepraszam.

Aktualizacja 2: Może nie. Możemy skorzystać z tego, że nawet jeśli konkatenacja nie zwraca żądanej kolejności, to, co zwraca, ma stałe odwzorowanie na to, czego chcesz. d to liczba wierszy na znacznik czasu, a m to liczba znaczników czasu.

Wygląda na to, że chcesz, aby wiersze z testu wyglądały następująco: [0, m, 2m, 3m, 1, m + 1,2 m + 1,3 m + 1,2, m + 2,2 m + 2,3 m +2, ..., m-1,2m-1,3m-1,4m-1]

Jestem pewien, że istnieje wiele ładniejszych sposobów generowania tej listy indeksów, ale to zadziałało dla mnie

d = 4 
m = 10 
small = (np.arange(0,m).reshape(m,1).repeat(d,1).T.reshape(-1,1)) 
shifter = (np.arange(0,d).repeat(m).reshape(-1,1).T * m) 
NewIndex = (shifter.reshape(d,-1) + small.reshape(d,-1)).T.reshape(-1,1) 
NewIndex = NewIndex.reshape(-1) 
test = test.ix[NewIndex] 
+0

Istnieje inne podejście obejmujące pd.stack i pd.merge, które mogą działać. To zależy od pól czasowych. Jak widzę pola w twoich danych, wiersze 3 i 4 mają ten sam znacznik czasu i dnia. Czy jest to efekt formatowania lub precyzji, w której dane są rejestrowane. Pytam, ponieważ gdy wyświetlasz dane wyjściowe: – BKay

+0

Jeśli jest to tylko formatowanie, a czas jest zapisywany z dokładnością, że wszystkie wpisy są unikalne, to stos i scalenie Zrób to. Daj mi znać, a ja opublikuję kod. – BKay

1

Oto rozwiązanie oparte na powtarzaniu numpy i indeksowaniu tablic do budowania wartości ułożonych na stosie, a pandy łączą się, aby wyprowadzić połączony wynik.

Najpierw załaduj próbkę danych do DataFrame (nieznacznie zmienione argumenty read_csv).

from cStringIO import StringIO 

data = """; No Time Date MoistAve MatTemp TDRConduct TDRAve DeltaCount tpAve Moist1 Moist2 Moist3 Moist4 TDR1 TDR2 TDR3 TDR4 
1 11:38:17 11.07.2012 11.37 48.20 5.15 88.87 15 344.50 11.84 11.35 11.59 15.25 89.0 89.0 89.0 88.0 
2 11:38:18 11.07.2012 11.44 48.20 5.13 88.88 2 346.22 12.08 11.83 -1.00 -1.00 89.0 89.0 -1.0 -1.0 
3 11:38:19 11.07.2012 11.10 48.20 4.96 89.00 3 337.84 11.83 11.59 10.62 -1.00 89.0 89.0 89.0 -1.0 
4 11:38:19 11.07.2012 11.82 48.20 5.54 88.60 3 355.92 11.10 13.54 12.32 -1.00 89.0 88.0 88.0 -1.0 
""" 

date_spec = {'FetchTime': [1, 2]} 
df = pd.read_csv(StringIO(data), header=0, sep='\s\s+',parse_dates=date_spec, na_values=['-1.0', '-1.00']) 

Następnie zbudować de ułożone wektor TDR i połączyć je z oryginalnym ramki danych

stacked_col_names = ['TDR1','TDR2','TDR3','TDR4'] 

repeated_row_indexes = np.repeat(np.arange(df.shape[0]),4) 
repeated_col_indexes = [np.where(df.columns == c)[0][0] for c in stacked_col_names] 

destacked_tdrs = pd.DataFrame(data=df.values[repeated_row_indexes,repeated_col_indexes],index=df.index[repeated_row_indexes],columns=['TDR']) 

ouput = pd.merge(left_index = True, right_index = True, left = df, right = destacked_tdrs) 

Z żądanej wyjściowej:

output.ix[:,['TDR1','TDR2','TDR3','TDR4','TDR']] 

    TDR1 TDR2 TDR3 TDR4 TDR 
0 89 89 89 88 89 
0 89 89 89 88 89 
0 89 89 89 88 89 
0 89 89 89 88 88 
1 89 89 NaN NaN 89 
1 89 89 NaN NaN 89 
1 89 89 NaN NaN NaN 
1 89 89 NaN NaN NaN 
2 89 89 89 NaN 89 
2 89 89 89 NaN 89 
2 89 89 89 NaN 89 
2 89 89 89 NaN NaN 
3 89 88 88 NaN 89 
3 89 88 88 NaN 88 
3 89 88 88 NaN 88 
3 89 88 88 NaN NaN 
Powiązane problemy