echarts 数据转换
应用:给定数据集以及转换方法,生成一个新的数据集,使用新的数据集绘制图表
***********************
dataset 属性配置
id:数据集id,默认不指定
source:原始数据
dimensions:维度名
sourceHeader:第一行或者列是否是维度名,可选值:null(自动探测)、true、false
transform:转换方法
fromDatasetIndex:transform方法使用的dataset(index指定)
fromDatasetId:transform方法使用的dataset(id指定)
fromTransformResult:获取transform方法产生的result(一般在transform产生多个结果时使用)
source 属性:可以使用三种形式设置
# 二维数组:第一行或者列是维度名、也可以直接是数据
[
['product', '2015', '2016', '2017'],
['Matcha Latte', 43.3, 85.8, 93.7],
['Milk Tea', 83.1, 73.4, 55.1],
['Cheese Cocoa', 86.4, 65.2, 82.5],
['Walnut Brownie', 72.4, 53.9, 39.1]
]
# key-value对象数组,key是维度名
[
{product: 'Matcha Latte', count: 823, score: 95.8},
{product: 'Milk Tea', count: 235, score: 81.4},
{product: 'Cheese Cocoa', count: 1042, score: 91.2},
{product: 'Walnut Brownie', count: 988, score: 76.9}
]
# key value数组,key为维度名
{
'product': ['Matcha Latte', 'Milk Tea', 'Cheese Cocoa', 'Walnut Brownie'],
'count': [823, 235, 1042, 988],
'score': [95.8, 81.4, 91.2, 76.9]
}
transform:数据转换方法
type:转换类型,内置:filter、sort,也可引入外部转换器
config:转换配置
print:是否将转换结果打印出来,默认false
# 数据过滤
option = {
dataset: [
{
source: [
['Product', 'Sales', 'Price', 'Year'],
['Cake', 123, 32, 2011],
['Latte', 231, 14, 2011],
['Tofu', 235, 5, 2011],
['Milk Tee', 341, 25, 2011],
['Porridge', 122, 29, 2011],
['Cake', 143, 30, 2012],
['Latte', 201, 19, 2012],
['Tofu', 255, 7, 2012],
['Milk Tee', 241, 27, 2012],
['Porridge', 102, 34, 2012],
['Cake', 153, 28, 2013],
['Latte', 181, 21, 2013],
['Tofu', 395, 4, 2013],
['Milk Tee', 281, 31, 2013],
['Porridge', 92, 39, 2013],
['Cake', 223, 29, 2014],
['Latte', 211, 17, 2014],
['Tofu', 345, 3, 2014],
['Milk Tee', 211, 35, 2014],
['Porridge', 72, 24, 2014]
]
},
{
transform: {
type: 'filter',
config: { dimension: 'Year', '=': 2011 } //过滤出'Year'为2011的所有数据项
}
}
],
series: {
type: 'pie',
datasetIndex: 1
}
}
# 数据排序
option = {
dataset: [
{
dimensions: ['name', 'age', 'profession', 'score', 'date'],
source: [
[' Hannah Krause ', 41, 'Engineer', 314, '2011-02-12'],
['Zhao Qian ', 20, 'Teacher', 351, '2011-03-01'],
[' Jasmin Krause ', 52, 'Musician', 287, '2011-02-14'],
['Li Lei', 37, 'Teacher', 219, '2011-02-18'],
[' Karle Neumann ', 25, 'Engineer', 253, '2011-04-02'],
[' Adrian Groß', 19, 'Teacher', null, '2011-01-16'],
['Mia Neumann', 71, 'Engineer', 165, '2011-03-19'],
[' Böhm Fuchs', 36, 'Musician', 318, '2011-02-24'],
['Han Meimei ', 67, 'Engineer', 366, '2011-03-12']
]
},
{
transform: {
type: 'sort',
config: { dimension: 'score', order: 'asc' } //按score排序
}
}
],
series: {
type: 'bar',
datasetIndex: 1
}
};
transform config说明
数字比较操作符:>、>=、=、!=、<、<=
字符串比较操作符:=、!=
正则匹配操作符:regex
逻辑比较操作符:and、or、not
# and、or支持多个比较条件、not后面只能有一个比较条件
解析器:time、trim、number
time:把原始值解析成时间戳( timestamp )后再做比较,如果不能解析则转换为NAN
trim:如果原始数据是字符串,则把字符串两端的空格(全角半角)和换行符去掉
如果不是字符串,还保持为原始数据
number:强制把原始数据转成数值,如果不能转换,则解析为NAN
默认情况下,数字字符串会直接转换为数字
含尾缀的字符串(20%、20px等)要转换为数字,需使用parser:'number'
# 示例
{
transform: {
type: 'filter', //过滤出Year 2013的数据
config: { dimension: 'Year', value: 2013 }
}
}
{
transform: {
type: 'filter', //过滤出Year 2013的数据
config: { dimension: 'Year', '=': 2013 }
}
}
{
transform: {
type: 'filter', //过滤出Year 2013的数据(维度名索引从0开始)
config: { dimension: 0, value: 2013 }
}
}
# transform 链式调用
{
transform: [
{
type: 'filter',
config: { dimension: 'Product', value: 'Tofu' }
},
{
type: 'sort',
config: { dimension: 'Year', order: 'desc' }
} //先过滤出Product为Tofu的产品,在根据Year降序排序
]
}
# 逻辑运算
{
transform: {
type: 'filter',
config: {
and: [
{ dimension: 'Year', '=': 2011 },
{ dimension: 'Price', '>=': 20, '<': 30 }
]
} //过滤出2011年价格大于等于20、小于30的产品
}
}
and与如下等价
{
transform: {
type: 'filter',
config: [
{ dimension: 'Year', '=': 2011 },
{ dimension: 'Price', '>=': 20, '<': 30 }
] //过滤出2011年价格大于等于20、小于30的产品
}
}
{
transform: {
type: 'filter',
config: {
or: [
{ dimension: 'Price', '<': 20 },
{ dimension: 'Price', '>': 30 }
]
} //过滤出2011年价格小于20,或者大于30的产品
}
}
{
transform: {
type: 'filter',
config: {
not: { dimension: 'Price', '<': 20 }
} //过滤出2011年价格不小于20的产品
}
}
# 逻辑嵌套
transform: {
type: 'filter',
config: {
or: [{
and: [{
dimension: 'Price', '>=': 10, '<': 20
}, {
dimension: 'Sales', '<': 100
}, {
not: { dimension: 'Product', '=': 'Tofu' }
}]
}, {
and: [{
dimension: 'Price', '>=': 10, '<': 20
}, {
dimension: 'Sales', '<': 100
}, {
not: { dimension: 'Product', '=': 'Cake' }
}]
}]
}
}
# 解析器使用
{
transform: {
type: 'filter',
config: {
dimension: 'Date',
'>=': '2012-05',
'<': '2012-06',
parser: 'time'
} //过滤出时间大于等于2012-05、小于2012-06的数据
}
}
transform输出多个结果
# fromTransformResult单独使用:使用transform生成的指定结果
option = {
dataset: [
{
source: [ //dataset index为0
...
]
},
{
transform: { //dataset index为1
type: 'boxplot'
} //boxplot transform生成2份数据:
//result[0]:boxplot series需要的数据
//result[1]:离群点数据
//当其他dataset、series使用该数据集时,默认使用result[0]
//若其他dataset想使用result[1],需指定fromDatasetResult:1
//若其他series想使用result[1],需先创建一个使用result[1]的数据集,series在使用新建的数据集
},
{
fromDatasetIndex: 1, //dataset index为2,使用dataset 1中的数据
fromTransformResult: 1 //使用transform转换生成的result[1]
}
],
xAxis: {
type: 'category'
},
yAxis: {},
series: [
{
name: 'boxplot',
type: 'boxplot',
datasetIndex: 1 //使用transform转换生成的result[0]
},
{
name: 'outlier',
type: 'scatter',
datasetIndex: 2 //使用transform转换生成的result[1]
}
]
};
# fromTransformResult、transform同时使用:使用上游transform生成的指定结果
{
fromDatasetIndex: 1,
fromTransformResult: 1,
transform: {
type: 'sort',
config: { dimension: 2, order: 'desc' }
}
}
transform使用外部转换器:先注册,使用时添加命名空间
<script src="/echarts/ecStat.min.js"></script> //导入ecStat js脚本
echarts.registerTransform(ecStat.transform.regression); //注册转换方法
const data = [
...
];
option = {
dataset: [
{
source: data
},
{
transform: {
type: 'ecStat:regression' //引用外部转换器需要设置命名空间:esStat
//内置转换器(filter、sort)不需要
}
}
],
...
};
***********************
示例
过滤年度分布数据
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="/echarts/echarts.min.js"></script>
<script src="/jquery/jquery-3.6.0.min.js"></script>
<script type="text/javascript">
$(function (){
const myChart = echarts.init($("#con")[0]);
// 指定图表的配置项和数据
const option = {
title: {
left: 'center',
text: '中国神华营业总收入季度分布图',
textStyle: {
color: '#b28'
}
},
tooltip: {},
legend: {
left: 'right',
top: '10',
orient: 'vertical',
data:['一季度','二季度','三季度','四季度']
},
dataset: [
{
source: [
['quarter', 'income', 'year'],
['一季度', 510.8, 2020],
['二季度', 539.2, 2020],
['三季度', 611, 2020],
['四季度', 672, 2020],
['一季度', 570.1, 2019],
['二季度', 593.9, 2019],
['三季度', 614, 2019],
['四季度', 641, 2019],
]
},
{
transform:{
type: 'filter',
config: {dimension: 'year', value: '2020'}
} //过滤2020季度分布数据
},
{
transform:{
type: 'filter',
config: {dimension: 'year', value: '2019'}
} //过滤2019季度分布数据
}
],
series: [
{
name: '中国神华2020',
type: 'pie',
center: ['25%','50%'], //圆心横坐标、纵坐标
radius: '40%',
datasetIndex: 1,
encode: {
itemName: 0, //数据项名称,在legend中展示
value: 1
},
label: {
show: false
}
},
{
name: '中国神华2019',
type: 'pie',
center: ['75%','50%'], //圆心横坐标、纵坐标
radius: '40%',
datasetIndex: 2,
encode: {
itemName: 0, //数据项名称,在legend中展示
value: 1
},
label: {
show: false
}
}
]
};
myChart.setOption(option);
})
</script>
</head>
<body>
<!-- 为 ECharts 准备一个定义了宽高的 DOM -->
<div id="con" style="width: 500px;height:300px;"></div>
</body>
</html>
使用外部转换器(指数线性回归)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="/echarts/echarts.min.js"></script>
<script src="/echarts/ecStat.min.js"></script>
<script src="/jquery/jquery-3.6.0.min.js"></script>
<script type="text/javascript">
$(function (){
echarts.registerTransform(ecStat.transform.regression);
const myChart = echarts.init($("#con")[0]);
const option = {
dataset: [
{
source: [
[1, 4862.4],
[2, 5294.7],
[3, 5934.5],
[4, 7171.0],
[5, 8964.4],
[6, 10202.2],
[7, 11962.5],
[8, 14928.3],
[9, 16909.2],
[10, 18547.9],
[11, 21617.8],
[12, 26638.1],
[13, 34634.4],
[14, 46759.4],
[15, 58478.1],
[16, 67884.6],
[17, 74462.6],
[18, 79395.7]
]
},
{
transform: {
type: 'ecStat:regression',
config: {
method: 'exponential'
}
}
}
],
title: {
text: '1981 - 1998 gross domestic product GDP (trillion yuan)',
subtext: 'By ecStat.regression',
sublink: 'https://github.com/ecomfe/echarts-stat',
left: 'center'
},
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'cross'
}
},
xAxis: {
splitLine: {
lineStyle: {
type: 'dashed'
}
}
},
yAxis: {
splitLine: {
lineStyle: {
type: 'dashed'
}
}
},
series: [
{
name: 'scatter',
type: 'scatter',
datasetIndex: 0
},
{
name: 'line',
type: 'line',
smooth: true,
datasetIndex: 1,
symbolSize: 0.1,
symbol: 'circle',
label: { show: true, fontSize: 16 },
labelLayout: { dx: -20 },
encode: { label: 2, tooltip: 1 }
}
]
};
myChart.setOption(option);
})
</script>
</head>
<body>
<!-- 为 ECharts 准备一个定义了宽高的 DOM -->
<div id="con" style="width: 600px;height:400px;"></div>
</body>
</html>