In numeric range facets, show the other choices only if they have positive counts in the base distribution.
git-svn-id: http://google-refine.googlecode.com/svn/trunk@445 7d457c2a-affb-35e4-300a-418c747d4874
This commit is contained in:
parent
5928a689e2
commit
75ea8304a3
@ -32,6 +32,14 @@ public class ExpressionNumericRowBinner implements RowVisitor {
|
||||
public int blankCount;
|
||||
public int errorCount;
|
||||
|
||||
/*
|
||||
* Scratchpad variables
|
||||
*/
|
||||
private boolean rowHasError;
|
||||
private boolean rowHasBlank;
|
||||
private boolean rowHasNumeric;
|
||||
private boolean rowHasNonNumeric;
|
||||
|
||||
public ExpressionNumericRowBinner(Evaluable evaluable, String columnName, int cellIndex, NumericBinIndex index) {
|
||||
_evaluable = evaluable;
|
||||
_columnName = columnName;
|
||||
@ -47,45 +55,70 @@ public class ExpressionNumericRowBinner implements RowVisitor {
|
||||
ExpressionUtils.bind(bindings, row, rowIndex, _columnName, cell);
|
||||
|
||||
Object value = _evaluable.evaluate(bindings);
|
||||
|
||||
rowHasError = false;
|
||||
rowHasBlank = false;
|
||||
rowHasNumeric = false;
|
||||
rowHasNonNumeric = false;
|
||||
|
||||
if (value != null) {
|
||||
if (value.getClass().isArray()) {
|
||||
Object[] a = (Object[]) value;
|
||||
for (Object v : a) {
|
||||
processValue(v);
|
||||
}
|
||||
updateCounts();
|
||||
return false;
|
||||
} else if (value instanceof Collection<?>) {
|
||||
for (Object v : ExpressionUtils.toObjectCollection(value)) {
|
||||
processValue(v);
|
||||
}
|
||||
updateCounts();
|
||||
return false;
|
||||
} // else, fall through
|
||||
}
|
||||
|
||||
processValue(value);
|
||||
updateCounts();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected void updateCounts() {
|
||||
if (rowHasError) {
|
||||
errorCount++;
|
||||
}
|
||||
if (rowHasBlank) {
|
||||
blankCount++;
|
||||
}
|
||||
if (rowHasNumeric) {
|
||||
numericCount++;
|
||||
}
|
||||
if (rowHasNonNumeric) {
|
||||
nonNumericCount++;
|
||||
}
|
||||
}
|
||||
|
||||
protected void processValue(Object value) {
|
||||
if (ExpressionUtils.isError(value)) {
|
||||
errorCount++;
|
||||
rowHasError = true;
|
||||
} else if (ExpressionUtils.isNonBlankData(value)) {
|
||||
if (value instanceof Number) {
|
||||
double d = ((Number) value).doubleValue();
|
||||
if (!Double.isInfinite(d) && !Double.isNaN(d)) {
|
||||
numericCount++;
|
||||
rowHasNumeric = true;
|
||||
|
||||
int bin = (int) Math.floor((d - _index.getMin()) / _index.getStep());
|
||||
|
||||
bins[bin]++;
|
||||
} else {
|
||||
errorCount++;
|
||||
rowHasError = true;
|
||||
}
|
||||
} else {
|
||||
nonNumericCount++;
|
||||
rowHasNonNumeric = true;
|
||||
}
|
||||
} else {
|
||||
blankCount++;
|
||||
rowHasBlank = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -23,13 +23,18 @@ import com.metaweb.gridworks.model.Row;
|
||||
*/
|
||||
public class NumericBinIndex {
|
||||
|
||||
private int _total_count;
|
||||
private int _number_count;
|
||||
private int _totalValueCount;
|
||||
private int _numbericValueCount;
|
||||
private double _min;
|
||||
private double _max;
|
||||
private double _step;
|
||||
private int[] _bins;
|
||||
|
||||
private int _numericRowCount;
|
||||
private int _nonNumericRowCount;
|
||||
private int _blankRowCount;
|
||||
private int _errorRowCount;
|
||||
|
||||
public NumericBinIndex(Project project, String columnName, int cellIndex, Evaluable eval) {
|
||||
Properties bindings = ExpressionUtils.createBindings(project);
|
||||
|
||||
@ -44,32 +49,79 @@ public class NumericBinIndex {
|
||||
ExpressionUtils.bind(bindings, row, i, columnName, cell);
|
||||
|
||||
Object value = eval.evaluate(bindings);
|
||||
if (value != null) {
|
||||
|
||||
boolean rowHasError = false;
|
||||
boolean rowHasNonNumeric = false;
|
||||
boolean rowHasNumeric = false;
|
||||
boolean rowHasBlank = false;
|
||||
|
||||
if (ExpressionUtils.isError(value)) {
|
||||
rowHasError = true;
|
||||
} else if (ExpressionUtils.isNonBlankData(value)) {
|
||||
if (value.getClass().isArray()) {
|
||||
Object[] a = (Object[]) value;
|
||||
for (Object v : a) {
|
||||
_total_count++;
|
||||
if (v instanceof Number) {
|
||||
processValue(((Number) v).doubleValue(), allValues);
|
||||
_totalValueCount++;
|
||||
|
||||
if (ExpressionUtils.isError(v)) {
|
||||
rowHasError = true;
|
||||
} else if (ExpressionUtils.isNonBlankData(v)) {
|
||||
if (v instanceof Number) {
|
||||
rowHasNumeric = true;
|
||||
processValue(((Number) v).doubleValue(), allValues);
|
||||
} else {
|
||||
rowHasNonNumeric = true;
|
||||
}
|
||||
} else {
|
||||
rowHasBlank = true;
|
||||
}
|
||||
}
|
||||
} else if (value instanceof Collection<?>) {
|
||||
for (Object v : ExpressionUtils.toObjectCollection(value)) {
|
||||
_total_count++;
|
||||
if (v instanceof Number) {
|
||||
processValue(((Number) v).doubleValue(), allValues);
|
||||
_totalValueCount++;
|
||||
|
||||
if (ExpressionUtils.isError(v)) {
|
||||
rowHasError = true;
|
||||
} else if (ExpressionUtils.isNonBlankData(v)) {
|
||||
if (v instanceof Number) {
|
||||
rowHasNumeric = true;
|
||||
processValue(((Number) v).doubleValue(), allValues);
|
||||
} else {
|
||||
rowHasNonNumeric = true;
|
||||
}
|
||||
} else {
|
||||
rowHasBlank = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
_total_count++;
|
||||
_totalValueCount++;
|
||||
|
||||
if (value instanceof Number) {
|
||||
rowHasNumeric = true;
|
||||
processValue(((Number) value).doubleValue(), allValues);
|
||||
} else {
|
||||
rowHasNonNumeric = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
rowHasBlank = true;
|
||||
}
|
||||
|
||||
if (rowHasError) {
|
||||
_errorRowCount++;
|
||||
}
|
||||
if (rowHasBlank) {
|
||||
_blankRowCount++;
|
||||
}
|
||||
if (rowHasNumeric) {
|
||||
_numericRowCount++;
|
||||
}
|
||||
if (rowHasNonNumeric) {
|
||||
_nonNumericRowCount++;
|
||||
}
|
||||
}
|
||||
|
||||
_number_count = allValues.size();
|
||||
_numbericValueCount = allValues.size();
|
||||
|
||||
if (_min >= _max) {
|
||||
_step = 1;
|
||||
@ -116,11 +168,7 @@ public class NumericBinIndex {
|
||||
}
|
||||
|
||||
public boolean isNumeric() {
|
||||
return _number_count > _total_count / 2;
|
||||
}
|
||||
|
||||
public int getNumberCount() {
|
||||
return _number_count;
|
||||
return _numbericValueCount > _totalValueCount / 2;
|
||||
}
|
||||
|
||||
public double getMin() {
|
||||
@ -139,6 +187,22 @@ public class NumericBinIndex {
|
||||
return _bins;
|
||||
}
|
||||
|
||||
public int getNumericRowCount() {
|
||||
return _numericRowCount;
|
||||
}
|
||||
|
||||
public int getNonNumericRowCount() {
|
||||
return _nonNumericRowCount;
|
||||
}
|
||||
|
||||
public int getBlankRowCount() {
|
||||
return _blankRowCount;
|
||||
}
|
||||
|
||||
public int getErrorRowCount() {
|
||||
return _errorRowCount;
|
||||
}
|
||||
|
||||
protected void processValue(double v, List<Double> allValues) {
|
||||
if (!Double.isInfinite(v) && !Double.isNaN(v)) {
|
||||
_min = Math.min(_min, v);
|
||||
@ -146,4 +210,5 @@ public class NumericBinIndex {
|
||||
allValues.add(v);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -51,6 +51,11 @@ public class RangeFacet implements Facet {
|
||||
protected int[] _baseBins;
|
||||
protected int[] _bins;
|
||||
|
||||
protected int _baseNumericCount;
|
||||
protected int _baseNonNumericCount;
|
||||
protected int _baseBlankCount;
|
||||
protected int _baseErrorCount;
|
||||
|
||||
protected int _numericCount;
|
||||
protected int _nonNumericCount;
|
||||
protected int _blankCount;
|
||||
@ -103,6 +108,11 @@ public class RangeFacet implements Facet {
|
||||
}
|
||||
}
|
||||
|
||||
writer.key("baseNumericCount"); writer.value(_baseNumericCount);
|
||||
writer.key("baseNonNumericCount"); writer.value(_baseNonNumericCount);
|
||||
writer.key("baseBlankCount"); writer.value(_baseBlankCount);
|
||||
writer.key("baseErrorCount"); writer.value(_baseErrorCount);
|
||||
|
||||
writer.key("numericCount"); writer.value(_numericCount);
|
||||
writer.key("nonNumericCount"); writer.value(_nonNumericCount);
|
||||
writer.key("blankCount"); writer.value(_blankCount);
|
||||
@ -210,6 +220,11 @@ public class RangeFacet implements Facet {
|
||||
_step = index.getStep();
|
||||
_baseBins = index.getBins();
|
||||
|
||||
_baseNumericCount = index.getNumericRowCount();
|
||||
_baseNonNumericCount = index.getNonNumericRowCount();
|
||||
_baseBlankCount = index.getBlankRowCount();
|
||||
_baseErrorCount = index.getErrorRowCount();
|
||||
|
||||
if (_selected) {
|
||||
_from = Math.max(_from, _min);
|
||||
_to = Math.min(_to, _max);
|
||||
|
@ -11,6 +11,11 @@ function RangeFacet(div, config, options) {
|
||||
this._selectBlank = ("selectBlank" in this._config) ? this._config.selectBlank : true;
|
||||
this._selectError = ("selectError" in this._config) ? this._config.selectError : true;
|
||||
|
||||
this._baseNumericCount = 0;
|
||||
this._baseNonNumericCount = 0;
|
||||
this._baseBlankCount = 0;
|
||||
this._baseErrorCount = 0;
|
||||
|
||||
this._numericCount = 0;
|
||||
this._nonNumericCount = 0;
|
||||
this._blankCount = 0;
|
||||
@ -177,6 +182,10 @@ RangeFacet.prototype._renderOtherChoices = function() {
|
||||
var self = this;
|
||||
var container = this._otherChoicesDiv.empty();
|
||||
|
||||
if (this._baseNonNumericCount === 0 && this._baseBlankCount === 0 && this._baseErrorCount === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
var table = $('<table>').attr("cellpadding", "0").attr("cellspacing", "1").css("white-space", "pre").appendTo(container)[0];
|
||||
var tr0 = table.insertRow(0);
|
||||
var tr1 = table.insertRow(1);
|
||||
@ -185,6 +194,8 @@ RangeFacet.prototype._renderOtherChoices = function() {
|
||||
* Numeric
|
||||
*/
|
||||
var td00 = $(tr0.insertCell(0)).attr("width", "1%");
|
||||
var td01 = $(tr0.insertCell(1));
|
||||
|
||||
var numericCheck = $('<input type="checkbox" />').appendTo(td00).change(function() {
|
||||
self._selectNumeric = !self._selectNumeric;
|
||||
self._updateRest();
|
||||
@ -193,7 +204,6 @@ RangeFacet.prototype._renderOtherChoices = function() {
|
||||
numericCheck[0].checked = true;
|
||||
}
|
||||
|
||||
var td01 = $(tr0.insertCell(1));
|
||||
$('<span>').text("Numeric ").addClass("facet-choice-label").appendTo(td01);
|
||||
$('<span>').text(this._numericCount).addClass("facet-choice-count").appendTo(td01);
|
||||
|
||||
@ -201,50 +211,64 @@ RangeFacet.prototype._renderOtherChoices = function() {
|
||||
* Blank
|
||||
*/
|
||||
var td02 = $(tr0.insertCell(2)).attr("width", "1%");
|
||||
var blankCheck = $('<input type="checkbox" />').appendTo(td02).change(function() {
|
||||
self._selectBlank = !self._selectBlank;
|
||||
self._updateRest();
|
||||
});
|
||||
if (this._selectBlank) {
|
||||
blankCheck[0].checked = true;
|
||||
}
|
||||
|
||||
var td03 = $(tr0.insertCell(3));
|
||||
$('<span>').text("Blank ").addClass("facet-choice-label").appendTo(td03);
|
||||
$('<span>').text(this._blankCount).addClass("facet-choice-count").appendTo(td03);
|
||||
if (this._baseBlankCount === 0) {
|
||||
td02.hide();
|
||||
td03.hide();
|
||||
} else {
|
||||
var blankCheck = $('<input type="checkbox" />').appendTo(td02).change(function() {
|
||||
self._selectBlank = !self._selectBlank;
|
||||
self._updateRest();
|
||||
});
|
||||
if (this._selectBlank) {
|
||||
blankCheck[0].checked = true;
|
||||
}
|
||||
|
||||
$('<span>').text("Blank ").addClass("facet-choice-label").appendTo(td03);
|
||||
$('<span>').text(this._blankCount).addClass("facet-choice-count").appendTo(td03);
|
||||
}
|
||||
|
||||
/*
|
||||
* Non-Numeric
|
||||
*/
|
||||
var td10 = $(tr1.insertCell(0)).attr("width", "1%");
|
||||
var nonNumericCheck = $('<input type="checkbox" />').appendTo(td10).change(function() {
|
||||
self._selectNonNumeric = !self._selectNonNumeric;
|
||||
self._updateRest();
|
||||
});
|
||||
if (this._selectNonNumeric) {
|
||||
nonNumericCheck[0].checked = true;
|
||||
}
|
||||
|
||||
var td11 = $(tr1.insertCell(1));
|
||||
$('<span>').text("Non-numeric ").addClass("facet-choice-label").appendTo(td11);
|
||||
$('<span>').text(this._nonNumericCount).addClass("facet-choice-count").appendTo(td11);
|
||||
if (this._baseNonNumericCount === 0) {
|
||||
td10.hide();
|
||||
td11.hide();
|
||||
} else {
|
||||
var nonNumericCheck = $('<input type="checkbox" />').appendTo(td10).change(function() {
|
||||
self._selectNonNumeric = !self._selectNonNumeric;
|
||||
self._updateRest();
|
||||
});
|
||||
if (this._selectNonNumeric) {
|
||||
nonNumericCheck[0].checked = true;
|
||||
}
|
||||
|
||||
$('<span>').text("Non-numeric ").addClass("facet-choice-label").appendTo(td11);
|
||||
$('<span>').text(this._nonNumericCount).addClass("facet-choice-count").appendTo(td11);
|
||||
}
|
||||
|
||||
/*
|
||||
* Error
|
||||
*/
|
||||
var td12 = $(tr1.insertCell(2)).attr("width", "1%");
|
||||
var errorCheck = $('<input type="checkbox" />').appendTo(td12).change(function() {
|
||||
self._selectError = !self._selectError;
|
||||
self._updateRest();
|
||||
});
|
||||
if (this._selectError) {
|
||||
errorCheck[0].checked = true;
|
||||
}
|
||||
|
||||
var td13 = $(tr1.insertCell(3));
|
||||
$('<span>').text("Error ").addClass("facet-choice-label").appendTo(td13);
|
||||
$('<span>').text(this._errorCount).addClass("facet-choice-count").appendTo(td13);
|
||||
if (this._baseErrorCount === 0) {
|
||||
td12.hide();
|
||||
td13.hide();
|
||||
} else {
|
||||
var errorCheck = $('<input type="checkbox" />').appendTo(td12).change(function() {
|
||||
self._selectError = !self._selectError;
|
||||
self._updateRest();
|
||||
});
|
||||
if (this._selectError) {
|
||||
errorCheck[0].checked = true;
|
||||
}
|
||||
|
||||
$('<span>').text("Error ").addClass("facet-choice-label").appendTo(td13);
|
||||
$('<span>').text(this._errorCount).addClass("facet-choice-count").appendTo(td13);
|
||||
}
|
||||
};
|
||||
|
||||
RangeFacet.prototype._setRangeIndicators = function() {
|
||||
@ -290,6 +314,11 @@ RangeFacet.prototype.updateState = function(data) {
|
||||
}
|
||||
}
|
||||
|
||||
this._baseNumericCount = data.baseNumericCount;
|
||||
this._baseNonNumericCount = data.baseNonNumericCount;
|
||||
this._baseBlankCount = data.baseBlankCount;
|
||||
this._baseErrorCount = data.baseErrorCount;
|
||||
|
||||
this._numericCount = data.numericCount;
|
||||
this._nonNumericCount = data.nonNumericCount;
|
||||
this._blankCount = data.blankCount;
|
||||
|
Loading…
Reference in New Issue
Block a user