【问题标题】:How to remove timezone from a Timestamp column in a pandas dataframe如何从熊猫数据框中的时间戳列中删除时区
【发布时间】:2018-08-18 06:42:35
【问题描述】:

我阅读了Pandas change timezone for forex DataFrame,但我想让我的数据框时区的时间列变得幼稚,以便与 sqlite3 数据库进行互操作。

我的 pandas 数据框中的数据已经转换为 UTC 数据,但我不想在数据库中维护这个 UTC 时区信息。

给定一个从其他来源获得的数据样本,它看起来像这样:

print(type(testdata))
print(testdata)
print(testdata.applymap(type))

给予:

<class 'pandas.core.frame.DataFrame'>
                        time  navd88_ft  station_id  new
0  2018-03-07 01:31:02+00:00  -0.030332          13    5
1  2018-03-07 01:21:02+00:00  -0.121653          13    5
2  2018-03-07 01:26:02+00:00  -0.072945          13    5
3  2018-03-07 01:16:02+00:00  -0.139917          13    5
4  2018-03-07 01:11:02+00:00  -0.152085          13    5
                                     time        navd88_ft     station_id  \
0  <class 'pandas._libs.tslib.Timestamp'>  <class 'float'>  <class 'int'>   
1  <class 'pandas._libs.tslib.Timestamp'>  <class 'float'>  <class 'int'>   
2  <class 'pandas._libs.tslib.Timestamp'>  <class 'float'>  <class 'int'>   
3  <class 'pandas._libs.tslib.Timestamp'>  <class 'float'>  <class 'int'>   
4  <class 'pandas._libs.tslib.Timestamp'>  <class 'float'>  <class 'int'>   

             new  
0  <class 'int'>  
1  <class 'int'>  
2  <class 'int'>  
3  <class 'int'>  
4  <class 'int'>  

但是

newstamp = testdata['time'].tz_convert(None)

给出一个最终错误:

TypeError: index is not a valid DatetimeIndex or PeriodIndex

如何将列替换为时区原始时间戳?

【问题讨论】:

标签: python pandas dataframe timezone timestamp-with-timezone


【解决方案1】:

列必须是datetime dtype,例如在使用pd.to_datetime 之后。 然后,您可以使用tz_localize 更改时区,一个幼稚的时间戳对应时区None

testdata['time'].dt.tz_localize(None)

除非列是索引 (DatetimeIndex),否则必须使用 .dt accessor 访问 pandas datetime functions

【讨论】:

    【解决方案2】:

    当您的数据包含跨越不同时区或应用夏令时之前和之后的日期时间时,例如从带有 psycopg2 的 postges 数据库中获得,根据 pandas 版本,您最终可能会遇到一些最佳转换方法是:

    testdata['time'].apply(lambda x: x.replace(tzinfo=None))
    

    这种情况下的情况(注意FixedOffsetTimezone 与不同的offset 的用法)而.dt.tz_localize(None) 的用法不起作用:

    df = pd.DataFrame([
        datetime.datetime(2018, 5, 17, 21, 40, 20, 775854, 
                          tzinfo=psycopg2.tz.FixedOffsetTimezone(offset=120, name=None)),
        datetime.datetime(2021, 3, 17, 14, 36, 13, 902741, 
                          tzinfo=psycopg2.tz.FixedOffsetTimezone(offset=60, name=None))
    ])
    
    
    pd.__version__
    '0.24.2'
    
    
    df[0].dt.tz_localize(None)
    
    Traceback (most recent call last):
      File "/usr/local/lib/python3.7/site-packages/pandas/core/arrays/datetimes.py", line 1861, in objects_to_datetime64ns
        values, tz_parsed = conversion.datetime_to_datetime64(data)
      File "pandas/_libs/tslibs/conversion.pyx", line 185, in pandas._libs.tslibs.conversion.datetime_to_datetime64
    ValueError: Array must be all same time zone
    
    pd.__version__
    '1.1.2'
    
    
    df[0].dt.tz_localize(None)
    
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "/usr/local/lib/python3.8/site-packages/pandas/core/generic.py", line 5132, in __getattr__
        return object.__getattribute__(self, name)
      File "/usr/local/lib/python3.8/site-packages/pandas/core/accessor.py", line 187, in __get__
        accessor_obj = self._accessor(obj)
      File "/usr/local/lib/python3.8/site-packages/pandas/core/indexes/accessors.py", line 480, in __new__
        raise AttributeError("Can only use .dt accessor with datetimelike values")
    AttributeError: Can only use .dt accessor with datetimelike values
    
    

    【讨论】:

      【解决方案3】:

      我知道您提到您的时间戳已经采用 UTC,但为了防御起见,您不妨让您的代码不受时间戳(部分或全部)位于不同时区的情况的影响。这不会花费任何成本,并且会更加强大:

      newcol = testdata['time'].dt.tz_convert(None)
      

      作为per the docs:

      None 中的 tz 将转换为 UTC 并删除时区信息。

      这比仅仅删除时间戳可能包含的任何时区更安全。

      【讨论】:

        【解决方案4】:

        这是一个函数

        • 查找其中包含任何 pd.Timestamp 实例的所有列
        • 将这些列转换为 dtype datetime(以便能够在 Series 上使用 .dt 访问器)
        • 使用 dt.tz_localize(None) 本地化所有时间戳,这将保持相对于 UTC 的时移
        def remove_tz_from_dataframe(df_in):
            df = df_in.copy()
            col_times = [ col for col in df.columns if any([isinstance(x, pd.Timestamp for x in df[col]])]
            for col in col_times:
                df[col] = pd.to_datetime(
                    df[col], infer_datetime_format=True) 
                df[col] = df[col].dt.tz_localize(None) 
            return df
        

        【讨论】:

          猜你喜欢
          • 2018-02-02
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多