Superset BI 数据可视化平台,可视化组件二次开发之集成 Echarts 图表

简介: Superset BI 数据可视化平台,可视化组件二次开发之集成 Echarts 图表

前置基础



Flask 是什么?


Flask 是一个使用 Python 编写的轻量级 Web 应用框架。

  • 官方文档
  • 中文文档


NumPy 是什么?


NumPy是Python的一个用于科学计算的基础包。它提供了多维数组对象,多种衍生的对象(例如隐藏数组和矩阵)和一个用于数组快速运算的混合的程序,包括数学,逻辑,排序,选择,I/O,离散傅立叶变换,基础线性代数,基础统计操作,随机模拟等等。

  • 官网

微信图片_20220611112325.png

Pandas 是什么?


Pandas是一个强大的分析结构化数据的工具集;它的使用基础是Numpy(提供高性能的矩阵运算);用于数据挖掘和数据分析,同时也提供数据清洗功能。

  • 官方文档
  • 中文文档


微信图片_20220611112339.png

Echarts 是什么?


ECharts 是一款开源的、基于 web 的、跨平台的支持快速创建交互式可视化的框架,它易于使用、拥有丰富的内置交互以及高性能。ECharts 通过一套声明式的可视设计语言定制内置的图表类型,并且底层的流式架构和高性能的图形渲染器极大地提高了 ECharts 的扩展性和性能。

Echarts 官网

Echarts Multiple Y Axis 图表

官网 multiple-y-axis 图表 demo

接下来,我们就是要集成它到我们的 Superset


二次开发 Step-By-Step



使用容器环境安装 Echarts

微信图片_20220611112400.png微信图片_20220611112403.png


docker-compose ps
docker-compose exec superset-node bash
cd /app/superset-frontend/
npm i echarts


visualizations 文件夹


它位于项目 superset-frontend/src/visualizations

我们在此处新建如下文件夹 EchartsMultipleYAxis,它包含:


  • images (可视化组件展示用的缩略图)
  • thumbnail.png
  • thumbnailLarge.png
  • EchartsMultipleYAxisPlugin.jsx(组件核心逻辑)
  • index.js(组件导出)
  • options.js(Echarts Multiple Y Axis 图表官方默认配置项)
  • transformProps.js(将 Superset 传过来的属性过滤一下)


EchartsMultipleYAxisPlugin.jsx为少 这里简单的写了一下(大家可以根据需求自行调整):


.....
function EchartsMultipleYAxisPlugin(elem, props) {
  const {
    width, height,
    data, colorScheme,
  } = props;
  elem.style.width = width;
  elem.style.height = height;
  const echart = echarts.init(elem);
  let colors = CategoricalColorNamespace.getScale(colorScheme).colors;
  defaultOptions.color = colors;
  const legend = [];
  const xAxisData = [];
  let xAxisDataFlag = true;
  let yAxisMaxs = [];
  defaultOptions.yAxis.forEach((y, index) => {
    const sd = data[index];
    const title = sd.key;
    y.name = sd.key;
    y.axisLabel.formatter = `{value}`;
    y.axisLine.lineStyle.color = colors[index];
    const seriesD = [];
    defaultOptions.series[index].data = [];
    sd.values.forEach((value) => {
      xAxisDataFlag && xAxisData.push(value.x);
      defaultOptions.series[index].data.push((value.y).toFixed(2));
    })
    defaultOptions.series[index].name = y.name
    const yAxisMax = Math.max.apply(null, defaultOptions.series[index].data);
    y.max = Math.ceil(yAxisMax) + 5;
    yAxisMaxs.push(yAxisMax);
    xAxisDataFlag = false;
    defaultOptions.legend.data.push(y.name);
  });
  defaultOptions.xAxis[0].data = xAxisData;
  echart.setOption(defaultOptions);
}
....


进入 presets/MainPreset.js,加入如下两句:


