blob: 15e209722929596369bfc3efc05b73e84b71ea53 [file] [log] [blame]
__NUXT_JSONP__("/zh/concepts/data-transform", (function(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,_,$,aa,ab,ac,ad,ae,af,ag,ah,ai,aj,ak,al,am){return {data:[{article:{slug:"data-transform",toc:[{id:E,depth:C,text:E},{id:F,depth:C,text:F},{id:P,depth:C,text:Q},{id:R,depth:C,text:S},{id:G,depth:C,text:G}],body:{type:"root",children:[{type:b,tag:"h1",props:{id:"使用-transform-进行数据转换"},children:[{type:b,tag:h,props:{href:"#%E4%BD%BF%E7%94%A8-transform-%E8%BF%9B%E8%A1%8C%E6%95%B0%E6%8D%AE%E8%BD%AC%E6%8D%A2",ariaHidden:r,tabIndex:s},children:[{type:b,tag:t,props:{className:[u,v]},children:[]}]},{type:a,value:"使用 transform 进行数据转换"}]},{type:a,value:c},{type:b,tag:e,props:{},children:[{type:a,value:"Apache ECharts"},{type:b,tag:"sup",props:{},children:[{type:a,value:"TM"}]},{type:a,value:" 5 开始支持了“数据转换”( data transform )功能。在 echarts 中,“数据转换” 这个词指的是,给定一个已有的“数据集”("},{type:b,tag:h,props:{href:T,rel:[i,j,k],target:l},children:[{type:a,value:U}]},{type:a,value:")和一个“转换方法”("},{type:b,tag:h,props:{href:I,rel:[i,j,k],target:l},children:[{type:a,value:J}]},{type:a,value:"),echarts 能生成一个新的“数据集”,然后可以使用这个新的“数据集”绘制图表。这些工作都可以声明式地完成。"}]},{type:a,value:c},{type:b,tag:e,props:{},children:[{type:a,value:"抽象地来说,数据转换是这样一种公式:"},{type:b,tag:d,props:{},children:[{type:a,value:"outData = f(inputData)"}]},{type:a,value:x},{type:b,tag:d,props:{},children:[{type:a,value:"f"}]},{type:a,value:" 是转换方法,例如:"},{type:b,tag:d,props:{},children:[{type:a,value:"filter"}]},{type:a,value:y},{type:b,tag:d,props:{},children:[{type:a,value:"sort"}]},{type:a,value:y},{type:b,tag:d,props:{},children:[{type:a,value:"regression"}]},{type:a,value:y},{type:b,tag:d,props:{},children:[{type:a,value:"boxplot"}]},{type:a,value:y},{type:b,tag:d,props:{},children:[{type:a,value:"cluster"}]},{type:a,value:y},{type:b,tag:d,props:{},children:[{type:a,value:"aggregate"}]},{type:a,value:"(todo) 等等。有了数据转换能力后,我们就至少可以做到这些事情:"}]},{type:a,value:c},{type:b,tag:w,props:{},children:[{type:a,value:c},{type:b,tag:f,props:{},children:[{type:a,value:"把数据分成多份用不同的饼图展现。"}]},{type:a,value:c},{type:b,tag:f,props:{},children:[{type:a,value:"进行一些数据统计运算,并展示结果。"}]},{type:a,value:c},{type:b,tag:f,props:{},children:[{type:a,value:"用某些数据可视化算法处理数据,并展示结果。"}]},{type:a,value:c},{type:b,tag:f,props:{},children:[{type:a,value:"数据排序。"}]},{type:a,value:c},{type:b,tag:f,props:{},children:[{type:a,value:"去除或直选择数据项。"}]},{type:a,value:c},{type:b,tag:f,props:{},children:[{type:a,value:"..."}]},{type:a,value:c}]},{type:a,value:c},{type:b,tag:D,props:{id:E},children:[{type:b,tag:h,props:{href:"#%E6%95%B0%E6%8D%AE%E8%BD%AC%E6%8D%A2%E5%9F%BA%E7%A1%80%E4%BD%BF%E7%94%A8",ariaHidden:r,tabIndex:s},children:[{type:b,tag:t,props:{className:[u,v]},children:[]}]},{type:a,value:E}]},{type:a,value:c},{type:b,tag:e,props:{},children:[{type:a,value:"在 echarts 中,数据转换是依托于数据集("},{type:b,tag:h,props:{href:T,rel:[i,j,k],target:l},children:[{type:a,value:U}]},{type:a,value:")来实现的. 我们可以设置 "},{type:b,tag:h,props:{href:I,rel:[i,j,k],target:l},children:[{type:a,value:V}]},{type:a,value:" 来表示,此 dataset 的数据,来自于此 transform 的结果。例如。"}]},{type:a,value:c},{type:b,tag:e,props:{},children:[{type:a,value:"下面是上述例子的效果,三个饼图分别显示了 2011、2012、2013 年的数据。"}]},{type:a,value:c},{type:b,tag:m,props:{className:[n]},children:[{type:b,tag:W,props:{lang:o,layout:X},children:[{type:a,value:"var option = {\n dataset: [\n {\n \u002F\u002F 这个 dataset 的 index 是 `0`。\n source: [\n ['Product', 'Sales', 'Price', 'Year'],\n ['Cake', 123, 32, 2011],\n ['Cereal', 231, 14, 2011],\n ['Tofu', 235, 5, 2011],\n ['Dumpling', 341, 25, 2011],\n ['Biscuit', 122, 29, 2011],\n ['Cake', 143, 30, 2012],\n ['Cereal', 201, 19, 2012],\n ['Tofu', 255, 7, 2012],\n ['Dumpling', 241, 27, 2012],\n ['Biscuit', 102, 34, 2012],\n ['Cake', 153, 28, 2013],\n ['Cereal', 181, 21, 2013],\n ['Tofu', 395, 4, 2013],\n ['Dumpling', 281, 31, 2013],\n ['Biscuit', 92, 39, 2013],\n ['Cake', 223, 29, 2014],\n ['Cereal', 211, 17, 2014],\n ['Tofu', 345, 3, 2014],\n ['Dumpling', 211, 35, 2014],\n ['Biscuit', 72, 24, 2014]\n ]\n \u002F\u002F id: 'a'\n },\n {\n \u002F\u002F 这个 dataset 的 index 是 `1`。\n \u002F\u002F 这个 `transform` 配置,表示,此 dataset 的数据,来自于此 transform 的结果。\n transform: {\n type: 'filter',\n config: { dimension: 'Year', value: 2011 }\n }\n \u002F\u002F 我们还可以设置这些可选的属性: `fromDatasetIndex` 或 `fromDatasetId`。\n \u002F\u002F 这些属性,指定了,transform 的输入,来自于哪个 dataset。例如,\n \u002F\u002F `fromDatasetIndex: 0` 表示输入来自于 index 为 `0` 的 dataset 。又例如,\n \u002F\u002F `fromDatasetId: 'a'` 表示输入来自于 `id: 'a'` 的 dataset。\n \u002F\u002F 当这些属性都不指定时,默认认为,输入来自于 index 为 `0` 的 dataset 。\n },\n {\n \u002F\u002F 这个 dataset 的 index 是 `2`。\n \u002F\u002F 同样,这里因为 `fromDatasetIndex` 和 `fromDatasetId` 都没有被指定,\n \u002F\u002F 那么输入默认来自于 index 为 `0` 的 dataset 。\n transform: {\n \u002F\u002F 这个类型为 \"filter\" 的 transform 能够遍历并筛选出满足条件的数据项。\n type: 'filter',\n \u002F\u002F 每个 transform 如果需要有配置参数的话,都须配置在 `config` 里。\n \u002F\u002F 在这个 \"filter\" transform 中,`config` 用于指定筛选条件。\n \u002F\u002F 下面这个筛选条件是:选出维度( dimension )'Year' 中值为 2012 的所有\n \u002F\u002F 数据项。\n config: { dimension: 'Year', value: 2012 }\n }\n },\n {\n \u002F\u002F 这个 dataset 的 index 是 `3`。\n transform: {\n type: 'filter',\n config: { dimension: 'Year', value: 2013 }\n }\n }\n ],\n series: [\n {\n type: 'pie',\n radius: 50,\n center: ['25%', '50%'],\n \u002F\u002F 这个饼图系列,引用了 index 为 `1` 的 dataset 。也就是,引用了上述\n \u002F\u002F 2011 年那个 \"filter\" transform 的结果。\n datasetIndex: 1\n },\n {\n type: 'pie',\n radius: 50,\n center: ['50%', '50%'],\n datasetIndex: 2\n },\n {\n type: 'pie',\n radius: 50,\n center: ['75%', '50%'],\n datasetIndex: 3\n }\n ]\n};\n"}]}]},{type:a,value:c},{type:b,tag:e,props:{},children:[{type:a,value:"现在我们简单总结下,使用 transform 时的几个要点:"}]},{type:a,value:c},{type:b,tag:w,props:{},children:[{type:a,value:c},{type:b,tag:f,props:{},children:[{type:a,value:"在一个空的 dataset 中声明 "},{type:b,tag:d,props:{},children:[{type:a,value:J}]},{type:a,value:q},{type:b,tag:d,props:{},children:[{type:a,value:"fromDatasetIndex"}]},{type:a,value:K},{type:b,tag:d,props:{},children:[{type:a,value:"fromDatasetId"}]},{type:a,value:" 来表示我们要生成新的数据。"}]},{type:a,value:c},{type:b,tag:f,props:{},children:[{type:a,value:"系列引用这个 dataset 。"}]},{type:a,value:c}]},{type:a,value:c},{type:b,tag:D,props:{id:F},children:[{type:b,tag:h,props:{href:"#%E6%95%B0%E6%8D%AE%E8%BD%AC%E6%8D%A2%E7%9A%84%E8%BF%9B%E9%98%B6%E4%BD%BF%E7%94%A8",ariaHidden:r,tabIndex:s},children:[{type:b,tag:t,props:{className:[u,v]},children:[]}]},{type:a,value:F}]},{type:a,value:c},{type:b,tag:L,props:{id:"链式声明-transform"},children:[{type:b,tag:h,props:{href:"#%E9%93%BE%E5%BC%8F%E5%A3%B0%E6%98%8E-transform",ariaHidden:r,tabIndex:s},children:[{type:b,tag:t,props:{className:[u,v]},children:[]}]},{type:a,value:"链式声明 transform"}]},{type:a,value:c},{type:b,tag:e,props:{},children:[{type:b,tag:d,props:{},children:[{type:a,value:J}]},{type:a,value:" 可以被链式声明,这是一个语法糖。"}]},{type:a,value:c},{type:b,tag:m,props:{className:[n]},children:[{type:b,tag:p,props:{lang:o,"line-highlights":g,"file-name":g},children:[{type:a,value:"option = {\n dataset: [\n {\n source: [\n \u002F\u002F 原始数据\n ]\n },\n {\n \u002F\u002F 几个 transform 被声明成 array ,他们构成了一个链,\n \u002F\u002F 前一个 transform 的输出是后一个 transform 的输入。\n transform: [\n {\n type: 'filter',\n config: { dimension: 'Product', value: 'Tofu' }\n },\n {\n type: 'sort',\n config: { dimension: 'Year', order: 'desc' }\n }\n ]\n }\n ],\n series: {\n type: 'pie',\n \u002F\u002F 这个系列引用上述 transform 的结果。\n datasetIndex: 1\n }\n};\n"}]}]},{type:a,value:c},{type:b,tag:"blockquote",props:{},children:[{type:a,value:c},{type:b,tag:e,props:{},children:[{type:a,value:"注意:理论上,任何 transform 都可能有多个输入或多个输出。但是,如果一个 transform 被链式声明,它只能获取前一个 transform 的第一个输出作为输入(第一个 transform 除外),以及它只能把自己的第一个输出给到后一个 transform (最后一个 transform 除外)。"}]},{type:a,value:c}]},{type:a,value:c},{type:b,tag:L,props:{id:"一个-transform-输出多个-data"},children:[{type:b,tag:h,props:{href:"#%E4%B8%80%E4%B8%AA-transform-%E8%BE%93%E5%87%BA%E5%A4%9A%E4%B8%AA-data",ariaHidden:r,tabIndex:s},children:[{type:b,tag:t,props:{className:[u,v]},children:[]}]},{type:a,value:"一个 transform 输出多个 data"}]},{type:a,value:c},{type:b,tag:e,props:{},children:[{type:a,value:"在大多数场景下,transform 只需输出一个 data 。但是也有一些场景,需要输出多个 data ,每个 data 可以被不同的 series 或者 dataset 所使用。"}]},{type:a,value:c},{type:b,tag:e,props:{},children:[{type:a,value:"例如,在内置的 \"boxplot\" transform 中,除了 boxplot 系列所需要的 data 外,离群点( outlier )也会被生成,并且可以用例如散点图系列显示出来。例如,"},{type:b,tag:h,props:{href:"https:\u002F\u002Fecharts.apache.org\u002Fexamples\u002Fzh\u002Feditor.html?c=boxplot-light-velocity",rel:[i,j,k],target:l},children:[{type:a,value:"example"}]},{type:a,value:x}]},{type:a,value:c},{type:b,tag:e,props:{},children:[{type:a,value:"我们提供配置 "},{type:b,tag:h,props:{href:Y,rel:[i,j,k],target:l},children:[{type:a,value:Z}]},{type:a,value:" 来满足这种情况,例如:"}]},{type:a,value:c},{type:b,tag:m,props:{className:[n]},children:[{type:b,tag:p,props:{lang:o,"line-highlights":g,"file-name":g},children:[{type:a,value:"option = {\n dataset: [\n {\n \u002F\u002F 这个 dataset 的 index 为 `0`。\n source: [\n \u002F\u002F 原始数据\n ]\n },\n {\n \u002F\u002F 这个 dataset 的 index 为 `1`。\n transform: {\n type: 'boxplot'\n }\n \u002F\u002F 这个 \"boxplot\" transform 生成了两个数据:\n \u002F\u002F result[0]: boxplot series 所需的数据。\n \u002F\u002F result[1]: 离群点数据。\n \u002F\u002F 当其他 series 或者 dataset 引用这个 dataset 时,他们默认只能得到\n \u002F\u002F result[0] 。\n \u002F\u002F 如果想要他们得到 result[1] ,需要额外声明如下这样一个 dataset :\n },\n {\n \u002F\u002F 这个 dataset 的 index 为 `2`。\n \u002F\u002F 这个额外的 dataset 指定了数据来源于 index 为 `1` 的 dataset。\n fromDatasetIndex: 1,\n \u002F\u002F 并且指定了获取 transform result[1] 。\n fromTransformResult: 1\n }\n ],\n xAxis: {\n type: 'category'\n },\n yAxis: {},\n series: [\n {\n name: 'boxplot',\n type: 'boxplot',\n \u002F\u002F Reference the data from result[0].\n \u002F\u002F 这个 series 引用 index 为 `1` 的 dataset 。\n datasetIndex: 1\n },\n {\n name: 'outlier',\n type: 'scatter',\n \u002F\u002F 这个 series 引用 index 为 `2` 的 dataset 。\n \u002F\u002F 从而也就得到了上述的 transform result[1] (即离群点数据)\n datasetIndex: 2\n }\n ]\n};\n"}]}]},{type:a,value:c},{type:b,tag:e,props:{},children:[{type:a,value:"另外,"},{type:b,tag:h,props:{href:Y,rel:[i,j,k],target:l},children:[{type:a,value:Z}]},{type:a,value:" 和 "},{type:b,tag:h,props:{href:I,rel:[i,j,k],target:l},children:[{type:a,value:V}]},{type:a,value:" 能同时出现在一个 dataset 中,这表示,这个 transform 的输入,是上游的结果中以 "},{type:b,tag:d,props:{},children:[{type:a,value:"fromTransformResult"}]},{type:a,value:" 获取的结果。例如:"}]},{type:a,value:c},{type:b,tag:m,props:{className:[n]},children:[{type:b,tag:p,props:{lang:o,"line-highlights":g,"file-name":g},children:[{type:a,value:"{\n fromDatasetIndex: 1,\n fromTransformResult: 1,\n transform: {\n type: 'sort',\n config: { dimension: 2, order: 'desc' }\n }\n}\n"}]}]},{type:a,value:c},{type:b,tag:L,props:{id:"在开发环境中-debug"},children:[{type:b,tag:h,props:{href:"#%E5%9C%A8%E5%BC%80%E5%8F%91%E7%8E%AF%E5%A2%83%E4%B8%AD-debug",ariaHidden:r,tabIndex:s},children:[{type:b,tag:t,props:{className:[u,v]},children:[]}]},{type:a,value:"在开发环境中 debug"}]},{type:a,value:c},{type:b,tag:e,props:{},children:[{type:a,value:"使用 transform 时,有时候我们会配不对,显示不出来结果,并且不知道哪里错了。所以,这里提供了一个配置项 "},{type:b,tag:d,props:{},children:[{type:a,value:"transform.print"}]},{type:a,value:" 方便 debug 。这个配置项只在开发环境中生效。如下例:"}]},{type:a,value:c},{type:b,tag:m,props:{className:[n]},children:[{type:b,tag:p,props:{lang:o,"line-highlights":g,"file-name":g},children:[{type:a,value:"option = {\n dataset: [\n {\n source: []\n },\n {\n transform: {\n type: 'filter',\n config: {},\n \u002F\u002F 配置为 `true` 后, transform 的结果\n \u002F\u002F 会被 console.log 打印出来。\n print: true\n }\n }\n ]\n \u002F\u002F ...\n};\n"}]}]},{type:a,value:c},{type:b,tag:D,props:{id:P},children:[{type:b,tag:h,props:{href:"#%E6%95%B0%E6%8D%AE%E8%BD%AC%E6%8D%A2%E5%99%A8-filter",ariaHidden:r,tabIndex:s},children:[{type:b,tag:t,props:{className:[u,v]},children:[]}]},{type:a,value:Q}]},{type:a,value:c},{type:b,tag:e,props:{},children:[{type:a,value:"echarts 内置提供了能起过滤作用的数据转换器。我们只需声明 "},{type:b,tag:d,props:{},children:[{type:a,value:"transform.type: \"filter\""}]},{type:a,value:",以及给出数据筛选条件。如下例:"}]},{type:a,value:c},{type:b,tag:m,props:{className:[n]},children:[{type:b,tag:W,props:{lang:o,layout:X},children:[{type:a,value:"option = {\n dataset: [\n {\n source: [\n ['Product', 'Sales', 'Price', 'Year'],\n ['Cake', 123, 32, 2011],\n ['Latte', 231, 14, 2011],\n ['Tofu', 235, 5, 2011],\n ['Milk Tee', 341, 25, 2011],\n ['Porridge', 122, 29, 2011],\n ['Cake', 143, 30, 2012],\n ['Latte', 201, 19, 2012],\n ['Tofu', 255, 7, 2012],\n ['Milk Tee', 241, 27, 2012],\n ['Porridge', 102, 34, 2012],\n ['Cake', 153, 28, 2013],\n ['Latte', 181, 21, 2013],\n ['Tofu', 395, 4, 2013],\n ['Milk Tee', 281, 31, 2013],\n ['Porridge', 92, 39, 2013],\n ['Cake', 223, 29, 2014],\n ['Latte', 211, 17, 2014],\n ['Tofu', 345, 3, 2014],\n ['Milk Tee', 211, 35, 2014],\n ['Porridge', 72, 24, 2014]\n ]\n },\n {\n transform: {\n type: 'filter',\n config: { dimension: 'Year', '=': 2011 }\n \u002F\u002F 这个筛选条件表示,遍历数据,筛选出维度( dimension )\n \u002F\u002F 'Year' 上值为 2011 的所有数据项。\n }\n }\n ],\n series: {\n type: 'pie',\n datasetIndex: 1\n }\n};\n"}]}]},{type:a,value:c},{type:b,tag:e,props:{},children:[{type:a,value:"这是 filter 的另一个例子的效果:"}]},{type:a,value:c},{type:b,tag:M,props:{src:"data-transform-filter"},children:[{type:a,value:c}]},{type:a,value:c},{type:b,tag:e,props:{},children:[{type:a,value:"在 \"filter\" transform 中,有这些要素:"}]},{type:a,value:c},{type:b,tag:e,props:{},children:[{type:b,tag:z,props:{},children:[{type:a,value:"关于维度( dimension ):"}]}]},{type:a,value:c},{type:b,tag:e,props:{},children:[{type:b,tag:d,props:{},children:[{type:a,value:"config.dimension"}]},{type:a,value:" 指定了维度,能设成这样的值:"}]},{type:a,value:c},{type:b,tag:w,props:{},children:[{type:a,value:c},{type:b,tag:f,props:{},children:[{type:a,value:"设定成声明在 dataset 中的维度名,例如 "},{type:b,tag:d,props:{},children:[{type:a,value:"config: { dimension: 'Year', '=': 2011 }"}]},{type:a,value:"。不过, dataset 中维度名的声明并非强制,所以我们也可以"}]},{type:a,value:c},{type:b,tag:f,props:{},children:[{type:a,value:"设定成 dataset 中的维度 index (index 值从 0 开始)例如 "},{type:b,tag:d,props:{},children:[{type:a,value:"config: { dimension: 3, '=': 2011 }"}]},{type:a,value:x}]},{type:a,value:c}]},{type:a,value:c},{type:b,tag:e,props:{},children:[{type:b,tag:z,props:{},children:[{type:a,value:"关于关系比较操作符:"}]}]},{type:a,value:c},{type:b,tag:e,props:{},children:[{type:a,value:"关系操作符,可以设定这些:\n"},{type:b,tag:d,props:{},children:[{type:a,value:_}]},{type:a,value:A},{type:b,tag:d,props:{},children:[{type:a,value:"gt"}]},{type:a,value:B},{type:b,tag:d,props:{},children:[{type:a,value:$}]},{type:a,value:A},{type:b,tag:d,props:{},children:[{type:a,value:"gte"}]},{type:a,value:B},{type:b,tag:d,props:{},children:[{type:a,value:aa}]},{type:a,value:A},{type:b,tag:d,props:{},children:[{type:a,value:"lt"}]},{type:a,value:B},{type:b,tag:d,props:{},children:[{type:a,value:ab}]},{type:a,value:A},{type:b,tag:d,props:{},children:[{type:a,value:"lte"}]},{type:a,value:B},{type:b,tag:d,props:{},children:[{type:a,value:ac}]},{type:a,value:A},{type:b,tag:d,props:{},children:[{type:a,value:"eq"}]},{type:a,value:B},{type:b,tag:d,props:{},children:[{type:a,value:ad}]},{type:a,value:A},{type:b,tag:d,props:{},children:[{type:a,value:"ne"}]},{type:a,value:y},{type:b,tag:d,props:{},children:[{type:a,value:"\u003C\u003E"}]},{type:a,value:B},{type:b,tag:d,props:{},children:[{type:a,value:ae}]},{type:a,value:"。(小括号中的符号或名字,是别名,设置起来作用相同)。他们首先基本地能基于数值大小进行比较,然后也有些额外的功能特性:"}]},{type:a,value:c},{type:b,tag:w,props:{},children:[{type:a,value:c},{type:b,tag:f,props:{},children:[{type:a,value:"多个关系操作符能声明在一个 {} 中,例如 "},{type:b,tag:d,props:{},children:[{type:a,value:"{ dimension: 'Price', '\u003E=': 20, '\u003C': 30 }"}]},{type:a,value:"。这表示“与”的关系,即,筛选出价格大于等于 20 小雨 30 的数据项。"}]},{type:a,value:c},{type:b,tag:f,props:{},children:[{type:a,value:"data 里的值,不仅可以是数值( number ),也可以是“类数值的字符串”(“ numeric string ”)。“类数值的字符串”本身是一个字符串,但是可以被转换为字面所描述的数值,例如 "},{type:b,tag:d,props:{},children:[{type:a,value:"' 123 '"}]},{type:a,value:"。转换过程中,空格(全角半角空格)和换行符都能被消除( trim )。"}]},{type:a,value:c},{type:b,tag:f,props:{},children:[{type:a,value:"如果我们需要对日期对象(JS "},{type:b,tag:d,props:{},children:[{type:a,value:N}]},{type:a,value:")或者日期字符串(如 '2012-05-12')进行比较,我们需要手动指定 "},{type:b,tag:d,props:{},children:[{type:a,value:H}]},{type:a,value:",例如 "},{type:b,tag:d,props:{},children:[{type:a,value:"config: { dimension: 3, lt: '2012-05-12', parser: 'time' }"}]},{type:a,value:x}]},{type:a,value:c},{type:b,tag:f,props:{},children:[{type:a,value:"纯字符串比较也被支持,但是只能用在 "},{type:b,tag:d,props:{},children:[{type:a,value:ac}]},{type:a,value:" 或 "},{type:b,tag:d,props:{},children:[{type:a,value:ad}]},{type:a,value:" 上。而 "},{type:b,tag:d,props:{},children:[{type:a,value:_}]},{type:a,value:q},{type:b,tag:d,props:{},children:[{type:a,value:$}]},{type:a,value:q},{type:b,tag:d,props:{},children:[{type:a,value:aa}]},{type:a,value:q},{type:b,tag:d,props:{},children:[{type:a,value:ab}]},{type:a,value:" 并不支持纯字符串比较,也就是说,这四个操作符的右值,不能是字符串。"}]},{type:a,value:c},{type:b,tag:f,props:{},children:[{type:b,tag:d,props:{},children:[{type:a,value:ae}]},{type:a,value:" 操作符能提供正则表达式比较。例如, "},{type:b,tag:d,props:{},children:[{type:a,value:"{ dimension: 'Name', reg: \u002F\\s+Müller\\s*$\u002F }"}]},{type:a,value:" 能在 "},{type:b,tag:d,props:{},children:[{type:a,value:"'Name'"}]},{type:a,value:" 维度上选出姓 "},{type:b,tag:d,props:{},children:[{type:a,value:"'Müller'"}]},{type:a,value:" 的数据项。"}]},{type:a,value:c}]},{type:a,value:c},{type:b,tag:e,props:{},children:[{type:b,tag:z,props:{},children:[{type:a,value:"关于逻辑比较:"}]}]},{type:a,value:c},{type:b,tag:e,props:{},children:[{type:a,value:"我们也支持了逻辑比较操作符 "},{type:b,tag:z,props:{},children:[{type:a,value:"与或非"}]},{type:a,value:"( "},{type:b,tag:d,props:{},children:[{type:a,value:af}]},{type:a,value:ag},{type:b,tag:d,props:{},children:[{type:a,value:ah}]},{type:a,value:ag},{type:b,tag:d,props:{},children:[{type:a,value:ai}]},{type:a,value:" ):"}]},{type:a,value:c},{type:b,tag:m,props:{className:[n]},children:[{type:b,tag:p,props:{lang:o,"line-highlights":g,"file-name":g},children:[{type:a,value:"option = {\n dataset: [\n {\n source: [\n \u002F\u002F ...\n ]\n },\n {\n transform: {\n type: 'filter',\n config: {\n \u002F\u002F 使用 and 操作符。\n \u002F\u002F 类似地,同样的位置也可以使用 “or” 或 “not”。\n \u002F\u002F 但是注意 “not” 后应该跟一个 {...} 而非 [...] 。\n and: [\n { dimension: 'Year', '=': 2011 },\n { dimension: 'Price', '\u003E=': 20, '\u003C': 30 }\n ]\n }\n \u002F\u002F 这个表达的是,选出 2011 年价格大于等于 20 但小于 30 的数据项。\n }\n }\n ],\n series: {\n type: 'pie',\n datasetIndex: 1\n }\n};\n"}]}]},{type:a,value:c},{type:b,tag:e,props:{},children:[{type:b,tag:d,props:{},children:[{type:a,value:af}]},{type:a,value:K},{type:b,tag:d,props:{},children:[{type:a,value:ah}]},{type:a,value:K},{type:b,tag:d,props:{},children:[{type:a,value:ai}]},{type:a,value:" 自然可以被嵌套,例如:"}]},{type:a,value:c},{type:b,tag:m,props:{className:[n]},children:[{type:b,tag:p,props:{lang:o,"line-highlights":g,"file-name":g},children:[{type:a,value:"transform: {\n type: 'filter',\n config: {\n or: [{\n and: [{\n dimension: 'Price', '\u003E=': 10, '\u003C': 20\n }, {\n dimension: 'Sales', '\u003C': 100\n }, {\n not: { dimension: 'Product', '=': 'Tofu' }\n }]\n }, {\n and: [{\n dimension: 'Price', '\u003E=': 10, '\u003C': 20\n }, {\n dimension: 'Sales', '\u003C': 100\n }, {\n not: { dimension: 'Product', '=': 'Cake' }\n }]\n }]\n }\n}\n"}]}]},{type:a,value:c},{type:b,tag:e,props:{},children:[{type:b,tag:z,props:{},children:[{type:a,value:"关于解析器( parser ):"}]}]},{type:a,value:c},{type:b,tag:e,props:{},children:[{type:a,value:"还可以指定“解析器”( parser )来对值进行解析后再做比较。现在支持的解析器有:"}]},{type:a,value:c},{type:b,tag:w,props:{},children:[{type:a,value:c},{type:b,tag:f,props:{},children:[{type:b,tag:d,props:{},children:[{type:a,value:H}]},{type:a,value:":把原始值解析成时间戳( timestamp )后再做比较。这个解析器的行为,和 "},{type:b,tag:d,props:{},children:[{type:a,value:"echarts.time.parse"}]},{type:a,value:" 相同,即,当原始值为时间对象( JS "},{type:b,tag:d,props:{},children:[{type:a,value:N}]},{type:a,value:" 实例),或者是时间戳,或者是描述时间的字符串(例如 "},{type:b,tag:d,props:{},children:[{type:a,value:"'2012-05-12 03:11:22'"}]},{type:a,value:" ),都可以被解析为时间戳,然后就可以基于数值大小进行比较。如果原始数据是其他不可解析为时间戳的值,那么会被解析为 NaN。"}]},{type:a,value:c},{type:b,tag:f,props:{},children:[{type:b,tag:d,props:{},children:[{type:a,value:"parser: 'trim'"}]},{type:a,value:":如果原始数据是字符串,则把字符串两端的空格(全角半角)和换行符去掉。如果不是字符串,还保持为原始数据。"}]},{type:a,value:c},{type:b,tag:f,props:{},children:[{type:b,tag:d,props:{},children:[{type:a,value:O}]},{type:a,value:":强制把原始数据转成数值。如果不能转成有意义的数值,那么转成 "},{type:b,tag:d,props:{},children:[{type:a,value:aj}]},{type:a,value:"。在大多数场景下,我们并不需要这个解析器,因为按默认策略,“像数值的字符串”就会被转成数值。但是默认策略比较严格,这个解析器比较宽松,如果我们遇到含有尾缀的字符串(例如 "},{type:b,tag:d,props:{},children:[{type:a,value:ak}]},{type:a,value:q},{type:b,tag:d,props:{},children:[{type:a,value:"12px"}]},{type:a,value:"),我们需要手动指定 "},{type:b,tag:d,props:{},children:[{type:a,value:O}]},{type:a,value:",从而去掉尾缀转为数值才能比较。"}]},{type:a,value:c}]},{type:a,value:c},{type:b,tag:e,props:{},children:[{type:a,value:"这个例子显示了如何使用 "},{type:b,tag:d,props:{},children:[{type:a,value:H}]},{type:a,value:":"}]},{type:a,value:c},{type:b,tag:m,props:{className:[n]},children:[{type:b,tag:p,props:{lang:o,"line-highlights":g,"file-name":g},children:[{type:a,value:"option = {\n dataset: [\n {\n source: [\n ['Product', 'Sales', 'Price', 'Date'],\n ['Milk Tee', 311, 21, '2012-05-12'],\n ['Cake', 135, 28, '2012-05-22'],\n ['Latte', 262, 36, '2012-06-02'],\n ['Milk Tee', 359, 21, '2012-06-22'],\n ['Cake', 121, 28, '2012-07-02'],\n ['Latte', 271, 36, '2012-06-22']\n \u002F\u002F ...\n ]\n },\n {\n transform: {\n type: 'filter',\n config: {\n dimension: 'Date',\n '\u003E=': '2012-05',\n '\u003C': '2012-06',\n parser: 'time'\n }\n }\n }\n ]\n};\n"}]}]},{type:a,value:c},{type:b,tag:e,props:{},children:[{type:b,tag:z,props:{},children:[{type:a,value:"形式化定义:"}]}]},{type:a,value:c},{type:b,tag:e,props:{},children:[{type:a,value:"最后,我们给出,数据转换器 \"filter\" 的 config 的形式化定义:"}]},{type:a,value:c},{type:b,tag:m,props:{className:[n]},children:[{type:b,tag:p,props:{lang:al,"line-highlights":g,"file-name":g},children:[{type:a,value:"type FilterTransform = {\n type: 'filter';\n config: ConditionalExpressionOption;\n};\ntype ConditionalExpressionOption =\n | true\n | false\n | RelationalExpressionOption\n | LogicalExpressionOption;\ntype RelationalExpressionOption = {\n dimension: DimensionName | DimensionIndex;\n parser?: 'time' | 'trim' | 'number';\n lt?: DataValue; \u002F\u002F less than\n lte?: DataValue; \u002F\u002F less than or equal\n gt?: DataValue; \u002F\u002F greater than\n gte?: DataValue; \u002F\u002F greater than or equal\n eq?: DataValue; \u002F\u002F equal\n ne?: DataValue; \u002F\u002F not equal\n '\u003C'?: DataValue; \u002F\u002F lt\n '\u003C='?: DataValue; \u002F\u002F lte\n '\u003E'?: DataValue; \u002F\u002F gt\n '\u003E='?: DataValue; \u002F\u002F gte\n '='?: DataValue; \u002F\u002F eq\n '!='?: DataValue; \u002F\u002F ne\n '\u003C\u003E'?: DataValue; \u002F\u002F ne (SQL style)\n reg?: RegExp | string; \u002F\u002F RegExp\n};\ntype LogicalExpressionOption = {\n and?: ConditionalExpressionOption[];\n or?: ConditionalExpressionOption[];\n not?: ConditionalExpressionOption;\n};\ntype DataValue = string | number | Date;\ntype DimensionName = string;\ntype DimensionIndex = number;\n"}]}]},{type:a,value:c},{type:b,tag:D,props:{id:R},children:[{type:b,tag:h,props:{href:"#%E6%95%B0%E6%8D%AE%E8%BD%AC%E6%8D%A2%E5%99%A8-sort",ariaHidden:r,tabIndex:s},children:[{type:b,tag:t,props:{className:[u,v]},children:[]}]},{type:a,value:S}]},{type:a,value:c},{type:b,tag:e,props:{},children:[{type:a,value:"\"sort\" 是另一个内置的数据转换器,用于排序数据。目前主要能用于在类目轴( "},{type:b,tag:d,props:{},children:[{type:a,value:"axis.type: 'category'"}]},{type:a,value:" )中显示排过序的数据。例如:"}]},{type:a,value:c},{type:b,tag:m,props:{className:[n]},children:[{type:b,tag:p,props:{lang:o,"line-highlights":g,"file-name":g},children:[{type:a,value:"option = {\n dataset: [\n {\n dimensions: ['name', 'age', 'profession', 'score', 'date'],\n source: [\n [' Hannah Krause ', 41, 'Engineer', 314, '2011-02-12'],\n ['Zhao Qian ', 20, 'Teacher', 351, '2011-03-01'],\n [' Jasmin Krause ', 52, 'Musician', 287, '2011-02-14'],\n ['Li Lei', 37, 'Teacher', 219, '2011-02-18'],\n [' Karle Neumann ', 25, 'Engineer', 253, '2011-04-02'],\n [' Adrian Groß', 19, 'Teacher', null, '2011-01-16'],\n ['Mia Neumann', 71, 'Engineer', 165, '2011-03-19'],\n [' Böhm Fuchs', 36, 'Musician', 318, '2011-02-24'],\n ['Han Meimei ', 67, 'Engineer', 366, '2011-03-12']\n ]\n },\n {\n transform: {\n type: 'sort',\n \u002F\u002F 按分数排序\n config: { dimension: 'score', order: 'asc' }\n }\n }\n ],\n series: {\n type: 'bar',\n datasetIndex: 1\n }\n \u002F\u002F ...\n};\n"}]}]},{type:a,value:c},{type:b,tag:M,props:{src:"data-transform-sort-bar"},children:[{type:a,value:c}]},{type:a,value:c},{type:b,tag:e,props:{},children:[{type:a,value:"数据转换器 \"sort\" 还有一些额外的功能:"}]},{type:a,value:c},{type:b,tag:w,props:{},children:[{type:a,value:c},{type:b,tag:f,props:{},children:[{type:a,value:"可以多重排序,多个维度一起排序。见下面的例子。"}]},{type:a,value:c},{type:b,tag:f,props:{},children:[{type:a,value:"排序规则是这样的:\n"},{type:b,tag:w,props:{},children:[{type:a,value:c},{type:b,tag:f,props:{},children:[{type:a,value:"默认按照数值大小排序。其中,“可转为数值的字符串”也被转换成数值,和其他数值一起按大小排序。"}]},{type:a,value:c},{type:b,tag:f,props:{},children:[{type:a,value:"对于其他“不能转为数值的字符串”,也能在它们之间按字符串进行排序。这个特性有助于这种场景:把相同标签的数据项排到一起,尤其是当多个维度共同排序时。见下面的例子。"}]},{type:a,value:c},{type:b,tag:f,props:{},children:[{type:a,value:"当“数值及可转为数值的字符串”和“不能转为数值的字符串”进行排序时,或者它们和“其他类型的值”进行比较时,它们本身是不知如何进行比较的。那么我们称呼“后者”为“incomparable”,并且可以设置 "},{type:b,tag:d,props:{},children:[{type:a,value:"incomparable: 'min' | 'max'"}]},{type:a,value:" 来指定一个“incomparable”在这个比较中是最大还是最小,从而能使它们能产生比较结果。这个设定的用途,比如可以是,决定空值(例如 "},{type:b,tag:d,props:{},children:[{type:a,value:"null"}]},{type:a,value:q},{type:b,tag:d,props:{},children:[{type:a,value:"undefined"}]},{type:a,value:q},{type:b,tag:d,props:{},children:[{type:a,value:aj}]},{type:a,value:q},{type:b,tag:d,props:{},children:[{type:a,value:"''"}]},{type:a,value:q},{type:b,tag:d,props:{},children:[{type:a,value:"'-'"}]},{type:a,value:")在排序的头还是尾。"}]},{type:a,value:c}]},{type:a,value:c}]},{type:a,value:c},{type:b,tag:f,props:{},children:[{type:a,value:"过滤器 "},{type:b,tag:d,props:{},children:[{type:a,value:"filter: 'time' | 'trim' | 'number'"}]},{type:a,value:" 可以被使用,和数据转换器 \"filter\" 中的情况一样。\n"},{type:b,tag:w,props:{},children:[{type:a,value:c},{type:b,tag:f,props:{},children:[{type:a,value:"如果要对时间进行排序(例如,值为 JS "},{type:b,tag:d,props:{},children:[{type:a,value:N}]},{type:a,value:" 实例或者时间字符串如 "},{type:b,tag:d,props:{},children:[{type:a,value:"'2012-03-12 11:13:54'"}]},{type:a,value:"),我们需要声明 "},{type:b,tag:d,props:{},children:[{type:a,value:H}]},{type:a,value:x}]},{type:a,value:c},{type:b,tag:f,props:{},children:[{type:a,value:"如果需要对有后缀的数值进行排序(如 "},{type:b,tag:d,props:{},children:[{type:a,value:ak}]},{type:a,value:q},{type:b,tag:d,props:{},children:[{type:a,value:"'16px'"}]},{type:a,value:")我们需要声明 "},{type:b,tag:d,props:{},children:[{type:a,value:O}]},{type:a,value:x}]},{type:a,value:c}]},{type:a,value:c}]},{type:a,value:c}]},{type:a,value:c},{type:b,tag:e,props:{},children:[{type:a,value:"这是一个“多维度排序”的例子。"}]},{type:a,value:c},{type:b,tag:m,props:{className:[n]},children:[{type:b,tag:p,props:{lang:o,"line-highlights":g,"file-name":g},children:[{type:a,value:"option = {\n dataset: [\n {\n dimensions: ['name', 'age', 'profession', 'score', 'date'],\n source: [\n [' Hannah Krause ', 41, 'Engineer', 314, '2011-02-12'],\n ['Zhao Qian ', 20, 'Teacher', 351, '2011-03-01'],\n [' Jasmin Krause ', 52, 'Musician', 287, '2011-02-14'],\n ['Li Lei', 37, 'Teacher', 219, '2011-02-18'],\n [' Karle Neumann ', 25, 'Engineer', 253, '2011-04-02'],\n [' Adrian Groß', 19, 'Teacher', null, '2011-01-16'],\n ['Mia Neumann', 71, 'Engineer', 165, '2011-03-19'],\n [' Böhm Fuchs', 36, 'Musician', 318, '2011-02-24'],\n ['Han Meimei ', 67, 'Engineer', 366, '2011-03-12']\n ]\n },\n {\n transform: {\n type: 'sort',\n config: [\n \u002F\u002F 对两个维度按声明的优先级分别排序。\n { dimension: 'profession', order: 'desc' },\n { dimension: 'score', order: 'desc' }\n ]\n }\n }\n ],\n series: {\n type: 'bar',\n datasetIndex: 1\n }\n \u002F\u002F...\n};\n"}]}]},{type:a,value:c},{type:b,tag:M,props:{src:"doc-example\u002Fdata-transform-multiple-sort-bar"},children:[{type:a,value:c}]},{type:a,value:c},{type:b,tag:e,props:{},children:[{type:a,value:"最后,我们给出数据转换器 \"sort\" 的 config 的形式化定义。"}]},{type:a,value:c},{type:b,tag:m,props:{className:[n]},children:[{type:b,tag:p,props:{lang:al,"line-highlights":g,"file-name":g},children:[{type:a,value:"type SortTransform = {\n type: 'filter';\n config: OrderExpression | OrderExpression[];\n};\ntype OrderExpression = {\n dimension: DimensionName | DimensionIndex;\n order: 'asc' | 'desc';\n incomparable?: 'min' | 'max';\n parser?: 'time' | 'trim' | 'number';\n};\ntype DimensionName = string;\ntype DimensionIndex = number;\n"}]}]},{type:a,value:c},{type:b,tag:D,props:{id:G},children:[{type:b,tag:h,props:{href:"#%E4%BD%BF%E7%94%A8%E5%A4%96%E9%83%A8%E7%9A%84%E6%95%B0%E6%8D%AE%E8%BD%AC%E6%8D%A2%E5%99%A8",ariaHidden:r,tabIndex:s},children:[{type:b,tag:t,props:{className:[u,v]},children:[]}]},{type:a,value:G}]},{type:a,value:c},{type:b,tag:e,props:{},children:[{type:a,value:"除了上述的内置的数据转换器外,我们也可以使用外部的数据转换器。外部数据转换器能提供或自己定制更丰富的功能。下面的例子中,我们使用第三方库 "},{type:b,tag:h,props:{href:"https:\u002F\u002Fgithub.com\u002Fecomfe\u002Fecharts-stat",rel:[i,j,k],target:l},children:[{type:a,value:"ecStat"}]},{type:a,value:" 提供的数据转换器。"}]},{type:a,value:c},{type:b,tag:e,props:{},children:[{type:a,value:"生成数据的回归线:"}]},{type:a,value:c},{type:b,tag:m,props:{className:[n]},children:[{type:b,tag:p,props:{lang:o,"line-highlights":g,"file-name":g},children:[{type:a,value:"\u002F\u002F 首先要注册外部数据转换器。\necharts.registerTransform(ecStatTransform(ecStat).regression);\n"}]}]},{type:a,value:c},{type:b,tag:m,props:{className:[n]},children:[{type:b,tag:p,props:{lang:o,"line-highlights":g,"file-name":g},children:[{type:a,value:"option = {\n dataset: [\n {\n source: rawData\n },\n {\n transform: {\n \u002F\u002F 引用注册的数据转换器。\n \u002F\u002F 注意,每个外部的数据转换器,都有名空间(如 'ecStat:xxx','ecStat' 是名空间)。\n \u002F\u002F 而内置数据转换器(如 'filter', 'sort')没有名空间。\n type: 'ecStat:regression',\n config: {\n \u002F\u002F 这里是此外部数据转换器所需的参数。\n method: 'exponential'\n }\n }\n }\n ],\n xAxis: { type: 'category' },\n yAxis: {},\n series: [\n {\n name: 'scatter',\n type: 'scatter',\n datasetIndex: 0\n },\n {\n name: 'regression',\n type: 'line',\n symbol: 'none',\n datasetIndex: 1\n }\n ]\n};\n"}]}]},{type:a,value:c},{type:b,tag:e,props:{},children:[{type:a,value:"一些使用 echarts-stat 的例子:"}]},{type:a,value:c},{type:b,tag:w,props:{},children:[{type:a,value:c},{type:b,tag:f,props:{},children:[{type:b,tag:h,props:{href:"https:\u002F\u002Fecharts.apache.org\u002Fexamples\u002Fzh\u002Feditor.html?c=data-transform-aggregate&edit=1&reset=1",rel:[i,j,k],target:l},children:[{type:a,value:"聚集 (Aggregate)"}]}]},{type:a,value:c},{type:b,tag:f,props:{},children:[{type:b,tag:h,props:{href:"https:\u002F\u002Fecharts.apache.org\u002Fexamples\u002Fzh\u002Feditor.html?c=bar-histogram&edit=1&reset=1",rel:[i,j,k],target:l},children:[{type:a,value:"直方图 (Histogram)"}]}]},{type:a,value:c},{type:b,tag:f,props:{},children:[{type:b,tag:h,props:{href:"https:\u002F\u002Fecharts.apache.org\u002Fexamples\u002Fzh\u002Feditor.html?c=scatter-clustering&edit=1&reset=1",rel:[i,j,k],target:l},children:[{type:a,value:"简单聚类 (Clustering)"}]}]},{type:a,value:c},{type:b,tag:f,props:{},children:[{type:b,tag:h,props:{href:"https:\u002F\u002Fecharts.apache.org\u002Fexamples\u002Fzh\u002Feditor.html?c=scatter-linear-regression&edit=1&reset=1",rel:[i,j,k],target:l},children:[{type:a,value:"线性回归线 (Linear Regression)"}]}]},{type:a,value:c},{type:b,tag:f,props:{},children:[{type:b,tag:h,props:{href:"https:\u002F\u002Fecharts.apache.org\u002Fexamples\u002Fzh\u002Feditor.html?c=scatter-exponential-regression&edit=1&reset=1",rel:[i,j,k],target:l},children:[{type:a,value:"指数回归线 (Exponential Regression)"}]}]},{type:a,value:c},{type:b,tag:f,props:{},children:[{type:b,tag:h,props:{href:"https:\u002F\u002Fecharts.apache.org\u002Fexamples\u002Fzh\u002Feditor.html?c=scatter-logarithmic-regression&edit=1&reset=1",rel:[i,j,k],target:l},children:[{type:a,value:"对数回归线 (Logarithmic Regression)"}]}]},{type:a,value:c},{type:b,tag:f,props:{},children:[{type:b,tag:h,props:{href:"https:\u002F\u002Fecharts.apache.org\u002Fexamples\u002Fzh\u002Feditor.html?c=scatter-polynomial-regression&edit=1&reset=1",rel:[i,j,k],target:l},children:[{type:a,value:"多项式回归线 (Polynomial Regression)"}]}]},{type:a,value:c}]}]},dir:"\u002Fzh\u002Fconcepts",path:"\u002Fzh\u002Fconcepts\u002Fdata-transform",extension:".md",createdAt:am,updatedAt:am},postPath:"zh\u002Fconcepts\u002Fdata-transform"}],fetch:{},mutations:[]}}("text","element","\n","code","p","li","","a","nofollow","noopener","noreferrer","_blank","div","nuxt-content-highlight","js","md-code-block",", ","true",-1,"span","icon","icon-link","ul","。","、","strong","(",")、",2,"h2","数据转换基础使用","数据转换的进阶使用","使用外部的数据转换器","parser: 'time'","https:\u002F\u002Fecharts.apache.org\u002Foption.html##dataset.transform","transform","\u002F","h4","md-example","Date","parser: 'number'","数据转换器-filter","数据转换器 \"filter\"","数据转换器-sort","数据转换器 \"sort\"","https:\u002F\u002Fecharts.apache.org\u002Foption.html##dataset","dataset","dataset.transform","md-live","tb","https:\u002F\u002Fecharts.apache.org\u002Foption.html##dataset.fromTransformResult","dataset.fromTransformResult","\u003E","\u003E=","\u003C","\u003C=","=","!=","reg","and"," | ","or","not","NaN","'33%'","ts","2021-08-02T05:33:02.867Z")));