Apriori算法原理

article/2025/9/20 18:12:03

实验环境

  • python 3.6.5
  • jupyter

  • 【原理】Apriori算法原理

    Apriori算法是一种用于关联规则挖掘的代表性算法。从本节开始,我们已经进入了机器学习和数据挖掘相交叉的地带。

    数据挖掘与机器学习

    数据挖掘和机器学习的关系就好比,机器学习是数据挖掘的弹药库中一类相当庞大的弹药集。既然是一类弹药,其实也就是在说数据挖掘中肯定还有其他非机器学习范畴的技术存在。Apriori算法就属于一种非机器学习的数据挖掘技术。
    在非机器学习的数据挖掘技术中,我们并不会去建立这样一个模型,而是直接从原数据集入手,设法分析出隐匿在数据背后的某些信息或知识。在后续介绍Apriori算法时,你会相当明显地感受到这一特点。

    Apriori算法

    我们先从一个例子了解一下apriori原理。被大家所熟知的"啤酒尿布"的购买行为问题,其实就是一个具有关联性的行为。而发现这种关联性行为的方式,可以用apriori原理来实现。
    从大规模数据集中寻找物品间的隐含关系被称作“关联分析”或者“关联规则学习”。而我们需要关注的问题是,如何使用更智能的方法,在更合理的时间范围内找到我们所需要的关联规则。
    以此,引出了我们的aprori算法。

    我们先来介绍几个概念。

    关联分析,是一种在大规模数据集中寻找有趣关系的任务。在这种关系中,存在着两种形式:频繁项集或者关联规则。

    频繁项集(frequent item sets),是经常出现在一块的物品的集合;关联规则(association rules),暗示两种物品之间可能存在很强的关系。频繁项集是我们对原始数据格式化后的源数据集,而关联规则则是寻找源数据集关系得到的结果数据集。{}为集合标识。在下图中,{葡萄酒,尿布,豆奶}就是频繁项集的一个例子。在频繁项集中,我们也可以找到诸如“{尿布}->{葡萄酒}”的关联规则。这意味着如果有人买了尿布,那么他很可能也会买葡萄酒。

  •  

    那么应该如何定义这些有趣的关系?谁来定义什么是有趣?当寻找频繁项集时,频繁的定义又是什么?

    一个项集的支持度(support)被定义为数据集中包含该项集的记录所占的比例。支持度是针对项集,我们可以定义一个最小支持度,来保留满足最小支持度的项集。

    如在上图中,{豆奶}的支持度为4/5,而{豆奶,尿布}的支持度为3/5

    可信度又称为置信度(confidence)是针对一条关联规则定义的。

    对于关联规则“{尿布}->{葡萄酒}”,它的可信度被定义为“支持度({尿布,葡萄酒})/支持度({尿布})”,计算该规则可信度为0.75,这意味着对于包含“尿布”的所有记录,我们的规则对其中75%的记录都适用。

    在上面介绍的支持度和可信度被用来量化关联分析是否成功。但在实际操作的过程中,我们需要对物品所有的组合计算其支持度和可信度,当物品量上万时,上述的操作会非常非常慢。

    我们该如何解决这种问题呢?

    我们已经知道,大多数关联规则挖掘算法通常采用的一种策略是,将关联规则挖掘任务分解为如下两个主要的子任务。

  • 频繁项集产生:其目标是发现满足最小支持度阈值的所有项集,这些项集称作频繁项集(frequent itemset)。
    规则的产生:其目标是从上一步发现的频繁项集中提取所有高置信度的规则,这些规则称作强规则(strong rule)。

    Apriori算法是生成频繁集的一种算法。

  •  

  • 上图显示了4种商品所有可能的组合。对给定的集合项集{0,3},需要遍历每条记录并检查是否同时包含0和3,扫描完后除以记录总数即可得支持度。对于包含N种物品的数据集共有2的N次方-1种项集组合,即使100种,也会有1.26×10的30次方种可能的项集组成。

    为降低计算时间,可用Apriori原理:如果某个项集是频繁的,那么它的所有子集也是频繁的。而我们需要使用的则是它的逆反定义:如果一个项集是非频繁集,那么它的所有超集也是非频繁的。

    在下图中,已知阴影项集{2,3}是非频繁的,根据Apriori原理,我们知道{0,2,3},{1,2,3}以及{0,1,2,3}也是非频繁的,我们就不需要计算其支持度了。

  •  这样就可以避免项集数目的指数增长,从而找到频繁项集。

  • 【实验】python实现Apriori算法——发现频繁集

    我们已经知道关联分析的目标分为:发现频繁项集和发现关联规则。

    首先需要找到频繁项集,然后才能获得关联规则。本节我们将重点放在如何发现频繁项集上。

    Apriori算法会首先构建集合C1,C1是大小为1的所有候选项集的集合,然后扫描数据集来判断只有一个元素的项集是否满足最小支持度的要求。那么满足最低要求的项集构成集合L1。

    而集合L1中的元素相互组合构成C2,C2再进一步过滤变成L2,以此循环直到Lk为空。

    在上述对Apriori算法的描述中,我们可以很清楚的看到,需要构建相应的功能函数来实现该算法:

    1.createC1 -构建集合C1
    2.scanD -过滤集合C1,构建L1
    3.aprioriGen -对集合Lk中的元素相互组合构建Ck+1
    4.apriori -集成函数

    我们按照该逻辑来实现我们的apriori算法,并找到频繁项集。

    在当前工作目录下,添加如下代码:

  • # -*-coding:utf-8 -*-
    from numpy import *
    """
    函数说明:加载数据集
    """
    def loadDataSet():return [[1, 3, 4], [2, 3, 5], [1, 2, 3, 5], [2, 5]]
    """
    函数说明:构建集合C1。即所有候选项元素的集合。
    parameters:dataSet -数据集
    return:frozenset列表
    output:[forzenset([1]),forzenset([2]),……]
    """
    def createC1(dataSet):C1 = []                     #创建一个空列表for transaction in dataSet: #对于数据集中的每条记录for item in transaction:#对于每条记录中的每一个项if not [item] in C1:       #如果该项不在C1中,则添加C1.append([item])C1.sort()                   #对集合元素排序return list(map(frozenset,C1))    #将C1的每个单元列表元素映射到forzenset()
    """
    函数说明:构建符合支持度的集合Lk
    parameters:D -数据集Ck -候选项集列表minSupport -感兴趣项集的最小支持度
    return:retList -符合支持度的频繁项集合列表LsupportData -最频繁项集的支持度
    """
    def scanD(D,Ck,minSupport):ssCnt = {}                                              #创建空字典#在下面添加代码,遍历数据集中的交易记录,统计Ck中候选集的计数,结果存放在ssCnt中for temp in D:for temp1 in Ck:if temp1.issubset(temp):if not temp1 in ssCnt:ssCnt[temp1] = 1else:ssCnt[temp1] += 1#print("整理后的字典为:")                #print(ssCnt)                numItems = float(len(D))                                #得到数据集中交易记录的条数retList = []                                            #新建空列表supportData = {}                                        #新建空字典用来存储最频繁集和支持度for key in ssCnt:support = ssCnt[key] / numItems                     #计算每个元素的支持度if support >= minSupport:                           #如果大于最小支持度则添加到retList中retList.insert(0,key)supportData[key] = support                          #并记录当前支持度,索引值即为元素值return retList,supportDataif __name__ == '__main__':dataSet = loadDataSet()print("数据集:\n",dataSet)C1 = createC1(dataSet)print("候选集C1:\n",C1)D = list(map(set,dataSet))  #将数据转换为集合形式#print(D)L1,supportData = scanD(D,C1,0.5)print("满足最小支持度为0.5的频繁项集L1:\n",L1)

    运行结果如下:

  • 数据集:[[1, 3, 4], [2, 3, 5], [1, 2, 3, 5], [2, 5]]
    候选集C1:[frozenset({1}), frozenset({2}), frozenset({3}), frozenset({4}), frozenset({5})]
    满足最小支持度为0.5的频繁项集L1:[frozenset({5}), frozenset({2}), frozenset({3}), frozenset({1})]

