如何在大数据上找到相似的模式以及丢失的实体?

时间:2018-10-02 08:48:19

标签: python pattern-matching bigdata data-mining data-science

我想在数据列表及其缺少的实体中搜索某种模式数据。 例如,我有以下用户数据:

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算法来找到模式,但是它没有按预期工作。此外,数据大小非常大,即使创建模式图或模式树也花费了太长时间。以上数据仅为示例数据。我需要对数千个用户数据进行此分析。

完成此任务的最佳方法是什么?

3 个答案:

答案 0 :(得分:2)

这就是我可能会在纯Python中做到的方式。

时间复杂度为O(um+n),其中m是搜索模式的大小,u是输入字典中的用户数,n是大小输入字典的对于问题定义中所述的相对较小的搜索模式,此方法有效地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)时间内执行几个set操作并返回输出。无需更复杂或更聪明的表示。稍作调整,您就能比我的代码做得更好,但在一般情况下并没有渐近地变得更好。


还请注意,如果要处理大数据,则可能要使用Spark之类的东西。只需使用一些Scala代码就可以很好地完成同一件事,并且您可以在集群中很好地并行处理几乎任意大小的数据集。

答案 1 :(得分:1)

这是最适合我的方法(但这可能不是效果最好的解决方案):

我认为您可以以某种方式将输入内容转换为以下形式的dict

d = {'User 1': [123, 254, 225, 367, 125, 745, 587],
     'User 2': [333, 444, 225, 123 ,254], ...}

现在,使用给定的模式

pattern = [254, 225, 125, 587, 745]

let产生另一个保存输出的字典:

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]

也许这是您可以开始的。

答案 2 :(得分:1)

使用用户字典和清单,可以使用字典理解

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]}