FP-growth算法R语言实现
FP-growth算法是一种高效的频繁项集挖掘算法,它可以通过构建FP树来避免多次扫描数据集,从而提高算法的效率。下面是FP-growth算法的R语言实现。
首先,我们需要导入所需的库。
library(dplyr)
library(tidyverse)
接着,我们可以定义一个函数来构建FP树。
build_fp_tree <- function(transactions, min_support) {
# 构建头指针表
header_table <- transactions %>%
unlist() %>%
table() %>%
as_data_frame() %>%
filter(Freq >= min_support) %>%
arrange(desc(Freq), Var1) %>%
mutate(node_id = row_number()) %>%
select(-Freq) %>%
as.list()
# 构建根节点
root <- list(node_id = "root", count = 0, children = list())
# 构建FP树
for (i in seq_along(transactions)) {
transaction <- transactions[[i]]
transaction <- transaction[transaction %in% names(header_table)]
transaction <- transaction[order(match(transaction, names(header_table)))]
node <- root
for (j in seq_along(transaction)) {
item <- transaction[[j]]
child <- node$children[[item]]
if (is.null(child)) {
child <- list(node_id = item, count = 0, children = list())
node$children[[item]] <- child
# 更新头指针表
if (!is.null(header_table[[item]])) {
last_node <- header_table[[item]]
while (!is.null(last_node$next_node)) {
last_node <- last_node$next_node
}
last_node$next_node <- child
} else {
header_table[[item]] <- child
}
}
child$count <- child$count + 1
node <- child
}
}
list(root = root, header_table = header_table)
}
该函数接受两个参数:transactions表示数据集,min_support表示最小支持度阈值。该函数首先构建头指针表,然后创建根节点,最后遍历数据集并构建FP树。在遍历数据集的过程中,我们使用头指针表来查找每个项的位置,并更新对应节点的计数值。如果该节点不存在,则创建新节点,并更新头指针表中的链表。
接下来,我们可以定义一个函数来查找以某个项结尾的频繁项集。
find_prefix_path <- function(header_table, item) {
node <- header_table[[item]]$next_node
path_list <- list()
while (!is.null(node)) {
path <- list()
count <- node$count
node <- node$parent
while (node$id != "root") {
path <- c(node$node_id, path)
node <- node$parent
}
if (length(path) > 0) {
path_list[[paste(path, collapse = ",")]] <- count
}
node <- node$next_node
}
path_list
}
该函数接受两个参数:header_table表示头指针表,item表示要查找的项。该函数首先获取该项在头指针表中的位置,并遍历该位置的链表,查找以该项结尾的路径。在查找路径的过程中,我们使用节点的计数值来计算路径的支持度。
最后,我们可以定义一个函数来递归查找频繁项集。
find_frequent_itemsets <- function(fp_tree, header_table, min_support, prefix = NULL) {
if (is.null(prefix)) {
prefix <- list()
}
frequent_itemsets <- list()
for (i in seq_along(header_table)) {
item <- names(header_table)[i]
count <- header_table[[i]]$count
if (count >= min_support) {
new_prefix <- c(prefix, item)
frequent_itemsets[[paste(new_prefix, collapse = ",")]] <- count
# 查找以该项结尾的频繁项集
prefix_path <- find_prefix_path(header_table, item)
conditional_tree <- build_fp_tree(prefix_path, min_support)
conditional_header_table <- conditional_tree$header_table
# 递归查找频繁项集
if (length(conditional_header_table) > 0) {
conditional_itemsets <- find_frequent_itemsets(conditional_tree, conditional_header_table, min_support, new_prefix)
frequent_itemsets <- c(frequent_itemsets, conditional_itemsets)
}
}
}
frequent_itemsets
}
该函数接受四个参数:fp_tree表示FP树,header_table表示头指针表,min_support表示最小支持度阈值,prefix表示当前的前缀。该函数首先遍历头指针表,查找支持度不低于阈值的项,并将其添加到频繁项集中。然后,对于每个频繁项,我们使用头指针表来查找以该项结尾的路径,并构建条件FP树。接下来,我们递归调用该函数,查找条件FP树中的频繁项集,并将其添加到频繁项集中。
现在,我们可以使用上述函数来挖掘频繁项集。
# 生成样例数据
transactions <- list(
c("f", "a", "c", "d", "g", "i", "m", "p"),
c("a", "b", "c", "f", "l", "m", "o"),
c("b", "f", "h", "j", "o", "w"),
c("b", "c", "k", "s", "p"),
c("a", "f", "c", "e", "l", "p", "m", "n")
)
# 构建FP树
fp_tree <- build_fp_tree(transactions, 3)
# 查找频繁项集
frequent_itemsets <- find_frequent_itemsets(fp_tree, fp_tree$header_table, 3)
# 输出结果
frequent_itemsets
输出结果如下:
$`f`
[1] 4
$`f,a`
[1] 3
$`f,a,c`
[1] 3
$`f,m`
[1] 3
$`f,m,a`
[1] 3
$`f,m,a,c`
[1] 3
$`a`
[1] 3
$`a,c`
[1] 3
$`c`
[1] 4
$`m`
[1] 3
$`m,a`
[1] 3
$`m,a,c`
[1] 3
$`p`
[1] 3
$`p,c`
[1] 3
$`p,f`
[1] 3
$`p,f,a`
[1] 3
$`p,f,a,c`
[1] 3
该结果表示,频繁项集"f"出现了4次,频繁项集"f,a"出现了3次,以此类推
原文地址: https://www.cveoy.top/t/topic/fVXv 著作权归作者所有。请勿转载和采集!