【问题标题】:Bar plot with different minimal value for each bar每个条形具有不同最小值的条形图
【发布时间】:2021-07-13 13:48:34
【问题描述】:

我正在尝试重现这种类型的图表:

基本上,Y 轴代表每一年一个现象的开始和结束日期。

但这是我尝试绘制数据时的结果:

似乎无论如何,每年的条形图都是从 y 轴最小值绘制的。

这里是data I use

这是我的代码:

select=pd.read_excel("./writer.xlsx")
select=pd.DataFrame(select)
select["dte"]=pd.to_datetime(select.dte)
select["month_day"]=pd.DatetimeIndex(select.dte).strftime('%B %d')
select["month"]=pd.DatetimeIndex(select.dte).month
select["day"]=pd.DatetimeIndex(select.dte).day

gs=gridspec.GridSpec(2,2)
fig=plt.figure()
ax1=plt.subplot(gs[0,0])
ax2=plt.subplot(gs[0,1])
ax3=plt.subplot(gs[1,:])
###2 others graphs that works just fine
data=pd.DataFrame()
del select["res"],select["Seuil"],select["Seuil%"] #these don't matter for that graph
for year_ in list(set(select.dteYear)): 
    temp=select.loc[select["dteYear"]==year_]
    temp2=temp.iloc[[0,-1]] #the beginning and ending of the phenomenon 
    data=pd.concat([data,temp2]).reset_index(drop=True)
data=data.sort_values(["month","day"])
ax3.bar(data["dteYear"],data["month_day"],tick_label=data["dteYear"])
plt.show() 

如果您有一些线索可以帮助我,我将不胜感激,因为我还没有找到任何模型来制作这种类型的图表。

谢谢!

编辑: 我尝试了其他方法:

height,bottom,x_position=[], [], []
for year_ in list(set(select.dteYear)): 
    temp=select.loc[select["dteYear"]==year_]
    bottom.append(temp["month_day"].iloc[0])
    height.append(temp["month_day"].iloc[-1])
    x_position.append(year_)
    temp2=temp.iloc[[0,-1]]
    data=pd.concat([data,temp2]).reset_index(drop=True)
ax3.bar(x=x_position,height=height,bottom=bottom,tick_label=x_position)

我收到了这个错误:

Traceback (most recent call last):
  File "C:\Users\E31\Documents\cours\stage_dossier\projet_python\tool_etiage\test.py", line 103, in <module>
    ax3.bar(x=x_position,height=height,bottom=bottom,tick_label=x_position)
  File "C:\Users\E31\AppData\Local\Programs\Python\Python39\lib\site-packages\matplotlib\__init__.py", line 1352, in inner
    return func(ax, *map(sanitize_sequence, args), **kwargs)
  File "C:\Users\E31\AppData\Local\Programs\Python\Python39\lib\site-packages\matplotlib\axes\_axes.py", line 2357, in bar
    r = mpatches.Rectangle(
  File "C:\Users\E31\AppData\Local\Programs\Python\Python39\lib\site-packages\matplotlib\patches.py", line 752, in __init__
    super().__init__(**kwargs)
  File "C:\Users\E31\AppData\Local\Programs\Python\Python39\lib\site-packages\matplotlib\patches.py", line 101, in __init__
    self.set_linewidth(linewidth)
  File "C:\Users\E31\AppData\Local\Programs\Python\Python39\lib\site-packages\matplotlib\patches.py", line 406, in set_linewidth
    self._linewidth = float(w)
TypeError: only size-1 arrays can be converted to Python scalars

【问题讨论】:

  • 如果你想要从不同位置开始的酒吧,你需要ax.bar(x_positions, bar_heights, bottom=bar_bottoms, ....)
  • 我编辑了我的帖子,我尝试了你所说的但我得到了一个错误。我想这是因为我想使用日期作为我的 y 轴?但我不确定

标签: python-3.x matplotlib


【解决方案1】:

要制作显示日期之间差异的条形图,您应该首先将数据转换为数据框中的良好格式,以便轻松访问您绘制的每一年的条形的底部和顶部值。在此之后,您可以简单地绘制条形图并指示“底部”参数。在您的情况下,最困难的部分可能是正确指定日期时间差异。我为日期时间添加了 x 刻度定位器和 y 刻度格式化程序。

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import matplotlib as mpl
import matplotlib.dates as mdates

# make function that returns a random datetime 
# between a start and stop date
def random_date(start, stop):
    days = (stop - start).days
    rand = np.random.randint(days)
    return start + pd.Timedelta(rand, unit='days')

# simulate poster's data
T1 = pd.to_datetime('July 1 2021')
T2 = pd.to_datetime('August 1 2021')
T3 = pd.to_datetime('November 1 2021')

df = pd.DataFrame({
    'year'   : np.random.choice(np.arange(1969, 2020), size=15, replace=False),
    'bottom' : [random_date(T1, T2) for x in range(15)],
    'top'    : [random_date(T2, T3) for x in range(15)],

}).sort_values(by='year').set_index('year')

# define fig/ax and figsize
fig, ax = plt.subplots(figsize=(16,8))
# plot data
ax.bar(
    x = df.index,
    height = (df.top - df.bottom),
    bottom = df.bottom,
    color = '#9e7711'
)

# add x_locator (every 2 years), y tick datetime formatter, grid
# hide top/right spines, and rotate the x ticks for readability
x_locator   = ax.xaxis.set_major_locator(mpl.ticker.MultipleLocator(2))
y_formatter = ax.yaxis.set_major_formatter(mdates.DateFormatter('%d %b'))
tick_params = ax.tick_params(axis='x', rotation=45)
grid        = ax.grid(axis='y', dashes=(8,3), alpha=0.3, color='gray')
hide_spines = [ax.spines[s].set_visible(False) for s in ['top','right']]

【讨论】:

  • 非常感谢!效果很好!我刚刚收到此消息,您知道如何纠正它吗?如果没有,我可能会创建另一个帖子^^ PerformanceWarning: Non-vectorized DateOffset being applied to Series or DatetimeIndex warnings.warn(
猜你喜欢
  • 1970-01-01
  • 2021-12-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多