BI 产品中的数据可视化研发实践

技术

可视化作为BI产品门户,其展现形式、交互效果、性能等诸多特性在很大层面上决定了一款产品的成败。本文基于字节跳动开源可视化解决方案VisActor在BI产品中的业务实践总结而来,为您提供最佳指南。

什么是BI

商业智能,又称商业智慧或商务智能,指用现代数据仓库技术、线上分析处理技术、数据挖掘和数据可视化技术进行数据分析以实现商业价值。

picture.image

BI 产品通常需要具备以下四个基本能力:

  1. 数据接入 :能够支持各种常见数据源的接入。
  2. 数据分析 :能够提供多种数据分析方法和工具,帮助用户深入挖掘数据背后的规律和洞察。
  3. 数据可视化 :能够以直观、易于理解的方式呈现数据,帮助用户快速了解数据的分布、趋势和关系。通过可视化来探索和挖掘数据的内在意义。
  4. 决策支持 :能够根据用户的需求和问题,提供相应的决策依据和建议,帮助用户做出更加明智的决策。
BI 产品需要具备的可视化能力

可视化作为BI产品门户,其展现形式、交互效果、性能等诸多特性在很大层面上决定了一款产品的成败。

丰富的图表类型

为用户提供了丰富的图表类型供用户使用, 包括统计图表、透视图表、表格、Gis 地图等,才能满足不同数据类型、不同展示目的的用户需求。

picture.image

picture.image

picture.image

picture.image

不同风格的主题

需要将查询结果对外展示的时候,需要给用户提供不同的主题来满足不同场景的美化需求。

picture.image

picture.image

轻松上手的交互形式

简单好用的交互,才能让用户体验BI 产品在探索分析方面的强大能力。常见的交互形式有如下几种:

  • 选择和过滤picture.image

  • 缩放 与 平移

picture.image

  • 嵌入图表的提示信息

picture.image

  • 上卷与下钻 & 标注

picture.image

懂数据更懂用户的分析助手

目前借助LLM实现的分析助手已经成为各种BI产品的标配, 它可以进行二次分析,帮助用户快速找到数据中的洞察。亦可根据用户当前选中的维度与指标,自动推荐相关的图表类型。分析助手基于 @VisActor/VMind 实现。

picture.image

picture.image

极致的性能

性能是用户体验的重中之重,BI产品的性能指标体现在如下几个方面:

  1. 查询性能, 支持千亿级数据量的秒级查询。

  2. 单图表渲染性能, 在100 毫秒内出图。透视图表, 可以渲染上千个图表, 而没有卡顿。

  3. 多图表无阻塞渲染。渲染调度, 按照图表优先级以及内部策略,依次有序的进行渲染工作的调度与分配,不阻塞页面交互。picture.image

移动端体验

图表和仪表盘需要完美适配了移动端场景,随时随地查看数据报表。

picture.image

BI产品可视化实现原理

基础模块

picture.image

如上图,是我们在BI中实现各种可视化能力的核心模块:

  • Schema : 是业务 数据结构, 用于描述BI产品中的可视化业务属性配置。
  • QueryService : 是一个查询服务 , 根据一个 schema, 查询得到数据, 拼装到 VizData 中。
  • VizData : 用于统一描述图表、表格的数据结构, 是业务和图表库之间的桥梁
  • Spec : @VisActor/VChart 和 @VisActor/VTable 的配置文件。

Schema

schema 是一个描述UI 层图表或者表格的数据结构。一个 schema 就是一个图表, 其结构与可视化查询 UI 对应,包含对图表的所有配置。

示例

基于一个“超市”数据集, 想简单的分析一下销售额趋势, 做了以下操作:

  1. 增加 1 个日期维度, 2 个指标, 并调整日期格式为“季度”

  2. dimensionsmeasures

  3. 图表类型“折线图”

  4. 添加一个筛选器, 筛选 2016 和 2017 两年的数据。

  5. whereList

  6. 增加 1 个列透视和 1 个行透视。

  7. rowscolumns

  8. 增加 1 个参考系的分析功能

生成的Schema 信息大致如下:


            
{
            
  "columns": [
            
  ],
            
  "dimensions": [
            

            
  ],
            
  "display": {
            
      "conf": {
            
          "axisDimension": [
            
              {
            
              }
            
          ],
            
          "axisMeasure": [
            
              {
            
                
            
              }
            
          ],
            
          "color": {
            
              "colorScheme": "scheme7",
            
              "colors": []
            
          },
            
          "customFields": {
            
              "enable": false
            
          },
            
          "displayMode": "adaptive",
            
          "label": {
            

            
          },
            
          "legend": {
            
          },
            
          "lineStyle": {
            
          },
            
          "pivot": {
            

            
          },
            
          "stack": true,
            
          "tooltip": {
            
          },
            
      },
            
  },
            
  "drill": [],
            
  "extensions": {
            
  },
            
  "measures": [
            
    
            
  ],
            
 
            
  "whereList": [
            
      {
            
          "aggrConf": {},
            
          "dataSetId": 3061904,
            
          "dimMetId": 1700056731609,
            
          "filter": {
            
              "op": "between",
            
              "option": {
            
                  "dateMode": "absolute",
            
                  "isReportFilter": false,
            
                  "isWhereInAggr": true
            
              },
            
              "val": [
            
                  "2016-01-01 00:00:00",
            
                  "2017-12-31 23:59:59"
            
              ],
            
              "valOption": {}
            
          },
            
          "format": {},
            
          "id": "1700056731609",
            
          "index": 0,
            
          "location": "whereList",
            
          "name": "订单日期",
            
          "originId": "1700056731609",
            
          "preRelation": "and",
            
          "roleType": 0,
            
          "showEditComponent": false,
            
          "uniqueId": 240524174219108
            
      }
            
  ],
            
  "whiteList": []
            
}
            

            
(....)
            
}
        

