热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

频繁模式挖掘中Apriori、FP-Growth和Eclat算法的实现和对比(Python实现)

最近上数据挖掘的课程,其中学习到了频繁模式挖掘这一章,这章介绍了三种算法,Apriori、FP-Growth和Eclat算法;由于对于不同的数据来说,这三种算法的表现不同,所以我们本次就对这三种算法在

最近上数据挖掘的课程,其中学习到了频繁模式挖掘这一章,这章介绍了三种算法,Apriori、FP-Growth和Eclat算法;由于对于不同的数据来说,这三种算法的表现不同,所以我们本次就对这三种算法在不同情况下的效率进行对比。从而得出适合相应算法的情况。

(一)算法原理

其中相应的算法原理在之前的博客中都有非常详细的介绍,这里就不再赘述,这里给出三种算法大概的介绍

但是这里给出每个算法的关键点:

1.1 Apriori算法:

  • 限制候选产生发现频繁项集
  • 重要性质:频繁项集所有非空子集也一定是频繁的。
  • 主要步骤:
  1. 连接
  2. 剪枝
  • 特点:需要多次扫描数据库,对于大规模数据效率很低!

Apriori算法原理详细介绍:http://www.cnblogs.com/90zeng/p/apriori.html

1.2 FP-Growth算法

  • 通过模式增长挖掘频繁模式
  • 主要步骤:
  1. 构建频繁模式树
  2. 构造条件模式基
  3. 挖掘频繁模式
  • 特点:两次扫描数据库,采用分治的策略有效降低搜索开销

FP-Growth算法原理详细介绍:http://www.cnblogs.com/datahunter/p/3903413.html

1.3 Eclat算法

  • 使用垂直格式挖掘频繁项集
  • 主要步骤:
  1. 将数据倒排{ item:TID_set }
  2. 通过求频繁k项集的交集来获取k+1项集
  • 特点:仅需要一次扫描数据库,TID集合很长的话需要消耗大量的内存和计算时间

Eclat算法原理详细介绍:http://www.cnblogs.com/catkins/p/5270484.html

(二)算法实现

由于各个博客给出的算法实现并不统一,而且本人在实现《机器学习实战》中FP-Growth算法的时候发现,在在创建FP-Tree时根据headTable中元素的支持度顺序的排序过程中,这个地方的排序方法写的有问题,当在模式稠密时,具有很多支持度相同的项集,书中的代码并没有考虑着一点,所以如果遇到支持度相同的项集那个就会出现一定的随机性,导致建树过程出错,最后的频繁项集结果会偏小,因此这里对改错误进行了纠正,在支持度相同时,添加了按照项集排序的规则,这样建立的FP-Tree才完全正确。

1.1 Apriori算法实现:

 1 # -*- coding: utf-8 -*-
 2 '''
 3 @author: Infaraway
 4 @time: 2017/4/15 12:54
 5 @Function:
 6 '''
 7 
 8 
 9 def init_c1(data_set_dict, min_support):