其中forzenset为不可变集合,它的值是不可变的,好处是它可以作为字典的key,也可以作为其他集合的元素。我们这里必须使用forzenset而不是set,就是因为我们需要将这些集合作为字典键值使用。

至此,我们完成了C1和L1的构建。那么对于L1中元素的组合,我们需要先引入一个组合定义。
假定我们的L1中元素为[{0},{1},{2}],我们想要aprioriGen函数生成元素的组合C2,即[{0,1},{0,2},{1,2}]。这是单个项的组合。那么我们考虑一下,如果想利用[{0,1},{0,2},{1,2}]来创建三元素的候选项集C3呢?如果依旧按照单个项的组合方法,将每两个集合合并,就会得到{0,1,2},{0,1,2},{0,1,2}。也就是说,我们重复操作了3次。

接下来还需要扫描该结果来得到非重复结果,但我们要确保的是遍历列表的次数最少。那么如何解决这个问题呢?我们观察到,如果比较集合{0,1},{0,2},{1,2}的第一个元素并只对第一个元素相同的集合求并操作,我们会得到{0,1,2}相同的结果,但只操作了1次!这样的话就不需要遍历列表来寻找非重复值。也能够实现apriori算法的原理。当我们创建三元素的候选集时,k=3,但此时待组合的频繁项集元素为f=2,即我们只需比较前f-1个元素,也就是前k-2个元素。

