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

时间:2016-07-02 14:22:41

标签: python matplotlib bar-chart linechart

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

@Entity
@Table( name="usuarios" ) 
public class Usuario implements Serializable {
    private static final long serialVersionUID = 3L;

    @Id
    @Column( name="userid", length=8 )
    private String        userId;

    @Column
    private String        nombre;

    @Column
    private String        apellido;

    @Column(name="nro_fun")
    private int           nroFuncionario;

    @OneToMany( cascade=CascadeType.ALL, mappedBy="usuario" )
    private List<UsuarioPermisos> permisos;

问题

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

我想要什么

所以我想添加行,以便更清楚地看到每个群组的趋势。这些行应该从一个组中每个条的顶部到相应其他组中的条的顶部。

我在网上找不到类似的东西。

这可能吗?

2 个答案:

答案 0 :(得分:3)

我最近开始学习 Matplotlib Numpy ,发现你的问题非常有趣。

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

<强>结果enter image description here

<强>代码:

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()

答案 1 :(得分: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()