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 blankCount;
|
||||||
public int errorCount;
|
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) {
|
public ExpressionNumericRowBinner(Evaluable evaluable, String columnName, int cellIndex, NumericBinIndex index) {
|
||||||
_evaluable = evaluable;
|
_evaluable = evaluable;
|
||||||
_columnName = columnName;
|
_columnName = columnName;
|
||||||
@ -47,45 +55,70 @@ public class ExpressionNumericRowBinner implements RowVisitor {
|
|||||||
ExpressionUtils.bind(bindings, row, rowIndex, _columnName, cell);
|
ExpressionUtils.bind(bindings, row, rowIndex, _columnName, cell);
|
||||||
|
|
||||||
Object value = _evaluable.evaluate(bindings);
|
Object value = _evaluable.evaluate(bindings);
|
||||||
|
|
||||||
|
rowHasError = false;
|
||||||
|
rowHasBlank = false;
|
||||||
|
rowHasNumeric = false;
|
||||||
|
rowHasNonNumeric = false;
|
||||||
|
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
if (value.getClass().isArray()) {
|
if (value.getClass().isArray()) {
|
||||||
Object[] a = (Object[]) value;
|
Object[] a = (Object[]) value;
|
||||||
for (Object v : a) {
|
for (Object v : a) {
|
||||||
processValue(v);
|
processValue(v);
|
||||||
}
|
}
|
||||||
|
updateCounts();
|
||||||
return false;
|
return false;
|
||||||
} else if (value instanceof Collection<?>) {
|
} else if (value instanceof Collection<?>) {
|
||||||
for (Object v : ExpressionUtils.toObjectCollection(value)) {
|
for (Object v : ExpressionUtils.toObjectCollection(value)) {
|
||||||
processValue(v);
|
processValue(v);
|
||||||
}
|
}
|
||||||
|
updateCounts();
|
||||||
return false;
|
return false;
|
||||||
} // else, fall through
|
} // else, fall through
|
||||||
}
|
}
|
||||||
|
|
||||||
processValue(value);
|
processValue(value);
|
||||||
|
updateCounts();
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void updateCounts() {
|
||||||
|
if (rowHasError) {
|
||||||
|
errorCount++;
|
||||||
|
}
|
||||||
|
if (rowHasBlank) {
|
||||||
|
blankCount++;
|
||||||
|
}
|
||||||
|
if (rowHasNumeric) {
|
||||||
|
numericCount++;
|
||||||
|
}
|
||||||
|
if (rowHasNonNumeric) {
|
||||||
|
nonNumericCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected void processValue(Object value) {
|
protected void processValue(Object value) {
|
||||||
if (ExpressionUtils.isError(value)) {
|
if (ExpressionUtils.isError(value)) {
|
||||||
errorCount++;
|
rowHasError = true;
|
||||||
} else if (ExpressionUtils.isNonBlankData(value)) {
|
} else if (ExpressionUtils.isNonBlankData(value)) {
|
||||||
if (value instanceof Number) {
|
if (value instanceof Number) {
|
||||||
double d = ((Number) value).doubleValue();
|
double d = ((Number) value).doubleValue();
|
||||||
if (!Double.isInfinite(d) && !Double.isNaN(d)) {
|
if (!Double.isInfinite(d) && !Double.isNaN(d)) {
|
||||||
numericCount++;
|
rowHasNumeric = true;
|
||||||
|
|
||||||
int bin = (int) Math.floor((d - _index.getMin()) / _index.getStep());
|
int bin = (int) Math.floor((d - _index.getMin()) / _index.getStep());
|
||||||
|
|
||||||
bins[bin]++;
|
bins[bin]++;
|
||||||
} else {
|
} else {
|
||||||
errorCount++;
|
rowHasError = true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
nonNumericCount++;
|
rowHasNonNumeric = true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
blankCount++;
|
rowHasBlank = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,13 +23,18 @@ import com.metaweb.gridworks.model.Row;
|
|||||||
*/
|
*/
|
||||||
public class NumericBinIndex {
|
public class NumericBinIndex {
|
||||||
|
|
||||||
private int _total_count;
|
private int _totalValueCount;
|
||||||
private int _number_count;
|
private int _numbericValueCount;
|
||||||
private double _min;
|
private double _min;
|
||||||
private double _max;
|
private double _max;
|
||||||
private double _step;
|
private double _step;
|
||||||
private int[] _bins;
|
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) {
|
public NumericBinIndex(Project project, String columnName, int cellIndex, Evaluable eval) {
|
||||||
Properties bindings = ExpressionUtils.createBindings(project);
|
Properties bindings = ExpressionUtils.createBindings(project);
|
||||||
|
|
||||||
@ -44,32 +49,79 @@ public class NumericBinIndex {
|
|||||||
ExpressionUtils.bind(bindings, row, i, columnName, cell);
|
ExpressionUtils.bind(bindings, row, i, columnName, cell);
|
||||||
|
|
||||||
Object value = eval.evaluate(bindings);
|
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()) {
|
if (value.getClass().isArray()) {
|
||||||
Object[] a = (Object[]) value;
|
Object[] a = (Object[]) value;
|
||||||
for (Object v : a) {
|
for (Object v : a) {
|
||||||
_total_count++;
|
_totalValueCount++;
|
||||||
if (v instanceof Number) {
|
|
||||||
processValue(((Number) v).doubleValue(), allValues);
|
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<?>) {
|
} else if (value instanceof Collection<?>) {
|
||||||
for (Object v : ExpressionUtils.toObjectCollection(value)) {
|
for (Object v : ExpressionUtils.toObjectCollection(value)) {
|
||||||
_total_count++;
|
_totalValueCount++;
|
||||||
if (v instanceof Number) {
|
|
||||||
processValue(((Number) v).doubleValue(), allValues);
|
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 {
|
} else {
|
||||||
_total_count++;
|
_totalValueCount++;
|
||||||
|
|
||||||
if (value instanceof Number) {
|
if (value instanceof Number) {
|
||||||
|
rowHasNumeric = true;
|
||||||
processValue(((Number) value).doubleValue(), allValues);
|
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) {
|
if (_min >= _max) {
|
||||||
_step = 1;
|
_step = 1;
|
||||||
@ -116,11 +168,7 @@ public class NumericBinIndex {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean isNumeric() {
|
public boolean isNumeric() {
|
||||||
return _number_count > _total_count / 2;
|
return _numbericValueCount > _totalValueCount / 2;
|
||||||
}
|
|
||||||
|
|
||||||
public int getNumberCount() {
|
|
||||||
return _number_count;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public double getMin() {
|
public double getMin() {
|
||||||
@ -138,6 +186,22 @@ public class NumericBinIndex {
|
|||||||
public int[] getBins() {
|
public int[] getBins() {
|
||||||
return _bins;
|
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) {
|
protected void processValue(double v, List<Double> allValues) {
|
||||||
if (!Double.isInfinite(v) && !Double.isNaN(v)) {
|
if (!Double.isInfinite(v) && !Double.isNaN(v)) {
|
||||||
@ -146,4 +210,5 @@ public class NumericBinIndex {
|
|||||||
allValues.add(v);
|
allValues.add(v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -51,6 +51,11 @@ public class RangeFacet implements Facet {
|
|||||||
protected int[] _baseBins;
|
protected int[] _baseBins;
|
||||||
protected int[] _bins;
|
protected int[] _bins;
|
||||||
|
|
||||||
|
protected int _baseNumericCount;
|
||||||
|
protected int _baseNonNumericCount;
|
||||||
|
protected int _baseBlankCount;
|
||||||
|
protected int _baseErrorCount;
|
||||||
|
|
||||||
protected int _numericCount;
|
protected int _numericCount;
|
||||||
protected int _nonNumericCount;
|
protected int _nonNumericCount;
|
||||||
protected int _blankCount;
|
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("numericCount"); writer.value(_numericCount);
|
||||||
writer.key("nonNumericCount"); writer.value(_nonNumericCount);
|
writer.key("nonNumericCount"); writer.value(_nonNumericCount);
|
||||||
writer.key("blankCount"); writer.value(_blankCount);
|
writer.key("blankCount"); writer.value(_blankCount);
|
||||||
@ -210,6 +220,11 @@ public class RangeFacet implements Facet {
|
|||||||
_step = index.getStep();
|
_step = index.getStep();
|
||||||
_baseBins = index.getBins();
|
_baseBins = index.getBins();
|
||||||
|
|
||||||
|
_baseNumericCount = index.getNumericRowCount();
|
||||||
|
_baseNonNumericCount = index.getNonNumericRowCount();
|
||||||
|
_baseBlankCount = index.getBlankRowCount();
|
||||||
|
_baseErrorCount = index.getErrorRowCount();
|
||||||
|
|
||||||
if (_selected) {
|
if (_selected) {
|
||||||
_from = Math.max(_from, _min);
|
_from = Math.max(_from, _min);
|
||||||
_to = Math.min(_to, _max);
|
_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._selectBlank = ("selectBlank" in this._config) ? this._config.selectBlank : true;
|
||||||
this._selectError = ("selectError" in this._config) ? this._config.selectError : 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._numericCount = 0;
|
||||||
this._nonNumericCount = 0;
|
this._nonNumericCount = 0;
|
||||||
this._blankCount = 0;
|
this._blankCount = 0;
|
||||||
@ -177,6 +182,10 @@ RangeFacet.prototype._renderOtherChoices = function() {
|
|||||||
var self = this;
|
var self = this;
|
||||||
var container = this._otherChoicesDiv.empty();
|
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 table = $('<table>').attr("cellpadding", "0").attr("cellspacing", "1").css("white-space", "pre").appendTo(container)[0];
|
||||||
var tr0 = table.insertRow(0);
|
var tr0 = table.insertRow(0);
|
||||||
var tr1 = table.insertRow(1);
|
var tr1 = table.insertRow(1);
|
||||||
@ -185,6 +194,8 @@ RangeFacet.prototype._renderOtherChoices = function() {
|
|||||||
* Numeric
|
* Numeric
|
||||||
*/
|
*/
|
||||||
var td00 = $(tr0.insertCell(0)).attr("width", "1%");
|
var td00 = $(tr0.insertCell(0)).attr("width", "1%");
|
||||||
|
var td01 = $(tr0.insertCell(1));
|
||||||
|
|
||||||
var numericCheck = $('<input type="checkbox" />').appendTo(td00).change(function() {
|
var numericCheck = $('<input type="checkbox" />').appendTo(td00).change(function() {
|
||||||
self._selectNumeric = !self._selectNumeric;
|
self._selectNumeric = !self._selectNumeric;
|
||||||
self._updateRest();
|
self._updateRest();
|
||||||
@ -193,7 +204,6 @@ RangeFacet.prototype._renderOtherChoices = function() {
|
|||||||
numericCheck[0].checked = true;
|
numericCheck[0].checked = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
var td01 = $(tr0.insertCell(1));
|
|
||||||
$('<span>').text("Numeric ").addClass("facet-choice-label").appendTo(td01);
|
$('<span>').text("Numeric ").addClass("facet-choice-label").appendTo(td01);
|
||||||
$('<span>').text(this._numericCount).addClass("facet-choice-count").appendTo(td01);
|
$('<span>').text(this._numericCount).addClass("facet-choice-count").appendTo(td01);
|
||||||
|
|
||||||
@ -201,50 +211,64 @@ RangeFacet.prototype._renderOtherChoices = function() {
|
|||||||
* Blank
|
* Blank
|
||||||
*/
|
*/
|
||||||
var td02 = $(tr0.insertCell(2)).attr("width", "1%");
|
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));
|
var td03 = $(tr0.insertCell(3));
|
||||||
$('<span>').text("Blank ").addClass("facet-choice-label").appendTo(td03);
|
if (this._baseBlankCount === 0) {
|
||||||
$('<span>').text(this._blankCount).addClass("facet-choice-count").appendTo(td03);
|
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
|
* Non-Numeric
|
||||||
*/
|
*/
|
||||||
var td10 = $(tr1.insertCell(0)).attr("width", "1%");
|
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));
|
var td11 = $(tr1.insertCell(1));
|
||||||
$('<span>').text("Non-numeric ").addClass("facet-choice-label").appendTo(td11);
|
if (this._baseNonNumericCount === 0) {
|
||||||
$('<span>').text(this._nonNumericCount).addClass("facet-choice-count").appendTo(td11);
|
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
|
* Error
|
||||||
*/
|
*/
|
||||||
var td12 = $(tr1.insertCell(2)).attr("width", "1%");
|
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));
|
var td13 = $(tr1.insertCell(3));
|
||||||
$('<span>').text("Error ").addClass("facet-choice-label").appendTo(td13);
|
if (this._baseErrorCount === 0) {
|
||||||
$('<span>').text(this._errorCount).addClass("facet-choice-count").appendTo(td13);
|
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() {
|
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._numericCount = data.numericCount;
|
||||||
this._nonNumericCount = data.nonNumericCount;
|
this._nonNumericCount = data.nonNumericCount;
|
||||||
this._blankCount = data.blankCount;
|
this._blankCount = data.blankCount;
|
||||||
|
Loading…
Reference in New Issue
Block a user