2013-03-15 47 views
13

Tôi có dữ liệu sau đây được đọc từ tệp .csv có cột "Ngày" làm chỉ mục. Các ngày nằm trong các hàng và các cột hiển thị các giá trị cho giờ trong ngày đó.Làm cách nào để sắp xếp lại một khung dữ liệu pandas python?

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

Tôi muốn sắp xếp nó như thế này, do đó có một cột chỉ số với ngày/giờ và một cột với các giá trị trong một chuỗi

>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 

Tôi đã cố gắng nó bằng cách sử dụng hai vòng lặp đi qua khung dữ liệu. Có cách nào dễ dàng hơn để làm điều này trong gấu trúc không?

Trả lời

15

tôi không phải là tốt nhất tại thao tác cập nhật, nhưng có lẽ một cái gì đó như thế này:

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

Một số lời giải thích sau.

Bắt đầu từ

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

Chúng ta có thể sử dụng pd.melt để làm cho cột giờ vào một cột với giá trị đó:

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

Loại bỏ những 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 

Kết hợp hai cột dưới dạng ngày:

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

lắp ráp lại và dọn dẹp:

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

Giải pháp tốt! Bạn có thể kết hợp 'df ['hour']. Áp dụng (...)' và 'combined = ...' các dòng vào 'df ['Date'] + = df ['hour']. Apply (lambda x: timedelta (giờ = int (x.lstrip ('h')) - 1)) '. – unutbu

+0

Giải pháp tuyệt vời. Cảm ơn rất nhiều. Tôi vừa đặt Ngày làm chỉ mục và nó hoạt động hoàn hảo. > df = df.set_index ('Ngày') –

1

Bạn luôn có thể lấy data_array giờ và làm phẳng nó. Bạn sẽ tạo ra một DatetimeIndex mới với freq theo giờ.

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) 

Tôi giả định rằng read_csv đang phân tích cú pháp cột 'Ngày' và biến nó thành chỉ mục. Chúng tôi thay đổi thành tần số 'D' để các dòng new_ind hoạt động chính xác nếu bạn bị thiếu ngày. Những ngày còn thiếu sẽ được lấp đầy với np.nan mà bạn có thể thả với s.dropna().

notebook link

Các vấn đề liên quan