10     c1 = []
11     freq_dic = {}
12     for trans in data_set_dict:
13         for item in trans:
14             freq_dic[item] = freq_dic.get(item, 0) + data_set_dict[trans]
15     # 优化初始的集合,使不满足最小支持度的直接排除
16     c1 = [[k] for (k, v) in freq_dic.iteritems() if v >= min_support]
17     c1.sort()
18     return map(frozenset, c1)
19 
20 
21 def scan_data(data_set, ck, min_support, freq_items):
22     """
23     计算Ck中的项在数据集合中的支持度,剪枝过程
24     :param data_set:
25     :param ck:
26     :param min_support: 最小支持度
27     :param freq_items: 存储满足支持度的频繁项集
28     :return:
29     """
30     ss_cnt = {}
31     # 每次遍历全体数据集
32     for trans in data_set:
33         for item in ck:
34             # 对每一个候选项集, 检查是否是 term中的一部分(子集),即候选项能否得到支持
35             if item.issubset(trans):
36                 ss_cnt[item] = ss_cnt.get(item, 0) + 1
37     ret_list = []
38     for key in ss_cnt:
39         support = ss_cnt[key]  # 每个项的支持度
40         if support >= min_support:
41             ret_list.insert(0, key)  # 将满足最小支持度的项存入集合
42             freq_items[key] = support  #
43     return ret_list
44 
45 
46 def apriori_gen(lk, k):
47     """
48     由Lk的频繁项集生成新的候选项集  连接过程
49     :param lk:  频繁项集集合
50     :param k:  k 表示集合中所含的元素个数
51     :return: 候选项集集合
52     """
53     ret_list = []
54     for i in range(len(lk)):
55         for j in range(i+1, len(lk)):
56             l1 = list(lk[i])[:k-2]
57             l2 = list(lk[j])[:k-2]
58             l1.sort()
59             l2.sort()
60             if l1 == l2:
61                 ret_list.append(lk[i] | lk[j])  # 求并集
62     # retList.sort()
63     return ret_list
64 
65 
66 def apriori_zc(data_set, data_set_dict, min_support=5):
67     """
68     Apriori算法过程
69     :param data_set: 数据集
70     :param min_support: 最小支持度,默认值 0.5
71     :return:
72     """
73     c1 = init_c1(data_set_dict, min_support)
74     data = map(set, data_set)  # 将dataSet集合化,以满足scanD的格式要求
75     freq_items = {}
76     l1 = scan_data(data, c1, min_support, freq_items)  # 构建初始的频繁项集
77     l = [l1]
78     # 最初的L1中的每个项集含有一个元素,新生成的项集应该含有2个元素,所以 k=2
79     k = 2
80     while len(l[k - 2]) > 0:
81         ck = apriori_gen(l[k - 2], k)
82         lk = scan_data(data, ck, min_support, freq_items)
83         l.append(lk)
84         k += 1  # 新生成的项集中的元素个数应不断增加
85     return freq_items
View Code

1.2 FP-Growth算法实现:

1)FP_Growth文件:

在create_tree()函数中修改《机器学习实战》中的代码:

