数据, 术→技巧

Python数据可视化之华夫饼图

钱魏Way · · 112 次浏览
!文章内容如有错误或排版问题,请提交反馈,非常感谢!

PyWaffle简介

PyWaffle是一个基于Matplotlib的Python库,用于创建华夫图(Waffle Chart)。华夫图是一种数据可视化工具,类似于饼图,用于表示部分与整体之间的关系,但它通过网格形式展现数据,更加直观和易于理解。

这个库依赖于Matplotlib库来绘制图片,并且支持Python 3.5及更高版本,确保了广泛的应用兼容性。通过简单的参数配置,如rows(行数)、columns(列数)以及values(数值),PyWaffle即可生成美观且信息量大的瓦片图。此外,颜色、标签、图例等细节均可定制化,满足多样化的视觉需求。

PyWaffle的特点

  • 开源与兼容性:
    • PyWaffle遵循MIT协议,是一个完全开源的项目。
    • 它支持Python 3.5+版本,并依赖于Matplotlib库,确保了广泛的应用兼容性。
  • 简洁的API设计:
    • PyWaffle定义了一个Waffle类,作为matplotlib的Figure构造器的一个扩展,允许直接通过pyplot.figure调用,无缝融合到现有的数据可视化流程中。
    • 通过简单的参数配置如rows(行数)、columns(列数)以及values(值),即可生成美观且信息量大的瓦片图。
  • 高度可定制:
    • PyWaffle提供了丰富的自定义选项,包括颜色方案、图表尺寸、布局样式等,可以满足多样化的视觉需求。
    • 用户可以自定义每个类别的颜色、标签、图例等,使图表更加个性化。
  • 直观展示比例:
    • 华夫饼图的排列天然适合展示各类比例数据,尤其当数值范围广、分类多时更为明显。
    • 通过方格的数量和颜色,用户可以直观地理解不同类别之间的比例关系。
  • 广泛的应用场景:
    • PyWaffle适用于市场分析、销售业绩展示、项目管理等多种场景。
    • 在市场分析中,可以迅速反映出不同产品线或区域的销售额占比;在项目管理中,可以监控不同任务的完成进度。

PyWaffle的使用

安装PyWaffle

在使用PyWaffle之前,你需要先安装它。可以使用以下命令通过pip进行安装:pip install pywaffle

class pywaffle.waffle.Waffle(*args, **kwargs)

