matplotlib:如何将多个条形与线组合

mat*_*eus 3 python linechart matplotlib bar-chart

我有一个非常简单的分组条形图,每个组有5组,每组4条。我使用了matplotlib文档中的示例,该示例如下所示:

import numpy as np
import matplotlib.pyplot as plt

ind = np.arange(5)
avg_bar1 = (81191,79318,57965,60557,14793)
avg_bar2 = (26826,26615,31364,31088,55472)
avg_bar3 = (36232,38038,38615,39014,40812)
avg_bar4 = (26115,25879,25887,28326,27988)

fig, ax = plt.subplots()

rects1 = ax.bar(ind, avg_bar1, 0.15, label='bar1')
rects2 = ax.bar(ind + 0.15, avg_bar2, 0.15, label='bar2')
rects3 = ax.bar(ind + 0.30, avg_bar3, 0.15, label='bar2')
rects4 = ax.bar(ind + 0.45, avg_bar4, 0.15, label='bar2')

plt.xlabel('Distributions')
plt.ylabel('ms')
plt.xticks(ind + 0.15, ('50/50', '60/40', '70/30', '80/20', '90/10'))
plt.legend()

plt.tight_layout()
plt.show()
Run Code Online (Sandbox Code Playgroud)

问题

但是相应的其他组中的bar的某些值(例如,group1中的bar1和group2中的bar1,等等)彼此之间相差不大。

我想要的是

因此,我想添加线条以更清楚地看到每个组的趋势。这些线应从一组中每个条的顶部到相应其他组中的条的顶部。

我在网上找不到任何类似的内容。

那可能吗?

ars*_*sho 5

我最近开始学习MatplotlibNumpy,发现您的问题很有趣。

因此,我花时间来创建组合条形图和与该组合条形图相关的折线图的组合图。

结果在此处输入图片说明

码:

import numpy as np
import matplotlib.pyplot as plt

ind = np.arange(5)
avg_bar1 = (81191,79318,57965,60557,14793)
avg_bar2 = (26826,26615,31364,31088,55472)
avg_bar3 = (36232,38038,38615,39014,40812)
avg_bar4 = (26115,25879,25887,28326,27988)

rects1 = plt.bar(ind, avg_bar1, 0.15, color='#ff0000',label='bar1')
rects2 = plt.bar(ind + 0.15, avg_bar2, 0.15, color='#00ff00', label='bar2')
rects3 = plt.bar(ind + 0.30, avg_bar3, 0.15, color='#0000ff', label='bar3')
rects4 = plt.bar(ind + 0.45, avg_bar4, 0.15, color='#000000', label='bar4')

high_point_x = []
high_point_y = []    
for i in range(0,5):
    single_bar_group={rects1[i].get_height():rects1[i].get_x() + rects1[i].get_width()/2.0,
                      rects2[i].get_height():rects2[i].get_x() + rects2[i].get_width()/2.0,
                      rects3[i].get_height():rects3[i].get_x() + rects3[i].get_width()/2.0,
                      rects4[i].get_height():rects4[i].get_x() + rects4[i].get_width()/2.0}

    height_list = list(single_bar_group.keys())
    height_list.sort(reverse=True)
    for single_height in height_list:
        high_point_y.append(single_height)
        high_point_x.append(single_bar_group[single_height])
        break

trend_line = plt.plot(high_point_x,high_point_y,marker='o', color='#5b74a8', label='Trend Line')

plt.xlabel('Distributions')
plt.ylabel('ms')
plt.xticks(ind+0.15, ('50/50', '60/40', '70/30', '80/20', '90/10'))
plt.legend()
plt.show()
Run Code Online (Sandbox Code Playgroud)


mat*_*eus 0

感谢@arsho 的意见。我把它弄得更紧凑了一点。它还修复了代码中最后一组条形的错误。请参阅代码中的注释。希望这可以帮助。

对于像我这样刚接触 matplotlib 的人来说:我们可以简单地在子图上绘制一条线,无论它是否已经包含条形图。

import numpy as np
import matplotlib.pyplot as plt

# fig, is the whole thing; ax1 is a subplot in the figure, 
# so we reference it to plot bars and lines there
fig, ax1 = plt.subplots()

ind = np.arange(3)
width = 0.15

# per dimension
colors = ['#00ff00', '#0000ff', '#ff00ff']
markers = ['x','o','v']
xticklabels = ['50/50', '60/40', '70/30']

# 
group1 = [12,6,5]
group2 = [6,8,12]
group3 = [2,4,9]

#
all_groups = [ group1, group2, group3 ]

# plot each group of bars; loop-variable bar_values contains values for bars
for i, bar_values in enumerate( all_groups ):

  # compute position for each bar
  bar_position = width*i
  ax1.bar( ind + bar_position, bar_values, width, color=colors[i] )

# plot line for each group of bars; loop-variable y_values contains values for lines
for i, y_values in enumerate( all_groups ):

  # moves the beginning of a line to the middle of the bar
  additional_space = (width*i) + (width/2);
  # x_values contains list indices plus additional space
  x_values = [ x + additional_space for x,_ in enumerate( y_values ) ]

  # simply plot the values in y_values
  ax1.plot( x_values, y_values, marker=markers[i], color=colors[i] )

plt.setp([ax1], xticks=ind + width, xticklabels=xticklabels)

plt.tight_layout()
plt.show()
Run Code Online (Sandbox Code Playgroud)