##############################################################################################
# 这里修改机器学习实战中的排序代码:
ordered_items = [v[0] for v in sorted(local_data.items(), key=lambda kv: (-kv[1], kv[0]))]
##############################################################################################

  1 # -*- coding: utf-8 -*-
  2 """
  3 @author: Infaraway
  4 @time: 2017/4/15 16:07
  5 @Function:
  6 """
  7 from DataMining.Unit6_FrequentPattern.FP_Growth.TreeNode import treeNode
  8 
  9 
 10 def create_tree(data_set, min_support=1):
 11     """
 12     创建FP树
 13     :param data_set: 数据集
 14     :param min_support: 最小支持度
 15     :return:
 16     """
 17     freq_items = {}  # 频繁项集
 18     for trans in data_set:  # 第一次遍历数据集
 19         for item in trans:
 20             freq_items[item] = freq_items.get(item, 0) + data_set[trans]
 21 
 22     header_table = {k: v for (k, v) in freq_items.iteritems() if v >= min_support}  # 创建头指针表
 23     # for key in header_table:
 24     #     print key, header_table[key]
 25 
 26     # 无频繁项集
 27     if len(header_table) == 0:
 28         return None, None
 29     for k in header_table:
 30         header_table[k] = [header_table[k], None]  # 添加头指针表指向树中的数据
 31     # 创建树过程
 32     ret_tree = treeNode('Null Set', 1, None)  # 根节点
 33 
 34     # 第二次遍历数据集
 35     for trans, count in data_set.items():
 36         local_data = {}
 37         for item in trans:
 38             if header_table.get(item, 0):
 39                 local_data[item] = header_table[item][0]
 40         if len(local_data) > 0:
 41             ##############################################################################################
 42             # 这里修改机器学习实战中的排序代码:
 43             ordered_items = [v[0] for v in sorted(local_data.items(), key=lambda kv: (-kv[1], kv[0]))]
 44             ##############################################################################################
 45             update_tree(ordered_items, ret_tree, header_table, count)  # populate tree with ordered freq itemset
 46     return ret_tree, header_table
 47 
 48 
 49 def update_tree(items, in_tree, header_table, count):
 50     '''
 51     :param items: 元素项
 52     :param in_tree: 检查当前节点
 53     :param header_table:
 54     :param count:
 55     :return:
 56     '''
 57     if items[0] in in_tree.children:  # check if ordered_items[0] in ret_tree.children
 58         in_tree.children[items[0]].increase(count)  # incrament count
 59     else:  # add items[0] to in_tree.children
 60         in_tree.children[items[0]] = treeNode(items[0], count, in_tree)
 61         if header_table[items[0]][1] is None:  # update header table
 62             header_table[items[0]][1] = in_tree.children[items[0]]
 63         else:
 64             update_header(header_table[items[0]][1], in_tree.children[items[0]])
 65     if len(items) > 1:  # call update_tree() with remaining ordered items
 66         update_tree(items[1::], in_tree.children[items[0]], header_table, count)
 67 
 68 
 69 def update_header(node_test, target_node):
 70     '''
 71     :param node_test:
 72     :param target_node:
 73     :return:
 74     '''
 75     while node_test.node_link is not None:  # Do not use recursion to traverse a linked list!
 76         node_test = node_test.node_link
 77     node_test.node_link = target_node
 78 
 79 
 80 def ascend_tree(leaf_node, pre_fix_path):
 81     '''
 82     遍历父节点,找到路径
 83     :param leaf_node:
 84     :param pre_fix_path:
 85     :return:
 86     '''
 87     if leaf_node.parent is not None:
 88         pre_fix_path.append(leaf_node.name)
 89         ascend_tree(leaf_node.parent, pre_fix_path)
 90 
 91 
 92 def find_pre_fix_path(base_pat, tree_node):
 93     '''
 94     创建前缀路径
 95     :param base_pat: 频繁项
 96     :param treeNode: FP树中对应的第一个节点
 97     :return:
 98     '''
 99     # 条件模式基
100     cond_pats = {}
101     while tree_node is not None:
102         pre_fix_path = []
103         ascend_tree(tree_node, pre_fix_path)
104         if len(pre_fix_path) > 1:
105             cond_pats[frozenset(pre_fix_path[1:])] = tree_node.count
106         tree_node = tree_node.node_link
107     return cond_pats
108 
109 
110 def mine_tree(in_tree, header_table, min_support, pre_fix, freq_items):
111     '''
112     挖掘频繁项集
113     :param in_tree:
114     :param header_table:
115     :param min_support:
116     :param pre_fix:
117     :param freq_items:
118     :return:
119     '''
120     # 从小到大排列table中的元素,为遍历寻找频繁集合使用
121     bigL = [v[0] for v in sorted(header_table.items(), key=lambda p: p[1])]  # (sort header table)
122     for base_pat in bigL:  # start from bottom of header table
123         new_freq_set = pre_fix.copy()
124         new_freq_set.add(base_pat)
125         # print 'finalFrequent Item: ',new_freq_set    #append to set
126         if len(new_freq_set) > 0:
127             freq_items[frozenset(new_freq_set)] = header_table[base_pat][0]
128         cond_patt_bases = find_pre_fix_path(base_pat, header_table[base_pat][1])
129         my_cond_tree, my_head = create_tree(cond_patt_bases, min_support)
130         # print 'head from conditional tree: ', my_head
131         if my_head is not None:  # 3. mine cond. FP-tree
132             # print 'conditional tree for: ',new_freq_set
133             # my_cond_tree.disp(1)
134             mine_tree(my_cond_tree, my_head, min_support, new_freq_set, freq_items)
135 
136 
137 def fp_growth(data_set, min_support=1):
138     my_fp_tree, my_header_tab = create_tree(data_set, min_support)
139     # my_fp_tree.disp()
140     freq_items = {}
141     mine_tree(my_fp_tree, my_header_tab, min_support, set([]), freq_items)
142     return freq_items
View Code

