2013-06-18 34 views
21

Tôi có dữ liệu có dấu thời gian trong UTC. Tôi muốn chuyển đổi múi giờ của dấu thời gian này thành 'US/Pacific' và thêm múi giờ đó làm chỉ mục phân cấp cho DataFrame gấu trúc. Tôi đã có thể chuyển đổi dấu thời gian dưới dạng Chỉ mục, nhưng nó mất định dạng múi giờ khi tôi cố thêm lại dấu thời gian vào DataFrame, dưới dạng cột hoặc làm chỉ mục.Thay đổi múi giờ của cột ngày giờ trong gấu trúc và thêm làm chỉ mục phân cấp

>>> import pandas as pd 
>>> dat = pd.DataFrame({'label':['a', 'a', 'a', 'b', 'b', 'b'], 'datetime':['2011-07-19 07:00:00', '2011-07-19 08:00:00', '2011-07-19 09:00:00', '2011-07-19 07:00:00', '2011-07-19 08:00:00', '2011-07-19 09:00:00'], 'value':range(6)}) 
>>> dat.dtypes 
#datetime object 
#label  object 
#value  int64 
#dtype: object 

Bây giờ, nếu tôi cố gắng chuyển đổi trực tiếp Series, tôi gặp lỗi.

>>> times = pd.to_datetime(dat['datetime']) 
>>> times.tz_localize('UTC') 
#Traceback (most recent call last): 
# File "<stdin>", line 1, in <module> 
# File "/Users/erikshilts/workspace/schedule-detection/python/pysched/env/lib/python2.7/site-packages/pandas/core/series.py", line 3170, in tz_localize 
# raise Exception('Cannot tz-localize non-time series') 
#Exception: Cannot tz-localize non-time series 

Nếu tôi chuyển đổi nó thành chỉ mục thì tôi có thể điều khiển nó thành một bộ đếm thời gian. Lưu ý rằng chỉ mục hiện có múi giờ Thái Bình Dương.

>>> times_index = pd.Index(times) 
>>> times_index_pacific = times_index.tz_localize('UTC').tz_convert('US/Pacific') 
>>> times_index_pacific 
#<class 'pandas.tseries.index.DatetimeIndex'> 
#[2011-07-19 00:00:00, ..., 2011-07-19 02:00:00] 
#Length: 6, Freq: None, Timezone: US/Pacific 

Tuy nhiên, bây giờ tôi chạy vào vấn đề thêm các chỉ số trở lại dataframe vì nó mất định dạng múi giờ của nó:

>>> dat_index = dat.set_index([dat['label'], times_index_pacific]) 
>>> dat_index 
#          datetime label value 
#label              
#a  2011-07-19 07:00:00 2011-07-19 07:00:00  a  0 
#  2011-07-19 08:00:00 2011-07-19 08:00:00  a  1 
#  2011-07-19 09:00:00 2011-07-19 09:00:00  a  2 
#b  2011-07-19 07:00:00 2011-07-19 07:00:00  b  3 
#  2011-07-19 08:00:00 2011-07-19 08:00:00  b  4 
#  2011-07-19 09:00:00 2011-07-19 09:00:00  b  5 

Bạn sẽ nhận thấy các chỉ số đã trở lại trên múi giờ UTC thay vì múi giờ Thái Bình Dương được chuyển đổi.

Làm cách nào để thay đổi múi giờ và thêm múi giờ đó làm chỉ mục cho DataFrame?

+3

Tôi nghĩ đây là lỗi ... –

+2

