source

판다 시간대 인식 날짜 시간 변환단순 타임스탬프로 인덱싱하지만 특정 시간대에 있음

nicesource 2023. 6. 8. 19:52
반응형

판다 시간대 인식 날짜 시간 변환단순 타임스탬프로 인덱싱하지만 특정 시간대에 있음

은 기능을 할 수 .tz_localize 또는 하도록 만드는 것, 할 수 : 시간대를할 수 ?인덱스 시간대 인식, 하지만 어떻게 반대로 할 수 있습니까? 타임스탬프를 인식하는 시간대를 단순한 시간대로 어떻게 변환할 수 있습니까?

예:

In [82]: t = pd.date_range(start="2013-05-18 12:00:00", periods=10, freq='s', tz="Europe/Brussels")

In [83]: t
Out[83]: 
<class 'pandas.tseries.index.DatetimeIndex'>
[2013-05-18 12:00:00, ..., 2013-05-18 12:00:09]
Length: 10, Freq: S, Timezone: Europe/Brussels

없음으로 설정하여 시간대를 제거할 수 있지만 결과는 UTC로 변환됩니다(12시가 10시가 됨).

In [86]: t.tz = None

In [87]: t
Out[87]: 
<class 'pandas.tseries.index.DatetimeIndex'>
[2013-05-18 10:00:00, ..., 2013-05-18 10:00:09]
Length: 10, Freq: S, Timezone: None

날짜 시간을 변환할 수 있는 다른 방법이 있습니까?인덱스에서 표준 시간대로 단순하지만 표준 시간대를 보존하는 동안 설정되었습니까?


제가 이 질문을 하는 이유에 대한 몇 가지 맥락:저는 (시간대와 관련된 추가적인 번거로움을 피하기 위해, 제가 작업하고 있는 경우에는 필요하지 않은) 시간대의 단순한 시계열로 작업하고 싶습니다.
하지만 어떤 이유에서인지 현지 시간대(유럽/브뤼셀)에서 시간대 인식 시계열을 처리해야 합니다.다른 모든 데이터는 표준 시간대가 단순하기 때문에(그러나 나의 로컬 시간대에 표시됨), 이 시계열을 단순하게 변환하여 추가 작업을 수행하고 싶지만 사용자가 볼 수 있는 시간대를 UTC로 변환하지 않고 표준 시간대 정보만 제거해야 합니다.

시간은 실제로 UTC로 내부 저장되어 있고 사용자가 표시할 때만 다른 시간대로 변환되므로 "비국재화"하려면 변환이 필요합니다.예를 들어, python datetime 모듈을 사용하면 다음과 같이 시간대를 "제거"할 수 있습니다.

In [119]: d = pd.Timestamp("2013-05-18 12:00:00", tz="Europe/Brussels")

In [120]: d
Out[120]: <Timestamp: 2013-05-18 12:00:00+0200 CEST, tz=Europe/Brussels>

In [121]: d.replace(tzinfo=None)
Out[121]: <Timestamp: 2013-05-18 12:00:00> 

따라서 이를 바탕으로 다음과 같은 작업을 수행할 수 있지만 더 큰 시계열로 작업할 때는 그다지 효율적이지 않을 것으로 생각합니다.

In [124]: t
Out[124]: 
<class 'pandas.tseries.index.DatetimeIndex'>
[2013-05-18 12:00:00, ..., 2013-05-18 12:00:09]
Length: 10, Freq: S, Timezone: Europe/Brussels

In [125]: pd.DatetimeIndex([i.replace(tzinfo=None) for i in t])
Out[125]: 
<class 'pandas.tseries.index.DatetimeIndex'>
[2013-05-18 12:00:00, ..., 2013-05-18 12:00:09]
Length: 10, Freq: None, Timezone: None

제 질문에 답하기 위해, 이 기능은 그동안 판다에 추가되었습니다.팬더 0.15.0부터 시작해서, 당신은 사용할 수 있습니다.tz_localize(None)시간대를 제거하여 로컬 시간을 생성합니다.
새로운 기능 항목을 참조하십시오.

위의 예를 들어 보겠습니다.

