如何在大数据上找到类似的模式以及缺失的实体?
Posted
技术标签:
【中文标题】如何在大数据上找到类似的模式以及缺失的实体?【英文标题】:How to find similar pattern along with missing entities over a big data? 【发布时间】:2019-03-07 09:08:03 【问题描述】:我想在数据列表中搜索某种模式数据及其缺失的实体。 例如,我有以下用户数据:
User 1: 123 254 225 367 125 745 587
User 2: 333 444 225 123 254
User 3: 777 451 225 745 254 458
User 4: 111 222 333 444 555 666 777 888
我有一个搜索模式:
254 225 125 587 745
我需要在用户数据上搜索此模式,无论其出现顺序如何,并提供如下结果:
User 1:
User 2: 125 587 745
User 3: 125 587
User 4: 254 225 125 587 745
结果中的数字表示模式中缺少的实体。
我尝试实现 Apriori 和 FP-Growth 算法来查找模式,但它没有按预期工作。而且数据量很大,甚至创建模式图或模式树也需要很长时间。以上数据只是一个样本数据。我需要对数千个用户数据执行此分析。
完成这项工作的最佳方法是什么?
【问题讨论】:
输入数据是什么类型的?是字典、字符串还是列表...? 【参考方案1】:这就是我在纯 Python 中的做法。
时间复杂度为O(um+n)
,其中m
是搜索模式的大小,u
是输入dict的用户数,n
是输入dict的大小。对于问题定义中描述的相对较小的搜索模式,这种方法实际上是O(n)
。
# Inputs
userDict =
'User 1': [123, 254, 225, 367, 125, 745, 587],
'User 2': [333, 444, 225, 123, 254],
'User 3': [777, 451, 225, 745, 254, 458],
'User 4': [111, 222, 333, 444, 555, 666, 777, 888]
filterList = [254, 225, 125, 587, 745]
# Filter a dictionary of lists based on a search pattern
# Returns for each value in the dictionary, the elements from the search pattern
# which were not found in the list
#
def filterLists(inputDict, filterList):
# Use a Set for the O(1) lookup
filterSet = set(filterList)
res =
for key, vals in inputDict.items():
# Creating a Set from a list of size n is O(n)
# Set difference is O(size of the leftmost set)
# Assuming the search pattern is shorter than the average User list,
# this gives us effectively O(n)
res[key] = list(filterSet - set(vals))
return res
print(filterLists(userDict, filterList))
基本上,不要想太多,Apriori 和 FP-Growth 算法针对的是与此不同的一类问题。你基本上是在这里实现一个过滤器或筛子,由于你的输入不是结构化或有序的,你真的不能至少读取每个整数一次,这意味着你不能比 O(n) 更快。
所以在我的代码中,我只需在 O(n) 时间内执行几个设置操作并返回输出。不需要更复杂或更聪明的表示。稍微调整一下,你可以比我的代码做得更好,但在一般情况下不会渐进地更好。
另请注意,如果您正在处理大数据,您可能希望使用 Spark 之类的东西。同样的事情可以通过一些 Scala 代码优雅地完成,并且您将拥有可以在集群中很好地并行处理几乎任意大小的数据集的东西。
【讨论】:
【参考方案2】:这对我有用(但它可能不是性能最好的解决方案):
我假设您可以以某种方式将您的输入转换为dict
的形式:
d = 'User 1': [123, 254, 225, 367, 125, 745, 587],
'User 2': [333, 444, 225, 123 ,254], ...
现在,使用给定的模式
pattern = [254, 225, 125, 587, 745]
让我们生成第二个 dict 来保存输出:
d_out =
for key in d.keys():
d_out[key] = []
for value in pattern:
d_out[key].append(value in d[key])
如果您的模式列表很大(由于循环),性能可能不是最佳的,但它应该或多或少独立于用户数据的大小。
现在我以pattern
为掩码,使用自定义版本的itertools.compress
函数获取结果(该函数在我的机器上产生错误,无法直接使用,抱歉):
for key in d.keys():
print(key, [data for data, mask in zip(pattern, d_out[key]) if not mask])
产生输出:
User 1 []
User 2 [125, 587, 745]
也许这是你可以开始的。
【讨论】:
这应该可以工作,但是正如你提到的性能不是最佳的,因为第一个循环将在 O(m*n) 时间内运行(m 是模式长度,n 是输入的大小) .您可以通过简单地将 d[key] 转换为内部循环之前的集合来加快速度,因为 'in' 运算符在集合上是 O(1)。【参考方案3】:使用用户字典和检查表,这可以通过字典理解
来完成users =
'User 1': [123, 254, 225, 367, 125, 745, 587],
'User 2': [333, 444, 225, 123, 254],
'User 3': [777, 451, 225, 745, 254, 458],
'User 4': [111, 222, 333, 444, 555, 666, 777, 888]
check = [254, 225, 125, 587, 745]
res = k: [i for i in check if i not in users[k]] for k in users
'User 1': [], 'User 2': [125, 587, 745], 'User 3': [125, 587], 'User 4': [254, 225, 125, 587, 745]
【讨论】:
漂亮干净,但性能不是很好。列表上的in
运算符是线性时间复杂度,导致列表理解的时间复杂度为 O(m*n)。
@JensRoland 如果我将列表理解列表从字典理解中拉出来,它会提高速度吗?以上是关于如何在大数据上找到类似的模式以及缺失的实体?的主要内容,如果未能解决你的问题,请参考以下文章