Apriori算法的JAVA实现

最新学习《数据挖掘概念与技术》将书中的Apriori算法用java实现(jdk7+Eclipse4)了,代码如下:

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.TreeSet;

public class MyApriori
{
	public static int min_sup = 2;

	/**
	 * @author weibin
	 * @param args
	 */
	public static void main(String[] args)
	{
		// TODO Auto-generated method stub
		long startTime = System.currentTimeMillis();
		// 事务数据库
		List<String> data = new ArrayList<String>();
		data.add("I1,I2,I5");
		data.add("I2,I4");
		data.add("I2,I3");
		data.add("I1,I2,I4");
		data.add("I1,I3");
		data.add("I2,I3");
		data.add("I1,I3");
		data.add("I1,I2,I3,I5");
		data.add("I1,I2,I3");
		System.out.println("ALLElectronics某分店的事务数据为:");
		for (int i = 0; i < data.size(); i++)
		{
			System.out.println("    " + data.get(i).toString());
		}

		MyApriori myapr = new MyApriori();

		TreeSet<String> Lk_1 = myapr.find_frequent_1_itemsets(data);
		System.out.println("第一次扫描事务数据库后L1=" + Lk_1);

		TreeSet<String> Ck = new TreeSet<String>();

		for (int k = 2; Lk_1.size() != 0; k++)
		{

			System.out.println("\n通过L" + (k - 1) + " × L" + (k - 1) + "生成C" + k
					+ "时:");
			Ck = myapr.apriori_gen(Lk_1, k);

			if (Ck.size() > 0)
			{
				System.out.println("\n通过L" + (k - 1) + " 生成L" + k + "为:");
				Iterator<String> it1 = Ck.iterator();
				while (it1.hasNext())
				{
					System.out.println("    " + it1.next());

				}
				System.out.println("\n");
			}

			HashMap<String, Integer> hm = new MyApriori().TreeSet2HashMap(Ck);

			ArrayList<String> al = new MyApriori().TreeSet2ArrayList(Ck);

			for (int j = 0; j < al.size(); j++)
			{
				TreeSet<String> set_al = new MyApriori().String2TreeSet(al
						.get(j));
				// System.out.println("set_al="+set_al);
				for (int i = 0; i < data.size(); i++)
				{

					TreeSet<String> set_data = new MyApriori()
							.String2TreeSet(data.get(i));
					// System.out.println("			set_data="+set_data);
					int size_o = set_data.size();
					set_data.addAll(set_al);
					int size_n = set_data.size();

					if (size_n == size_o)
					{
						// System.out.println("			"+al.get(j)+" 出现次数="+((hm.get(al.get(j)).intValue())
						// + 1));
						hm.put(al.get(j), hm.get(al.get(j)) + 1);

					}

				}
			}

			Lk_1 = new MyApriori().compareMinSup(hm);
			if (Lk_1.size() > 0)
			{
				System.out.println("\n将候选集C" + (k - 1) + "不满足最小支持度的元素删除后L" + k
						+ "为:");
				Iterator<String> it1 = Lk_1.iterator();
				while (it1.hasNext())
				{
					System.out.println("    " + it1.next());

				}
				System.out.println("\n");
			}
		}
		long endTime = System.currentTimeMillis();
		System.out.println("执行程序一共花费了" + (endTime - startTime) + "毫秒");
	}

	/*
	 * apriori_gen 将L(k-1)*L(k-1)得到Lk
	 */
	public TreeSet<String> apriori_gen(TreeSet<String> Lk_1, int k)
	{

		TreeSet<String> Ck = new TreeSet<String>();
		ArrayList<String> l1 = new MyApriori().TreeSet2ArrayList(Lk_1);
		ArrayList<String> l2 = new MyApriori().TreeSet2ArrayList(Lk_1);
		String c = new String();

		for (int i = 0; i < l2.size(); i++)
		{
			for (int j = i + 1; j < l2.size(); j++)
			{

				String str_l1 = l1.get(i).toString();
				String str_l2 = l2.get(j).toString();

				int lastSplit = str_l1.lastIndexOf(",");
				if (lastSplit == -1)// 如果为1项集,则通过1项集连接生成2项集
				{
					c = str_l1 + "," + l2.get(j).toString();
					// System.out.println("c=" + c);
					if (!has_infrequent_subset(c, Lk_1, k - 1))
					{
						Ck.add(c);
					}
				} else
				{

					if (str_l1.substring(0, lastSplit).equals(
							str_l2.substring(0, lastSplit))
							&& str_l1.substring(lastSplit).compareTo(
									str_l2.substring(lastSplit)) < 0)
					{
						c = str_l1 + str_l2.substring(lastSplit);
						// System.out.println("c=" + c);
						if (!has_infrequent_subset(c, Lk_1, k - 1))
						{
							Ck.add(c);
						}
					}
				}
			}

		}

		return Ck;
	}