打开apriori.py文件,修改代码如下:

"""
函数说明:构建集合Ck
parameters:Lk -频繁项集列表Lk -候选集的列表中元素项的个数
return:retList -候选集项列表Ck
"""
def aprioriGen(Lk,k):retList =[]                                           #创建一个空列表lenLk = len(Lk)                                         #得到当前频繁项集合列表中元素的个数#在下面添加代码,遍历Lk,比较每两个项集,如果符合合并要求,则用集合合并操作|来产生k+1项集,并存入retList#[注]此处需要比较两个项集的前k-2个元素,试说明原因for i in range(lenLk):for j in range(i+1,lenLk):L1=list(Lk[i])L2=list(Lk[j])L1.sort()L2.sort()if L1[0:k-2]==L2[0:k-2]:retList.append(Lk[i]|Lk[j])#print(retList)return retList
"""
函数说明:apriori算法实现
parameters:dataSet -数据集minSupport -最小支持度
return:L -候选项集的列表supportData -项集支持度
"""
def apriori(dataSet,minSupport=0.5):C1 = createC1(dataSet)D = list(map(set,dataSet))                      #将数据集转化为集合列表L1, supportData = scanD(D,C1,minSupport)    #调用scanD()函数,过滤不符合支持度的候选项集L = [L1]                                    #将过滤后的L1放入L列表中k = 2                                       #最开始为单个项的候选集,需要多个元素组合while(len(L[k-2])>0):Ck = aprioriGen(L[k-2],k)               #创建CkLk, supK = scanD(D,Ck,minSupport)       #由Ck得到LksupportData.update(supK)                #更新支持度L.append(Lk)                            #将Lk放入L列表中k += 1                                  #继续生成L3,L4....return L, supportDataif __name__ == '__main__':dataSet = loadDataSet()print("数据集:\n",dataSet)C1 = createC1(dataSet)print("候选集C1:\n",C1)D = list(map(set,dataSet))  #将数据转换为集合形式L1,supportData = scanD(D,C1,0.5)print("满足最小支持度为0.5的频繁项集L1:\n",L1)L,suppData = apriori(dataSet)print("满足最小支持度为0.5的频繁项集列表L:\n",L)print("L2:\n",L[1])print("使用L2生成的C3:\n",aprioriGen(L[1],3))

结果如下:

数据集:[[1, 3, 4], [2, 3, 5], [1, 2, 3, 5], [2, 5]]
候选集C1:[frozenset({1}), frozenset({2}), frozenset({3}), frozenset({4}), frozenset({5})]
满足最小支持度为0.5的频繁项集L1:[frozenset({5}), frozenset({2}), frozenset({3}), frozenset({1})]
满足最小支持度为0.5的频繁项集列表L:[[frozenset({5}), frozenset({2}), frozenset({3}), frozenset({1})], [frozenset({2, 3}), frozenset({3, 5}), frozenset({2, 5}), frozenset({1, 3})], [frozenset({2, 3, 5})], []]
L2:[frozenset({2, 3}), frozenset({3, 5}), frozenset({2, 5}), frozenset({1, 3})]
使用L2生成的C3:[frozenset({2, 3, 5})]

可以看到,使用L2生成的候选项集C3,只对k-2个项相同的元素合并。那其实不生成{1,3,5}的原因是,由于{1,5}是非频繁项,那么其超集均为非频繁项。故此极大减少计算量。
到此我们也得到了我们的最频繁项集列表。

【实验】python实现Apriori算法——挖掘关联规则

上一节介绍了如何使用Apriori算法来发现频繁集,现在需要解决的问题则是如何找出关联规则。

在原理讲解中,我们找到诸如“{尿布}->{葡萄酒}”的关联规则。这意味着如果有人买了尿布,那么他很可能也会买葡萄酒。但是,这一条反过来,却不一定成立。有可能买葡萄酒的人,根本不会去买尿布。那么,成立的定义是什么呢?还记得我们介绍的可信度度量值,对于关联规则的量化方法,则是使用可信度。

