环境
系统:centos7
python版本:3.7.6
superset版本:0.30
echarts版本:4.2.0以上
说明
因为一开始使用pip
(安装方法)直接安装的时候,进入安装路径下没有src
目录。又是一开始接触superset,所以就用源码安装了。
源码安装方法
搭建Anaconda
虚拟环境
- 首先下载安装文件
Anaconda3-2019.10-Linux-x86_64.sh
进入官网地址:https://www.anaconda.com/distribution/#download-section
,选择对应版本下载。 - 安装anaconda软件
sh Anaconda3-2019.10-Linux-x86_64.sh
安装过程中需要输入yes
和回车。 - 配置conda环境变量。
vim /etc/profile
# 添加如下几行,具体路径根据实际情况调整
export CONDA_HOME=/root/anaconda3
export PATH=$CONDA_HOME/bin:$PATH
# source 刚刚修改的文件
source /etc/profile
- 修改Anaconda的镜像文件
在安装Anaconda用户的家目录(需要注意的是用户的家目录,而不是CONDA_HOME目录,所以这里是/root下)
下创建.condarc
文件,并添加如下内容
channels:
- https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/
- https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/conda-forge/
show_channel_urls: true
也可以通过如下命令修改:
# 第一次运行下面的命令时,会自动在用户的家目录下创建 `.condarc` 文件
conda config
# 查看源
conda config --show-sources
# 修改源
conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/
conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/conda-forge/
# 设置搜索时显示通道地址
conda config --set show_channel_urls yes
- 在系统中添加如下依赖:
yum upgrade python-setuptools
yum install gcc gcc-c++ libffi-devel python-devel python-pip python-wheel openssl-devel libsasl2-devel openldap-devel
- 为了避免不同版本python之前相互冲突,创建python的虚拟环境(因为之前conda环境变量已配好,所以可以直接使用如下命令)。
conda create -n superset python=3.7
# 删除的时候可以使用下面的命令
# conda remove -n superset --all
- 进入虚拟环境环境,使用
source activate superset
,(退出时使用source deactivate superset
即可)
源码安装superset
- 首先从github上clone源码,github代码地址:
https://github.com/apache/incubator-superset.git
- 下载好之后切换到你所需要安装的分支,我这里选择的是
0.30
- 利用SFTP工具将代码复制到服务器某个目录下,我选择的是
/root/anaconda3/envs/superset
目录 - 之后按照如下命令输入即可
# 进入到源码的assets目录下
cd /root/anaconda3/envs/superset/incubator-superset/superset/assets
# 进行依赖的下载安装,因为过程中可能会报权限不足的错误,所以添加参数 --unsafe-perm=true --allow-root
npm install --unsafe-perm=true --allow-root -d
# 依赖下载完成之后修改如下配置文件
vim node_modules/webpack/lib/WebpackOptionsDefaulter.js
# 将文件中maxEntrypointSize的值(250000)修改为50000000,maxAssetSize的值(250000)修改为30000000
# 修改为如下所示
# this.set("performance.maxAssetSize", 30000000);
# this.set("performance.maxEntrypointSize", 50000000);
# 安装 core-js@2 依赖
npm install core-js@2
# 然后就可以编译了
npm run build
# 返回上一级目录
cd ..
# 前端编译完后,将incubator-superset-0.28.1/superset/static/目录下的assets链接文件删掉
rm -rf static/assets
# 将整个assets文件夹移动到incubator-superset-0.28.1/superset/static/目录下
cp -r assets/ static/
# 进入源码的根目录
cd /root/anaconda3/envs/superset/incubator-superset/
# 安装 requirements.txt 中的依赖(使用国内的源,不然会很慢)。过程可能会比较长,而且有的依赖可能会卡住,所以那个依赖可以手动安装
pip install -i http://pypi.douban.com/simple/ --trusted-host=pypi.douban.com/simple -r requirements.txt
# 安装numpy模块
pip install numpy -U
# 现在就可以直接安装了
python setup.py install
# 查看安装是否成功,出现下面的版本号,就安装成功了
superset version
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
Superset 0.30.0rc13
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
- 安装完成之后就可以进行如下配置使用了
# 创建一个admin用户,用户名为superset,并设置密码等参数
fabmanager create-admin --app superset
# 初始化数据库
superset db upgrade
# 加载一些使用的示例
superset load_examples
# 创建默认的角色和初始化权限
superset init
# 启动superset的web server
superset runserver
# 但是superset某个版本以后就不支持上面的命令了,0.30就不支持。所以运行如下命令:
superset run -p 端口号 -h ip地址
因为我之前在别的虚拟环境中安装过别的版本的superset,所以第一步就报了个错:alembic.util.exc.CommandError: Can't locate revision identified by '4a5a7be6c05a'
,这个是因为superset默认使用的是SQLite
数据库,默认路径是/root/.superset
,所以这里直接删除这个数据库(rm -rf /root/.superset
),再重新运行上面的命令即可。
- 打开浏览器输入刚刚设置的ip地址和端口号就可以访问了。
集成echarts中的漏斗图echarts_funnel
因为网上的教程基本都是0.28的,而0.30的superset目录结构又做了大改动,所以这一步真是走的一言难尽。一开始直接用 pip install superset
安装的,superset的目录下居然没有src,我就直接从源码中copy了src放到superset的对应目录下,不知道是我操作有问题还是这样做就是错的,没有集成成功(我也没有时间去试验了,如果有人这样安装成功了,麻烦留言告诉我一声,谢谢)
,所以索性就直接源码安装。皇天不负有心人,源码安装之后慢慢的就摸索出来了。虽然摸索出来了,有的步骤到底为什么这样做,还是不理解。等后面在慢慢了解吧。废话说了这么多,下面开始进入正题吧。
下面以漏斗图echarts_funnel
为例,介绍如何在superset中集成echarts图表
修改viz.py
文件
修改viz.py
文件,文件路径为:/root/anaconda3/envs/superset/lib/python3.7/site-packages/superset-0.30.0rc13-py3.7.egg/superset
,注册echarts_funnel
图表类型。
找到TableViz
,在上面添加EchartsFunnelViz
def get_csv(self):
df = self.get_df()
include_index = not isinstance(df.index, pd.RangeIndex)
return df.to_csv(index=include_index, **config.get('CSV_EXPORT'))
def get_data(self, df):
return df.to_dict(orient='records')
@property
def json_data(self):
return json.dumps(self.data)
# 下面一段是添加的代码
class EchartsFunnelViz(BaseViz):
viz_type = 'echarts_funnel'
is_timeseries = False
def get_data(self, df):
fd = self.form_data
metric = self.metric_labels[0]
columns = fd.get('groupby')
print(metric)
df = df.pivot_table(
index=self.groupby,
values=[metric]
)
df.sort_values(by=metric, ascending=False, inplace=True)
df = df.reset_index()
df.columns = ['name', 'value']
return df.to_dict(orient='records')
class TableViz(BaseViz):
"""A basic html table that is sortable and searchable"""
viz_type = 'table'
verbose_name = _('Table View')
credits = 'a <a href="https://github.com/airbnb/superset">Superset</a> original'
is_timeseries = False
enforce_numerical_metrics = False
添加echarts依赖
进入static/assets
目录,vim package.json
。在dependencies
中增加echarts的依赖"echarts": "^4.2.0"
,版本号可以根据实际情况改变,我这里使用的是4.2.0以上的版本。
添加图表的controlPanelSections
这一步添加的就是图表的Data
和Visual Properties
等配置。如下图所示:
进入src/explore/controlPanels
路径下,创建EchartsFunnel.js
文件。文件内容如下:
import { t } from '@superset-ui/translation';
export default {
controlPanelSections: [
{
label: t('Query'),
expanded: true,
controlSetRows: [
['metrics', 'groupby'],
['limit'],
],
},
{
label: t('Chart Options'),
controlSetRows: [
['color_scheme'],
],
},
],
};
然后在该目录下的index.js
中注册刚刚写的这个js文件。
- 引入:
import EchartsFunnel from './EchartsFunnel';
- 在
controlPanelConfigs
中配置,添加echarts_funnel: EchartsFunnel,
绘制图表模板
- 进入
assets
目录下的src/visualizations
目录,创建EchartsFunnel
文件夹。 - 在
EchartsFunnel
文件夹下创建images
文件夹,然后进入echarts官网,截取或者下载一张漏斗图的图片放到images
文件夹下,命名为thumbnail.png
。 - 创建
EchartsFunnel.js
文件,文件内容如下:
import echarts from 'echarts';
import {getColorFromScheme} from '../../modules/colors';
function echartsFunnelVis(payload, slice) {
const div = d3.select(payload);
var html = '<div id="main" style="width: ' + slice.width + ''
+ 'px;height:' + slice.height + 'px;">haha</div>';
div.html(html);
var myChart = echarts.init(document.getElementById('main'));
var option = {
title: {
text: '',
subtext: '纯属虚构',
left: 'left',
top: 'bottom'
},
tooltip: {
trigger: 'item',
formatter: "{a} <br/>{b} : {c}%"
},
toolbox: {
show: true,
orient: 'vertical',
top: 'center',
feature: {
dataView: {readOnly: false},
restore: {},
saveAsImage: {}
}
},
legend: {
orient: 'vertical',
left: 'left',
data: []
},
calculable: true,
series: [
{
name: '漏斗图',
type: 'funnel',
width: '40%',
height: '45%',
left: '5%',
top: '50%',
funnelAlign: 'right',
center: ['25%', '25%'], // for pie
data: []
},
{
name: '金字塔',
type: 'funnel',
width: '40%',
height: '45%',
left: '5%',
top: '5%',
sort: 'ascending',
funnelAlign: 'right',
center: ['25%', '75%'], // for pie
data: []
},
{
name: '漏斗图',
type: 'funnel',
width: '40%',
height: '45%',
left: '55%',
top: '5%',
funnelAlign: 'left',
center: ['75%', '25%'], // for pie
data: []
},
{
name: '金字塔',
type: 'funnel',
width: '40%',
height: '45%',
left: '55%',
top: '50%',
sort: 'ascending',
funnelAlign: 'left',
center: ['75%', '75%'], // for pie
data: []
}
]
};
myChart.setOption(option);
const json = slice.data;
var data_name = [];
var max_value = 0;
const data = json;
data.forEach(function (item, index, array) {
data_name.push(item['name']);
if (item['value'] > max_value) {
max_value = item['value'];
}
});
var tmp_series = [];
for (var i = 1; i < 5; i++) {
tmp_series.push({
data: data
});
}
var option2 = {
legend: {data: data_name},
series: tmp_series
};
myChart.setOption(option2);
}
export default echartsFunnelVis;
- 创建
transformProps.js
文件(用来处理接收参数的数据内容及格式),文件内容如下:
export default function transformProps(chartProps) {
const { width, height, payload } = chartProps;
console.log(chartProps); //可以用来验证数据是否正确
return {
data: payload.data,
width,
height,
};
}
- 创建
ReactEchartsFunnel.js
文件(这个文件是干啥的我也不知道—_— !),文件内容如下:
import reactify from '../../utils/reactify';
import Component from './EchartsFunnel';
export default reactify(Component);
- 创建
EchartsFunnelChartPlugin.js
文件,文件内容如下:
import { t } from '@superset-ui/translation';
import { ChartMetadata, ChartPlugin } from '@superset-ui/chart';
import transformProps from './transformProps';
import thumbnail from './images/thumbnail.png';
import { ANNOTATION_TYPES } from '../../modules/AnnotationTypes';
const metadata = new ChartMetadata({
name: t('echarts funnel'),
description: '',
canBeAnnotationTypes: [
ANNOTATION_TYPES.EVENT,
ANNOTATION_TYPES.INTERVAL,
],
thumbnail,
});
export default class EchartsFunnelChartPlugin extends ChartPlugin {
constructor() {
super({
metadata,
transformProps,
loadChart: () => import('./ReactEchartsFunnel.js'),
});
}
}
- 注册刚刚创建的plugin
进入cd ../presets/
,在CommonChartPreset.js
文件中引入import EchartsFunnelChartPlugin from '../EchartsFunnel/EchartsFunnelChartPlugin';
,并注册new EchartsFunnelChartPlugin().configure({ key: 'echarts_funnel' }),
- 进入
assets
目录下,npm install
,然后npm run dev
即可。 - 运行superset
superset run -h IP地址 -p 端口号
然后就大功告成了。