--- layout: page title: "Transformations for Zeppelin Visualization" description: "Description for Transformations" group: development --- {% include JB/setup %} # Transformations for Zeppelin Visualization
## Overview Transformations - **renders** setting which allows users to set columns and - **transforms** table rows according to the configured columns. Zeppelin provides 4 types of transformations. ## 1. PassthroughTransformation `PassthroughTransformation` is the simple transformation which does not convert original tabledata at all. See [passthrough.js](https://github.com/apache/zeppelin/blob/master/zeppelin-web/src/app/tabledata/passthrough.js) ## 2. ColumnselectorTransformation `ColumnselectorTransformation` is uses when you need `N` axes but do not need aggregation. See [columnselector.js](https://github.com/apache/zeppelin/blob/master/zeppelin-web/src/app/tabledata/columnselector.js) ## 3. PivotTransformation `PivotTransformation` provides group by and aggregation. Every chart using `PivotTransformation` has 3 axes. `Keys`, `Groups` and `Values`. See [pivot.js](https://github.com/apache/zeppelin/blob/master/zeppelin-web/src/app/tabledata/pivot.js) ## 4. AdvancedTransformation `AdvancedTransformation` has more detailed options while providing existing features of `PivotTransformation` and `ColumnselectorTransformation` - multiple sub charts - configurable chart axes - parameter widgets: `input`, `checkbox`, `option`, `textarea` - parsing parameters automatically based on their types - expand / fold axis and parameter panels - multiple transformation methods while supporting lazy converting - re-initialize the whole configuration based on spec hash. ### Spec `AdvancedTransformation` requires `spec` which includes axis and parameter details for charts. Let's create 2 sub-charts called `line` and `no-group`. Each sub chart can have different axis and parameter depending on their requirements.
```js class AwesomeVisualization extends Visualization { constructor(targetEl, config) { super(targetEl, config) const spec = { charts: { 'line': { transform: { method: 'object', }, sharedAxis: false, /** set if you want to share axes between sub charts, default is `false` */ axis: { 'xAxis': { dimension: 'multiple', axisType: 'key', description: 'serial', }, 'yAxis': { dimension: 'multiple', axisType: 'aggregator', description: 'serial', }, 'category': { dimension: 'multiple', axisType: 'group', description: 'categorical', }, }, parameter: { 'xAxisUnit': { valueType: 'string', defaultValue: '', description: 'unit of xAxis', }, 'yAxisUnit': { valueType: 'string', defaultValue: '', description: 'unit of yAxis', }, 'lineWidth': { valueType: 'int', defaultValue: 0, description: 'width of line', }, }, }, 'no-group': { transform: { method: 'object', }, sharedAxis: false, axis: { 'xAxis': { dimension: 'single', axisType: 'key', }, 'yAxis': { dimension: 'multiple', axisType: 'value', }, }, parameter: { 'xAxisUnit': { valueType: 'string', defaultValue: '', description: 'unit of xAxis', }, 'yAxisUnit': { valueType: 'string', defaultValue: '', description: 'unit of yAxis', }, }, }, } this.transformation = new AdvancedTransformation(config, spec) } ... // `render` will be called whenever `axis` or `parameter` is changed render(data) { const { chart, parameter, column, transformer, } = data if (chart === 'line') { const transformed = transformer() // draw line chart } else if (chart === 'no-group') { const transformed = transformer() // draw no-group chart } } } ```
### Spec: `axis` | Field Name | Available Values (type) | Description | | --- | --- | --- | |`dimension` | `single` | Axis can contains only 1 column | |`dimension` | `multiple` | Axis can contains multiple columns | |`axisType` | `key` | Column(s) in this axis will be used as `key` like in `PivotTransformation`. These columns will be served in `column.key` | |`axisType` | `aggregator` | Column(s) in this axis will be used as `value` like in `PivotTransformation`. These columns will be served in `column.aggregator` | |`axisType` | `group` | Column(s) in this axis will be used as `group` like in `PivotTransformation`. These columns will be served in `column.group` | |`axisType` | (string) | Any string value can be used here. These columns will be served in `column.custom` | |`maxAxisCount` (optional) | (int) | The max number of columns that this axis can contain. (unlimited if `undefined`) | |`minAxisCount` (optional) | (int) | The min number of columns that this axis should contain to draw chart. (`1` in case of single dimension) | |`description` (optional) | (string) | Description for the axis. |
Here is an example. ```js axis: { 'xAxis': { dimension: 'multiple', axisType: 'key', }, 'yAxis': { dimension: 'multiple', axisType: 'aggregator'}, 'category': { dimension: 'multiple', axisType: 'group', maxAxisCount: 2, valueType: 'string', }, }, ```
### Spec: `sharedAxis` If you set `sharedAxis: false` for sub charts, then their axes are persisted in global space (shared). It's useful for when you creating multiple sub charts sharing their axes but have different parameters. For example, - `basic-column`, `stacked-column`, `percent-column` - `pie` and `donut`
Here is an example. ```js const spec = { charts: { 'column': { transform: { method: 'array', }, sharedAxis: true, axis: { ... }, parameter: { ... }, }, 'stacked': { transform: { method: 'array', }, sharedAxis: true, axis: { ... } parameter: { ... }, }, ```
### Spec: `parameter` | Field Name | Available Values (type) | Description | | --- | --- | --- | |`valueType` | `string` | Parameter which has string value | |`valueType` | `int` | Parameter which has int value | |`valueType` | `float` | Parameter which has float value | |`valueType` | `boolean` | Parameter which has boolean value used with `checkbox` widget usually | |`valueType` | `JSON` | Parameter which has JSON value used with `textarea` widget usually. `defaultValue` should be `""` (empty string). This ||`defaultValue` | (any) | Default value of this parameter. `JSON` type should have `""` (empty string) | |`description` | (string) | Description of this parameter. This value will be parsed as HTML for pretty output | |`widget` | `input` | Use [input](https://developer.mozilla.org/en/docs/Web/HTML/Element/input) widget. This is the default widget (if `widget` is undefined)| |`widget` | `checkbox` | Use [checkbox](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/checkbox) widget. | |`widget` | `textarea` | Use [textarea](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/textarea) widget. | |`widget` | `option` | Use [select + option](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/select) widget. This parameter should have `optionValues` field as well. | |`optionValues` | (Array) | Available option values used with the `option` widget |
Here is an example. ```js parameter: { // string type, input widget 'xAxisUnit': { valueType: 'string', defaultValue: '', description: 'unit of xAxis', }, // boolean type, checkbox widget 'inverted': { widget: 'checkbox', valueType: 'boolean', defaultValue: false, description: 'invert x and y axes', }, // string type, option widget with `optionValues` 'graphType': { widget: 'option', valueType: 'string', defaultValue: 'line', description: 'graph type', optionValues: [ 'line', 'smoothedLine', 'step', ], }, // HTML in `description` 'dateFormat': { valueType: 'string', defaultValue: '', description: 'format of date (doc) (e.g YYYY-MM-DD)', }, // JSON type, textarea widget 'yAxisGuides': { widget: 'textarea', valueType: 'JSON', defaultValue: '', description: 'guides of yAxis ', }, ```
### Spec: `transform` | Field Name | Available Values (type) | Description | | --- | --- | --- | |`method` | `object` | designed for rows requiring object manipulation | |`method` | `array` | designed for rows requiring array manipulation | |`method` | `array:2-key` | designed for xyz charts (e.g bubble chart) | |`method` | `drill-down` | designed for drill-down charts | |`method` | `raw` | will return the original `tableData.rows` |
Whatever you specified as `transform.method`, the `transformer` value will be always function for lazy computation. ```js // advanced-transformation.util#getTransformer if (transformSpec.method === 'raw') { transformer = () => { return rows; } } else if (transformSpec.method === 'array') { transformer = () => { ... return { ... } } } ``` Here is actual usage. ```js class AwesomeVisualization extends Visualization { constructor(...) { /** setup your spec */ } ... // `render` will be called whenever `axis` or `parameter` are changed render(data) { const { chart, parameter, column, transformer, } = data if (chart === 'line') { const transformed = transformer() // draw line chart } else if (chart === 'no-group') { const transformed = transformer() // draw no-group chart } } ... } ```