许久没有管自己的博客了,问我要源码的亲们,现在可以看了,希望可以帮到你们。
代码如下:
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import Jama.Matrix;
import Util.DBConnection;
//因子分析
public class FactorAnalyse {
// 从数据库中获取数据
public double[][] getHseData(){
List<Double> list = new ArrayList<Double>();
double[][] result = new double[24][26];
double[] temp = new double[24*26];
String sql = "select score from HseScore";
ResultSet rs = DBConnection.executeQuery(sql);
try{
while(rs.next()){
list.add(rs.getDouble(1));
}
}catch(SQLException e){
e.printStackTrace();
}
for(int i=0;i<list.size();i++){
temp[i] = list.get(i);
}
for (int i = 0; i < 24; i++) {
for (int j = 0; j < 26; j++) {
result[i][j] = temp[26*i+j];
}
}
Matrix m = new Matrix(result);
m.print(3, 2);
return result;
}
// 计算均值
public double[] getAverage(double[][] array) {
int h = array.length; // 行号--h
int l = array[0].length;// 列号--l
double[] average = new double[l];// 每个变量的均值
for (int i = 0; i < l; i++) {
double temp = 0.0;
for (int j = 0; j < h; j++) {
temp += array[j][i];
}
average[i] = temp / h;
// System.out.printf("average[%d] = %.5f\n", i, average[i]);
}
return average;
}
// 计算方差
public double[] getVariance(double[][] array) {
int h = array.length; // 行号--h
int l = array[0].length;// 列号--l
double[] average = getAverage(array);
double[] var = new double[l];
for (int i = 0; i < l; i++) {
double temp = 0.0;
for (int j = 0; j < h; j++) {
temp += Math.pow((array[j][i] - average[i]), 2);
}
var[i] = temp / (h - 1);
// System.out.printf("var[%d] = %.5f\n", i, var[i]);
}
return var;
}
// 计算标准差
public double[] getStandardDevition(double[] var) {
double[] sd = new double[var.length];
for (int i = 0; i < var.length; i++) {
sd[i] = Math.sqrt(var[i]);
// System.out.printf("sd[%d] = %.5f\n", i, sd[i]);
}
return sd;
}
// 标准化数据
public double[][] getStandard(double[][] array, double[] sd) {
int h = array.length; // 行号--h
int l = array[0].length;// 列号--l
double[][] result = new double[h][l];// 标准化
double[] average = getAverage(array);
for (int i = 0; i < h; i++) {
for (int j = 0; j < l; j++) {
result[i][j] = (array[i][j] - average[j]) / sd[j];
}
}
Matrix m = new Matrix(result);
m.print(5, 3);
return result;
}
// 计算协方差矩阵--方阵
public double[][] getCovMatrix(double[][] array) {
int h = array.length;
int l = array[0].length;
double[][] temp = new double[h][l];// 保存计算协方差的中间矩阵
double[][] result = new double[l][l];
double[] average = getAverage(array); // 标准化后的矩阵求均值
for (int i = 0; i < h; i++) {
for (int j = 0; j < l; j++) {
temp[i][j] = array[i][j] - average[j];
}
}
for (int i = 0; i < l; i++) {
for (int j = 0; j < l; j++) {
double t = 0;
for (int k = 0; k < h; k++) {
t += temp[k][i] * temp[k][j];
}
result[i][j] = t / (h - 1);
}
}
Matrix m = new Matrix(result);
m.print(5, 3);
return result;
}
// 计算相关矩阵---方阵
public double[][] getCorrelationMatrix(double[][] cov, double[] sd) {
int l = cov.length;
double[][] result = new double[l][l];
for (int i = 0; i < l; i++) {
for (int j = 0; j < l; j++) {
result[i][j] = cov[i][j] / (sd[i] * sd[j]);
}
}
Matrix m = new Matrix(result);
m.print(5, 3);
return result;
}
// 求矩阵特征值
public double[][] getEigenvalue(double[][] array) {
int h = array.length;// 行号等于列号
double[][] result = new double[h][h];
Matrix m = new Matrix(array);
Matrix m1 = m.eig().getD(); // 由特征值组成的对角矩阵
System.out.println("由特征值组成的对角矩阵:");
m1.print(5, 3);
result = m1.getArray();
return result;
}
// 求矩阵的特征向量
public double[][] getEigenvector(double[][] array) {
int h = array.length;// 行号等于列号
double[][] result = new double[h][h];
Matrix m = new Matrix(array);
Matrix m1 = m.eig().getV(); // 该矩阵的每一列对应的是一个单位正交特征向量
System.out.println("\n特征向量矩阵:");
m1.print(5, 3);
result = m1.getArray();
return result;
}
// 特征值从大到小排序并保存成键值对形式
public TreeMap<Integer, Double> getMap(double[][] array) {
int h = array.length;
Map<Integer, Double> map = new HashMap<Integer, Double>();
ValueComparator bvc = new ValueComparator(map);
TreeMap<Integer, Double> sorted_map = new TreeMap<Integer, Double>(bvc);
double[] temp = new double[h]; // 存储特征值
for (int i = 0; i < h; i++) {
for (int j = 0; j < h; j++) {
if (i == j)
temp[i] = array[i][j];
}
}
for (int i = 0; i < temp.length; i++) {
map.put(i, temp[i]);
}
System.out.println("\n排序前键值对:\n" + map);
sorted_map.putAll(map);
System.out.println("\n排序后的键值对:\n" + sorted_map);
return sorted_map;
}
// 计算方差贡献率
public double[] getContibutionRatio(TreeMap<Integer, Double> tm) {
int h = tm.size();
double[] percent = new double[h];
Iterator titer = tm.entrySet().iterator();
int count = 0;
while (titer.hasNext()) {
Map.Entry ent = (Map.Entry) titer.next();
int keyt = (Integer) ent.getKey();
double valuet = (Double) ent.getValue();
percent[count] = valuet / h;
System.out.printf("\n键%d 对应的特征值 %.3f所占的比例为 %.3f \n",keyt,valuet,percent[count]);
count++;
}
return percent;
}
// 计算方差累积贡献率
public double[] getCumuContributionRatio(double[] array) {
double[] result = new double[array.length];
double temp = 0.0;
for (int i = 0; i < array.length; i++) {
temp += array[i];
result[i] = temp;
System.out.printf("\n累积贡献率:%.3f \n", result[i]);
}
return result;
}
// 确定公共因子的个数
public int getNum(double[] array) {
int number = 1;// 公因子个数
double t = 0.0;
for (int i = 0; i < array.length; i++) {
t = array[i];
if (t < 0.75)
number++;
}
System.out.println("\n公共因子个数:" + number);
return number;
}
// 获取特征值对应的特征向量
public double[][] getVVector(TreeMap<Integer, Double> tm, double[][] array) {
int h = array.length;
double[][] result = new double[h][h];
int[] temp = new int[h];
Iterator titer = tm.entrySet().iterator();
int count = 0;
while (titer.hasNext()) {
Map.Entry ent = (Map.Entry) titer.next();
int keyt = (Integer) ent.getKey();
temp[count] = keyt;
// System.out.println("temp["+count+"] = "+temp[count]);
count++;
}
for (int i = 0; i < h; i++) {
for (int j = 0; j < h; j++) {
result[i][j] = array[i][temp[j]];
}
}
System.out.println("特征值对应的特征向量组成的矩阵:");
Matrix m = new Matrix(result);
m.print(5, 3);
return result;
}
// 获取因子载荷矩阵
public double[][] getMatrixA(TreeMap<Integer, Double> tm, double[][] array,
int num) {
int h = array.length;
double[][] A = new double[h][num];
double[] temp = new double[h];
Iterator titer = tm.entrySet().iterator();
int count = 0;
while (titer.hasNext()) {
Map.Entry ent = (Map.Entry) titer.next();
double valuet = (Double) ent.getValue();
temp[count] = Math.sqrt(valuet);
// System.out.printf("特征值开平方根:%.5f\n", temp[count]);
count++;
}
System.out.println("因子载荷矩阵 A = ");
for (int i = 0; i < h; i++) {
for (int j = 0; j < num; j++) {
A[i][j] = temp[j] * array[i][j];
}
}
Matrix m = new Matrix(A);
m.print(5, 3);
return A;
}
// 获取特殊因子矩阵
public double[][] getMatrixD(TreeMap<Integer, Double> tm, double[][] array,
int num) {
int h = array.length;
double[][] B = new double[h][h - num];
double[][] C = new double[h][h];
double[][] D = new double[h][h];
double[] temp = new double[h];
Iterator titer = tm.entrySet().iterator();
int count = 0;
while (titer.hasNext()) {
Map.Entry ent = (Map.Entry) titer.next();
double valuet = (Double) ent.getValue();
temp[count] = Math.sqrt(valuet);
count++;
}
for (int i = 0; i < h; i++) {
for (int j = num; j < h; j++) {
B[i][j - num] = temp[j] * array[i][j];
}
}
Matrix m = new Matrix(B);
Matrix m1 = m.times(m.transpose());
C = m1.getArray();
for (int i = 0; i < h; i++) {
for (int j = 0; j < h; j++) {
if (i == j)
D[i][j] = C[i][j];
}
}
System.out.println("特殊因子矩阵 D = ");
Matrix m2 = new Matrix(D);
m2.print(5, 3);
return D;
}
// 进行因子旋转--方差最大正交旋转
public double[][] getVarimax(double[][] array, int num) {
int h = array.length;
int l = array[0].length;
double[] hi = new double[h]; // 变量共同度
double[][] standardA = new double[h][l];//标准化处理因子载荷阵
double[][] result = new double[h][l];// 旋转后的因子载荷矩阵
double[] u = new double[h];
double[] v = new double[h];
double A = 0.0;
double B = 0.0;
double C = 0.0;
double D = 0.0;
double E = 0.0;
//标准化处理A
for (int i = 0; i < h; i++) {
double temp = 0.0;
for (int j = 0; j < l; j++) {
temp += Math.pow(array[i][j], 2);
}
hi[i] = temp;
//System.out.printf("变量共同度:%.5f\n", hi[i]);
}
for(int i = 0; i < h; i++){
for(int j = 0; j < l; j++){
standardA[i][j] = Math.pow(array[i][j],2) / hi[i];
}
}
double[][] P = new double[l][l]; // 构造正交矩阵
Matrix m = new Matrix(standardA);
for (int k = 0; k < num-1; k++) {
for (int p = k+1; p < num; p++) {
for (int i = 0; i < h; i++) {
u[i] = (Math.pow(array[i][k], 2) - Math.pow(array[i][p], 2)) / hi[i];
}
for (int i = 0; i < h; i++) {
v[i] = (2 * array[i][k] * array[i][p]) / hi[i];
}
for (int i = 0; i < h; i++) {
A += u[i];
B += v[i];
C += (u[i] * u[i]) - (v[i] * v[i]);
D += 2 * u[i] * v[i];
}
E = (Math.atan((D - (2 * A * B) / h) / (C - (A * A - B * B) / h))) / 4.0;
//System.out.printf("\n旋转角度 E = %.5f\n", E);
for (int i = 0; i < l; i++) {
for (int j = 0; j < l; j++) {
if (i == j)
P[i][j] = 1;
else
P[i][j] = 0;
}
}
double[][] T = P;
T[k][k] = Math.cos(E);
T[k][p] = -Math.sin(E);
T[p][k] = Math.sin(E);
T[p][p] = Math.cos(E);
Matrix m1 = new Matrix(T);//正交矩阵
m = m.times(m1);
}
}
m.print(5, 3);
result = m.getArray();
return result;
}
// 计算旋转后的方差贡献率
public double[] getContibutionRatio1(double[][] array) {
int h = array.length;
int l = array[0].length;
double[] percent = new double[h];
double sum = 0.0;
for(int i = 0; i < l;i++){
double temp = 0.0;
for(int j = 0; j < h;j++){
temp += Math.pow(array[j][i],2);
}
percent[i] = temp / h;
//System.out.printf("\n旋转后的方差贡献率--F["+(i+1)+"]: %.3f\n",percent[i]);
sum += percent[i];
}
//System.out.printf("\n方差累积贡献率::%.3f\n",sum);
return percent;
}
// 计算因子载荷的方差
public double getA_Var(double[][] array) {
int h = array.length;
int l = array[0].length;
double[] var = new double[l];// 每一列的方差
double v = 0.0;// 总方差
double[][] B = new double[h][l];
for (int i = 0; i < h; i++) {
for (int j = 0; j < l; j++) {
B[i][j] = Math.pow(array[i][j],2);
}
}
double[] ad = getAverage(B);
for (int i = 0; i < l; i++) {
double temp = 0.0;
for (int j = 0; j < h; j++) {
temp += Math.pow(B[j][i] - ad[i], 2);
}
var[i] = temp / h;
//System.out.printf("每一列的方差:%.5f\n", var[i]);
v += var[i];
}
System.out.printf("总方差:%.3f\n", v);
return v;
}
// 计算因子得分
public double[][] getScore(double[][] R, double[][] A,double[][] array) {
int h = A.length;
int l = R[0].length;
double[][] F = new double[h][l];
Matrix m = new Matrix(A);
Matrix m1 = new Matrix(R);
Matrix m2 = (m.transpose()).times(m1.inverse());
Matrix m3 = new Matrix(array);
Matrix m4 = (m2).times(m3.transpose());
System.out.println("因子得分:");
m4.transpose().print(5, 3);
F = m4.transpose().getArray();
return F;
}
//计算因子综合得分
public double[] getScores(double[][] array,double[] percent){
int h = array.length;
int l = array[0].length;
double[] result = new double[h];
double temp = 0.0;
for(int i = 0; i < l; i++){
temp +=percent[i];
}
for(int i = 0; i < h; i++){
double t = 0.0;
for(int j = 0; j < l; j++){
t += array[i][j] * percent[j];
}
result[i] = t / temp;
System.out.printf("综合得分:%.3f\n",result[i]);
}
return result;
}
}
// map按值进行排序
class ValueComparator implements Comparator<Integer> {
Map<Integer, Double> base;
public ValueComparator(Map<Integer, Double> base) {
this.base = base;
}
public int compare(Integer a, Integer b) {
if (base.get(a) >= base.get(b)) {
return -1;
} else {
return 1;
}
}
}
完整代码已贴出,有需要的朋友请查看,转载请注明出处,谢谢!

本文深入解析因子分析算法,涵盖数据获取、标准化、协方差与相关矩阵计算、特征值及特征向量求解、方差贡献率计算、因子旋转、因子得分及综合得分等关键步骤。通过具体代码实现,展示如何利用因子分析进行数据降维。
829