	/*
	 * 第一次扫描数据库,找到一项集
	 * 
	 * 库为: "I1,I2,I5" "I2,I4" "I2,I3" "I1,I2,I4" "I1,I3" "I2,I3" "I1,I3"
	 * "I1,I2,I3,I5" "I1,I2,I3"
	 * 
	 * 扫描库后分别对一项集进行计数: 项集为I3 支持度计数为6 项集为I4 支持度计数为2 项集为I1 支持度计数为6 项集为I2 支持度计数为7
	 * 项集为I5 支持度计数为2
	 * 
	 * 则返回一项集:Lk_1=[I1, I2, I3, I4, I5]
	 */
	public TreeSet<String> find_frequent_1_itemsets(List<String> data)
	{

		String str[] = data.toString().replace(" ", "").replace("[", "")
				.replace("]", "").split(",");

		HashMap<String, Integer> hm = new HashMap<String, Integer>();
		TreeSet<String> set = new TreeSet<String>();
		for (int i = 0; i < str.length; i++)
		{
			// set.add(str[i]);
			if (hm.get(str[i]) == null)
			{
				hm.put(str[i], 1);
			} else
			{
				hm.put(str[i], hm.get(str[i]) + 1);
			}

		}
		set = new MyApriori().compareMinSup(hm);
		return set;
	}

	/*
	 * 判断参数HashMap hm中键值对,值与 min_sup比较,当小于min_sup时,删除此键值对,最后返回候选集 项集为I3 支持度计数为6
	 * 项集为I4 支持度计数为2 项集为I1 支持度计数为6 项集为I2 支持度计数为7 项集为I5 支持度计数为2
	 * 
	 * 则返回一项集:Lk_1=[I1, I2, I3, I4, I5]
	 */
	public TreeSet<String> compareMinSup(HashMap<String, Integer> hm)
	{
		TreeSet<String> set = new TreeSet<String>();
		Iterator iter = hm.entrySet().iterator();
		if (hm.size() > 0)
		{
			System.out.println("----项集----|----支持度----l");
		}
		while (iter.hasNext())
		{
			Map.Entry<String, Integer> entry = (Map.Entry) iter.next();
			String key = (String) (entry.getKey());
			int val = (Integer) (entry.getValue()).intValue();

			System.out.println("     " + key + "     |      " + val);

			if (val >= min_sup)
				set.add(key);
		}
		return set;

	}

	/*
	 * 将TreeSet<String>转为ArrayList
	 */
	public ArrayList<String> TreeSet2ArrayList(TreeSet<String> Lk_1)
	{
		ArrayList<String> al = new ArrayList<String>();
		Iterator<String> iterator = Lk_1.iterator();

		while (iterator.hasNext())
		{
			al.add(iterator.next().toString());
			// iterator.next();
		}
		return al;
	}

	/*
	 * 查询以分号分隔的字符串形成集合后,取其中K为元素作为子集,当其中存在子集不属于Lk_1中,返回真,都属于Lk_1中返回假
	 */
	public boolean has_infrequent_subset(String c, TreeSet<String> Lk_1, int k)
	{
		TreeSet<String> ts = new MyApriori().String2TreeSet(c);
		TreeSet<String> zh = new MyApriori().zh(ts, k);
		Iterator<String> it1 = zh.iterator();

		while (it1.hasNext())
		{
			String temp = it1.next();
			if (!Lk_1.contains(temp))
			{
				System.out.println("   {" + c + "} 的" + k + "项子集 { " + temp
						+ "} 不是L" + k + "的元素,根据先验性质剪技,删除!");
				return true;
			}
		}
		return false;
	}

	/*
	 * 将TreeSet<String>转为ArrayList
	 */
	public TreeSet<String> String2TreeSet(String c)
	{
		TreeSet<String> ts = new TreeSet<String>();
		String[] str = c.split(",");
		for (int i = 0; i < str.length; i++)
		{
			ts.add(str[i]);
		}
		return ts;
	}