对于关联规则“P->H”,它的可信度被定义为“支持度(P | H)/支持度(P)”。其中|符合在python中为合并符。在找出关联规则的过程中,首先从一个频繁项集开始,接着创建一个规则列表,其中规则右部只包含一个元素,然后对这些规则进行测试。接下来,合并所有剩余规则来创建一个新的规则列表,其中规则右部包含两个元素。直到规则左右剩余一个元素。

同样,我们需要创建相应的功能函数来实现:

1.rulesFromConseq -从频繁项集生成规则列表
2.calcConf -对规则进行测试并过滤
3.generateRules -集成函数

我们来看下这种方法的实际效果,对代码作出如下修改:

"""
函数说明:规则构建函数
parameters:freqSet -频繁项集合H -可以出现在规则右部的元素列表supportData -支持度字典brl -规则列表minConf -最小可信度
return:null
"""
def rulesFromConseq(freqSet,H,supportData,brl,minConf=0.7):m = len(H[0])                                               #得到H中的频繁集大小mif (len(freqSet) > (m+1)):                                  #查看该频繁集是否大到可以移除大小为m的子集Hmp1 = aprioriGen(H, m+1)                               #构建候选集Hm+1,Hmp1中包含所有可能的规则Hmp1 = calcConf(freqSet,Hmp1,supportData,brl,minConf)   #测试可信度以确定规则是否满足要求if (len(Hmp1)>1):                                       #如果不止一条规则满足要求,使用函数迭代判断是否能进一步组合这些规则rulesFromConseq(freqSet,Hmp1,supportData,brl,minConf)"""
函数说明:计算规则的可信度,找到满足最小可信度要求的规则
parameters:freqSet -频繁项集合H -可以出现在规则右部的元素列表supportData -支持度字典brl -规则列表minConf -最小可信度
return:prunedH -满足要求的规则列表
"""
def calcConf(freqSet,H,supportData,brl,minConf=0.7):prunedH = []                                                #为保存满足要求的规则创建一个空列表for conseq in H: conf = supportData[freqSet]/supportData[freqSet-conseq] #可信度计算[support(PUH)/support(P)]if conf>=minConf:print(freqSet-conseq,'-->',conseq,'可信度为:',conf)brl.append((freqSet-conseq,conseq,conf))            #对bigRuleList列表进行填充prunedH.append(conseq)                              #将满足要求的规则添加到规则列表return prunedH
"""
函数说明:关联规则生成函数
parameters:L -频繁项集合列表supportData -支持度字典minConf -最小可信度
return:bigRuleList -包含可信度的规则列表
"""
def generateRules(L,supportData,minConf=0.7):bigRuleList = []                                        #创建一个空列表for i in range(1,len(L)):                               #遍历频繁项集合列表for freqSet in L[i]:                                #遍历频繁项集合H1 = [frozenset([item]) for item in freqSet]    #为每个频繁项集合创建只包含单个元素集合的列表H1if (i>1):                                       #要从包含两个或者更多元素的项集开始规则构建过程rulesFromConseq(freqSet,H1,supportData,bigRuleList,minConf)else:                                           #如果项集中只有两个元素,则计算可信度值,(len(L)=2)calcConf(freqSet,H1,supportData,bigRuleList,minConf)return bigRuleListif __name__ == '__main__':dataSet = loadDataSet()print("数据集:\n",dataSet)C1 = createC1(dataSet)print("候选集C1:\n",C1)L,suppData = apriori(dataSet)print("满足最小支持度为0.5的频繁项集列表L:\n",L)print("满足最小可信度为0.7的规则列表为:")rules = generateRules(L,suppData,0.7)print(rules)print("满足最小可信度为0.5的规则列表为:")rules1 = generateRules(L,suppData,0.5)print(rules1)

运行结果如下:

数据集:[[1, 3, 4], [2, 3, 5], [1, 2, 3, 5], [2, 5]]
候选集C1:[frozenset({1}), frozenset({2}), frozenset({3}), frozenset({4}), frozenset({5})]
满足最小支持度为0.5的频繁项集列表L:[[frozenset({5}), frozenset({2}), frozenset({3}), frozenset({1})], [frozenset({2, 3}), frozenset({3, 5}), frozenset({2, 5}), frozenset({1, 3})], [frozenset({2, 3, 5})], []]
满足最小可信度为0.7的规则列表为:
frozenset({5}) --> frozenset({2}) 可信度为: 1.0
frozenset({2}) --> frozenset({5}) 可信度为: 1.0
frozenset({1}) --> frozenset({3}) 可信度为: 1.0
[(frozenset({5}), frozenset({2}), 1.0), (frozenset({2}), frozenset({5}), 1.0), (frozenset({1}), frozenset({3}), 1.0)]
满足最小可信度为0.5的规则列表为:
frozenset({3}) --> frozenset({2}) 可信度为: 0.6666666666666666
frozenset({2}) --> frozenset({3}) 可信度为: 0.6666666666666666
frozenset({5}) --> frozenset({3}) 可信度为: 0.6666666666666666
frozenset({3}) --> frozenset({5}) 可信度为: 0.6666666666666666
frozenset({5}) --> frozenset({2}) 可信度为: 1.0
frozenset({2}) --> frozenset({5}) 可信度为: 1.0
frozenset({3}) --> frozenset({1}) 可信度为: 0.6666666666666666
frozenset({1}) --> frozenset({3}) 可信度为: 1.0
frozenset({5}) --> frozenset({2, 3}) 可信度为: 0.6666666666666666
frozenset({3}) --> frozenset({2, 5}) 可信度为: 0.6666666666666666
frozenset({2}) --> frozenset({3, 5}) 可信度为: 0.6666666666666666
[(frozenset({3}), frozenset({2}), 0.6666666666666666), (frozenset({2}), frozenset({3}), 0.6666666666666666), (frozenset({5}), frozenset({3}), 0.6666666666666666), (frozenset({3}), frozenset({5}), 0.6666666666666666), (frozenset({5}), frozenset({2}), 1.0), (frozenset({2}), frozenset({5}), 1.0), (frozenset({3}), frozenset({1}), 0.6666666666666666), (frozenset({1}), frozenset({3}), 1.0), (frozenset({5}), frozenset({2, 3}), 0.6666666666666666), (frozenset({3}), frozenset({2, 5}), 0.6666666666666666), (frozenset({2}), frozenset({3, 5}), 0.6666666666666666)]

更改最小置信度后,可以获得更多的规则。


http://chatgpt.dhexx.cn/article/W5DHK7IY.shtml

相关文章

关联规则挖掘——Apriori算法的基本原理以及改进

问题引入 关联规则挖掘发现大量数据中项集之间有趣的关联或者相互联系。关联规则挖掘的一个典型例子就是购物篮分析,该过程通过发现顾客放入其购物篮中不同商品之间的联系,分析出顾客的购买习惯,通过了解哪些商品频繁地被顾客同时买入,能够帮助零售商制定合理的营销策略。…

学习序列模式挖掘

学习序列模式挖掘 1.1介绍 已Apriori算法为例,此算法是经典的挖掘频繁项集和关联规则的数据挖掘算法。A priori在拉丁语中指"来自以前"。当定义问题时,通常会使用先验知识或者假设,这被称作"一个先验"(a pr…

Python|判断素数

1. 判断一个从键盘输入的整型数是否是素数 num int(input()) for i in range(2, num//2):if num % i 0:print("%d不是一个素数" % num)break else:print("%d是一个素数" % num)控制台输入11,结果即: 2.随机生成10个两位正整数&a…

C语言if语句判断素数,利用简单的if语句判断素数

8种机械键盘轴体对比 本人程序员,要买一个写代码的键盘,请问红轴和茶轴怎么选? 判断素数这个问题是c语言条件,循环中最简单的一个问题 下面就来介绍一下判断素数的代码吧 #include “stdio.h” void main() { int x,i; int flag1;…

C语言 - 判断素数

定义: 素数(Prime number,又称质数),指在大于1的自然数中,除了1和该数自身外,无法被其他自然数整除的数 思路一:试除法 1.如果数字 i 能被 2 ~ i-1 整除,说明 i 就是素数…

函数判断素数

1、实现一个函数,判断一个数是不是素数。 2、利用上面实现的函数打印100到200之间的素数。 素数的定义:素数是指大于一的整数中,只能被1和这个数本身整除的数。 假设这个数是n,那么用for循环去遍历,在2——n-1&…

C语言判断素数

素数又称质数。所谓素数是指除了 1 和它本身以外,不能被任何整数整除的数,例如7就是素数,因为它不能被 2~6 的任一整数整除。注意:一般情况下,质数合数只是针对于非零自然数而言,负数没有质数合数一说。 思…

用python判断素数_python判断素数

广告关闭 腾讯云11.11云上盛惠 ,精选热门产品助力上云,云服务器首年88元起,买的越多返的越多,最高返5000元! 质数(prime number),又称素数,指在大于1的自然数中,除了1和该数自身外,无法被其他自然数整除的数(也可定义为只有1与该数本身两个因数的数)。 那么想计…

判断素数的方法(全部方法)

功能 最快、最合适地判断一个数为素数 说明 分为打表法和单个判断法两类方法 打表法 是开始时将所有素数标记出来,适合多次调用判断,前两种属于打表法 单个判断法 则是只一个数一个数判断,适合少量判断来节省时间,后俩种属…

c语言判断素数(c语言判断素数)

C语言中素数判断 是素数就返回1&#xff0c;不是的话返回0。 int IsPrime(int n) int i; if (n 1 || n 2 || n 3 || n 5) return 1; else if (n % 2) for (i 3; i < n / 2 1; i 2) if (n % i 0) return 0; return 1; else return 0; } 代码如下&#xf…

C语言判断素数的三种方法 判断素数(质数)

题目&#xff1a; 方法一&#xff1a;在2到n-1之间任取一个数,如果n能被整除则不是素数&#xff0c;否则就是素数 代码示例如下&#xff1a; #include <stdio.h> int main() {int i,n;printf("Please input: ");scanf("%d",&n);for(i2;i<n-…

C语言判断素数(求素数)

C语言判断素数&#xff08;求素数&#xff09; 素数又称质数。所谓素数是指除了 1 和它本身以外&#xff0c;不能被任何整数整除的数&#xff0c;例如17就是素数&#xff0c;因为它不能被 2~16 的任一整数整除。 思路1)&#xff1a;因此判断一个整数m是否是素数&#xff0c;只需…

Flink自定义生成 Watermark

Watermark 策略简介 # 为了使用事件时间语义&#xff0c;Flink 应用程序需要知道事件时间戳对应的字段&#xff0c;意味着数据流中的每个元素都需要拥有可分配的事件时间戳。其通常通过使用 TimestampAssigner API 从元素中的某个字段去访问/提取时间戳。 时间戳的分配与 wat…

Flink学习:WaterMark

WaterMark 一、什么是水位线?二、案例分析三、如何生成水位线?(一)、在SourceFunction中直接定义Timestamps和Watermarks(二)、自定义生成Timstamps和Watermarks 一、什么是水位线? 通常情况下,由于网络或系统等外部因素影响,事件数据往往不能及时传输至Flink系统中,导致数…

flink watermark

flink1.12版本开始&#xff0c;事件事件作为默认的时间语义 watermark是flink逻辑时钟&#xff0c;不是真正意义上的表&#xff0c;而是靠着数据去推动它的时间不停的往前走 工厂生产的商品上面印有时间戳&#xff0c;八点到九点的商品要坐一班车运走&#xff0c;商品从生产到…

Flink WaterMark 详解

摘录仅供学习使用&#xff0c;原文来自&#xff1a; Flink详解系列之五--水位线&#xff08;watermark&#xff09; - 简书 1、概念 在Flink中&#xff0c;水位线是一种衡量Event Time进展的机制&#xff0c;用来处理实时数据中的乱序问题的&#xff0c;通常是水位线和窗口结合…

Flink:watermark

Table of Contents 三种时间概念 Processing time Event Time Ingestion time watermark 并行流的Watermarks 迟到的事件 watermark分配器 watermark的两种分配器 三种时间概念 在谈watermark之前&#xff0c;首先需要了解flink的三种时间概念。在flink中&#xff0c;…

Flink 水位线(Watermark)

文章目录 什么是水位线水位线的特性如何生成水位线Flink 内置水位线生成器自定义水位线策略在自定义数据源中发送水位线水位线的总结 在实际应用中&#xff0c;一般会采用事件时间语义。而水位线&#xff0c;就是基于事件时间提出的概念。一个数据产生的时刻&#xff0c;就是流…

vue -- watermark水印添加方法

作者&#xff1a;蛙哇 原文链接&#xff1a; https://segmentfault.com/a/1190000022055867 来源&#xff1a;segmentfault 前言 项目生成公司水印是很普遍的需求&#xff0c;下面是vue项目生产水印的方法。话不多说&#xff0c;复制粘贴就可以马上解决你的需求。 步骤1 创建…