In [4]: t = pd.date_range(start="2013-05-18 12:00:00", periods=2, freq='H',
                          tz= "Europe/Brussels")

In [5]: t
Out[5]: DatetimeIndex(['2013-05-18 12:00:00+02:00', '2013-05-18 13:00:00+02:00'],
                       dtype='datetime64[ns, Europe/Brussels]', freq='H')

용사를 tz_localize(None)시간대 정보를 제거하여 로컬 시간을 단순하게 만듭니다.

In [6]: t.tz_localize(None)
Out[6]: DatetimeIndex(['2013-05-18 12:00:00', '2013-05-18 13:00:00'], 
                      dtype='datetime64[ns]', freq='H')

은 또다음수있다니습사용할을한을 사용할 .tz_convert(None)표준 시간대 정보를 제거하지만 UTC로 변환하여 순진한 UTC 시간을 산출합니다.

In [7]: t.tz_convert(None)
Out[7]: DatetimeIndex(['2013-05-18 10:00:00', '2013-05-18 11:00:00'], 
                      dtype='datetime64[ns]', freq='H')

이것은 그것보다 훨씬성능이 좋습니다.datetime.replace솔루션:

In [31]: t = pd.date_range(start="2013-05-18 12:00:00", periods=10000, freq='H',
                           tz="Europe/Brussels")

In [32]: %timeit t.tz_localize(None)
1000 loops, best of 3: 233 µs per loop

In [33]: %timeit pd.DatetimeIndex([i.replace(tzinfo=None) for i in t])
10 loops, best of 3: 99.7 ms per loop

저는 항상 기억하려고 노력하기 때문에, 이것들 각각이 무엇을 하는지에 대한 간단한 요약입니다.

>>> pd.Timestamp.now()  # naive local time
Timestamp('2019-10-07 10:30:19.428748')

>>> pd.Timestamp.utcnow()  # tz aware UTC
Timestamp('2019-10-07 08:30:19.428748+0000', tz='UTC')

>>> pd.Timestamp.now(tz='Europe/Brussels')  # tz aware local time
Timestamp('2019-10-07 10:30:19.428748+0200', tz='Europe/Brussels')

>>> pd.Timestamp.now(tz='Europe/Brussels').tz_localize(None)  # naive local time
Timestamp('2019-10-07 10:30:19.428748')

>>> pd.Timestamp.now(tz='Europe/Brussels').tz_convert(None)  # naive UTC
Timestamp('2019-10-07 08:30:19.428748')

>>> pd.Timestamp.utcnow().tz_localize(None)  # naive UTC
Timestamp('2019-10-07 08:30:19.428748')

>>> pd.Timestamp.utcnow().tz_convert(None)  # naive UTC
Timestamp('2019-10-07 08:30:19.428748')

저는 당신이 제안한 것보다 더 효율적으로 원하는 것을 이룰 수 없다고 생각합니다.

기본적인 문제는 타임스탬프가 두 부분으로 구성되어 있다는 것입니다.UTC 시간과 시간대인 tz_info를 나타내는 데이터입니다.표준 시간대 정보는 화면에 표준 시간대를 인쇄할 때 표시 목적으로만 사용됩니다.표시 시간에 데이터가 적절하게 오프셋되고 +01:00(또는 유사)이 문자열에 추가됩니다.tz_info 값(tz_convert(tz=Domino) 사용)을 제거해도 타임스탬프의 단순한 부분을 나타내는 데이터는 실제로 변경되지 않습니다.

따라서 원하는 작업을 수행할 수 있는 유일한 방법은 기본 데이터를 수정하는 것입니다(판다는 이를 허용하지 않습니다...날짜/시간색인은 변경할 수 없습니다. Datetime 도움말을 참조하십시오.인덱스) 또는 새 타임스탬프 객체 세트를 만들고 새 Datetime으로 래핑합니다.인덱스. 솔루션은 다음 작업을 수행합니다.

pd.DatetimeIndex([i.replace(tzinfo=None) for i in t])

참고로, 여기에 다음과 같은 것이 있습니다.replaceTimestampsetslib.pyx 조참):

def replace(self, **kwds):
    return Timestamp(datetime.replace(self, **kwds),
                     offset=self.offset)

