2013-03-15 15 views
13

Mam następujące dane ramek odczytu z pliku .csv z kolumna "Data" jest indeksem. Dni są w rzędach, a kolumny pokazują wartości dla godzin tego dnia.Jak zmienić rozmieszczenie ramki danych pandy Pythona?

> Date   h1 h2 h3 h4 ... h24 
> 14.03.2013 60 50 52 49 ... 73 

chciałbym zorganizować to tak, dlatego, że istnieje jedna kolumna indeksu z data/czas i jedna kolumna z wartościami w sekwencji

>Date/Time   Value 
>14.03.2013 00:00:00 60 
>14.03.2013 01:00:00 50 
>14.03.2013 02:00:00 52 
>14.03.2013 03:00:00 49 
>. 
>. 
>. 
>14.03.2013 23:00:00 73 

starałem go za pomocą dwie pętle do przejścia przez ramkę danych. Czy jest to łatwiejszy sposób w pandach?

Odpowiedz

15

Nie jestem najlepszy na dzień manipulacji, ale może coś takiego:

import pandas as pd 
from datetime import timedelta 

df = pd.read_csv("hourmelt.csv", sep=r"\s+") 

df = pd.melt(df, id_vars=["Date"]) 
df = df.rename(columns={'variable': 'hour'}) 
df['hour'] = df['hour'].apply(lambda x: int(x.lstrip('h'))-1) 

combined = df.apply(lambda x: 
        pd.to_datetime(x['Date'], dayfirst=True) + 
        timedelta(hours=int(x['hour'])), axis=1) 

df['Date'] = combined 
del df['hour'] 

df = df.sort("Date") 

Niektóre wyjaśnienie poniżej.

Począwszy od

>>> import pandas as pd 
>>> from datetime import datetime, timedelta 
>>> 
>>> df = pd.read_csv("hourmelt.csv", sep=r"\s+") 
>>> df 
     Date h1 h2 h3 h4 h24 
0 14.03.2013 60 50 52 49 73 
1 14.04.2013 5 6 7 8 9 

Możemy użyć pd.melt aby kolumny godzinę w jednej kolumnie z tej wartości:

>>> df = pd.melt(df, id_vars=["Date"]) 
>>> df = df.rename(columns={'variable': 'hour'}) 
>>> df 
     Date hour value 
0 14.03.2013 h1  60 
1 14.04.2013 h1  5 
2 14.03.2013 h2  50 
3 14.04.2013 h2  6 
4 14.03.2013 h3  52 
5 14.04.2013 h3  7 
6 14.03.2013 h4  49 
7 14.04.2013 h4  8 
8 14.03.2013 h24  73 
9 14.04.2013 h24  9 

pozbyć się tych h S:

>>> df['hour'] = df['hour'].apply(lambda x: int(x.lstrip('h'))-1) 
>>> df 
     Date hour value 
0 14.03.2013  0  60 
1 14.04.2013  0  5 
2 14.03.2013  1  50 
3 14.04.2013  1  6 
4 14.03.2013  2  52 
5 14.04.2013  2  7 
6 14.03.2013  3  49 
7 14.04.2013  3  8 
8 14.03.2013 23  73 
9 14.04.2013 23  9 

Połącz dwie kolumny jako datę:

>>> combined = df.apply(lambda x: pd.to_datetime(x['Date'], dayfirst=True) + timedelta(hours=int(x['hour'])), axis=1) 
>>> combined 
0 2013-03-14 00:00:00 
1 2013-04-14 00:00:00 
2 2013-03-14 01:00:00 
3 2013-04-14 01:00:00 
4 2013-03-14 02:00:00 
5 2013-04-14 02:00:00 
6 2013-03-14 03:00:00 
7 2013-04-14 03:00:00 
8 2013-03-14 23:00:00 
9 2013-04-14 23:00:00 

Zamontować i oczyścić:

>>> df['Date'] = combined 
>>> del df['hour'] 
>>> df = df.sort("Date") 
>>> df 
       Date value 
0 2013-03-14 00:00:00  60 
2 2013-03-14 01:00:00  50 
4 2013-03-14 02:00:00  52 
6 2013-03-14 03:00:00  49 
8 2013-03-14 23:00:00  73 
1 2013-04-14 00:00:00  5 
3 2013-04-14 01:00:00  6 
5 2013-04-14 02:00:00  7 
7 2013-04-14 03:00:00  8 
9 2013-04-14 23:00:00  9 
+0

Ładne rozwiązanie! Możesz połączyć 'df ['godzina']. Zastosuj (...)' i 'combined = ...' linie do 'df ['Date'] + = df ['hour']. Apply (lambda x: timedelta (hours = int (x.lstrip ('h')) - 1)) '. – unutbu

+0

Świetne rozwiązanie. Wielkie dzięki. Właśnie ustawiłem Date jako indeks i działa idealnie. > df = df.set_index ("Data") –

1

Można zawsze chwycić data_array godzinowej i spłaszcza go. Wygenerowałbyś nowy DatetimeIndex z godzinową freq.

df = df.asfreq('D') 
hourly_data = df.values[:, :] 
new_ind = pd.date_range(start=df.index[0], freq="H", periods=len(df) * 24) 
# create Series. 
s = pd.Series(hourly_data.flatten(), index=new_ind) 

Zakładam, że read_csv parsuje kolumnę "Data" i czyni ją indeksem. Zmieniamy częstotliwość na "D", aby linie new_ind wierszyły się poprawnie, jeśli brakuje dni. Brakujące dni zostaną wypełnione np.nan, które można usunąć za pomocą s.dropna().

notebook link

Powiązane problemy