......
import EchartsMultipleYAxisChartPlugin from "../EchartsMultipleYAxis";
......
new EchartsMultipleYAxisChartPlugin().configure({ key: 'echarts_multiple_y_axis' })
......


explore 文件夹

进入 superset-frontend/src/explore/components/controls/VizTypeControl.jsx 文件

加入 'echarts_multiple_y_axis',排序一下。


const DEFAULT_ORDER = [
  ...other,
  'echarts_multiple_y_axis'
]


进入 superset-frontend/src/explore/components/controlPanels 文件夹

我们在这里新建一个文件 EchartsMultipleYAxis.js为少 在这里加上相关配置。


import { t } from '@superset-ui/translation';
export default {
  label: t('Echarts Multiple Y Axis Chart'),
  controlPanelSections: [
    {
      label: t('Query'),
      expanded: true,
      controlSetRows: [
        ['metrics'],
        ['adhoc_filters'],
        ['groupby'],
        ['columns'],
        ['row_limit'],
        ['contribution'],
      ],
    },
    {
      label: t('Chart Options'),
      expanded: true,
      controlSetRows: [
        ['color_scheme', 'label_colors'],
      ],
    },
  ],
  controlOverrides: {
    groupby: {
      label: t('Series'),
    },
    columns: {
      label: t('Breakdowns'),
      description: t('Defines how each series is broken down'),
    },
  },
};


setup 文件夹


进入 superset-frontend/src/explore/setupPlugins.ts,加入如下代码:


....
.registerValue('echarts_multiple_y_axis', EchartsMultipleYAxis)


用来注册下这个插件。

viz.py 文件

我们加入如下 python 代码。


class EchartsMultipleYAxisViz(DistributionPieViz):
    """Echarts Multiple Y Axis Chart"""
    viz_type = "echarts_multiple_y_axis"
    verbose_name = _("Echarts Multiple Y Axis Chart")
    is_timeseries = False
    def query_obj(self) -> QueryObjectDict:
        d = super().query_obj()
        fd = self.form_data
        if len(d["groupby"]) < len(fd.get("groupby") or []) + len(
            fd.get("columns") or []
        ):
            raise QueryObjectValidationError(
                _("Can't have overlap between Series and Breakdowns")
            )
        if not fd.get("metrics"):
            raise QueryObjectValidationError(_("Pick at least one metric"))
        if not fd.get("groupby"):
            raise QueryObjectValidationError(_("Pick at least one field for [Series]"))
        return d
    def get_data(self, df: pd.DataFrame) -> VizData:
        if df.empty:
            return None
        fd = self.form_data
        metrics = self.metric_labels
        columns = fd.get("columns") or []
        # pandas will throw away nulls when grouping/pivoting,
        # so we substitute NULL_STRING for any nulls in the necessary columns
        filled_cols = self.groupby + columns
        df[filled_cols] = df[filled_cols].fillna(value=NULL_STRING)
        row = df.groupby(self.groupby).sum()[metrics[0]].copy()
        row.sort_values(ascending=False, inplace=True)
        pt = df.pivot_table(index=self.groupby, columns=columns, values=metrics)
        if fd.get("contribution"):
            pt = pt.T
            pt = (pt / pt.sum()).T
        pt = pt.reindex(row.index)
        chart_data = []
        for name, ys in pt.items():
            if pt[name].dtype.kind not in "biufc" or name in self.groupby:
                continue
            if isinstance(name, str):
                series_title = name
            else:
                offset = 0 if len(metrics) > 1 else 1
                series_title = ", ".join([str(s) for s in name[offset:]])
            values = []
            for i, v in ys.items():
                x = i
                if isinstance(x, (tuple, list)):
                    x = ", ".join([str(s) for s in x])
                else:
                    x = str(x)
                values.append({"x": x, "y": v})
            d = {"key": series_title, "values": values}
            chart_data.append(d)
        return chart_data