당신은 를참수다있니에 있는 할 수 .datetime.datetimedatetime.datetime.replace또한 새 개체를 만듭니다.

가능하면 시간대 없이 타임스탬프를 잘못 보고하도록 데이터 원본을 수정하는 것이 효율성을 위한 최선의 방법입니다.언급하신 내용:

저는 (시간대와 관련된 추가적인 번거로움을 피하기 위해, 제가 작업 중인 경우에는 필요하지 않은) 시간대 순진한 시계열로 작업하고 싶습니다.

저는 당신이 어떤 추가적인 번거로움을 말씀하시는 건지 궁금합니다.모든 소프트웨어 개발에 대한 일반적인 규칙으로 UTC에 타임스탬프를 '순수한 값'으로 유지하는 것이 좋습니다.두 개의 다른 int64 값이 어느 시간대에 속하는지 궁금해하는 것보다 더 나쁜 것은 없습니다.항상, 항상, 항상 내부 스토리지에 UTC를 사용하면 수많은 문제를 피할 수 있습니다.저는 Timezones가 사람의 I/O만을 위한 것이라고 생각합니다.

승인된 솔루션은 영상 시리즈에 여러 개의 서로 다른 시간대가 있는 경우에는 작동하지 않습니다.은 다던니를 던집니다.ValueError: Tz-aware datetime.datetime cannot be converted to datetime64 unless utc=True

솔루션은 다음을 사용하는 것입니다.apply방법.

아래의 예를 참조하십시오.

# Let's have a series `a` with different multiple timezones. 
> a
0    2019-10-04 16:30:00+02:00
1    2019-10-07 16:00:00-04:00
2    2019-09-24 08:30:00-07:00
Name: localized, dtype: object

> a.iloc[0]
Timestamp('2019-10-04 16:30:00+0200', tz='Europe/Amsterdam')

# trying the accepted solution
> a.dt.tz_localize(None)
ValueError: Tz-aware datetime.datetime cannot be converted to datetime64 unless utc=True

# Make it tz-naive. This is the solution:
> a.apply(lambda x:x.tz_localize(None))
0   2019-10-04 16:30:00
1   2019-10-07 16:00:00
2   2019-09-24 08:30:00
Name: localized, dtype: datetime64[ns]

# a.tz_convert() also does not work with multiple timezones, but this works:
> a.apply(lambda x:x.tz_convert('America/Los_Angeles'))
0   2019-10-04 07:30:00-07:00
1   2019-10-07 13:00:00-07:00
2   2019-09-24 08:30:00-07:00
Name: localized, dtype: datetime64[ns, America/Los_Angeles]

설정tz인덱스의 속성은 분명히 작동하는 것 같습니다.

ts_utc = ts.tz_convert("UTC")
ts_utc.index.tz = None

늦게 기여했지만 파이썬 날짜 시간에서 비슷한 것을 발견했고 판다는 같은 날짜에 대해 다른 타임스탬프를 제공합니다.

시간대를 인식하는 날짜/시간이 있는 경우pandas 기술적으로 에서는 내부적으로 사용되는 POSIX 타임스탬프를 타임스탬프의 로컬 시간이 UTC인 것처럼 변경합니다. 컨텍스트에서 로컬은 지정된 시간대의 로컬을 의미합니다.예:

import pandas as pd

t = pd.date_range(start="2013-05-18 12:00:00", periods=2, freq='H', tz="US/Central")
# DatetimeIndex(['2013-05-18 12:00:00-05:00', '2013-05-18 13:00:00-05:00'], dtype='datetime64[ns, US/Central]', freq='H')

t_loc = t.tz_localize(None)
# DatetimeIndex(['2013-05-18 12:00:00', '2013-05-18 13:00:00'], dtype='datetime64[ns]', freq='H')

# offset in seconds according to timezone:
(t_loc.values-t.values)//1e9
# array([-18000, -18000], dtype='timedelta64[ns]')

경우 DST 전환 중에 예를 들어 이상한 점이 발생합니다.

t = pd.date_range(start="2020-03-08 01:00:00", periods=2, freq='H', tz="US/Central")
(t.values[1]-t.values[0])//1e9
# numpy.timedelta64(3600,'ns')