	/*
	 * 返回集合data中所有元素不重复的n个组合
	 */
	public TreeSet<String> zh(TreeSet<String> data, int n)
	{
		TreeSet<String> result = new TreeSet<String>();
		if (n == 1)
		{
			result = data;
		} else
		{
			Iterator<String> it1 = zh(data, n - 1).iterator();
			Iterator<String> it2 = data.iterator();
			ArrayList<String> sal1 = new ArrayList<String>();
			ArrayList<String> sal2 = new ArrayList<String>();

			while (it1.hasNext())
			{
				sal1.add(it1.next());
				// iterator.next();
			}

			while (it2.hasNext())
			{
				sal2.add(it2.next());
				// iterator.next();
			}

			// System.out.println("sal1=" + sal1);
			// System.out.println("sal2=" + sal2);

			for (int i = 0; i < sal1.size() - 1; i++)
			{

				for (int j = 0; j < sal2.size(); j++)
				{
					if (sal1.get(i).compareTo(sal2.get(j)) < 0)
					{
						if (n == 2)
						{
							result.add(sal1.get(i) + "," + sal2.get(j));
						} else
						{
							// System.out.println("sal1.get("+i+")="+sal1.get(i));
							// System.out.println("sal2.get("+j+")="+sal2.get(j));

							String[] temp = sal1.get(i).split(",");

							// System.out.println("temp[temp.length-1]="+temp[temp.length-1]);
							if (temp[temp.length - 1].compareTo(sal2.get(j)) < 0)
							{
								result.add(sal1.get(i) + "," + sal2.get(j));
							}

						}
					}
				}

			}
		}

		return result;

	}

	/*
	 * 给定一个TreeSet 生成与一个HashMap<String, Integer>,其中String为TreeSet,Integer为0
	 */
	public HashMap<String, Integer> TreeSet2HashMap(TreeSet<String> set)
	{
		HashMap<String, Integer> hm = new HashMap<String, Integer>();

		Iterator<String> it1 = set.iterator();

		while (it1.hasNext())
		{
			hm.put(it1.next(), 0);

		}

		return hm;
	}
}


程序运行结果如下所示:

ALLElectronics某分店的事务数据为:
    I1,I2,I5
    I2,I4
    I2,I3
    I1,I2,I4
    I1,I3
    I2,I3
    I1,I3
    I1,I2,I3,I5
    I1,I2,I3
----项集----|----支持度----l
     I3     |      6
     I4     |      2
     I1     |      6
     I2     |      7
     I5     |      2
第一次扫描事务数据库后L1=[I1, I2, I3, I4, I5]


通过L1 × L1生成C2时:


通过L1 生成L2为:
    I1,I2
    I1,I3
    I1,I4
    I1,I5
    I2,I3
    I2,I4
    I2,I5
    I3,I4
    I3,I5
    I4,I5




----项集----|----支持度----l
     I3,I4     |      0
     I3,I5     |      1
     I2,I4     |      2
     I1,I5     |      2
     I2,I5     |      2
     I2,I3     |      4
     I4,I5     |      0
     I1,I2     |      4
     I1,I4     |      1
     I1,I3     |      4


将候选集C1不满足最小支持度的元素删除后L2为:
    I1,I2
    I1,I3
    I1,I5
    I2,I3
    I2,I4
    I2,I5






通过L2 × L2生成C3时:
   {I1,I3,I5} 的2项子集 { I3,I5} 不是L2的元素,根据先验性质剪技,删除!
   {I2,I3,I4} 的2项子集 { I3,I4} 不是L2的元素,根据先验性质剪技,删除!
   {I2,I3,I5} 的2项子集 { I3,I5} 不是L2的元素,根据先验性质剪技,删除!
   {I2,I4,I5} 的2项子集 { I4,I5} 不是L2的元素,根据先验性质剪技,删除!


通过L2 生成L3为:
    I1,I2,I3
    I1,I2,I5




----项集----|----支持度----l
     I1,I2,I5     |      2
     I1,I2,I3     |      2


将候选集C2不满足最小支持度的元素删除后L3为:
    I1,I2,I3
    I1,I2,I5






通过L3 × L3生成C4时:
   {I1,I2,I3,I5} 的3项子集 { I1,I3,I5} 不是L3的元素,根据先验性质剪技,删除!
执行程序一共花费了11毫秒




  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值