python - 如何将此时间序列转换为 UTC?
问题描述
我第一次来这里:)
我有关注 Pandas DataFrame
date time
0 2018-03-24 23
1 2018-03-24 24
2 2018-03-25 1
3 2018-03-25 2
4 2018-03-25 3
5 2018-03-25 4
6 2018-03-25 5
7 2018-03-25 6
8 2018-03-25 7
9 2018-03-25 8
10 2018-03-25 9
11 2018-03-25 10
12 2018-03-25 11
13 2018-03-25 12
14 2018-03-25 13
15 2018-03-25 14
16 2018-03-25 15
17 2018-03-25 16
18 2018-03-25 17
19 2018-03-25 18
20 2018-03-25 19
21 2018-03-25 20
22 2018-03-25 21
23 2018-03-25 22
24 2018-03-25 23
25 2018-03-26 1
26 2018-03-26 2
27 2018-03-26 3
28 2018-03-26 4
29 2018-03-26 5
30 2018-03-26 6
31 2018-10-27 23
32 2018-10-27 24
33 2018-10-28 1
34 2018-10-28 2
35 2018-10-28 3
36 2018-10-28 4
37 2018-10-28 5
38 2018-10-28 6
39 2018-10-28 7
40 2018-10-28 8
41 2018-10-28 9
42 2018-10-28 10
43 2018-10-28 11
44 2018-10-28 12
45 2018-10-28 13
46 2018-10-28 14
47 2018-10-28 15
48 2018-10-28 16
49 2018-10-28 17
50 2018-10-28 18
51 2018-10-28 19
52 2018-10-28 20
53 2018-10-28 21
54 2018-10-28 22
55 2018-10-28 23
56 2018-10-28 24
57 2018-10-28 25
58 2018-10-29 1
59 2018-10-29 2
列time
应该代表一天中的小时减一,例如
date time
2 2018-03-25 1
等于2018-03-25 00:00
欧洲/伦敦时间。
生成此时间序列数据的设备设置为根据'Europe/London'
时区工作,这就是为什么 2018 年 3 月 25 日结束于第 23 小时(记录[2:25]
),而 2018 年 10 月 28 日结束于第 25 小时(记录[33:58]
)(DST 开关)。
这是我已经尝试过的东西:
from pytz import timezone
tz = timezone("Europe/London")
dst_switch = [dt for dt in tz._utc_transition_times if dt.year == 2018]
dst_switch_date_range = pd.date_range(dst_switch[0],dst_switch[1], freq='h', tz='utc')
df['datetime'] = pd.to_datetime(df.date) + pd.to_timedelta(df.time - 1, unit='h')
df['dt_utc'] = df['datetime'].dt.tz_localize('UTC')
df['dst_switch'] = df['datetime'].map(lambda dt: 1 if dt in dst_switch_date_range else -1)
df['dt_p'] = df['datetime'] + pd.to_timedelta(df['dst_switch'], unit='h')
df['dt_utc_p'] = df['dt_p'].dt.tz_localize('Europe/London', ambiguous='NaT', nonexistent='NaT').dt.tz_convert('UTC')
df[['date', 'time', 'dt', 'dt_utc', 'map','dt_p', 'dt_utc_p']]
这导致:
date time dt dt_utc dst_switch dt_p dt_utc_p
0 2018-03-24 23 2018-03-24 23:00:00 2018-03-24 22:00:00+00:00 -1 2018-03-24 21:00:00 2018-03-24 21:00:00+00:00
1 2018-03-24 24 2018-03-25 00:00:00 2018-03-24 23:00:00+00:00 -1 2018-03-24 22:00:00 2018-03-24 22:00:00+00:00
2 2018-03-25 1 2018-03-25 01:00:00 2018-03-25 00:00:00+00:00 -1 2018-03-24 23:00:00 2018-03-24 23:00:00+00:00
3 2018-03-25 2 2018-03-25 02:00:00 2018-03-25 01:00:00+00:00 1 2018-03-25 02:00:00 2018-03-25 01:00:00+00:00
4 2018-03-25 3 2018-03-25 03:00:00 2018-03-25 02:00:00+00:00 1 2018-03-25 03:00:00 2018-03-25 02:00:00+00:00
5 2018-03-25 4 2018-03-25 04:00:00 2018-03-25 03:00:00+00:00 1 2018-03-25 04:00:00 2018-03-25 03:00:00+00:00
6 2018-03-25 5 2018-03-25 05:00:00 2018-03-25 04:00:00+00:00 1 2018-03-25 05:00:00 2018-03-25 04:00:00+00:00
7 2018-03-25 6 2018-03-25 06:00:00 2018-03-25 05:00:00+00:00 1 2018-03-25 06:00:00 2018-03-25 05:00:00+00:00
8 2018-03-25 7 2018-03-25 07:00:00 2018-03-25 06:00:00+00:00 1 2018-03-25 07:00:00 2018-03-25 06:00:00+00:00
9 2018-03-25 8 2018-03-25 08:00:00 2018-03-25 07:00:00+00:00 1 2018-03-25 08:00:00 2018-03-25 07:00:00+00:00
10 2018-03-25 9 2018-03-25 09:00:00 2018-03-25 08:00:00+00:00 1 2018-03-25 09:00:00 2018-03-25 08:00:00+00:00
11 2018-03-25 10 2018-03-25 10:00:00 2018-03-25 09:00:00+00:00 1 2018-03-25 10:00:00 2018-03-25 09:00:00+00:00
12 2018-03-25 11 2018-03-25 11:00:00 2018-03-25 10:00:00+00:00 1 2018-03-25 11:00:00 2018-03-25 10:00:00+00:00
13 2018-03-25 12 2018-03-25 12:00:00 2018-03-25 11:00:00+00:00 1 2018-03-25 12:00:00 2018-03-25 11:00:00+00:00
14 2018-03-25 13 2018-03-25 13:00:00 2018-03-25 12:00:00+00:00 1 2018-03-25 13:00:00 2018-03-25 12:00:00+00:00
15 2018-03-25 14 2018-03-25 14:00:00 2018-03-25 13:00:00+00:00 1 2018-03-25 14:00:00 2018-03-25 13:00:00+00:00
16 2018-03-25 15 2018-03-25 15:00:00 2018-03-25 14:00:00+00:00 1 2018-03-25 15:00:00 2018-03-25 14:00:00+00:00
17 2018-03-25 16 2018-03-25 16:00:00 2018-03-25 15:00:00+00:00 1 2018-03-25 16:00:00 2018-03-25 15:00:00+00:00
18 2018-03-25 17 2018-03-25 17:00:00 2018-03-25 16:00:00+00:00 1 2018-03-25 17:00:00 2018-03-25 16:00:00+00:00
19 2018-03-25 18 2018-03-25 18:00:00 2018-03-25 17:00:00+00:00 1 2018-03-25 18:00:00 2018-03-25 17:00:00+00:00
20 2018-03-25 19 2018-03-25 19:00:00 2018-03-25 18:00:00+00:00 1 2018-03-25 19:00:00 2018-03-25 18:00:00+00:00
21 2018-03-25 20 2018-03-25 20:00:00 2018-03-25 19:00:00+00:00 1 2018-03-25 20:00:00 2018-03-25 19:00:00+00:00
22 2018-03-25 21 2018-03-25 21:00:00 2018-03-25 20:00:00+00:00 1 2018-03-25 21:00:00 2018-03-25 20:00:00+00:00
23 2018-03-25 22 2018-03-25 22:00:00 2018-03-25 21:00:00+00:00 1 2018-03-25 22:00:00 2018-03-25 21:00:00+00:00
24 2018-03-25 23 2018-03-25 23:00:00 2018-03-25 22:00:00+00:00 1 2018-03-25 23:00:00 2018-03-25 22:00:00+00:00
25 2018-03-26 1 2018-03-26 01:00:00 2018-03-26 00:00:00+00:00 1 2018-03-26 01:00:00 2018-03-26 00:00:00+00:00
26 2018-03-26 2 2018-03-26 02:00:00 2018-03-26 01:00:00+00:00 1 2018-03-26 02:00:00 2018-03-26 01:00:00+00:00
27 2018-03-26 3 2018-03-26 03:00:00 2018-03-26 02:00:00+00:00 1 2018-03-26 03:00:00 2018-03-26 02:00:00+00:00
28 2018-03-26 4 2018-03-26 04:00:00 2018-03-26 03:00:00+00:00 1 2018-03-26 04:00:00 2018-03-26 03:00:00+00:00
29 2018-03-26 5 2018-03-26 05:00:00 2018-03-26 04:00:00+00:00 1 2018-03-26 05:00:00 2018-03-26 04:00:00+00:00
30 2018-03-26 6 2018-03-26 06:00:00 2018-03-26 05:00:00+00:00 1 2018-03-26 06:00:00 2018-03-26 05:00:00+00:00
31 2018-10-27 23 2018-10-27 23:00:00 2018-10-27 22:00:00+00:00 1 2018-10-27 23:00:00 2018-10-27 22:00:00+00:00
32 2018-10-27 24 2018-10-28 00:00:00 2018-10-27 23:00:00+00:00 1 2018-10-28 00:00:00 2018-10-27 23:00:00+00:00
33 2018-10-28 1 2018-10-28 01:00:00 2018-10-28 00:00:00+00:00 1 2018-10-28 01:00:00 NaT
34 2018-10-28 2 2018-10-28 02:00:00 2018-10-28 01:00:00+00:00 1 2018-10-28 02:00:00 2018-10-28 02:00:00+00:00
35 2018-10-28 3 2018-10-28 03:00:00 2018-10-28 02:00:00+00:00 -1 2018-10-28 01:00:00 NaT
36 2018-10-28 4 2018-10-28 04:00:00 2018-10-28 03:00:00+00:00 -1 2018-10-28 02:00:00 2018-10-28 02:00:00+00:00
37 2018-10-28 5 2018-10-28 05:00:00 2018-10-28 04:00:00+00:00 -1 2018-10-28 03:00:00 2018-10-28 03:00:00+00:00
38 2018-10-28 6 2018-10-28 06:00:00 2018-10-28 05:00:00+00:00 -1 2018-10-28 04:00:00 2018-10-28 04:00:00+00:00
39 2018-10-28 7 2018-10-28 07:00:00 2018-10-28 06:00:00+00:00 -1 2018-10-28 05:00:00 2018-10-28 05:00:00+00:00
40 2018-10-28 8 2018-10-28 08:00:00 2018-10-28 07:00:00+00:00 -1 2018-10-28 06:00:00 2018-10-28 06:00:00+00:00
41 2018-10-28 9 2018-10-28 09:00:00 2018-10-28 08:00:00+00:00 -1 2018-10-28 07:00:00 2018-10-28 07:00:00+00:00
42 2018-10-28 10 2018-10-28 10:00:00 2018-10-28 09:00:00+00:00 -1 2018-10-28 08:00:00 2018-10-28 08:00:00+00:00
43 2018-10-28 11 2018-10-28 11:00:00 2018-10-28 10:00:00+00:00 -1 2018-10-28 09:00:00 2018-10-28 09:00:00+00:00
44 2018-10-28 12 2018-10-28 12:00:00 2018-10-28 11:00:00+00:00 -1 2018-10-28 10:00:00 2018-10-28 10:00:00+00:00
45 2018-10-28 13 2018-10-28 13:00:00 2018-10-28 12:00:00+00:00 -1 2018-10-28 11:00:00 2018-10-28 11:00:00+00:00
46 2018-10-28 14 2018-10-28 14:00:00 2018-10-28 13:00:00+00:00 -1 2018-10-28 12:00:00 2018-10-28 12:00:00+00:00
47 2018-10-28 15 2018-10-28 15:00:00 2018-10-28 14:00:00+00:00 -1 2018-10-28 13:00:00 2018-10-28 13:00:00+00:00
48 2018-10-28 16 2018-10-28 16:00:00 2018-10-28 15:00:00+00:00 -1 2018-10-28 14:00:00 2018-10-28 14:00:00+00:00
49 2018-10-28 17 2018-10-28 17:00:00 2018-10-28 16:00:00+00:00 -1 2018-10-28 15:00:00 2018-10-28 15:00:00+00:00
50 2018-10-28 18 2018-10-28 18:00:00 2018-10-28 17:00:00+00:00 -1 2018-10-28 16:00:00 2018-10-28 16:00:00+00:00
51 2018-10-28 19 2018-10-28 19:00:00 2018-10-28 18:00:00+00:00 -1 2018-10-28 17:00:00 2018-10-28 17:00:00+00:00
52 2018-10-28 20 2018-10-28 20:00:00 2018-10-28 19:00:00+00:00 -1 2018-10-28 18:00:00 2018-10-28 18:00:00+00:00
53 2018-10-28 21 2018-10-28 21:00:00 2018-10-28 20:00:00+00:00 -1 2018-10-28 19:00:00 2018-10-28 19:00:00+00:00
54 2018-10-28 22 2018-10-28 22:00:00 2018-10-28 21:00:00+00:00 -1 2018-10-28 20:00:00 2018-10-28 20:00:00+00:00
55 2018-10-28 23 2018-10-28 23:00:00 2018-10-28 22:00:00+00:00 -1 2018-10-28 21:00:00 2018-10-28 21:00:00+00:00
56 2018-10-28 24 2018-10-29 00:00:00 2018-10-28 23:00:00+00:00 -1 2018-10-28 22:00:00 2018-10-28 22:00:00+00:00
57 2018-10-28 25 2018-10-29 01:00:00 2018-10-29 00:00:00+00:00 -1 2018-10-28 23:00:00 2018-10-28 23:00:00+00:00
58 2018-10-29 1 2018-10-29 01:00:00 2018-10-29 00:00:00+00:00 -1 2018-10-28 23:00:00 2018-10-28 23:00:00+00:00
59 2018-10-29 2 2018-10-29 02:00:00 2018-10-29 01:00:00+00:00 -1 2018-10-29 00:00:00 2018-10-29 00:00:00+00:00
我需要什么:我需要将这两列合并到日期时间列中,然后将时区从转换'Europe/London'
为'UTC'
(或其他方式:调整列中的值time
以适应'UTC'
然后与date
列结合)
我的逻辑线:1 年有 24 小时 * 365 天 = 8760 小时。如果我取全年的时间序列数据,我应该得到 363 天,每条记录 24 条记录,1 天有 23 条记录,1 天有 25 条记录,总共 8712 + 23 + 25 = 8760 条记录,所以,每个记录一条一年中的一个小时。
我失败的地方:将我的逻辑转换为代码:P。我不知道如何抵消这些日期,所以一切都会有意义,这意味着 DST 切换日期之间的平滑过渡,没有重复的时间序列值,也没有时间序列中的缺失值(漏洞)。
预期结果:
date time dt_utc
0 2018-03-24 23 2018-03-24 22:00:00+00:00
1 2018-03-24 24 2018-03-24 23:00:00+00:00
2 2018-03-25 1 2018-03-25 00:00:00+00:00
3 2018-03-25 2 2018-03-25 01:00:00+00:00
4 2018-03-25 3 2018-03-25 02:00:00+00:00
5 2018-03-25 4 2018-03-25 03:00:00+00:00
6 2018-03-25 5 2018-03-25 04:00:00+00:00
7 2018-03-25 6 2018-03-25 05:00:00+00:00
8 2018-03-25 7 2018-03-25 06:00:00+00:00
9 2018-03-25 8 2018-03-25 07:00:00+00:00
10 2018-03-25 9 2018-03-25 08:00:00+00:00
11 2018-03-25 10 2018-03-25 09:00:00+00:00
12 2018-03-25 11 2018-03-25 10:00:00+00:00
13 2018-03-25 12 2018-03-25 11:00:00+00:00
14 2018-03-25 13 2018-03-25 12:00:00+00:00
15 2018-03-25 14 2018-03-25 13:00:00+00:00
16 2018-03-25 15 2018-03-25 14:00:00+00:00
17 2018-03-25 16 2018-03-25 15:00:00+00:00
18 2018-03-25 17 2018-03-25 16:00:00+00:00
19 2018-03-25 18 2018-03-25 17:00:00+00:00
20 2018-03-25 19 2018-03-25 18:00:00+00:00
21 2018-03-25 20 2018-03-25 19:00:00+00:00
22 2018-03-25 21 2018-03-25 20:00:00+00:00
23 2018-03-25 22 2018-03-25 21:00:00+00:00
24 2018-03-25 23 2018-03-25 22:00:00+00:00
25 2018-03-26 1 2018-03-25 23:00:00+00:00
26 2018-03-26 2 2018-03-26 00:00:00+00:00
27 2018-03-26 3 2018-03-26 01:00:00+00:00
28 2018-03-26 4 2018-03-26 02:00:00+00:00
29 2018-03-26 5 2018-03-26 03:00:00+00:00
30 2018-03-26 6 2018-03-26 04:00:00+00:00
31 2018-10-27 23 2018-10-27 21:00:00+00:00
32 2018-10-27 24 2018-10-27 22:00:00+00:00
33 2018-10-28 1 2018-10-27 23:00:00+00:00
34 2018-10-28 2 2018-10-28 00:00:00+00:00
35 2018-10-28 3 2018-10-28 01:00:00+00:00
36 2018-10-28 4 2018-10-28 02:00:00+00:00
37 2018-10-28 5 2018-10-28 03:00:00+00:00
38 2018-10-28 6 2018-10-28 04:00:00+00:00
39 2018-10-28 7 2018-10-28 05:00:00+00:00
40 2018-10-28 8 2018-10-28 06:00:00+00:00
41 2018-10-28 9 2018-10-28 07:00:00+00:00
42 2018-10-28 10 2018-10-28 08:00:00+00:00
43 2018-10-28 11 2018-10-28 09:00:00+00:00
44 2018-10-28 12 2018-10-28 10:00:00+00:00
45 2018-10-28 13 2018-10-28 11:00:00+00:00
46 2018-10-28 14 2018-10-28 12:00:00+00:00
47 2018-10-28 15 2018-10-28 13:00:00+00:00
48 2018-10-28 16 2018-10-28 14:00:00+00:00
49 2018-10-28 17 2018-10-28 15:00:00+00:00
50 2018-10-28 18 2018-10-28 16:00:00+00:00
51 2018-10-28 19 2018-10-28 17:00:00+00:00
52 2018-10-28 20 2018-10-28 18:00:00+00:00
53 2018-10-28 21 2018-10-28 19:00:00+00:00
54 2018-10-28 22 2018-10-28 20:00:00+00:00
55 2018-10-28 23 2018-10-28 21:00:00+00:00
56 2018-10-28 24 2018-10-28 22:00:00+00:00
57 2018-10-28 25 2018-10-28 23:00:00+00:00
58 2018-10-29 1 2018-10-29 00:00:00+00:00
59 2018-10-29 2 2018-10-29 01:00:00+00:00
请帮忙 :)
解决方案
问题中的优秀 MCVE。让日期时间、时区和时间增量来处理 DST。我没有检查结果,但它应该是好的。
import pandas as pd
from pandas.compat import StringIO
print(pd.__version__)
data = """index date hour
0 2018-03-24 23
1 2018-03-24 24
2 2018-03-25 1
3 2018-03-25 2
4 2018-03-25 3
5 2018-03-25 4
6 2018-03-25 5
7 2018-03-25 6
8 2018-03-25 7
9 2018-03-25 8
10 2018-03-25 9
11 2018-03-25 10
12 2018-03-25 11
13 2018-03-25 12
14 2018-03-25 13
15 2018-03-25 14
16 2018-03-25 15
17 2018-03-25 16
18 2018-03-25 17
19 2018-03-25 18
20 2018-03-25 19
21 2018-03-25 20
22 2018-03-25 21
23 2018-03-25 22
24 2018-03-25 23
25 2018-03-26 1
26 2018-03-26 2
27 2018-03-26 3
28 2018-03-26 4
29 2018-03-26 5
30 2018-03-26 6
31 2018-10-27 23
32 2018-10-27 24
33 2018-10-28 1
34 2018-10-28 2
35 2018-10-28 3
36 2018-10-28 4
37 2018-10-28 5
38 2018-10-28 6
39 2018-10-28 7
40 2018-10-28 8
41 2018-10-28 9
42 2018-10-28 10
43 2018-10-28 11
44 2018-10-28 12
45 2018-10-28 13
46 2018-10-28 14
47 2018-10-28 15
48 2018-10-28 16
49 2018-10-28 17
50 2018-10-28 18
51 2018-10-28 19
52 2018-10-28 20
53 2018-10-28 21
54 2018-10-28 22
55 2018-10-28 23
56 2018-10-28 24
57 2018-10-28 25
58 2018-10-29 1
59 2018-10-29 2"""
df = pd.read_csv(StringIO(data), sep='\s+', index_col=0)
df['hour'] = pd.to_timedelta(df['hour'] - 1, 'h')
df['date'] = pd.to_datetime(df['date'])
df['naive_datetime'] = df['date'] + df['hour']
df.set_index(df['naive_datetime'], inplace=True)
df.index = df.index.tz_localize('Europe/London').tz_convert('UTC')
print(df)
生产
pytz.exceptions.NonExistentTimeError: 2018-03-25 01:00:00
因此,必须处理不存在的日期时间。有许多选项可以做到这一点,一个是忽略本地 DST 时区中不存在的日期时间,该时区每年跳转两次。
# receives non-existent time exception because of naive datetime that does not exist in Europe/London
#df.index = df.index.tz_localize('Europe/London').tz_convert('UTC')
# receives AmbiguousTimeError: Cannot infer dst time from 2018-10-28 01:00:00 as there are no repeated times
#df.index = df.index.tz_localize('Europe/London', ambiguous='infer').tz_convert('UTC')
df.index = df.index.tz_localize('Europe/London', ambiguous='NaT', nonexistent='NaT').tz_convert('UTC')
df.index.name = "datetime Europe/London"
# if there is timestamped data in the dataframe, something has to be done with it.
# The data for the missing time is probably best dropped
#df = df[df.index.notnull()]
# interpolate doesn't work: https://github.com/pandas-dev/pandas/issues/11701, but then again the time does not exist in local tz...
#df['datetime Europe/London interpolated'] = df.index.to_series().interpolate(method='linear')
推荐阅读
- python - 如何在 Pytorch Geometric 中使用 RemoveIsolatedNodes 变换?
- node.js - Node js程序给了我“TypeError:无法读取未定义的属性'split'”
- r - 在其他包的 S4 类之间创建转换方法
- sql - 计算用户在每个 post sql 上收到的喜欢的数量
- java - 无法启动监控 J4AXB761F692887 无法启动应用程序,为什么?
- google-apps-script - 我无法通过命令 getFilesByName 获取文件
- jquery - 为什么 $ajaxSetup 中的 beforeSend 不向无参数函数添加参数?
- kotlin - Korlin/Native 中 Koin 的 FreezingException
- html - 如何访问 vue.js 中动态文本框的值
- php - 从父类继承属性而不在 PHP 中再次调用父方法