mirror of
https://github.com/apache/zeppelin
synced 2026-05-24 09:38:26 +00:00
convert scatter chart
This commit is contained in:
parent
819c262392
commit
4e84467d4d
4 changed files with 311 additions and 37 deletions
|
|
@ -21,9 +21,4 @@ limitations under the License.
|
|||
id="p{{paragraph.id}}_{{viz.id}}"
|
||||
ng-show="getGraphMode()==viz.id">
|
||||
</div>
|
||||
|
||||
<div ng-if="getGraphMode()=='scatterChart'"
|
||||
id="p{{paragraph.id}}_scatterChart">
|
||||
<svg></svg>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -131,6 +131,11 @@
|
|||
name: 'Line Chart',
|
||||
icon: 'fa fa-line-chart',
|
||||
transformation: 'pivot'
|
||||
},
|
||||
{
|
||||
id: 'scatterChart',
|
||||
name: 'Scatter Chart',
|
||||
icon: 'cf cf-scatter-chart'
|
||||
}
|
||||
];
|
||||
|
||||
|
|
@ -157,6 +162,10 @@
|
|||
'lineChart': {
|
||||
class: zeppelin.LinechartVisualization,
|
||||
instance: undefined
|
||||
},
|
||||
'scatterChart': {
|
||||
class: zeppelin.ScatterchartVisualization,
|
||||
instance: undefined
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -1129,7 +1138,7 @@
|
|||
var xLabels;
|
||||
var yLabels;
|
||||
|
||||
if (type === 'scatterChart') {
|
||||
if (type === 'scatterChartxxx') {
|
||||
var scatterData = setScatterChart(data, refresh);
|
||||
|
||||
xLabels = scatterData.xLabels;
|
||||
|
|
@ -1861,39 +1870,13 @@
|
|||
}
|
||||
};
|
||||
|
||||
$scope.isValidSizeOption = function(options, rows) {
|
||||
var xValues = [];
|
||||
var yValues = [];
|
||||
|
||||
for (var i = 0; i < rows.length; i++) {
|
||||
var row = rows[i];
|
||||
var size = row[options.size.index];
|
||||
|
||||
//check if the field is numeric
|
||||
if (isNaN(parseFloat(size)) || !isFinite(size)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (options.xAxis) {
|
||||
var x = row[options.xAxis.index];
|
||||
xValues[i] = x;
|
||||
}
|
||||
if (options.yAxis) {
|
||||
var y = row[options.yAxis.index];
|
||||
yValues[i] = y;
|
||||
}
|
||||
}
|
||||
|
||||
//check if all existing fields are discrete
|
||||
var isAllDiscrete = ((options.xAxis && options.yAxis && isDiscrete(xValues) && isDiscrete(yValues)) ||
|
||||
(!options.xAxis && isDiscrete(yValues)) ||
|
||||
(!options.yAxis && isDiscrete(xValues)));
|
||||
|
||||
if (isAllDiscrete) {
|
||||
$scope.isValidSizeOption = function(options) {
|
||||
var builtInViz = builtInVisualizations.scatterChart;
|
||||
if (builtInViz && builtInViz.instance) {
|
||||
return builtInViz.instance.isValidSizeOption(options);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
$scope.resizeParagraph = function(width, height) {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,295 @@
|
|||
/*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Visualize data in scatter char
|
||||
*/
|
||||
zeppelin.ScatterchartVisualization = function(targetEl, config) {
|
||||
zeppelin.Nvd3ChartVisualization.call(this, targetEl, config);
|
||||
};
|
||||
|
||||
zeppelin.ScatterchartVisualization.prototype = Object.create(zeppelin.Nvd3ChartVisualization.prototype);
|
||||
|
||||
zeppelin.ScatterchartVisualization.prototype.type = function() {
|
||||
return 'scatterChart';
|
||||
};
|
||||
|
||||
zeppelin.ScatterchartVisualization.prototype.getTransformation = function() {
|
||||
return this.pivot;
|
||||
};
|
||||
|
||||
zeppelin.ScatterchartVisualization.prototype.render = function(tableData) {
|
||||
this.tableData = tableData;
|
||||
var d3Data = this.setScatterChart(tableData, true);
|
||||
this.xLabels = d3Data.xLabels;
|
||||
this.yLabels = d3Data.yLabels;
|
||||
|
||||
zeppelin.Nvd3ChartVisualization.prototype.render.call(this, d3Data);
|
||||
};
|
||||
|
||||
zeppelin.ScatterchartVisualization.prototype.configureChart = function(chart) {
|
||||
var self = this;
|
||||
|
||||
chart.xAxis.tickFormat(function(d) {return self.xAxisTickFormat(d, self.xLabels);});
|
||||
chart.yAxis.tickFormat(function(d) {return self.yAxisTickFormat(d, self.yLabels);});
|
||||
|
||||
// configure how the tooltip looks.
|
||||
chart.tooltipContent(function(key, x, y, graph, data) {
|
||||
var tooltipContent = '<h3>' + key + '</h3>';
|
||||
if (self.config.scatter.size &&
|
||||
self.isValidSizeOption(self.config.scatter, self.tableData.rows)) {
|
||||
tooltipContent += '<p>' + data.point.size + '</p>';
|
||||
}
|
||||
|
||||
return tooltipContent;
|
||||
});
|
||||
|
||||
chart.showDistX(true).showDistY(true);
|
||||
//handle the problem of tooltip not showing when muliple points have same value.
|
||||
};
|
||||
|
||||
zeppelin.ScatterchartVisualization.prototype.setScatterChart = function(data, refresh) {
|
||||
var xAxis = this.config.scatter.xAxis;
|
||||
var yAxis = this.config.scatter.yAxis;
|
||||
var group = this.config.scatter.group;
|
||||
var size = this.config.scatter.size;
|
||||
|
||||
var xValues = [];
|
||||
var yValues = [];
|
||||
var rows = {};
|
||||
var d3g = [];
|
||||
|
||||
var rowNameIndex = {};
|
||||
var colNameIndex = {};
|
||||
var grpNameIndex = {};
|
||||
var rowIndexValue = {};
|
||||
var colIndexValue = {};
|
||||
var grpIndexValue = {};
|
||||
var rowIdx = 0;
|
||||
var colIdx = 0;
|
||||
var grpIdx = 0;
|
||||
var grpName = '';
|
||||
|
||||
var xValue;
|
||||
var yValue;
|
||||
var row;
|
||||
|
||||
if (!xAxis && !yAxis) {
|
||||
return {
|
||||
d3g: []
|
||||
};
|
||||
}
|
||||
|
||||
for (var i = 0; i < data.rows.length; i++) {
|
||||
row = data.rows[i];
|
||||
if (xAxis) {
|
||||
xValue = row[xAxis.index];
|
||||
xValues[i] = xValue;
|
||||
}
|
||||
if (yAxis) {
|
||||
yValue = row[yAxis.index];
|
||||
yValues[i] = yValue;
|
||||
}
|
||||
}
|
||||
|
||||
var isAllDiscrete = ((xAxis && yAxis && this.isDiscrete(xValues) && this.isDiscrete(yValues)) ||
|
||||
(!xAxis && this.isDiscrete(yValues)) ||
|
||||
(!yAxis && this.isDiscrete(xValues)));
|
||||
|
||||
if (isAllDiscrete) {
|
||||
rows = this.setDiscreteScatterData(data);
|
||||
} else {
|
||||
rows = data.rows;
|
||||
}
|
||||
|
||||
if (!group && isAllDiscrete) {
|
||||
grpName = 'count';
|
||||
} else if (!group && !size) {
|
||||
if (xAxis && yAxis) {
|
||||
grpName = '(' + xAxis.name + ', ' + yAxis.name + ')';
|
||||
} else if (xAxis && !yAxis) {
|
||||
grpName = xAxis.name;
|
||||
} else if (!xAxis && yAxis) {
|
||||
grpName = yAxis.name;
|
||||
}
|
||||
} else if (!group && size) {
|
||||
grpName = size.name;
|
||||
}
|
||||
|
||||
for (i = 0; i < rows.length; i++) {
|
||||
row = rows[i];
|
||||
if (xAxis) {
|
||||
xValue = row[xAxis.index];
|
||||
}
|
||||
if (yAxis) {
|
||||
yValue = row[yAxis.index];
|
||||
}
|
||||
if (group) {
|
||||
grpName = row[group.index];
|
||||
}
|
||||
var sz = (isAllDiscrete) ? row[row.length - 1] : ((size) ? row[size.index] : 1);
|
||||
|
||||
if (grpNameIndex[grpName] === undefined) {
|
||||
grpIndexValue[grpIdx] = grpName;
|
||||
grpNameIndex[grpName] = grpIdx++;
|
||||
}
|
||||
|
||||
if (xAxis && rowNameIndex[xValue] === undefined) {
|
||||
rowIndexValue[rowIdx] = xValue;
|
||||
rowNameIndex[xValue] = rowIdx++;
|
||||
}
|
||||
|
||||
if (yAxis && colNameIndex[yValue] === undefined) {
|
||||
colIndexValue[colIdx] = yValue;
|
||||
colNameIndex[yValue] = colIdx++;
|
||||
}
|
||||
|
||||
if (!d3g[grpNameIndex[grpName]]) {
|
||||
d3g[grpNameIndex[grpName]] = {
|
||||
key: grpName,
|
||||
values: []
|
||||
};
|
||||
}
|
||||
|
||||
d3g[grpNameIndex[grpName]].values.push({
|
||||
x: xAxis ? (isNaN(xValue) ? rowNameIndex[xValue] : parseFloat(xValue)) : 0,
|
||||
y: yAxis ? (isNaN(yValue) ? colNameIndex[yValue] : parseFloat(yValue)) : 0,
|
||||
size: isNaN(parseFloat(sz)) ? 1 : parseFloat(sz)
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
xLabels: rowIndexValue,
|
||||
yLabels: colIndexValue,
|
||||
d3g: d3g
|
||||
};
|
||||
};
|
||||
zeppelin.ScatterchartVisualization.prototype.setDiscreteScatterData = function(data) {
|
||||
var xAxis = this.config.scatter.xAxis;
|
||||
var yAxis = this.config.scatter.yAxis;
|
||||
var group = this.config.scatter.group;
|
||||
|
||||
var xValue;
|
||||
var yValue;
|
||||
var grp;
|
||||
|
||||
var rows = {};
|
||||
|
||||
for (var i = 0; i < data.rows.length; i++) {
|
||||
var row = data.rows[i];
|
||||
if (xAxis) {
|
||||
xValue = row[xAxis.index];
|
||||
}
|
||||
if (yAxis) {
|
||||
yValue = row[yAxis.index];
|
||||
}
|
||||
if (group) {
|
||||
grp = row[group.index];
|
||||
}
|
||||
|
||||
var key = xValue + ',' + yValue + ',' + grp;
|
||||
|
||||
if (!rows[key]) {
|
||||
rows[key] = {
|
||||
x: xValue,
|
||||
y: yValue,
|
||||
group: grp,
|
||||
size: 1
|
||||
};
|
||||
} else {
|
||||
rows[key].size++;
|
||||
}
|
||||
}
|
||||
|
||||
// change object into array
|
||||
var newRows = [];
|
||||
for (var r in rows) {
|
||||
var newRow = [];
|
||||
if (xAxis) { newRow[xAxis.index] = rows[r].x; }
|
||||
if (yAxis) { newRow[yAxis.index] = rows[r].y; }
|
||||
if (group) { newRow[group.index] = rows[r].group; }
|
||||
newRow[data.rows[0].length] = rows[r].size;
|
||||
newRows.push(newRow);
|
||||
}
|
||||
return newRows;
|
||||
};
|
||||
|
||||
zeppelin.ScatterchartVisualization.prototype.isDiscrete = function(field) {
|
||||
var getUnique = function(f) {
|
||||
var uniqObj = {};
|
||||
var uniqArr = [];
|
||||
var j = 0;
|
||||
for (var i = 0; i < f.length; i++) {
|
||||
var item = f[i];
|
||||
if (uniqObj[item] !== 1) {
|
||||
uniqObj[item] = 1;
|
||||
uniqArr[j++] = item;
|
||||
}
|
||||
}
|
||||
return uniqArr;
|
||||
};
|
||||
|
||||
for (var i = 0; i < field.length; i++) {
|
||||
if (isNaN(parseFloat(field[i])) &&
|
||||
(typeof field[i] === 'string' || field[i] instanceof String)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
var threshold = 0.05;
|
||||
var unique = getUnique(field);
|
||||
if (unique.length / field.length < threshold) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
zeppelin.ScatterchartVisualization.prototype.isValidSizeOption = function(options) {
|
||||
var xValues = [];
|
||||
var yValues = [];
|
||||
var rows = this.tableData.rows;
|
||||
|
||||
for (var i = 0; i < rows.length; i++) {
|
||||
var row = rows[i];
|
||||
var size = row[options.size.index];
|
||||
|
||||
//check if the field is numeric
|
||||
if (isNaN(parseFloat(size)) || !isFinite(size)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (options.xAxis) {
|
||||
var x = row[options.xAxis.index];
|
||||
xValues[i] = x;
|
||||
}
|
||||
if (options.yAxis) {
|
||||
var y = row[options.yAxis.index];
|
||||
yValues[i] = y;
|
||||
}
|
||||
}
|
||||
|
||||
//check if all existing fields are discrete
|
||||
var isAllDiscrete = ((options.xAxis && options.yAxis && this.isDiscrete(xValues) && this.isDiscrete(yValues)) ||
|
||||
(!options.xAxis && this.isDiscrete(yValues)) ||
|
||||
(!options.yAxis && this.isDiscrete(xValues)));
|
||||
|
||||
if (isAllDiscrete) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
|
@ -163,6 +163,7 @@ limitations under the License.
|
|||
<script src="app/visualization/builtins/visualization-piechart.js"></script>
|
||||
<script src="app/visualization/builtins/visualization-areachart.js"></script>
|
||||
<script src="app/visualization/builtins/visualization-linechart.js"></script>
|
||||
<script src="app/visualization/builtins/visualization-scatterchart.js"></script>
|
||||
<script src="app/notebook/notebook.controller.js"></script>
|
||||
<script src="app/jobmanager/jobmanager.controller.js"></script>
|
||||
<script src="app/jobmanager/jobs/job.controller.js"></script>
|
||||
|
|
|
|||
Loading…
Reference in a new issue