2)treeNode对象文件

 1 # -*- coding: utf-8 -*-
 2 '''
 3 @author: Infaraway
 4 @time: 2017/3/31 0:14
 5 @Function:
 6 '''
 7 
 8 
 9 class treeNode:
10     def __init__(self, name_value, num_occur, parent_node):
11         self.name = name_value  # 节点元素名称
12         self.count = num_occur  # 出现的次数
13         self.node_link = None  # 指向下一个相似节点的指针,默认为None
14         self.parent = parent_node  # 指向父节点的指针
15         self.children = {}  # 指向孩子节点的字典 子节点的元素名称为键,指向子节点的指针为值
16 
17     def increase(self, num_occur):
18         """
19         增加节点的出现次数
20         :param num_occur: 增加数量
21         :return:
22         """
23         self.count += num_occur
24 
25     def disp(self, ind=1):
26         print '  ' * ind, self.name, ' ', self.count
27         for child in self.children.values():
28             child.disp(ind + 1)
View Code

1.3 Eclat算法实现

 1 # -*- coding: utf-8 -*-
 2 """
 3 @author: Infaraway
 4 @time: 2017/4/15 19:33
 5 @Function:
 6 """
 7 
 8 import sys
 9 import time
10 type = sys.getfilesystemencoding()
11 
12 
13 def eclat(prefix, items, min_support, freq_items):
14     while items:
15         # 初始遍历单个的元素是否是频繁
16         key, item = items.pop()
17         key_support = len(item)
18         if key_support >= min_support:
19             # print frozenset(sorted(prefix+[key]))
20             freq_items[frozenset(sorted(prefix+[key]))] = key_support
21             suffix = []  # 存储当前长度的项集
22             for other_key, other_item in items:
23                 new_item = item & other_item  # 求和其他集合求交集
24                 if len(new_item) >= min_support:
25                     suffix.append((other_key, new_item))
26             eclat(prefix+[key], sorted(suffix, key=lambda item: len(item[1]), reverse=True), min_support, freq_items)
27     return freq_items
28 
29 
30 def eclat_zc(data_set, min_support=1):
31     """
32     Eclat方法
33     :param data_set:
34     :param min_support:
35     :return:
36     """
37     # 将数据倒排
38     data = {}
39     trans_num = 0
40     for trans in data_set:
41         trans_num += 1
42         for item in trans:
43             if item not in data:
44                 data[item] = set()
45             data[item].add(trans_num)
46     freq_items = {}
47     freq_items = eclat([], sorted(data.items(), key=lambda item: len(item[1]), reverse=True), min_support, freq_items)
48     return freq_items
View Code

 

(三)试验阶段:

这样我们就统一了三种算法的调用以及返回值,现在我们可以开始试验阶段了,我们在试验阶段分别根据最小支持度阈值和数据规模的变化来判断这三种算法的效率:

首先我们先统一调用者三个算法:

 1 def test_fp_growth(minSup, dataSetDict, dataSet):
 2     freqItems = fp_growth(dataSetDict, minSup)
 3     freqItems = sorted(freqItems.iteritems(), key=lambda item: item[1])
 4     return freqItems
 5 
 6 
 7 def test_apriori(minSup, dataSetDict, dataSet):
 8     freqItems = apriori_zc(dataSet, dataSetDict, minSup)
 9     freqItems = sorted(freqItems.iteritems(), key=lambda item: item[1])
10     return freqItems
11 
12 
13 def test_eclat(minSup, dataSetDict, dataSet):
14     freqItems = eclat_zc(dataSet, minSup)
15     freqItems = sorted(freqItems.iteritems(), key=lambda item: item[1])
16     return freqItems

然后实现数据规模变化的效率改变

 1 def do_experiment_min_support():
 2 
 3     data_name = 'unixData8_pro.txt'
 4     x_name = "Min_Support"
 5     data_num = 1500
 6     minSup = data_num / 6
 7 
 8     dataSetDict, dataSet = loadDblpData(open("dataSet/" + data_name), ',', data_num)
 9     step = minSup / 5  # #################################################################