Spec

Spec 详细配置可以在 @VisActor/VChart 和 @VisActor/VTable 的站点查阅,这里我们简单介绍一下在BI 产品里颇具特色的透视组合图结构。

行列透视树

透视图表的行列透视结构实际上就是 2 个多叉树结构, 从 spec 上可以很容易看出并理解。

picture.image

图表单元格:

VTable 的指标配置中, 支持将单元格类型设置为 VChart 的图表, 传入 chartSpec 即可。

spec.indicators可以约定图表的配置, VTable 会代理 VChart, 进行图表绘制。

图表的 x、y 轴、坐标系、图例、标签、参考系, 都可以从图表的 spec 上看出。

picture.image

完整 spec示例:https://www.visactor.io/vtable/demo/table-type/pivot-chart

VizData

vizData 是用于统一描述图表、表格的数据结构, 是业务和图表库的桥梁。 我们从下面两个场景来说明 VizData 的作用。

ViZData概念

用户选定维度和指标后, 可以任意切换图表类型, 得到可视化图表, 这是怎么做到的?

picture.image

‍切换图表功能在 schema 层面是逻辑自洽的, 但图表库并不直接提供图表类型的切换能力, 例如由表格切换到柱状图, 其实是 2 个可视化库,无法顺利的支持图表切换能力。所以需要一个中间层做转换。

VizData 针对这种场景, 就需要对业务的图表切换能力进行抽象, 由此便基于图形语法 设计 VizData, 可以让 VizData 脱离了具体的图表限制, 支持同一份数据渲染为多种图表。

示例中, 指标有 2 个, 但图表只有 1 根轴, 多个指标是如何绘制到一个轴上的?

picture.image

这涉及到一个将多个指标 转换为 1 个指标的概念, 将多个指标转换为一个指标, 以更好的进行数据可视化, 这个操作被定义为“fold”。

picture.image

这类功能在业务上是合理的, 因此做在 schema 上是不合适的, 但图表并不直接支持多指标, 所以需要一个中间层做转换

VizData 针对这种场景, 就需要对指标的合并进行抽象, 以及封装。基于 fold 操作, 和图形语法中的视觉通道概念, 设计了 VizData.cells 结构, 用于描述这类关系。上述示例在 VizData 中会按此结构表示


            
// cell 结构
            
{
            
    foldInfo: {
            
        value: "10002",
            
    },
            
    color: '20001',
            
    x: ['班级'],
            
    y: ['10002']
            
}
            

            
// datasets 结构
            
[              { '班级': 'A', '20001': '男', '10002': 90},              { '班级': 'A', '20001': '女', '10002': 95},              { '班级': 'B', '20001': '男', '10002': 80},              { '班级': 'B', '20001': '女', '10002': 75},              { '班级': 'C', '20001': '男', '10002': 70},              { '班级': 'C', '20001': '女', '10002': 85},            ]
        

有了上述 2 个场景的举例说明, 可以得知:

贴近业务:VizData 需要将业务功能进行抽象, 通过 VizData 结构, 满足业务的需求。

承载技术:VizData 需要对图表、表格、地图能力进行封装, 提供绘制能力。

picture.image

基于VizData,我们可以处理非常多的可视化能力:

  • 图表类型随意切换。
  • 通用图表透视能力。
  • 约定配置:为每个图表提供默认配置, 让使用图表变得更加省心。
  • 处理多指标的合并。
  • 处理维度的笛卡尔积。
  • 图表国际化。
  • 图表数据格式、条件格式。
  • 图表标签。
  • 大量的图表样式配置。

VizData 作用

前端业务与图表解耦

隔离BI可视化与图表之间的强关联,schema 与 spec 隔离变化, 二者可以独立变化与切换, 互不影响, 只要 VizData 封装变化即可

后端取数与图表解耦

有了 VizData 后, VizData 解除了后端与图表类型的依赖, VizData 是在取数后创建的, 意味着后端不再需要关心具体的图表类型和展示方式,只需要专注于提供数据服务。

这样就可以提高后端的可复用性和可维护性,同时也可以让前端更加灵活地选择不同的图表库和展示方式。

BI图表能力对外开放

VizData 对BI业务进行了抽象,提供了通用接口,满足用户使用需求。因此,第三方开发者可以自定义图表。

声明

本文产品示例来源于 火山引擎DataWind。

DataWind 是一款支持千亿级别数据自助分析的一站式数据分析与协作平台。可打通从数据接入、数据整合、查询分析到全员协同共享的全流程,以数据门户、数字大屏、管理驾驶舱等可视化形态,助力业务用户实现智能洞察,让数据发挥价值。

联系我们

最后,我们诚挚的欢迎所有对数据可视化感兴趣的朋友参与进来,参与 VisActor 的开源建设:

更多内容

探索 VChart 图表库:简单、易用、强大、高性能、炫酷的可视化利器

VTable——不只是高性能的多维数据分析表格

VMind-智能图表生成引擎

0
0
0
0
评论
未登录
看完啦,登录分享一下感受吧~
暂无评论