42

UTC のタイムスタンプを持つデータがあります。このタイムスタンプのタイムゾーンを「US/Pacific」に変換し、階層インデックスとして pandas DataFrame に追加したいと思います。タイムスタンプをインデックスとして変換できましたが、列またはインデックスとして DataFrame に追加しようとすると、タイムゾーンの書式設定が失われます。

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

シリーズを直接変換しようとすると、エラーが発生します。

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

それをインデックスに変換すると、時系列として操作できます。インデックスに太平洋タイムゾーンが含まれるようになったことに注意してください。

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

ただし、タイムゾーンのフォーマットが失われるため、インデックスをデータフレームに追加し直すときに問題が発生しました。

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

インデックスが、変換された太平洋タイムゾーンではなく、UTC タイムゾーンに戻っていることに気付くでしょう。

タイムゾーンを変更して DataFrame のインデックスとして追加するにはどうすればよいですか?

4

4 に答える 4

30

これをインデックスとして設定すると、自動的にインデックスに変換されます。

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

次に、次のことを行います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

次に、ラベル列をインデックスに追加できます。

うーん、これは間違いなくバグです!

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

ハックな回避策は、(datetime) レベルを直接変換することです (既に 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
于 2013-06-18T01:24:42.940 に答える
23

今のところ、これは修正されています。たとえば、次のように呼び出すことができます。

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

ただし、この例では 2 回呼び出す必要があります。(つまり、各レベルで 1 回)。

于 2016-07-29T12:18:11.103 に答える