matplotlib 创建一个将第一个轴分组的两级x轴[复制]

8ljdwjyq  于 2023-06-06  发布在  其他
关注(0)|答案(1)|浏览(316)

此问题已在此处有答案

Hierarchical axis labeling in matplotlib (Python)(2个答案)
How to add group labels for bar charts(2个答案)
5天前关闭。
我正在尝试重新创建这个图表的一个变体:

主要的区别是,我创建了一个条形图,x轴是日期时间(以3小时为增量),条形图是基于另一系列称为强度(低绿色,高红色)着色的。
也就是说,一个轴应该是一天中的小时,它下面的第二个轴应该将这些时间分组到它们所属的一天中。
到目前为止我有:

import matplotlib as mplt
import matplotlib.pyplot as plt
from matplotlib import dates
import numpy as np
import datetime as pdt
from datetime import datetime, timedelta
import seaborn as sns

start_dt = np.datetime64('today').astype(np.datetime64)
end_dt = np.datetime64('today') + np.timedelta64(6, 'D')

x = np.arange(start_dt,
                  end_dt, np.timedelta64(180, 'm'))
x = [i.astype(datetime) for i in x]

intensity = np.random.uniform(0, 10, len(x))

y = np.ones(shape=len(x))

plt.rcParams["figure.figsize"] = [17, 1.2]
plt.rcParams["figure.autolayout"] = True
sns.set_style("whitegrid")
sns.despine(bottom = True, left = True, top = True)
fig, ax = plt.subplots()

colors = []
for i in intensity:
    if 0 <= i <= 5:
        colors.append('#75FF71')
    elif 6 <= i < 8:
        colors.append('#FFC53D')
    else:
        colors.append('#FF5C5C')

graph = sns.barplot(x=x, y=y, palette=colors, width=1.0, linewidth=0)
graph.grid(False)
graph.set(yticklabels=[])
x_tick_label = []
for val in x:
    min_ts = min(x)
    diff_days = (val - min_ts).days
    diff_hours = (val - min_ts).seconds/3600
    total = diff_days*24 + int(diff_hours)
    if val.time() == pdt.time(0,0):
        # x_tick_label.append(val.strftime("%m/%d"))
        x_tick_label.append("")
    elif val.time() == pdt.time(6,0) or val.time() == pdt.time(12,0) or val.time() == pdt.time(18,0) :
    # elif val.time() == pdt.time(12,0):
        x_tick_label.append(f"{val.strftime('%-H')}:00")
    else:
        x_tick_label.append('')
graph.set(xticklabels=x_tick_label)
for ticklabel in graph.axes.get_xticklabels():
    ticklabel.set_color("#FFC53D")

ax2 = ax.axes.twiny()

ax2.spines['top'].set_position(('axes', -0.15))
ax2.spines['top'].set_visible(False)

# ax2.xaxis.set_major_formatter(day_locator)

plt.xticks(fontweight='light',ha='right', rotation=90)
plt.box(on=None)

          
plt.show()

4urapxun

4urapxun1#

让我为主持人提到的过时答案添加价值。让我们尽可能多地使用现代API方法。我的方法是利用次要和主要刻度,做到这两点:分组并制作交替图案。

import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.transforms import ScaledTranslation
import matplotlib.dates as mdates

## DATA

ts = pd.date_range('2023/01/01', '2023/06/30', freq='1H')
xs = np.arange(len(ts))
vals = np.random.normal(size=(len(ts),)).cumsum()
df = pd.DataFrame({'date':ts,'value':vals})

## Plot 
fig, ax = plt.subplots(figsize = (24,6), constrained_layout=True) 

month_locs = mdates.MonthLocator(interval=1)
month_locs_fmt = mdates.DateFormatter('%b')
ax.xaxis.set_major_locator(month_locs)
ax.xaxis.set_major_formatter(month_locs_fmt)

day_locs = mdates.DayLocator(interval=7)
day_locs_fmt = mdates.DateFormatter('%d')
ax.xaxis.set_minor_locator(day_locs,)
ax.xaxis.set_minor_formatter(day_locs_fmt)
ax.xaxis.set_tick_params(which='major', pad=-10, length=40)

ax.plot(df['date'], df['value'])



## Align

offset = ScaledTranslation(1.6, 0, fig.dpi_scale_trans)
for label in ax.xaxis.get_majorticklabels():
    label.set_transform(label.get_transform() + offset)

## Add alternating pattern

plt.grid(axis='x', which='major')
xticks = [t._loc for t in ax.xaxis.get_major_ticks()]
for x0, x1 in zip(xticks[::2], xticks[1::2]):
    ax.axvspan(x0, x1, color='black', alpha=0.1, zorder=0)

plt.show()

相关问题