10     all_time = []
11     x_value = []
12     for k in range(5):
13 
14         x_value.append(minSup)  # #################################################################
15         if minSup <0:  # #################################################################
16             break
17         time_fp = 0
18         time_et = 0
19         time_ap = 0
20         freqItems_fp = {}
21         freqItems_eclat = {}
22         freqItems_ap = {}
23         for i in range(10):
24             ticks0 = time.time()
25             freqItems_fp = test_fp_growth(minSup, dataSetDict, dataSet)
26             time_fp += time.time() - ticks0
27             ticks0 = time.time()
28             freqItems_eclat = test_eclat(minSup, dataSetDict, dataSet)
29             time_et += time.time() - ticks0
30             ticks0 = time.time()
31             freqItems_ap = test_apriori(minSup, dataSetDict, dataSet)
32             time_ap += time.time() - ticks0
33         print "minSup :", minSup, "      data_num :", data_num, \
34             "  freqItems_fp:", len(freqItems_fp), " freqItems_eclat:", len(freqItems_eclat), "  freqItems_ap:", len(
35             freqItems_ap)
36         print "fp_growth:", time_fp / 10, "       eclat:", time_et / 10, "      apriori:", time_ap / 10
37         # print_freqItems("show", freqItems_eclat)
38         minSup -= step   # #################################################################
39         use_time = [time_fp / 10, time_et / 10, time_ap / 10]
40         all_time.append(use_time)
41         # print use_time
42     y_value = []
43     for i in range(len(all_time[0])):
44         tmp = []
45         for j in range(len(all_time)):
46             tmp.append(all_time[j][i])
47         y_value.append(tmp)
48     plot_pic(x_value, y_value, data_name, x_name)
49     return x_value, y_value
View Code

然后实现最小支持度变化的效率改变

 1 def do_experiment_data_size():
 2 
 3     data_name = 'kosarakt.txt'
 4     x_name = "Data_Size"
 5     data_num = 200000
 6 
 7     step = data_num / 5  # #################################################################
 8     all_time = []
 9     x_value = []
10     for k in range(5):
11         minSup = data_num * 0.010
12         dataSetDict, dataSet = loadDblpData(open("dataSet/"+data_name), ' ', data_num)
13         x_value.append(data_num)  # #################################################################
14         if data_num <0:  # #################################################################
15             break
16         time_fp = 0
17         time_et = 0
18         time_ap = 0
19         freqItems_fp = {}
20         freqItems_eclat = {}
21         freqItems_ap = {}
22         for i in range(2):
23             ticks0 = time.time()
24             freqItems_fp = test_fp_growth(minSup, dataSetDict, dataSet)
25             time_fp += time.time() - ticks0
26             ticks0 = time.time()
27             freqItems_eclat = test_eclat(minSup, dataSetDict, dataSet)
28             time_et += time.time() - ticks0
29             ticks0 = time.time()
30             # freqItems_ap = test_apriori(minSup, dataSetDict, dataSet)
31             # time_ap += time.time() - ticks0
32         print "minSup :", minSup, "      data_num :", data_num, \
33             "  freqItems_fp:", len(freqItems_fp), " freqItems_eclat:", len(freqItems_eclat), "  freqItems_ap:", len(freqItems_ap)
34         print "fp_growth:", time_fp / 10, "       eclat:", time_et / 10, "      apriori:", time_ap / 10
35         # print_freqItems("show", freqItems_eclat)
36         data_num -= step   # #################################################################
37         use_time = [time_fp / 10, time_et / 10, time_ap / 10]
38         all_time.append(use_time)
39         # print use_time
40 
41     y_value = []
42     for i in range(len(all_time[0])):
43         tmp = []
44         for j in range(len(all_time)):
45             tmp.append(all_time[j][i])
46         y_value.append(tmp)
47     plot_pic(x_value, y_value, data_name, x_name)
48     return x_value, y_value
View Code

