package edu.brown.mappings;
import java.util.Vector;
/**
*
* @author svelagap
*
*/
public class PearsonCorrelationMapping extends AbstractMapping {
private final Vector<Number> values0 = new Vector<Number>();
private final Vector<Number> values1 = new Vector<Number>();
/**
* Constructor
*/
public PearsonCorrelationMapping() {
super();
}
/**
* Remove all entries in this PearsonCorrelation instance
*/
public void clear() {
this.values0.clear();
this.values1.clear();
this.num_entries = 0;
this.last_calculation = null;
}
/**
* Add two values to be correlated with each other
*
* @param x
* @param y
*/
@Override
public synchronized <K extends Number, V extends Number> void addOccurrence(K x, V y) {
this.values0.add(x);
this.values1.add(y);
this.num_entries++;
this.last_calculation = null;
}
/**
* Algorithm for calculating PearsonCorrelation's r shamelessly stolen from Wikipedia.
* http://en.wikipedia.org/wiki/PearsonCorrelation_correlation
*
* @return The PearsonCorrelation's r of the two variables associated with this object
*/
@Override
public synchronized Double calculate() {
assert(this.num_entries == this.values0.size());
assert(this.num_entries == this.values1.size());
if (this.last_calculation != null || this.num_entries == 0) return (this.last_calculation);
double sum_sq_x = 0;
double sum_sq_y = 0;
double sum_coproduct = 0;
double mean_x = this.values0.get(0).doubleValue();
double mean_y = this.values1.get(0).doubleValue();
for (int i = 2; i <= this.num_entries; i++) {
double x = this.values0.get(i - 1).doubleValue();
double y = this.values1.get(i - 1).doubleValue();
double sweep = (i - 1.0) / i;
double delta_x = x - mean_x;
double delta_y = y - mean_y;
// System.out.println("first " + next + "\n second " + this.get(next));
sum_sq_x += delta_x * delta_x * sweep;
sum_sq_y += delta_y * delta_y * sweep;
sum_coproduct += delta_x * delta_y * sweep;
mean_x += delta_x / i;
mean_y += delta_y / i;
// System.out.println("mean_x " + mean_x + "\n mean_y " + mean_y);
} // FOR
double pop_sd_x = Math.sqrt(sum_sq_x / this.num_entries);
double pop_sd_y = Math.sqrt(sum_sq_y / this.num_entries);
double cov_x_y = sum_coproduct / this.num_entries;
// Special Case: Single-point (always the same values)
if (pop_sd_x == 0 && pop_sd_y == 0) {
this.last_calculation = 1.0d;
// Special Case: Horizontal Line
} else if (pop_sd_y == 0) {
// Special Case: Vertical Line
} else if (pop_sd_y == 0) {
} else {
this.last_calculation = cov_x_y / (pop_sd_x * pop_sd_y); // Correlation;
}
return (this.last_calculation);
}
@Override
public String toString() {
String ret = this.getClass().getSimpleName() +
"[# of Entries=" + this.values0.size() + ", Last Calculation=" + this.last_calculation + "]";
return (ret);
}
}