Vâng, đây là hành vi lạ (múi giờ là ác). Có lẽ đáng để tạo [vấn đề] (https://github.com/pydata/pandas/issues)! –

+0

"múi giờ là điều ác" - được ưu tiên. – Jason

Trả lời

8

Hiện tại, lỗi này đã được sửa.Ví dụ: bây giờ bạn có thể gọi:

dataframe.tz_localize('UTC', level=0) 

Bạn sẽ phải gọi nó hai lần cho ví dụ cụ thể. (Tức là, một lần cho mỗi cấp độ.)

18

Nếu bạn đặt nó như là chỉ mục, nó sẽ tự động chuyển đổi thành một Index:

In [11]: dat.index = pd.to_datetime(dat.pop('datetime'), utc=True) 

In [12]: dat 
Out[12]: 
        label value 
datetime 
2011-07-19 07:00:00  a  0 
2011-07-19 08:00:00  a  1 
2011-07-19 09:00:00  a  2 
2011-07-19 07:00:00  b  3 
2011-07-19 08:00:00  b  4 
2011-07-19 09:00:00  b  5 

Sau đó làm tz_localize:

In [12]: dat.index = dat.index.tz_localize('UTC').tz_convert('US/Pacific') 

In [13]: dat 
Out[13]: 
          label value 
datetime 
2011-07-19 00:00:00-07:00  a  0 
2011-07-19 01:00:00-07:00  a  1 
2011-07-19 02:00:00-07:00  a  2 
2011-07-19 00:00:00-07:00  b  3 
2011-07-19 01:00:00-07:00  b  4 
2011-07-19 02:00:00-07:00  b  5 

Và sau đó bạn có thể thêm cột nhãn để chỉ số :

Hmmm đây chắc chắn là lỗi!

In [14]: dat.set_index('label', append=True).swaplevel(0, 1) 
Out[14]: 
          value 
label datetime 
a  2011-07-19 07:00:00  0 
     2011-07-19 08:00:00  1 
     2011-07-19 09:00:00  2 
b  2011-07-19 07:00:00  3 
     2011-07-19 08:00:00  4 
     2011-07-19 09:00:00  5 

Một workaround hacky là để chuyển đổi (datetime) cấp trực tiếp (khi nó đã là một MultiIndex):

In [15]: dat.index.levels[1] = dat.index.get_level_values(1).tz_localize('UTC').tz_convert('US/Pacific') 

In [16]: dat1 
Out[16]: 
           value 
label datetime 
a  2011-07-19 00:00:00-07:00  0 
     2011-07-19 01:00:00-07:00  1 
     2011-07-19 02:00:00-07:00  2 
b  2011-07-19 00:00:00-07:00  3 
     2011-07-19 01:00:00-07:00  4 
     2011-07-19 02:00:00-07:00  5 
+0

Có hai vấn đề mà tôi đang gặp phải với điều này: 1) Tôi không thể gọi tz_localize hoặc tz_convert trên MultiIndex; 2) Truy cập trường giờ từ một chỉ mục duy nhất vẫn mang lại cho tôi mảng '[7,8,9,7,8,9]' khi tôi muốn các giá trị Thái Bình Dương (tức là '[0, 1, 2, 0, 1, 2] '). –

+1

Xin lỗi về điều đó, đây là * chắc chắn * một lỗi (cảm ơn bạn đã tìm thấy nó)! Tôi đã thêm một workaround (đó là để chuyển đổi mức datetime một khi nó là một MultiIndex) ... –

0

Cách giải quyết dường như không làm việc vì mức chỉ số của một chỉ số thứ bậc dường như không thay đổi được (FrozenList là không thay đổi).

Bắt đầu với chỉ mục số ít và phụ thêm cũng không hoạt động.

Tạo hàm lambda hoạt động như Dấu thời gian và chuyển đổi từng thành viên của chuỗi được trả về bởi to_datetime() cũng không hoạt động.

Có cách nào để tạo chuỗi nhận biết múi giờ và sau đó chèn chúng vào một khung dữ liệu/tạo chúng thành chỉ mục không?

joined_event_df = joined_event_df.set_index(['pandasTime']) 
joined_event_df.index = joined_event_df.index.get_level_values(1).tz_localize('UTC').tz_convert('US/Central') 
# we have tz-awareness above this line 
joined_event_df = joined_event_df.set_index('sequence', append = True) 
# we lose tz-awareness in the index as soon as we add another index 
joined_event_df = joined_event_df.swaplevel(0,1) 
1

Một workaround khác mà làm việc trong gấu trúc 0.13.1, và giải quyết các FrozenList không thể được gán vấn đề:

index.levels = pandas.core.base.FrozenList([ 
    index.levels[0].tz_localize('UTC').tz_convert(tz), 
    index.levels[1].tz_localize('UTC').tz_convert(tz) 
]) 

Đấu tranh rất nhiều với vấn đề này, MultiIndex mất tz trong nhiều điều kiện khác nữa .

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