同时为了观察方便,我们需要对三种算法返回的结果进行绘图

 1 # -*- coding: utf-8 -*-
 2 """
 3 @author: Infaraway
 4 @time: 2017/4/16 20:48
 5 @Function:
 6 """
 7 
 8 import matplotlib.pyplot as plt
 9 
10 
11 def plot_pic(x_value, y_value, title, x_name):
12     plot1 = plt.plot(x_value, y_value[0], 'r', label='Kulc')  # use pylab to plot x and y
13     plot2 = plt.plot(x_value, y_value[1], 'g', label='IR')  # use pylab to plot x and y
14     # plot3 = plt.plot(x_value, y_value[2], 'b', label='Apriori')  # use pylab to plot x and y
15     plt.title(title)  # give plot a title
16     plt.xlabel(x_name)  # make axis labels
17     plt.ylabel('value ')
18     plt.legend(loc='upper right')  # make legend
19 
20     plt.show()  # show the plot on the screen
View Code

 将两个部分统一执行:

1 if __name__ == '__main__':
2 
3     # x_value, y_value = do_experiment_min_support()
4     # x_value, y_value = do_experiment_data_size()
5     # do_test()

(四)实验结果分析:

本次实验我们主要从以下几个方面来讨论三种算法的效率:

  • 数据规模大小
  • 最小支持度阈值
  • 长事物数据
  • 模式的稠密性

4.1 数据规模大小:

数据集:unxiData8

规模:900-1500

           Min_support = 1/30时                                    Min_support = 1/20时

数据集:kosarakt
规模:6000-10000

             Min_support = 1/50                                                 Min_support = 1/80                                     Min_support = 1/100


结论:一般情况下,数据规模越大,使用Apriori算法的效率越低,因为该算法需要多次扫描数据库,当数据量越大时,扫描数据库带来的消耗越多。

4.2 最小支持度大小

数据集:unixData8
支持度:4% - 20%

                    Data_size = 500                                 Data_size = 1000                                       Data_size = 1500

数据集:kosarakt
支持度:1% - 2%

 

            Data_size = 3000                                                   Data_size = 5000                                         Data_size = 10000

结论:

  • 最小支持度越小,各个算法所花费的时间越多且Apriori算法效率最差;
  1. Apriori算法候选项集较多,扫描数据库次数较多
  2. FP-Growth算法FP树较茂盛,求解模式更多
  3. Eclat算法求交集次数较多
  • 随着最小支持度的增加,各个算法的效率逐渐接近,相当于数据量较小的情况。

4.3 长事物数据:

数据集:movieItem                       DataSize = 943

特点:单个事务数据比较长, 大量单个条目达到500个项(但频繁模式并不长)

 

             Min_support = 1/4                                                      Min_support = 1/6                                           Min_support = 1/8

结论:对于长事物的数据集来说

  • 最小支持度较大时,此时由于生成的FP树深度较大,求解的子问题较多,FP算法性能显著下降;
  • 最小支持度较小时,此时Apriori算法生成大量候选项,扫描数据库次数显著增加,Apriori算法性能显著下降

4.4 模式稠密性:

数据集:movieItem
特点:单个事物间相似度很大(导致频繁模式特别多且比较长)

 

                    Min_support = 0.8                                          Min_support = 0.9

结论: 对于模式比较稠密的数据集来说,由于会产生特别多而且比较长的模式,三种算法的效率均有下降,其中FP-Growth算法中FP树层次较深,会产生较多的子问题,Eclat算法则需要进行大量的求交集运算,并且消耗大量的存储空间,Apriori算法则需要更多次的扫描数据库,因此效率最低。

(五)总结:

从上面实验可以看到,Apriori算法的效率最低,因为他需要很多次的扫描数据库;其次FP—Growth算法在长事物数据上表现很差,因为当事物很长时,树的深度也很大,需要求解的子问题就变得特别多,因此效率会迅速下降;Eclat算法的效率最高,但是由于我们事先使用了递归的思想,当数据量很大的时候会给系统带来巨大的负担,因此不适合数据量很大的情况;当然有一种叫做diffset的技术可以解决Eclat算法的不足,这里我们不做讨论!

