按 UTC 顺序排列时区字符串列表以标记日期时间图的 plt.x 轴

Putting list of timezones strings in order by UTC to label plt.x-axis of datetime plot

所以我有一个 pandas df 列,其中包含以下信息:

67               America/Buenos_Aires
68     America/Argentina/Buenos_Aires
70     America/Argentina/Buenos_Aires
77     America/Argentina/Buenos_Aires
78                   Pacific/Auckland
79     America/Argentina/Buenos_Aires
80          America/Argentina/Tucuman
81                      Europe/Lisbon
82     America/Argentina/Buenos_Aires
83     America/Argentina/Buenos_Aires
84     America/Argentina/Buenos_Aires
85     America/Argentina/Buenos_Aires
86     America/Argentina/Buenos_Aires
87     America/Argentina/Buenos_Aires
88          America/Argentina/Cordoba
89     America/Argentina/Buenos_Aires
90          America/Argentina/Mendoza
91     America/Argentina/Buenos_Aires
92                      Europe/Madrid

为了绘制时区分布图,我转换为 datetime.now obj 并绘制了以下内容: [![在此处输入图片描述][1]][1]

我想用适当的时区名称标记 x 轴,例如“America/Argentina/Buenos_Aires”或“Europe/Madrid”等。但无法弄清楚如何将 datetime.now 对象与时区名称相匹配。已转换为 datetime.now objs 的列如下所示:

0      2021-04-01 16:41:51.302270+02:00
2      2021-04-01 11:41:51.302270-03:00
3      2021-04-01 11:41:51.302270-03:00
4      2021-04-01 11:41:51.302270-03:00
10     2021-04-01 11:41:51.302270-03:00

遍历唯一的时区列表如下所示:

timezones = timezone_df['Timezone'].unique()
for tz in timezones:
    print(tz)

我得到:

Europe/Madrid
America/Argentina/Buenos_Aires
America/Buenos_Aires
America/Montevideo
America/Argentina/Cordoba
Pacific/Auckland
America/Argentina/Tucuman
Europe/Lisbon
America/Argentina/Mendoza
America/Argentina/Salta
America/Santiago
America/New_York
America/Los_Angeles
America/Chicago
Poland
Europe/Rome
America/Cayman
America/Bogota
America/Argentina/Jujuy
America/Mexico_City
Asia/Aqtobe
America/Sao_Paulo
Europe/Berlin
Brazil/East
America/Cordoba

我尝试根据日期时间文档 (https://docs.python.org/3/library/datetime.html#strftime-and-strptime-format-codes) 使用 strftime、mdates.DateFormatter 和 tzname,但似乎没有任何效果。

有没有办法放置字符串列表(所以采用这种格式 -> "America/Sao_Paulo", "Europe/Berlin", "Brazil/East", "America/Cordoba" ) 按 UTC +01:00、+02:00 等排序?所以顺序如下:

(UTC +00:00) Western European Time',
'+01:00' => '(UTC +01:00) Central European Time',
'+02:00' => '(UTC +02:00) Eastern European Time',
'+03:00' => '(UTC +03:00) Further-Eastern European Time',
'+04:00' => '(UTC +04:00) Gulf Standard Time',
'+05:00' => '(UTC +05:00) Pakistan Standard Time',
'+05:30' => '(UTC +05:30) Indian Standard Time',
'+05:45' => '(UTC +05:45) Nepal Time',
'+06:00' => '(UTC +06:00)
```

I'm plotting it like this because I want the timezones to appear on the x-axis as they would if you were follow them on a map from west to east. Doing this:
[![enter image description here][2]][2]
means the timezones are ordered by distribution and not by how they'd appear on a map.


  [1]: https://i.stack.imgur.com/cxYnj.png
  [2]: https://i.stack.imgur.com/EPm8Q.png

可以根据utcoffsetdocs)对df进行排序。举个例子给你思路:

import pandas as pd
# some sample data...
df = pd.DataFrame({'tzname': ["Europe/Madrid",
                              "America/Argentina/Buenos_Aires",
                              "Europe/London",
                              "America/Los_Angeles"]})

df['dt'] = df['tzname'].apply(lambda t: pd.Timestamp.now(t))
df['utcoffset'] = df['dt'].apply(lambda t: t.utcoffset())
df = df.sort_values('utcoffset', ascending=True).reset_index()

# df
# Out[87]: 
#    index  ...         utcoffset
# 0      3  ... -1 days +17:00:00
# 1      1  ... -1 days +21:00:00
# 2      2  ...   0 days 01:00:00
# 3      0  ...   0 days 02:00:00

# [4 rows x 4 columns]

请注意,UTC 偏移量对于一年中的所有时区来说并不是恒定的,因为有些时区有夏令时。所以一年中不同时期的顺序可能会有所不同。

现在你可以画图了,例如喜欢

# a quick way to adjust the margins:    
import matplotlib.pyplot as plt
plt.subplots_adjust(top=0.95, bottom=0.4, left=0.14, right=0.94)
title = f"UTC offsets on {pd.Timestamp.now('UTC').date().isoformat()} UTC"
ax = (df['utcoffset'].dt.total_seconds()//3600).plot(title=title, 
                                                     marker='*', markersize=8, 
                                                     color='b', linestyle='')
ax.set_ylabel('UTC offset [h]')
ax.set_xticks(df.index)
ax.set_xticklabels(df['tzname'], rotation=45)
ax.xaxis.grid()
ax.yaxis.grid()