分享一个拿来即用的柱状图绘制函数

分享一个自己写的柱状图绘制函数,可用来绘制横向的多柱状图、堆积柱状图,纵向的多柱状图、堆积柱状图。便于我们方便快捷的绘制相应的柱状图。该函数参数不多,只用于观察数据形式是足够的,若要绘制更加精美的柱状图,大家可自行调整。

欢迎关注本人同名公众号--交通数据探索师

import random
import matplotlib.pyplot as plt
import numpy as np

def generate_colors(num):
    """随机生成num个不同的颜色"""
    random.seed(123)

    colors = []
    while len(colors) <= num:
        color = '#{:06x}'.format(random.randint(0, 0xFFFFFF))
        if color not in colors:
            colors.append(color)
    return colors

def bars(data, cols, labels, kind='s', title='', x_label='', y_label='', width=0.4, grid=False, x_rotation=0,
         y_rotation=0, legend=False, filename=''):
    """绘制柱状图 包括双柱状图等多柱状图  横竖累积柱状图
    demo: bars(data, cols=['a', 'b', 'c', 'd', 'e'], labels=['b', 'c', 'd', 'e'], width=0.2, filename='l1')
    cols中第一个元素对应x轴, 其余元素对应y轴
    kind: 绘制柱状图的种类  {h: 横柱状图, s: 竖柱状图, l1: 竖累积柱状图, l2: 横累积柱状图}
    title: 标题
    x_label: x轴标签
    y_label: y轴标签
    width: 柱子宽度
    grid: 是否显示网格
    x_rotation: x轴标签旋转角度
    legend: 是否显示图例
    filename: 保存的文件名
    """
    # 解决中文乱码问题,并设置字体
    plt.rcParams['axes.unicode_minus'] = False
    plt.rcParams['font.family'] = ['SimHei']
    plt.rcParams['font.sans-serif'] = ['SimHei']
    
    fig, ax = plt.subplots(figsize=(6, 2.5), dpi=300)

    x_ticks = np.arange(data[cols[0]].nunique())

    if len(cols[1:]) > 4:
        bar_colors = generate_colors(len(cols) - 1)
    else:
        # 设置好的四个颜色 如果柱子个数<=4就用这四个颜色中的几个
        bar_colors = ['#63b5ef', '#73de94', '#ffce7b', '#ff948c']

    if (len(cols) - 1) % 2 == 0:  # 偶数根柱子
        center = (len(cols) - 1) / 2
        for r, col in enumerate(cols[1:]):
            if kind == 's':
                ax.bar([x + (r - center) * width + width / 2 for x in x_ticks], data[col], lw=0.4,
                       color=bar_colors[r], edgecolor="k", label=labels[r], width=width)
                plt.xticks(x_ticks, labels=data[cols[0]].unique())
                plt.xlabel(x_label, fontsize=5)
                plt.ylabel(y_label, fontsize=5)
            elif kind == 'h':
                ax.barh([x + (r - center) * width + width / 2 for x in x_ticks], data[col], lw=0.4,
                        color=bar_colors[r], edgecolor="k", label=labels[r], height=width)
                plt.yticks(x_ticks, labels=data[cols[0]].unique())
                plt.xlabel(y_label, fontsize=5)
                plt.ylabel(x_label, fontsize=5)  
            elif kind == 'l1':
                # r==0表示是最下面那根柱子, 则bottom=0 否则==前面几列的和
                bottom = 0 if r == 0 else data[cols[1:][:r]].sum(axis=1)
                ax.bar(x_ticks, data[col], bottom=bottom, lw=0.4,
                       color=bar_colors[r], edgecolor="k", label=labels[r], width=width)
                plt.xticks(x_ticks, labels=data[cols[0]].unique())
                plt.xlabel(x_label, fontsize=5)
                plt.ylabel(y_label, fontsize=5)
            elif kind == 'l2':
                bottom = 0 if r == 0 else data[cols[1:][:r]].sum(axis=1)
                ax.barh(x_ticks, data[col], left=bottom, lw=0.4,
                        color=bar_colors[r], edgecolor="k", label=labels[r], height=width)
                plt.yticks(x_ticks, labels=data[cols[0]].unique())
                plt.xlabel(y_label, fontsize=5)
                plt.ylabel(x_label, fontsize=5)
            else:
                print('kind参数输入错误: {h: 横柱状图, s: 竖柱状图, l1: 竖累积柱状图, l2: 横累积柱状图}')

    else:
        center = (len(cols) - 1) // 2
        for r, col in enumerate(cols[1:]):
            if kind == 's':
                ax.bar([x + (r - center) * width for x in x_ticks], data[col], lw=0.4,
                       color=bar_colors[r], edgecolor="k", label=labels[r], width=width)
                plt.xticks(x_ticks, labels=data[cols[0]].unique())
                plt.xlabel(x_label, fontsize=5)
                plt.ylabel(y_label, fontsize=5)
            elif kind == 'h':
                ax.barh([x + (r - center) * width for x in x_ticks], data[col], lw=0.4,
                        color=bar_colors[r], edgecolor="k", label=labels[r], height=width)
                plt.yticks(x_ticks, labels=data[cols[0]].unique())
                plt.xlabel(y_label, fontsize=5)
                plt.ylabel(x_label, fontsize=5)
            elif kind == 'l1':
                # r==0表示是最下面那根柱子, 则bottom=0 否则==前面几列的和
                bottom = 0 if r == 0 else data[cols[1:][:r]].sum(axis=1)
                ax.bar(x_ticks, data[col], bottom=bottom, lw=0.4,
                       color=bar_colors[r], edgecolor="k", label=labels[r], width=width)
                plt.xticks(x_ticks, labels=data[cols[0]].unique())
                plt.xlabel(x_label, fontsize=5)
                plt.ylabel(y_label, fontsize=5)
            elif kind == 'l2':
                bottom = 0 if r == 0 else data[cols[1:][:r]].sum(axis=1)
                ax.barh(x_ticks, data[col], left=bottom, lw=0.4,
                        color=bar_colors[r], edgecolor="k", label=labels[r], height=width)
                plt.yticks(x_ticks, labels=data[cols[0]].unique())
                plt.xlabel(y_label, fontsize=5)
                plt.ylabel(x_label, fontsize=5)
            else:
                print('kind参数输入错误: {h: 横柱状图, s: 竖柱状图, l1: 竖累积柱状图, l2: 横累积柱状图}')

    # 修饰参数
    plt.title(title, fontsize=7)
    if grid:
        plt.grid(axis='both', linestyle=":")
    if legend:
        plt.legend(fontsize=5, ncols=4, loc='lower center', bbox_to_anchor=(0.5, -0.27))
    else:
        plt.legend(fontsize=5)
    # 轴刻度参数
    ax.tick_params(axis='x', labelsize=5, rotation=x_rotation)
    ax.tick_params(axis='y', labelsize=5, rotation=y_rotation)
    plt.tight_layout()
    if filename == '':
        plt.savefig('柱状图.png')
    else:
        plt.savefig('{filename}.png')
    return fig

使用如下示例数据进行演示

import pandas as pd

data = pd.DataFrame(
    {
        '1': list('abcdefg'),
        '2':range(1, 8),
        '3': range(2, 9),
        '4': range(3, 10),
        '5': range(4, 11),
        '6': range(5, 12)
    }
)

竖柱状图

bars(data, ['1', '2', '3', '4', '5', '6'], ['2', '3', '4', '5', '6'], width=0.1, kind='s')

bars(data, ['1', '2', '3', '4'], ['2', '3', '4'], width=0.1, kind='s')

 

横柱状图

bars(data, ['1', '2', '3', '4'], ['2', '3', '4'], width=0.2, kind='h')

bars(data, ['1', '2', '3', '4'], ['2', '3', '4'], width=0.2, kind='l1')

 

横累积柱状图

bars(data, ['1', '2', '3', '4'], ['2', '3', '4'], width=0.4, kind='l2')

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

煮雨小筑

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值