参数说明:

  • values (list|dict|pandas.Series) – 每个类别的数值。如果是字典,键将用作标签。
  • rows (int) – 华夫图的行数。
  • columns (int) – 华夫图的列数。行和列至少需要一个。如果传递了行或列中的一个,则另一个参数将通过数值的绝对值自动计算。如果同时传递了行和列,则块数量是固定的,并从缩放后的值中计算块数量。
  • colors (list[str]|tuple[str], optional) – 每个类别的颜色列表。其长度应与值相同。默认值来自Set2色图。
  • labels (list[str]|tuple[str], optional) – 每个类别的名称。如果values是字典,则此参数将被值的键替代。
  • legend (dict, optional) – Matplotlib pyplot.legend的参数,以字典形式提供。例如:{‘loc’:”, ‘bbox_to_anchor’:(,), …}。完整参数列表见legend。
  • interval_ratio_x (float, optional) – 块之间水平距离与块宽度的比率。[默认2]
  • interval_ratio_y (float, optional) – 块之间垂直距离与块高度的比率。[默认2]
  • block_aspect_ratio (float, optional) – 块宽与高的比率。[默认1]
  • cmap_name (str, optional) – 默认颜色的色图名称,如果未指定颜色。完整列表见colormaps_reference。[默认‘Set2’]
  • title (dict, optional) – Matplotlib axes.Axes.set_title的参数,以字典形式提供。例如:{‘label’:”, ‘fontdict’:{}, ‘loc’:”}。完整参数列表见title。
  • characters – 字符串中的一个字符或每个类别的字符列表。[默认None]
  • font_size – FontAwesome图标的字体大小。默认大小不是固定的,取决于块大小。可以是相对值(如‘xx-small’, ‘x-small’, ‘small’, ‘medium’, ‘large’, ‘x-large’, ‘xx-large’)或绝对字体大小。
  • font_file – 自定义字体文件的路径。
  • icons (str|list[str]|tuple[str], optional) – FontAwesome的图标名称。如果是字符串,则所有类别使用相同的图标;如果是图标的列表或元组,长度应与值相同。FontAwesome的完整列表见FontAwesome。[默认None]
  • icon_style (str|list[str]|tuple[str], optional) – 要使用的图标样式。FontAwesome图标通过样式和图标名称找到图标。样式可以是‘brands’, ‘regular’和‘solid’。详细信息见FontAwesome Cheatsheet。如果是字符串,则在给定样式内搜索图标。如果是列表或元组,长度应与值相同,表示每个图标的样式。[默认‘solid’]
  • icon_size (int|str, optional) – FontAwesome图标的字体大小。已弃用!请使用font_size。默认大小不是固定的,取决于块大小。可以是相对值(如‘xx-small’, ‘x-small’, ‘small’, ‘medium’, ‘large’, ‘x-large’, ‘xx-large’)或绝对字体大小。
  • icon_legend (bool, optional) – 是否在图例中使用图标而不是颜色条。[默认False]
  • plot_anchor (str, optional) – 子图的对齐方式。{‘C’, ‘SW’, ‘S’, ‘SE’, ‘E’, ‘NE’, ‘N’, ‘NW’, ‘W’}。详细信息见axes.Axes.set_anchor。[默认‘W’]
  • plots (dict, optional) – 子图中Waffle类的位置和参数,以字典形式提供,格式如{pos:{subplot_args:values, }, }。pos可以是三个整数的元组,其中第一个数字是行数,第二个是列数,第三个是子图的索引。pos也可以是3位数字的整数或字符串类型。例如,它接受235或’235’代表在具有J行和K列的网格上的第I个图。注意,对于此格式,所有整数必须小于10。子图的参数与Waffle类参数相同,不包括plots本身。如果未指定子图的任何参数,则使用Waffle类中的相同参数作为默认值。
  • vertical (bool, optional) – 是否垂直绘制图形。[默认False]
  • starting_location (str, optional) – 更改绘制块的起始位置。{‘NW’, ‘SW’, ‘NE’, ‘SE’}。当为’NW’时,表示从左上角开始绘制;’SW’表示从左下角开始绘制;’NE’表示从右上角开始绘制;’SE’表示从右下角开始绘制。[默认‘SW’]
  • rounding_rule (str, optional) – 调整值以适应图表大小时应用的舍入规则。{‘nearest’, ‘floor’, ‘ceil’}。当为’nearest’时,是“四舍五入到最近,偶数优先”的舍入模式;当为’floor’时,舍入到区间的较小端点;当为’ceil’时,舍入到区间的较大端点。[默认‘nearest’]

