|
|
@@ -29,6 +29,9 @@ import org.apache.poi.ss.formula.eval.RefEval; |
|
|
|
import org.apache.poi.ss.formula.eval.StringValueEval; |
|
|
|
import org.apache.poi.ss.formula.eval.ValueEval; |
|
|
|
|
|
|
|
import java.util.Arrays; |
|
|
|
import java.util.List; |
|
|
|
|
|
|
|
/** |
|
|
|
* Implementation for Excel CORREL() function. |
|
|
|
* <p> |
|
|
@@ -50,22 +53,34 @@ public class Correl extends Fixed2ArgFunction { |
|
|
|
@Override |
|
|
|
public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1) { |
|
|
|
try { |
|
|
|
final List<DoubleList> arrays = getNumberArrays(arg0, arg1); |
|
|
|
final PearsonsCorrelation pc = new PearsonsCorrelation(); |
|
|
|
final double correl = pc.correlation( |
|
|
|
getNumberArray(arg0), getNumberArray(arg1)); |
|
|
|
arrays.get(0).toArray(), arrays.get(1).toArray()); |
|
|
|
return new NumberEval(correl); |
|
|
|
} catch (EvaluationException e) { |
|
|
|
return e.getErrorEval(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
private double[] getNumberArray(ValueEval operand) throws EvaluationException { |
|
|
|
DoubleList retval = new DoubleList(); |
|
|
|
collectValues(operand, retval); |
|
|
|
return retval.toArray(); |
|
|
|
private List<DoubleList> getNumberArrays(ValueEval operand0, ValueEval operand1) throws EvaluationException { |
|
|
|
double[] retval0 = collectValuesWithBlanks(operand0).toArray(); |
|
|
|
double[] retval1 = collectValuesWithBlanks(operand1).toArray(); |
|
|
|
DoubleList filtered0 = new DoubleList(); |
|
|
|
DoubleList filtered1 = new DoubleList(); |
|
|
|
for (int i = 0; i < retval0.length; i++) { |
|
|
|
if (Double.isNaN(retval0[i]) || Double.isNaN(retval1[i])) { |
|
|
|
//ignore |
|
|
|
} else { |
|
|
|
filtered0.add(retval0[i]); |
|
|
|
filtered1.add(retval1[i]); |
|
|
|
} |
|
|
|
} |
|
|
|
return Arrays.asList(filtered0, filtered1); |
|
|
|
} |
|
|
|
|
|
|
|
private void collectValues(ValueEval operand, DoubleList temp) throws EvaluationException { |
|
|
|
private DoubleList collectValuesWithBlanks(ValueEval operand) throws EvaluationException { |
|
|
|
DoubleList doubleList = new DoubleList(); |
|
|
|
if (operand instanceof ThreeDEval) { |
|
|
|
ThreeDEval ae = (ThreeDEval) operand; |
|
|
|
for (int sIx = ae.getFirstSheetIndex(); sIx <= ae.getLastSheetIndex(); sIx++) { |
|
|
@@ -74,11 +89,16 @@ public class Correl extends Fixed2ArgFunction { |
|
|
|
for (int rrIx = 0; rrIx < height; rrIx++) { |
|
|
|
for (int rcIx = 0; rcIx < width; rcIx++) { |
|
|
|
ValueEval ve = ae.getValue(sIx, rrIx, rcIx); |
|
|
|
collectValue(ve, temp); |
|
|
|
Double d = collectValue(ve); |
|
|
|
if (d == null) { |
|
|
|
doubleList.add(Double.NaN); |
|
|
|
} else { |
|
|
|
doubleList.add(d.doubleValue()); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
return; |
|
|
|
return doubleList; |
|
|
|
} |
|
|
|
if (operand instanceof TwoDEval) { |
|
|
|
TwoDEval ae = (TwoDEval) operand; |
|
|
@@ -87,46 +107,54 @@ public class Correl extends Fixed2ArgFunction { |
|
|
|
for (int rrIx = 0; rrIx < height; rrIx++) { |
|
|
|
for (int rcIx = 0; rcIx < width; rcIx++) { |
|
|
|
ValueEval ve = ae.getValue(rrIx, rcIx); |
|
|
|
collectValue(ve, temp); |
|
|
|
Double d = collectValue(ve); |
|
|
|
if (d == null) { |
|
|
|
doubleList.add(Double.NaN); |
|
|
|
} else { |
|
|
|
doubleList.add(d.doubleValue()); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
return; |
|
|
|
return doubleList; |
|
|
|
} |
|
|
|
if (operand instanceof RefEval) { |
|
|
|
RefEval re = (RefEval) operand; |
|
|
|
for (int sIx = re.getFirstSheetIndex(); sIx <= re.getLastSheetIndex(); sIx++) { |
|
|
|
collectValue(re.getInnerValueEval(sIx), temp); |
|
|
|
Double d = collectValue(re.getInnerValueEval(sIx)); |
|
|
|
if (d == null) { |
|
|
|
doubleList.add(Double.NaN); |
|
|
|
} else { |
|
|
|
doubleList.add(d.doubleValue()); |
|
|
|
} |
|
|
|
} |
|
|
|
return; |
|
|
|
return doubleList; |
|
|
|
} |
|
|
|
Double d = collectValue(operand); |
|
|
|
if (d == null) { |
|
|
|
doubleList.add(Double.NaN); |
|
|
|
} else { |
|
|
|
doubleList.add(d.doubleValue()); |
|
|
|
} |
|
|
|
collectValue(operand, temp); |
|
|
|
return doubleList; |
|
|
|
} |
|
|
|
|
|
|
|
private void collectValue(ValueEval ve, DoubleList temp) throws EvaluationException { |
|
|
|
private Double collectValue(ValueEval ve) throws EvaluationException { |
|
|
|
if (ve == null) { |
|
|
|
throw new IllegalArgumentException("ve must not be null"); |
|
|
|
} |
|
|
|
if (ve instanceof NumericValueEval) { |
|
|
|
NumericValueEval ne = (NumericValueEval) ve; |
|
|
|
temp.add(ne.getNumberValue()); |
|
|
|
return; |
|
|
|
return ne.getNumberValue(); |
|
|
|
} |
|
|
|
if (ve instanceof StringValueEval) { |
|
|
|
String s = ((StringValueEval) ve).getStringValue().trim(); |
|
|
|
Double d = OperandResolver.parseDouble(s); |
|
|
|
if (d == null) { |
|
|
|
throw new EvaluationException(ErrorEval.VALUE_INVALID); |
|
|
|
} else { |
|
|
|
temp.add(d.doubleValue()); |
|
|
|
} |
|
|
|
return; |
|
|
|
return OperandResolver.parseDouble(s); |
|
|
|
} |
|
|
|
if (ve instanceof ErrorEval) { |
|
|
|
throw new EvaluationException((ErrorEval) ve); |
|
|
|
} |
|
|
|
if (ve == BlankEval.instance) { |
|
|
|
temp.add(0.0); |
|
|
|
return; |
|
|
|
return null; |
|
|
|
} |
|
|
|
throw new RuntimeException("Invalid ValueEval type passed for conversion: (" |
|
|
|
+ ve.getClass() + ")"); |