设置 pandas 数据框中时间戳数据的时区

Slo*_*ner 5 python pandas

我有一个经常更改的 pandas 数据框,如下所示:

         date name  time       timezone
0  2016-08-01  aaa  0900     Asia/Tokyo
1  2016-08-04  bbb  1200  Europe/Berlin
2  2016-08-05  ccc  1400  Europe/London
Run Code Online (Sandbox Code Playgroud)

日期、时间和时区是指交货日期,通常是海外地点,名称是客户公司的名称。

计划是获取这些数据并创建一个datetime_local列,其中包含数据帧列中显示的时区timezone。然后,我想添加一个datetime_london包含该日期和时间的列,但以伦敦的时间和日期表示。

我已经完成了大部分工作,但是当我打电话时,tz_localize我最终得到了一个ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all(),这表明我没有正确处理时区列。

关于如何进行有什么建议吗?

mydf = pd.DataFrame(data={'date':['2016-08-01','2016-08-04','2016-08-05'],
                          'time':['0900','1200','1400'],
                          'timezone':['Asia/Tokyo','Europe/Berlin','Europe/London'],
                          'name':['aaa','bbb','ccc']}
)
print(mydf)
mydf["datetime"] = mydf["date"].map(str) + " " + mydf["time"]
mydf.datetime = pd.to_datetime(mydf.datetime)
mydf.index = mydf.datetime
print(mydf)
mydf["datetime_local"] = mydf.datetime
mydf.datetime_local.tz_localize(mydf.timezone)
Run Code Online (Sandbox Code Playgroud)

Fel*_*niz 5

虽然前面的答案工作得很好,但当面对处理大数据的问题时,apply 方法效率有点低(对于 10^6 数量级的行)。逐行处理的 apply 方法花了我 10-15 分钟来处理这个规模。如果与数据框中的行数相比,时区列的唯一值的比例非常小,则此代码的效率要高得多:

for tz in df['timezone'].unique():    #iterates over each unique value of timezone in the dataframe
    mask = df['timezone'] == tz       #selects all rows with current unique tz value
    df.loc[mask,'datetime_local'] = pd.DatetimeIndex(df.loc[mask, 'datetime']).tz_localize('UTC').tz_convert(tz)
Run Code Online (Sandbox Code Playgroud)

最后一行代码将datetime列转换为DatetimeIndex,这使得datetimeUTC 和tz-naive(如果还没有)。因此,tz_localize('UTC')是必需的,因为tz_convert不适用于tz-naive日期时间。

我知道这是一个老问题,但我确实需要一个更快的解决方案,我认为我的答案可能会对我之后的人有所帮助。


Max*_*Max 1

import pandas as pd

def convert_to_local_time(row):
    return pd.to_datetime(row.datetime).tz_localize(row.timezone)

def convert_to_london_time(row):
    return pd.to_datetime(row.datetime_local).tz_convert('Europe/London')

mydf = pd.DataFrame(data={'date':['2016-08-01','2016-08-04','2016-08-05'],
                          'time':['0900','1200','1400'],
                          'timezone':['Asia/Tokyo','Europe/Berlin','Europe/    London'],
                          'name':['aaa','bbb','ccc']}
)
print(mydf)
Run Code Online (Sandbox Code Playgroud)

输出:

         date name  time       timezone
0  2016-08-01  aaa  0900     Asia/Tokyo
1  2016-08-04  bbb  1200  Europe/Berlin
2  2016-08-05  ccc  1400  Europe/London
Run Code Online (Sandbox Code Playgroud)

添加datetime_local栏目

mydf["datetime"] = mydf["date"].map(str) + " " + mydf["time"]
mydf['datetime_local'] = mydf.apply(convert_to_local_time, axis=1)
print(mydf)
Run Code Online (Sandbox Code Playgroud)

输出:

         date name  time       timezone         datetime  \
0  2016-08-01  aaa  0900     Asia/Tokyo  2016-08-01 0900   
1  2016-08-04  bbb  1200  Europe/Berlin  2016-08-04 1200   
2  2016-08-05  ccc  1400  Europe/London  2016-08-05 1400   

              datetime_local  
0  2016-08-01 09:00:00+09:00  
1  2016-08-04 12:00:00+02:00  
2  2016-08-05 14:00:00+01:00  
Run Code Online (Sandbox Code Playgroud)

添加datetime_london栏目

mydf['datetime_london'] = mydf.apply(convert_to_london_time, axis=1)
print('After adding datetime_london:')
print(mydf)
Run Code Online (Sandbox Code Playgroud)

输出:

         date name  time       timezone         datetime  \
0  2016-08-01  aaa  0900     Asia/Tokyo  2016-08-01 0900   
1  2016-08-04  bbb  1200  Europe/Berlin  2016-08-04 1200   
2  2016-08-05  ccc  1400  Europe/London  2016-08-05 1400   

              datetime_local           datetime_london  
0  2016-08-01 09:00:00+09:00 2016-08-01 01:00:00+01:00  
1  2016-08-04 12:00:00+02:00 2016-08-04 11:00:00+01:00  
2  2016-08-05 14:00:00+01:00 2016-08-05 14:00:00+01:00  
Run Code Online (Sandbox Code Playgroud)