第一次寫博客,本着共享知識而來,爲技術的發展作點小貢獻。最近在研究Superset安裝、集成ECharts和漢化的工做,網上關於Superset的相關文章感受挺少的,因此想寫這一篇綜合點的博客,來和你們共享,若有不足,請多指教。javascript
操做系統:CentOS Linux release 7.5.1804 (Core)
python版本:3.6.4(直接安裝Anaconda便可)html
Superset 0.22版本的看板中存在不少bug,好比:多個類型同樣的圖表加入到看板中,只有第一個圖能夠顯示,其餘同類型的圖均顯示不出。在最新版本中不存在,故建議安裝最新版本Superset 0.28。
(1)萬事開頭難。首先我們得要先安裝Anaconda,由於接下來須要用到pip,去這裏下載安裝,最新Superset支持使用python3的版本。
(2)安裝superset前端
pip install superset
劃重點!用pip安裝的最新版本Superset的目錄與0.28.1版本源碼有差別,實際上是不全,去這裏下載源碼,下載好以後,要用源碼中Superset\superset\assets下的src目錄替換本身安裝的superset的assets下的src目錄便可,這個步驟爲後續集成ECharts作準備。
(3)初始化java
fabmanager create-admin --app superset //建立管理員帳號
python
superset db upgrade //初始化數據庫
webpack
superset load_examples //載入模板數據
git
superset init //初始化角色和權限
github
superset runserver -d -p 8088 //啓動服務,端口號 8088,使用 -p 更改端口號
web
最後若是瀏覽器進入不了登陸界面,這是由於防火牆的問題,打開就行了。
(4)後臺運行superset
使用以下命令,就可讓superset在後臺運行,就不用每一次啓動服務了。sql
nohup superset runserver -d -p 8088 &
tail -f nohup.out
有圖有真相!
(5)安裝編譯前端須要的js包
這一步是爲接下來的ECharts集成作準備,進入到superset\static\assets下,在命令行中輸入
npm install
(6)編譯前端
須要的包所有安裝完以後,進入superset\static\assets下,在命令行中輸入
npm run dev
這一步若是報錯,排除語法和權限問題,是包沒有安裝全的緣由,必定要把包安裝全才行。
我遇到的是這兩個錯誤:
ERROR in ./src/visualizations/index.js 86:19
Module parse failed: Unexpected token (86:19)
You may need an appropriate loader to handle this file type.
| var loadNvd3 = function () {
| function loadNvd3() {
> return loadVis(import( /* webpackChunkName: "nvd3_vis" */'./nvd3/adaptor.jsx'));
| }
|
@ ./src/modules/AnnotationTypes.js 15:15-30
@ ./src/chart/chartAction.js
@ ./src/explore/components/ExploreViewContainer.jsx
@ ./src/explore/App.jsx
@ ./src/explore/index.jsx
@ multi babel-polyfill ./src/explore/index.jsx
把包安裝全以後,再執行npm run dev命令,編譯就經過了。以後在ECharts集成時就能夠看到實時編譯的網頁效果了。
Superset集成ECharts其實說來也簡單,主要操做5個地方,分別是:
(1)後端文件
處理傳入前端的數據格式
superset/viz.py
(2)先後端函數匹配文件
superset/static/assets/src/visualizations/index.js
(3)你的新增圖表名稱.js
superset/static/assets/src/visualizations/你的新增圖表名稱.js
(4)前端圖標配置區組件設置
它是Superset左側的GroupBy等組件的開關,需根據你新增的圖表要用的數據格式選擇合適的組件
superset/static/assets/src/explore/visTypes.jsx
(5)縮略圖
superset/static/assets/images/viz_thumbnails
下面來舉兩個集成Echarts圖表的例子
(1)後端文件
進入到superset/viz.py文件中,在BaseViz類的下方和TableViz的上方加入以下代碼(與其餘的類似):
class EchartsBarPolar(BaseViz):
viz_type = 'echarts_bar_polar' #對應前端的名字
is_timeseries = False
def should_be_timeseries(self):
fd = self.form_data
conditions_met = (
(fd.get('granularity') and fd.get('granularity') != 'all') or
(fd.get('granularity_sqla') and fd.get('time_grain_sqla'))
)
if fd.get('include_time') and not conditions_met:
raise Exception(_(
'Pick a granularity in the Time section or '
"uncheck 'Include Time'"))
return fd.get('include_time')
def query_obj(self):
d = super(EchartsBarPolar, self).query_obj()
fd = self.form_data
if fd.get('all_columns') and (fd.get('groupby') or fd.get('metrics')):
raise Exception(_(
'Choose either fields to [Group By] and [Metrics] or '
'[Columns], not both'))
sort_by = fd.get('timeseries_limit_metric')
if fd.get('all_columns'):
d['columns'] = fd.get('all_columns')
d['groupby'] = []
order_by_cols = fd.get('order_by_cols') or []
d['orderby'] = [json.loads(t) for t in order_by_cols]
elif sort_by:
if sort_by not in d['metrics']:
d['metrics'] += [sort_by]
d['orderby'] = [(sort_by, not fd.get('order_desc', True))]
if 'percent_metrics' in fd:
d['metrics'] = d['metrics'] + list(filter(
lambda m: m not in d['metrics'],
fd['percent_metrics'],
))
d['is_timeseries'] = self.should_be_timeseries()
return d
def get_data(self, df):
fd = self.form_data
if not self.should_be_timeseries() and DTTM_ALIAS in df:
del df[DTTM_ALIAS]
return dict(
records=df.to_dict(orient='records'),
columns=list(df.columns),
)
(2)先後端函數匹配文件
進入到superset/static/assets/src/visualizations/index.js文件中,
在export const VIZ_TYPES裏新增
echarts_bar_polar: 'echarts_bar_polar',
在const vizMap裏新增
[VIZ_TYPES.echarts_bar_polar]: () => loadVis(import(/*webpackChunkName: 'echarts_bar_polar' */ './echarts_bar_polar.js')),
(3)echarts_bar_polar.js
在superset/static/assets/src/visualizations文件夾下,放入echarts_bar_polar.js文件,代碼以下:
import echarts from 'echarts';
import {getColorFromScheme} from '../javascripts/modules/colors';
function EchartsBarPolarVis(slice, payload) {
var div = d3.select(slice.selector);
const sliceId = 'e_bar_polar' + slice.formData.slice_id
var html = '<div id="' + sliceId + '" style="width:' + slice.width() + 'px;' + ''
+ 'px;height:' + slice.height() + 'px;"></div>';
div.html(html);
var myChart = echarts.init(document.getElementById(sliceId));
var option = {
angleAxis: {
type: 'category',
data: [],
z: 10
},
radiusAxis: {},
polar: {},
series: []
};
myChart.setOption(option);
const fd = slice.formData;
const json = payload.data;
const data = json;
const records = data['records'];
const data_column = data.columns;
const metrics = fd.metrics;
const group_by = fd.groupby;
var legend_name = [];
var axis_name = [];
var series_data = [];
for (var i = 0; i < records.length; i++) {
axis_name.push(records[i][data_column[0]]);
}
for (var i = 0; i < metrics.length; i++) {
legend_name.push(metrics[i]);
var tmp_data = [];
for (var j = 0; j < records.length; j++) {
tmp_data.push(records[j][metrics[i]]);
}
series_data.push(
{
type: 'bar',
data: tmp_data,
coordinateSystem: 'polar',
name: legend_name[i],
stack: 'a'
}
)
}
var option2 = {
angleAxis: {
data: axis_name
},
series: series_data
};
myChart.setOption(option2);
}
module.exports = EchartsBarPolarVis;
(4)前端圖標配置區組件設置
進入superset/static/assets/src/explore/visTypes.jsx文件中,在export const visTypes裏新增以下代碼:
echarts_bar_polar: {
label: t('Bar Polar'),
showOnExplore: true,
controlPanelSections: [
{
label: t('GROUP BY'),
controlSetRows: [
['groupby'],
['metrics'],
['percent_metrics'],
['include_time'],
['timeseries_limit_metric', 'order_desc'],
],
},
{
label: t('NOT GROUPED BY'),
description: t('Use this section if you want to query atomic rows'),
controlSetRows: [
['all_columns'],
['order_by_cols'],
],
},
{
label: t('Options'),
controlSetRows: [
['table_timestamp_format'],
['row_limit', 'page_length'],
['include_search', 'table_filter'],
],
},
],
controlOverrides: {
metrics: {
validators: [],
},
time_grain_sqla: {
default: null,
},
},
},
(5)縮略圖
在superset/static/assets/images/viz_thumbnails文件夾下放入極座標柱狀圖的縮略圖
到此極座標柱狀圖就集成好啦,快來看看下面的效果吧!
(1)後端文件
進入到superset/viz.py文件中,在BaseViz類的下方和TableViz的上方加入以下代碼(與其餘的類似):
class ChinaMap(BaseViz):
""" ChinaMap viz """
viz_type = 'ChinaMap'
verbose_name = _('ChinaMap')
is_timeseries = False
def get_data(self, df):
form_data = self.form_data
df.sort_values(by=df.columns[0], inplace=True)
print(df.values.tolist())
ori_data = df.values.tolist()
data = [{'name' : ori_data[i][0], 'value' : ori_data[i][1]} for i in range(len(ori_data))]
data_name = [ori_data[i][0] for i in range(len(ori_data))]
max_data = max([ori_data[i][1] for i in range(len(ori_data))])
min_data = min([ori_data[i][1] for i in range(len(ori_data))])
return [data, data_name, max_data, min_data]
(2)先後端函數匹配文件
進入到superset/static/assets/src/visualizations/index.js文件中,
在export const VIZ_TYPES裏新增
ChinaMap: 'ChinaMap',
在const vizMap裏新增
[VIZ_TYPES.ChinaMap]: () => loadVis(import(/*webpackChunkName: 'ChinaMap' */ './ChinaMap.js')),
(3)ChinaMap.js
在superset/static/assets/src/visualizations文件夾下,放入ChinaMap.js文件,代碼以下:
import echarts from 'echarts';
require('echarts/map/js/china.js');
require('echarts/map/js/province/index.js');
function ChinaMapVis(slice, payload) {
const div = d3.select(slice.selector);
const sliceId = 'echarts_slice_' + slice.formData.slice_id;
const html = '<div id=' + sliceId + ' style="width:' + slice.width() + 'px;height:' + slice.height() + 'px;"></div>';
div.html(html); // reset
const myChart = echarts.init(document.getElementById(sliceId));
const get_data = payload.data;
const data_value = get_data[0];
const data_name = get_data[1];
const max_data = get_data[2];
const min_data = get_data[3];
const option = {
title : {
subtext:'點擊進入下一級,雙擊返回中國地圖',
x:'center',
bottom:'5%'
},
tooltip : {
trigger: 'item',
formatter: "{c}"
},
toolbox: {
show: true,
orient: 'vertical',
left: 'right',
top: 'center',
feature: {
dataView: {readOnly: false},
restore: {},
saveAsImage: {}
}
},
visualMap: {
//type: 'continuous',
min: min_data,
max: max_data,
text:['高','低'],
realtime: false,
calculable: true,
//right:'-15%',
inRange:{
color: ['#d0f4fc',
'#a9dbf6',
'#9cd3f4',
'#93cdf3',
'#83c2f0',
'#6eb5ed',
'yellow']
}
},
series : [
{
type : 'map',
map: 'china',
selectedMode: 'single',
roam: 'scale',
data : data_value,
label: {
normal: {
show: true,
textStyle:{color:"#b6a38a"}
},
emphasis: {
show: true,
textStyle:{color:"#ff6347"}
}
},
itemStyle: {
emphasis: {
areaColor:"#2e4783",
borderWidth: 0
}
}
}
]
};
myChart.setOption(option);
myChart.on('mouseover', function (params) {
var dataIndex = params.dataIndex;
console.log(dataIndex);
});
myChart.on('click', function (chinaParam) {
if (chinaParam.name == chinaParam.name
&&data_name.indexOf(chinaParam.name)>-1) {
var option = myChart.getOption();
option.series[0].map = chinaParam.name;
myChart.setOption(option);
}
});
myChart.on('dblclick', function (chinaParam) {
if (myChart.getOption().series[0].map != 'china') {
var option = myChart.getOption();
option.series[0].map = 'china';
myChart.setOption(option);
}
});
}
module.exports = ChinaMapVis;
(4)前端圖標配置區組件設置
進入superset/static/assets/src/explore/visTypes.jsx文件中,在export const visTypes裏新增以下代碼:
ChinaMap: {
label: t('ChinaMap'),
showOnExplore: true,
controlPanelSections: [
{
label: t('GROUP BY'),
controlSetRows: [
['groupby'],
['metrics'],
['percent_metrics'],
['include_time'],
['timeseries_limit_metric', 'order_desc'],
],
},
{
label: t('NOT GROUPED BY'),
description: t('Use this section if you want to query atomic rows'),
controlSetRows: [
['all_columns'],
['order_by_cols'],
],
},
{
label: t('Options'),
controlSetRows: [
['table_timestamp_format'],
['row_limit', 'page_length'],
['include_search', 'table_filter'],
],
},
],
controlOverrides: {
metrics: {
validators: [],
},
time_grain_sqla: {
default: null,
},
},
},
(5)縮略圖
在superset/static/assets/images/viz_thumbnails文件夾下放入中國地圖的縮略圖
到此中國地圖就集成好啦,快來看看下面的效果吧!點擊中國地圖的省份能夠下鑽到市級,雙擊返回中國地圖。
在上面的圖中點擊北京市,可進行下鑽,雙擊可返回中國地圖。
在superset/translations/zh/LC_MESSAGES安裝目錄下有兩個文件:messages.po文件和messages.json文件,只須要把這兩個文件中的英文對應的中文添上,這但是個費時的工做,而後編譯便可。
(1)messages.po文件
在msgstr字段中添上對應的中文
(2)messages.json文件
在[""]中添上對應的中文
(3)設置默認語言爲中文
在superset目錄下有一個config.py文件,編輯它,找到BABEL_DEFAULT_LOCALE處,更改成’zh’,以下圖:
(4)編譯
翻譯完英文以後就能夠在superset目錄下進行編譯了 ,命令以下:
pybabel compile -d translations
重啓Superset便可看到漢化以後的成果啦!
從升級安裝Superset,到Superset集成ECharts,最後在漢化,這個過程總共用了七天的時間,收穫仍是很大的,有了些進步,對於先後端也有了些認識。回頭再看看Superset這個BI工具真的太棒了,各類圖很是炫,對於數據的分析也是很是輕鬆。可視化是數據的一種重要的呈現形式,也是數據分析的「最後一千米」,Superset絕對算得上一名有實力的高富帥,快來使用吧!
原文連接:https://blog.csdn.net/qq_33703137/article/details/87874277
歡迎關注,本號將持續分享本人在編程路上的各類見聞。