如何从pandas数据帧中的Timestamp列中删除时区

Dav*_*e X 10 python timezone dataframe pandas timestamp-with-timezone

为外汇DataFrame阅读了Pandas更改时区,但是我想让我的数据帧时区的时间列与sqlite3数据库的互操作性.

我的pandas数据帧中的数据已经转换为UTC数据,但我不想在数据库中维护此UTC时区信息.

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

print(type(testdata))
print(testdata)
print(testdata.applymap(type))
Run Code Online (Sandbox Code Playgroud)

得到:

<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'>  
Run Code Online (Sandbox Code Playgroud)

newstamp = testdata['time'].tz_convert(None)
Run Code Online (Sandbox Code Playgroud)

给出了最终的错误:

TypeError: index is not a valid DatetimeIndex or PeriodIndex
Run Code Online (Sandbox Code Playgroud)

如何使用时区天真时间戳替换列?

MaF*_*aFF 20

您可以使用tz_localize更改时区,天真时间戳对应于时区None:

testdata['time'].dt.tz_localize(None)
Run Code Online (Sandbox Code Playgroud)

除非列是索引,否则您必须调用方法dt来访问pandas datetime函数.


Ems*_*msi 13

当您的数据包含跨越不同时区或应用夏令时之前和之后的日期时间(例如使用 psycopg2 从 postges 数据库获取)时,根据 pandas 版本,您可能最终会遇到以下情况,其中最佳转换方法是:

testdata['time'].apply(lambda x: x.replace(tzinfo=None))
Run Code Online (Sandbox Code Playgroud)

FixedOffsetTimezone当此方法有效时的场景(注意与 different的用法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))
])

Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
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

Run Code Online (Sandbox Code Playgroud)


Pie*_*e D 8

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

newcol = testdata['time'].dt.tz_convert(None)
Run Code Online (Sandbox Code Playgroud)

根据文档

A tzofNone将转换为 UTC 并删除时区信息。

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