关于 viz.py 代码细节


数据科学本身就是复杂的。

NumPy or Pandas 都可以拿出来单独讲好久,好久,好久……


选择图表


微信图片_20220611112452.png

看效果

微信图片_20220611112455.png

目录
打赏
0
0
0
0
26
分享
相关文章
RuoYi AI:1人搞定AI中台!开源全栈式AI开发平台,快速集成大模型+RAG+支付等模块
RuoYi AI 是一个全栈式 AI 开发平台,支持本地 RAG 方案,集成多种大语言模型和多媒体功能,适合企业和个人开发者快速搭建个性化 AI 应用。
716 21
RuoYi AI:1人搞定AI中台!开源全栈式AI开发平台,快速集成大模型+RAG+支付等模块
LangBot:无缝集成到QQ、微信等消息平台的AI聊天机器人平台
LangBot 是一个开源的多模态即时聊天机器人平台,支持多种即时通信平台和大语言模型,具备多模态交互、插件扩展和Web管理面板等功能。
758 14
LangBot:无缝集成到QQ、微信等消息平台的AI聊天机器人平台
Quick BI评测报告:从IT开发视角评测“全场景数据消费式BI平台”
Quick BI评测报告:从IT开发视角评测“全场景数据消费式BI平台”
51 0
Airweave:快速集成应用数据打造AI知识库的开源平台,支持多源整合和自动同步数据
Airweave 是一个开源工具,能够将应用程序的数据同步到图数据库和向量数据库中,实现智能代理检索。它支持无代码集成、多租户支持和自动同步等功能。
162 14
AllData数据中台核心菜单十一:数据集成平台
杭州奥零数据科技有限公司成立于2023年,专注于数据中台业务,维护开源项目AllData并提供商业版解决方案。AllData提供数据集成、存储、开发、治理及BI展示等一站式服务,支持AI大模型应用,助力企业高效利用数据价值。
AllData数据中台核心菜单十一:数据集成平台
NodeTool:AI 工作流可视化构建器,通过拖放节点设计复杂的工作流,集成 OpenAI 等多个平台
NodeTool 是一个开源的 AI 工作流可视化构建器,通过拖放节点的方式设计复杂的工作流,无需编码即可快速原型设计和测试。它支持本地 GPU 运行 AI 模型,并与 Hugging Face、OpenAI 等平台集成,提供模型访问能力。
213 14
NodeTool:AI 工作流可视化构建器,通过拖放节点设计复杂的工作流,集成 OpenAI 等多个平台
构建深度可观测、可集成的网络智能运维平台
本文介绍了构建深度可观测、可集成的网络智能运维平台(简称NIS),旨在解决云上网络运维面临的复杂挑战。内容涵盖云网络运维的三大难题、打造云原生AIOps工具集的解决思路、可观测性对业务稳定的重要性,以及产品发布的亮点,包括流量分析NPM、网络架构巡检和自动化运维OpenAPI,助力客户实现自助运维与优化。
Pandas数据可视化:matplotlib集成(df)
Pandas 是 Python 中强大的数据分析库,Matplotlib 是常用的绘图工具。两者结合可方便地进行数据可视化,帮助理解数据特征和趋势。本文从基础介绍如何在 Pandas 中集成 Matplotlib 绘制图表,如折线图、柱状图等,并深入探讨常见问题及解决方案,包括图表显示不完整、乱码、比例不合适、多子图布局混乱、动态更新图表等问题,提供实用技巧和代码示例。掌握这些方法后,你将能更高效地处理数据可视化任务。
100 9
AllData数据中台核心菜单八:BI平台
杭州奥零数据科技有限公司成立于2023年,专注于数据中台业务,维护开源项目AllData并提供商业版解决方案。AllData提供数据集成、存储、开发、治理及BI展示等一站式服务,支持AI大模型应用,助力企业高效利用数据价值。

热门文章

最新文章

AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等