1. 程式人生 > >GIS資訊關聯規則挖掘——Apriori演算法的實現(下)

GIS資訊關聯規則挖掘——Apriori演算法的實現(下)

上篇說明了原理,這篇就直接上核心程式碼了~


程式碼比較長,所以理解可能有點麻煩,核心思路就是計算選擇的維度後遍歷資料,逐步進行迴圈計算置信度,並淘汰每次迴圈後的最低值。

這裡有一點要注意的,我一開始想用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;

        }
    }
}