t_loc = t.tz_localize(None)
(t_loc.values[1]-t_loc.values[0])//1e9
# numpy.timedelta64(7200,'ns')

그에 반해서,tz_convert(None)내부 타임스탬프를 수정하지 않고, 단지 제거할 뿐입니다.tzinfo.

t_utc = t.tz_convert(None)
(t_utc.values-t.values)//1e9
# array([0, 0], dtype='timedelta64[ns]')

제 결론은: 사용할 수 있거나 사용만 가능한 경우 시간대 인식 날짜 시간을 고수하는 것입니다.t.tz_convert(None)기본 POSIX 타임스탬프를 수정하지 않습니다.그렇다면 실제로 UTC와 함께 작업하고 있다는 것을 명심하십시오.

(Windows 10의 경우 Python 3.8.2 x64,pandasv1.0.5).

D 위에 건물."원하는 일을 할 수 있는 유일한 방법은 기본 데이터를 수정하는 것"이라는 A.의 제안과 기본 데이터를 수정하기 위해 numpy를 사용하는 것...

이것은 저에게 효과적이고 매우 빠릅니다.

def tz_to_naive(datetime_index):
    """Converts a tz-aware DatetimeIndex into a tz-naive DatetimeIndex,
    effectively baking the timezone into the internal representation.

    Parameters
    ----------
    datetime_index : pandas.DatetimeIndex, tz-aware

    Returns
    -------
    pandas.DatetimeIndex, tz-naive
    """
    # Calculate timezone offset relative to UTC
    timestamp = datetime_index[0]
    tz_offset = (timestamp.replace(tzinfo=None) - 
                 timestamp.tz_convert('UTC').replace(tzinfo=None))
    tz_offset_td64 = np.timedelta64(tz_offset)

    # Now convert to naive DatetimeIndex
    return pd.DatetimeIndex(datetime_index.values + tz_offset_td64)

가장 중요한 것은 추가입니다.tzinfodatetime 개체를 정의할 때 사용합니다.

from datetime import datetime, timezone
from tzinfo_examples import HOUR, Eastern
u0 = datetime(2016, 3, 13, 5, tzinfo=timezone.utc)
for i in range(4):
     u = u0 + i*HOUR
     t = u.astimezone(Eastern)
     print(u.time(), 'UTC =', t.time(), t.tzname())

유럽에서 15분 빈도의 날짜/시간 인덱스를 사용하여 이 문제를 처리한 방법.

시간대를 인지하고 있는 상황이라면 (Europe/Amsterdam나의 경우) 인덱스와 모든 것을 현지 시간으로 변환하여 시간대 순진한 인덱스로 변환하고 싶다면, 당신은 dst 문제를 겪을 것입니다.

  • 3월의 마지막 일요일에 1시간이 누락될 것입니다(유럽이 여름 시간으로 전환할 때)
  • 10월 마지막 일요일에 1시간 중복됩니다(유럽이 여름 시간으로 전환할 때).

처리 방법은 다음과 같습니다.

# make index tz naive
df.index = df.index.tz_localize(None)

# handle dst
if df.index[0].month == 3:
    # last sunday of march, one hour is lost
    df = df.resample("15min").pad()

if df.index[0].month == 10:
    # in october, one hour is added
    df = df[~df.index.duplicated(keep='last')]

참고: 저의 경우, 위의 코드를 실행합니다.df단 한 달만 포함되어 있기 때문에, 나는.df.index[0].month그 달을 알기 위해.만약 당신의 것이 더 많은 달을 포함하고 있다면, 당신은 언제 DST를 해야 하는지 알기 위해 그것을 다른 방식으로 색인해야 할 것입니다.

이는 1시간의 손실을 방지하기 위해 3월의 마지막 유효 값에서 재샘플링으로 구성됩니다(저의 경우 모든 데이터가 15분 간격으로 있으므로 이와 유사합니다).구간에 관계없이 다시 샘플링합니다.그리고 10월에는 복제품을 보냅니다.

언급URL : https://stackoverflow.com/questions/16628819/convert-pandas-timezone-aware-datetimeindex-to-naive-timestamp-but-in-certain-t

반응형