tight (bool|dict, optional) – 设置绘制时是否以及如何调用 .tight_layout。可以是 bool 或具有键 “pad”, “w_pad”, “h_pad”, “rect” 的字典或 None。如果是 bool,则设置是否在绘制时调用 .tight_layout。如果为 None,则使用 autolayout 参数代替。如果是字典,则将其作为 kwargs 传递给 .tight_layout,覆盖默认填充。[默认 True]

  • block_arranging_style (string, optional) – 设置如何排列块。{‘normal’, ‘snake’, ‘new-line’}。如果为 ‘normal’,则逐行绘制块,方向相同。如果为 ‘snake’,则以蛇形模式绘制块。如果为 ‘new-line’,则在绘制每个类别时从新行开始。这仅在只分配了行或列中的一个时有效,并且当 rows 被分配时 vertical=False 或 vertical=True 时有效。[默认 ‘normal’]
  • 基本用法

    首先,我们来看一个简单的例子,展示如何使用 PyWaffle 创建一个基本的华夫图。

    import matplotlib.pyplot as plt
    from pywaffle import Waffle
    
    fig = plt.figure(
        FigureClass=Waffle,
        rows=5,
        columns=10,  # Either rows or columns could be omitted
        values=[30, 16, 4]  # Pass a list of integers to values
    )
    plt.show()
    

    使用字典中的值和自动调整大小:

    data = {'Cat1': 10, 'Cat2': 7, 'Cat3': 9}
    fig = plt.figure(
        FigureClass=Waffle,
        rows=5,
        values=data,
        legend={'loc': 'upper left', 'bbox_to_anchor': (1.05, 1)},
    )
    plt.show()
    

    更多样式设置:

    data = {'Car': 58, 'Pickup': 21, 'Truck': 11, 'Motorcycle': 7}
    fig = plt.figure(
        FigureClass=Waffle,
        rows=5,
        values=data,
        colors=["#C1D82F", "#00A4E4", "#FBB034", '#6A737B'],
        title={'label': 'Vehicle Sales by Vehicle Type', 'loc': 'left'},
        labels=[f"{k} ({v}%)" for k, v in data.items()],
        legend={'loc': 'lower left', 'bbox_to_anchor': (0, -0.4), 'ncol': len(data), 'framealpha': 0},
        starting_location='NW',
        vertical=True,
        block_arranging_style='snake'
    )
    fig.set_facecolor('#EEEEEE')
    plt.show()
    

    PyWaffle 允许你使用图标而不是方块来表示数据。你可以使用 icons 参数来设置图标,并使用 icon_size 来设置图标大小。

    data = {'Car': 58, 'Pickup': 21, 'Truck': 11, 'Motorcycle': 7}
    fig = plt.figure(
        FigureClass=Waffle,
        rows=5,
        values=data,
        colors=["#c1d82f", "#00a4e4", "#fbb034", '#6a737b'],
        legend={'loc': 'upper left', 'bbox_to_anchor': (1, 1)},
        icons=['car-side', 'truck-pickup', 'truck', 'motorcycle'],
        font_size=12,
        icon_legend=True
    )
    plt.show()
    

    还可以在一个图中组合多个华夫图。只需在 plots 字典中添加多个子图配置即可。

    import pandas as pd
    data = pd.DataFrame(
    {
    'labels': ['Car', 'Truck', 'Motorcycle'],
    'FactoryA': [32384, 13354, 5245],
    'FactoryB': [22147, 6678, 2156],
    'FactoryC': [8932, 3879, 896],
    },
    ).set_index('labels')
    
    # A glance of the data:
    # FactoryA FactoryB FactoryC
    # labels
    # Car 27384 22147 8932
    # Truck 7354 6678 3879
    # Motorcycle 3245 2156 1196
    
    fig = plt.figure(
    FigureClass=Waffle,
    plots={
    311: {
    'values': data['FactoryA']/1000, # Convert actual number to a reasonable block number
    'labels': [f"{k} ({v})" for k, v in data['FactoryA'].items()],
    'legend': {'loc': 'upper left', 'bbox_to_anchor': (1.05, 1), 'fontsize': 8},
    'title': {'label': 'Vehicle Production of Factory A', 'loc': 'left', 'fontsize': 12}
    },
    312: {
    'values': data['FactoryB']/1000,
    'labels': [f"{k} ({v})" for k, v in data['FactoryB'].items()],
    'legend': {'loc': 'upper left', 'bbox_to_anchor': (1.2, 1), 'fontsize': 8},
    'title': {'label': 'Vehicle Production of Factory B', 'loc': 'left', 'fontsize': 12}
    },
    313: {
    'values': data['FactoryC']/1000,
    'labels': [f"{k} ({v})" for k, v in data['FactoryC'].items()],
    'legend': {'loc': 'upper left', 'bbox_to_anchor': (1.3, 1), 'fontsize': 8},
    'title': {'label': 'Vehicle Production of Factory C', 'loc': 'left', 'fontsize': 12}
    },
    },
    rows=5, # Outside parameter applied to all subplots, same as below
    cmap_name="Accent", # Change color with cmap
    rounding_rule='ceil', # Change rounding rule, so value less than 1000 will still have at least 1 block
    figsize=(6, 5)
    )
    
    fig.suptitle('Vehicle Production by Vehicle Type', fontsize=14, fontweight='bold')
    fig.supxlabel('1 block = 1000 vehicles', fontsize=8, x=0.14)
    fig.set_facecolor('#EEEDE7')
    
    plt.show()
    

    参考链接:

    发表回复

    您的邮箱地址不会被公开。 必填项已用 * 标注