本次实验的所有代码和数据下载:链接:http://pan.baidu.com/s/1jHAT7cq 密码:21pb

 


推荐阅读
  • 一.数据基本类型之set集合set和dict类似,也是一组key的集合,但不存储value。由于key不能重复,所以,在se ... [详细]
  • 本文介绍了进程的基本概念及其在操作系统中的重要性,探讨了进程与程序的区别,以及如何通过多进程实现并发和并行。文章还详细讲解了Python中的multiprocessing模块,包括Process类的使用方法、进程间的同步与异步调用、阻塞与非阻塞操作,并通过实例演示了进程池的应用。 ... [详细]
  • 帝国cms各数据表有什么用
    CMS教程|帝国CMS帝国cmsCMS教程-帝国CMS精易编程助手源码,ubuntu桥接设置,500错误是tomcat吗,爬虫c原理,php会话包括什么,营销seo关键词优化一般多 ... [详细]
  • BeautifulSoup4 是一个功能强大的HTML和XML解析库,它能够帮助开发者轻松地从网页中提取信息。本文将介绍BeautifulSoup4的基本功能、安装方法、与其他解析工具的对比以及简单的使用示例。 ... [详细]
  • [编程题] LeetCode上的Dynamic Programming(动态规划)类型的题目
    继上次把backTracking的题目做了一下之后:backTracking,我把LeetCode的动态规划的题目又做了一下,还有几道比较难的Medium的题和Hard的题没做出来,后面会继续 ... [详细]
  • 利用50行Python代码打造经典游戏,既是休闲娱乐,也是编程学习的利器
    Free Python Games 是一个适合学生和初学者的项目,它不仅提供了高度的组织性和灵活性,还极大地激发了用户的探索与理解能力。 ... [详细]
  • 本文介绍如何使用Python编程语言合并字典中具有相同集合值的键,并提供两种实现方法。 ... [详细]
  • Python 中 filter、map 和 reduce 函数详解
    本文深入探讨了 Python 编程语言中 filter、map 和 reduce 函数的功能与用法,包括它们的基本语法、应用场景及代码示例,旨在帮助读者更好地理解和运用这些高阶函数。 ... [详细]
  • Python闭包深度解析与应用实例
    本文详细介绍了Python闭包的基本概念、必要条件及其实现方式,并通过具体示例说明闭包在提高代码复用性和维护性方面的作用。文章最后还探讨了闭包的内部机制及其在实际项目中的应用。 ... [详细]
  • Python脚本实现批量删除多种类型文件的扩展名
    本文介绍了一个Python脚本,用于批量处理并移除指定目录下不同格式文件(如png、jpg、xml、json、txt、gt等)的文件扩展名。该方法通过递归遍历文件夹中的所有文件,并对每个文件执行重命名操作。 ... [详细]
  • 本文简要介绍了如何使用 Python Elasticsearch DSL 进行基本和高级查询,包括连接 Elasticsearch、执行简单和复杂查询、聚合、排序及分页等。 ... [详细]
  • 本文探讨了在Eclipse环境中使用Python执行操作系统命令时遇到的问题及解决方案,特别是关于环境变量访问和命令执行结果的获取。 ... [详细]
  • 时序数据是指按时间顺序排列的数据集。通过时间轴上的数据点连接,可以构建多维度报表,揭示数据的趋势、规律及异常情况。 ... [详细]
  • 本文探讨了Java中有效停止线程的多种方法,包括使用标志位、中断机制及处理阻塞I/O操作等,旨在帮助开发者避免使用已废弃的危险方法,确保线程安全和程序稳定性。 ... [详细]
  • 解决远程桌面连接时的身份验证错误问题
    本文介绍了如何解决在尝试远程访问服务器时遇到的身份验证错误,特别是当系统提示‘要求的函数不受支持’时的具体解决步骤。通过调整Windows注册表设置,您可以轻松解决这一常见问题。 ... [详细]
author-avatar
猫ranran
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有