使用 Docker 探索 Superset BI 数据可视化平台,动真格、二次开发新的可视化组件之集成 Echarts 图表 | 🏆 技术专题第三期征文

使用 Docker 探索 Superset BI 数据可视化平台,动真格、二次开发新的可视化组件之集成 Echarts 图表 | 🏆 技术专题第三期征文本教程是 为少 基于 Superset 0.37, Superset 0.37, Superset 0.37 版本的实操记录。 Flask 是一个使用 Python 编写的轻量级 Web 应用框架。 NumPy是Python的一个用于科学计算的基础包。它提供了多维数组对象,多种…

介绍

本教程是 为少 基于 Superset 0.37, Superset 0.37, Superset 0.37 版本的实操记录。

项目

这是一个系列

前置基础

Flask 是什么?

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

使用 Docker 探索 Superset BI 数据可视化平台,动真格、二次开发新的可视化组件之集成 Echarts 图表 | 🏆 技术专题第三期征文

NumPy 是什么?

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

使用 Docker 探索 Superset BI 数据可视化平台,动真格、二次开发新的可视化组件之集成 Echarts 图表 | 🏆 技术专题第三期征文

Pandas 是什么?

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

使用 Docker 探索 Superset BI 数据可视化平台,动真格、二次开发新的可视化组件之集成 Echarts 图表 | 🏆 技术专题第三期征文

Echarts 是什么?

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

Echarts 官网

Echarts Multiple Y Axis 图表

官网 multiple-y-axis 图表 demo

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

二次开发 Step-By-Step

使用容器环境安装 Echarts

使用 Docker 探索 Superset BI 数据可视化平台,动真格、二次开发新的可视化组件之集成 Echarts 图表 | 🏆 技术专题第三期征文

使用 Docker 探索 Superset BI 数据可视化平台,动真格、二次开发新的可视化组件之集成 Echarts 图表 | 🏆 技术专题第三期征文

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 都可以拿出来单独讲好久,好久,好久……

选择图表

使用 Docker 探索 Superset BI 数据可视化平台,动真格、二次开发新的可视化组件之集成 Echarts 图表 | 🏆 技术专题第三期征文

看效果

使用 Docker 探索 Superset BI 数据可视化平台,动真格、二次开发新的可视化组件之集成 Echarts 图表 | 🏆 技术专题第三期征文

参考 & 感谢

使用 Docker 探索 Superset BI 数据可视化平台,动真格、二次开发新的可视化组件之集成 Echarts 图表 | 🏆 技术专题第三期征文

未完待续……

🏆 技术专题第三期 | 数据可视化的那些事……

今天的文章使用 Docker 探索 Superset BI 数据可视化平台,动真格、二次开发新的可视化组件之集成 Echarts 图表 | 🏆 技术专题第三期征文分享到此就结束了,感谢您的阅读。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/14815.html

(0)
编程小号编程小号

相关推荐

发表回复

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