Public
Edited
May 11, 2023
Insert cell
Insert cell
main = html`<div style="height: 100%; min-height:300px;width:100%;"></div>`
Insert cell
dimensions = ["MONTH", "main_SM", "time_period"]
Insert cell
metrics = [
"_tempMetric_ZB05221018_GJTL_MONTH_QY_CWD_CWD(AJMHF)_CZ_JT_SM",
"_tempMetric_ZB05221018_GJTL_MONTH_ACC_QY_CWD_CWD(AJMHF)_CZ_JT_SM",
"_localMetric__tempMetric_ZB05221018_GJTL_MONTH_QY_CWD_CWD(AJMHF)_CZ_JT_SM_predict",
"_localMetric__tempMetric_ZB05221018_GJTL_MONTH_QY_CWD_CWD(AJMHF)_CZ_JT_SM_predict_completion",
"_localMetric__tempMetric_ZB05221018_GJTL_MONTH_ACC_QY_CWD_CWD(AJMHF)_CZ_JT_SM_predict",
"_localMetric__tempMetric_ZB05221018_GJTL_MONTH_ACC_QY_CWD_CWD(AJMHF)_CZ_JT_SM_predict_completion"
]
Insert cell
Insert cell
translationDict = ({
"time_period": "统计周期",
"main_SM": "省名",
"_tempMetric_ZB05221018_GJTL_MONTH_QY_CWD_CWD(AJMHF)_CZ_JT_SM": "指标05221018_国家铁路-本期",
"_tempMetric_ZB05221018_GJTL_MONTH_ACC_QY_CWD_CWD(AJMHF)_CZ_JT_SM": "指标05221018_国家铁路-本期",
"MONTH": "时间",
"_localMetric__tempMetric_ZB05221018_GJTL_MONTH_QY_CWD_CWD(AJMHF)_CZ_JT_SM_predict": "指标05221018_国家铁路-预期",
"_localMetric__tempMetric_ZB05221018_GJTL_MONTH_QY_CWD_CWD(AJMHF)_CZ_JT_SM_predict_completion": "指标05221018_国家铁路-比预期(%)",
"_localMetric__tempMetric_ZB05221018_GJTL_MONTH_ACC_QY_CWD_CWD(AJMHF)_CZ_JT_SM_predict": "指标05221018_国家铁路-预期",
"_localMetric__tempMetric_ZB05221018_GJTL_MONTH_ACC_QY_CWD_CWD(AJMHF)_CZ_JT_SM_predict_completion": "指标05221018_国家铁路-比预期(%)"
})
Insert cell
finalTranDict = ({
...translationDict,
..._(translationDict)
.pickBy(v => /预期/.test(v))
.mapKeys((v, k) => k + '_inv')
.mapValues(v => v.replace('预期', '年度计划'))
.value()
})
Insert cell
sortedData = {
let currValMetric = metrics[0];
let lastMetric = _.last(metrics);
let last2Metric = metrics[metrics.length - 2];
let lastDimension = _.last(dimensions);

let datalj = _.filter(data, (d) => d[lastDimension].match("累计")); // 查找累计值
let dataWithout = _.filter(datalj, (d) => d[currValMetric] > 0); //排除本期 === 0 非数字,NaN:not a number
let sorted = _.orderBy(
dataWithout,
[lastMetric, currValMetric],
["desc", "desc"]
);

// 根据累计预期,反向推算年度计划
let timeDim = dimensions[0];
let patchedData = _.map(sorted, (d) => {
let t = d[timeDim];
let cumPlan = d[last2Metric];
// let days = moment(t, "YYYYMMDD")
// .endOf(dimensions[0])
// .dayOfYear();
let planYearly = cumPlan; // (cumPlan / days) * 365;
return {
...d,
[`${last2Metric}_inv`]: planYearly,
[`${lastMetric}_inv`]: d[currValMetric] / planYearly
};
});
return patchedData;
}
Insert cell
option = {
let lastMetric = _.last(metrics)
let last2Metric = metrics[metrics.length - 2]
let lastDimension = _.last(dimensions)
let sorted = sortedData
let translationDict = finalTranDict

lastMetric = `${lastMetric}_inv` in translationDict ? `${lastMetric}_inv` : lastMetric
last2Metric = `${last2Metric}_inv` in translationDict ? `${last2Metric}_inv` : last2Metric
return {
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'cross',
crossStyle: {
color: '#999'
}
}
},
legend: {type: 'scroll'},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true
},
xAxis: [
{
type: 'category',
data: (sorted || []).map((d) => d[dimensions[1]]),
axisLabel: { rotate: 30 }
}
],
yAxis: [
{
type: 'value',
boundaryGap: [0, 0.01]
},
{
//name: '(%)',
type: 'value',
boundaryGap: [0, 0.01],
splitLine: {show: false},
scale: true
}
],
color: [
'#5470c6', '#91cc75', '#fac858', '#ee6666', '#73c0de', '#3ba272', '#fc8452', '#9a60b4', '#ea7ccc'
],
series: [
{
name: translationDict[metrics[0]] || metrics[0],
type: "bar",
barMaxWidth: '30%',
data: (sorted || []).map((d) => d[metrics[0]])
},
{
name: translationDict[last2Metric] || last2Metric,
type: "bar",
barMaxWidth: '30%',
data: (sorted || []).map((d) => _.round(d[last2Metric], 2))
},
{
name: translationDict[lastMetric] || lastMetric,
type: 'line',
symbol: 'circle',
yAxisIndex: 1,
data: (sorted || []).map((d) => _.round(d[metrics[0]]/d[last2Metric]*100,2))
}
]
}
}
Insert cell
chartInst = echarts.init(main)
Insert cell
chartInst.setOption(option, { notMerge: true, lazyUpdate: true })
Insert cell
onEvents = ({})
Insert cell
function bindEvents(instance, events) {
function _bindEvent(eventName, func) {
if (eventName && func) {
instance.on(eventName, param => {
func(param, instance)
})
}
}

for (const eventName in events) {
_bindEvent(eventName, events[eventName])
}
}
Insert cell
bindEvents(chartInst, onEvents || {}); //调用bindEvents
Insert cell
(width, chartInst.resize()) // 自适应宽度
Insert cell
echarts = window.echarts || require("https://cdn.jsdelivr.net/npm/echarts@5/dist/echarts.min.js")
Insert cell
_ = window._ || require("lodash")
Insert cell
moment = window.moment || require('moment')
Insert cell

One platform to build and deploy the best data apps

Experiment and prototype by building visualizations in live JavaScript notebooks. Collaborate with your team and decide which concepts to build out.
Use Observable Framework to build data apps locally. Use data loaders to build in any language or library, including Python, SQL, and R.
Seamlessly deploy to Observable. Test before you ship, use automatic deploy-on-commit, and ensure your projects are always up-to-date.
Learn more