GIS資訊關聯規則挖掘——Apriori演算法的實現(下)
阿新 • • 發佈:2018-10-31
上篇說明了原理,這篇就直接上核心程式碼了~
程式碼比較長,所以理解可能有點麻煩,核心思路就是計算選擇的維度後遍歷資料,逐步進行迴圈計算置信度,並淘汰每次迴圈後的最低值。
這裡有一點要注意的,我一開始想用arraylist構造一個堆疊結構進行資料遍歷的儲存跟計算,因為這樣效率比較高。。
但是後來發現,那麼做的話,如果以後想要對型別跟因子的種類、數量進行修改的話,需要對程式碼進行大量重構才能實現功能的更新,而對於我朋友這樣的程式碼苦手來說估計跟寫天書差不多。。於是在實現的時候我放棄了部分效率,將每個型別單獨設定一個數據表,然後每個表寫入該型別所有的因子,最後通過在資料庫讀取這些表的形式進行資料的遍歷計算。這樣的話,後期想要更改型別跟因子,可以通過直接在資料庫修改的方式進行處理,程式碼也不需要大改了。
(=。= 沒辦法額,畢竟不是每個人都會寫程式碼的。。。)
namespace FManage { public partial class Analy : Form { private System.Windows.Forms.CheckBox[] checkBoxFactors; private DataSet ds; private int[] rowTables; private int[] flag; private int[] dimention; private int[] fee; private int p; public Analy() { InitializeComponent(); this.panel1.SuspendLayout(); this.SuspendLayout(); //資料載入過程略 this.checkBoxFactors = new System.Windows.Forms.CheckBox[6]; //設定要素選擇項 for (int i = 0; i < 6; i++) { this.checkBoxFactors[i] = new System.Windows.Forms.CheckBox(); this.checkBoxFactors[i].AutoSize = true; this.checkBoxFactors[i].Location = new System.Drawing.Point(90 + i % 3 * 150, 28 + (int)Math.Floor(Convert.ToDouble(i / 3) * 40)); this.checkBoxFactors[i].Size = new System.Drawing.Size(84, 16); this.checkBoxFactors[i].TabIndex = i + 1; this.checkBoxFactors[i].UseVisualStyleBackColor = true; this.panel1.Controls.Add(this.checkBoxFactors[i]); } this.panel1.ResumeLayout(false); this.panel1.PerformLayout(); this.ResumeLayout(false); this.PerformLayout(); } private void Analy_Load(object sender, EventArgs e) { rowTables = new int[8]; for (int i = 0; i < 8; i++) { rowTables[i] = ds.Tables[i].Rows.Count; } dimention = new int[8]; for (int i = 0; i < 8; i++) { dimention[i] = ds.Tables[i].Rows.Count; } } //計算選擇維度 private void countfee(ref int[] fee) { int p; for (int i = 0; i < dimention[7]; i++) { p = 0; for (int j = 0; j < 7; j++) { if (flag[j] == 1) fee[i] += System.Convert.ToInt32(ds.Tables[7].Rows[i].ItemArray[j + 1]) * (int)Math.Pow(10, p++); } } } private void CircleString(int a, int end, ref string[] finalString, ref int[] needle, string[][] tempString) { for (int i = 0; i < tempString[a].Length; i++) { needle[a] = i; if (a == end - 1) { for (int j = 0; j < end; j++) { finalString[p++] = tempString[j][needle[j]]; } } else { CircleString(a + 1, end, ref finalString, ref needle, tempString); } } } private void CircleCalculationString(int a, int end, ref string[] finalCalculation, ref int[] needleCalculation, string[][] tempCalculation) { for (int i = 0; i < tempCalculation[a].Length; i++) { needleCalculation[a] = i; if (a == end - 1) { for (int j = 0; j < end; j++) { finalCalculation[p++] = tempCalculation[j][needleCalculation[j]]; } } else { CircleCalculationString(a + 1, end, ref finalCalculation, ref needleCalculation, tempCalculation); } } } //計算支援度和置信度 private void buttonCalculate_Click(object sender, EventArgs e) { double zhichiduNumber = Convert.ToDouble(rank1.Text) / 100; double zhixinduNumber = Convert.ToDouble(rank2.Text) / 100; fee = new int[dimention[7]]; flag = new int[7]; flag[0] = 1; for (int i = 0; i < 6; i++) { if (this.checkBoxFactors[i].Checked) flag[i + 1] = 1; else flag[i + 1] = 0; } countfee(ref fee); #region ShowString string[][] tempString = new string[flag.Sum() - 1][]; int temp = 0; for (int i = 0; i < flag.Sum() - 1; i++) { do { temp++; if (temp == 7)break; } while (flag[temp] == 0); tempString[i] = new string[dimention[temp]]; for (int j = 0; j < dimention[temp]; j++) { tempString[i][j] = ds.Tables[temp].Rows[j].ItemArray[1].ToString(); } } int[] needleString = new int[flag.Sum() - 1]; for (int i = 0; i < flag.Sum() - 1; i++) { needleString[i] = 0; } int finalNumber = 1; for (int i = 1; i < 7; i++) { if (flag[i] == 1) finalNumber *= ds.Tables[i].Rows.Count; } DataTable showTable = new DataTable("showTable"); DataColumn finalCol = showTable.Columns.Add("ID", typeof(Int32)); finalCol.AllowDBNull = false; finalCol.Unique = true; for (int i = 1; i < 7; i++) { if (flag[i] == 1) showTable.Columns.Add(ds.Tables[7].Columns[i + 1].ColumnName, typeof(String)); } showTable.Columns.Add("支援度(%)", typeof(double)); showTable.Columns.Add("置信度(%)", typeof(double)); string[] showString = new string[finalNumber * (flag.Sum() - 1)]; p = 0; CircleString(0, flag.Sum() - 1, ref showString, ref needleString, tempString); DataRow showRow; p = 0; for (int i = 0; i < finalNumber; i++) { showRow = showTable.NewRow(); showRow[0] = i + 1; for (int j = 0; j < flag.Sum() - 1; j++) { showRow[j + 1] = showString[p++]; } showRow[flag.Sum()] = 0; showRow[flag.Sum() + 1] = 0; showTable.Rows.Add(showRow); } #endregion #region Calculation string[][] tempCalculation = new string[flag.Sum()][]; temp = 0; for (int i = 0; i < flag.Sum(); i++) { tempCalculation[i] = new string[dimention[temp]]; for (int j = 0; j < dimention[temp]; j++) { tempCalculation[i][j] = ds.Tables[temp].Rows[j].ItemArray[0].ToString(); } do { temp++; if (temp == 7)break; } while (flag[temp] == 0); } int[] needleCalculation = new int[flag.Sum()]; for (int i = 0; i < flag.Sum(); i++) { needleCalculation[i] = 0; } finalNumber = 1; for (int i = 0; i < 7; i++) { if (flag[i] == 1) finalNumber *= ds.Tables[i].Rows.Count; } DataTable calculationTable = new DataTable("calculationTable"); for (int i = 0; i < 7; i++) { if (flag[i] == 1) calculationTable.Columns.Add(ds.Tables[7].Columns[i + 1].ColumnName, typeof(String)); } string[] finalCalculation = new string[finalNumber * flag.Sum()]; p = 0; CircleCalculationString(0, flag.Sum(), ref finalCalculation, ref needleCalculation, tempCalculation); DataRow calculationRow; p = 0; for (int i = 0; i < finalNumber; i++) { calculationRow = calculationTable.NewRow(); for (int j = 0; j < flag.Sum(); j++) { calculationRow[j] = finalCalculation[p++]; } calculationTable.Rows.Add(calculationRow); } #endregion int[] objectiveFee = new int[finalNumber]; for (int i = 0; i < finalNumber; i++) { for (int j = 0; j < flag.Sum(); j++) { objectiveFee[i] += System.Convert.ToInt32(calculationTable.Rows[i].ItemArray[j]) * (int)Math.Pow(10, j); } } double[,] times = new double[3, finalNumber / 2]; for (int i = 0; i < finalNumber / 2; i++) { for (int j = 0; j < dimention[7]; j++) { if (objectiveFee[i] == fee[j]) times[0, i]++; } } for (int i = finalNumber / 2; i < finalNumber; i++) { for (int j = 0; j < dimention[7]; j++) { if (objectiveFee[i] == fee[j]) times[1, i - finalNumber / 2]++; } } for (int i = 0; i < finalNumber / 2; i++) { times[2, i] = times[0, i] + times[1, i]; } double[] zhichidu = new double[finalNumber / 2]; for (int i = 0; i < finalNumber / 2; i++) { zhichidu[i] = times[2, i] / 1000.0; } double[] zhixindu = new double[finalNumber / 2]; for (int i = 0; i < finalNumber / 2; i++) { if (times[2, i] > 0) { zhixindu[i] = ((int)(times[0, i] / times[2, i] * 10000)) / 10000.0; } else zhixindu[i] = 0; } for (int i = 0; i < finalNumber / 2; i++) { showTable.Rows[i][flag.Sum()] = zhichidu[i]; showTable.Rows[i][flag.Sum() + 1] = zhixindu[i]; } for (int i = 0; i < showTable.Rows.Count; i++) { showTable.Rows[i][0] = i + 1; showTable.Rows[i][flag.Sum()] = (int)(Convert.ToDouble(showTable.Rows[i][flag.Sum()]) * 1000) / 10.0; showTable.Rows[i][flag.Sum() + 1] = (int)(Convert.ToDouble(showTable.Rows[i][flag.Sum() + 1]) * 1000) / 10.0; } this.dataGridView1.DataSource = null; this.dataGridView1.DataSource = showTable.DefaultView; this.dataGridView1.Visible = true; } } }