【问题标题】:How to efficiently flatten a dictionary of Sorted dictionaries to numpy.arrays如何有效地将排序字典的字典展平为 numpy.arrays
【发布时间】:2021-05-07 05:05:09
【问题描述】:

我想知道是否有更有效的方法来展平我的数据。请参阅下面的扁平化数据结构示例:

 {t: SortedDict(
    {0: {'t': 5, 'ids': [{'1': ['data']}]}, 
    1: {'t': 2, 'ids': [{'1': ['data']}]}, 
    2: {'t': 4, 'ids': [{'1': ['data']}]}, 
    3: {'t': 1, 'ids': [{'1': ['data']}]}, 
    4: {'t': 4, 'ids': [{'1': ['data']}]}, 
    5: {'t': 1, 'ids': [{'1': ['data']}]}, 
    6: {'t': 3, 'ids': [{'1': ['data']}]}, 
    7: {'t': 2, 'ids': [{'1': ['data']}]}, 
    8: {'t': 1, 'ids': [{'1': ['data']}]}, 
    9: {'t': 1, 'ids': [{'1': ['data']}]}
    }),t:SortedDict(
    {
    27: {'t': 1, 'ids': [{'5': ['data','data']}]}, 
    28: {'t': 1, 'ids': [{'5': ['data','data','data','data']}]}, 
    29: {'t': 2, 'ids': [{'5': ['data','data']}]}, 
    30: {'t': 1, 'ids': [{'5': ['data']}]}, 
    31: {'t': 2, 'ids': [{'5': ['data','data','data','data']}]}, 
    32: {'t': 1, 'ids': [{'5': ['data']}]}
    })}

注意:SortedDict 来自 Sorted Containers 库,它是一个 Apache2 许可的 Python 排序集合。

我评估了其他几个 stackoverflow 帖子,它们使用列表理解或 lambda 函数执行类似的操作。最终,我写了一个方法,将字典扁平化为三个列表;但是,我不确定这种方法是否是最佳方法。方法如下:

def flatten(self, d,calculation_dict):
    l_key       = [] # Stores linearized keys
    l_results   = [] # Stores linearized values after calculation
    index       = [] # Stores the start of each individual sub-array
    i = 0
    for val in d.values():
            index.append(i)
            for key, t in val.t.items():
                #Add calculation in here since I am Iterating over every element
                l_results.append(t["t"] *  calculation_dict[key]) 
                l_key.append(key)
                i += 1
    h_index = numpy.array(index, dtype=numpy.int32)
    h_l_results = numpy.array(l_results,dtype=numpy.float)
    l_key = numpy.array(l_key, dtype=numpy.int32)
    index.append(i) 
    return (l_key,l_results,index)
    
    #Need output to be numpy.array
    l_key       = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 27, 28, 29, 30, 31, 32]
    l_results   = [5.0, 2.0, 4.0, 1.0, 4.0, 1.0, 3.0, 3.0, 1.0, 1.0, 1.0, 1.0, 2.0, 1.0, 2.0, 1,0]
    index       = [0, 10]

在我的应用程序中速度是极其重要的。因此,我们将不胜感激任何反馈或建议。

编辑:忘了提到我需要一个 numpy 数组中的最终结果。不确定这是否会改变任何事情。

编辑:感谢 Glauco 的建议,我将扁平化方法修改如下:

def flatten_numpy(self, d,calculation_dict):
        l_results   = numpy.empty(self.size,dtype=numpy.float)
        l_key       = numpy.empty(self.size, dtype=numpy.int32)
        index       = []
        i = 0
        for val in d.values():
                index.append(i)
                for key, t in val.t.items():
                    l_results[i] = (tf["tf"] *  idf[term]) 
                    l_key[i] = term
                    i += 1
        index.append(i) 
        h_index = numpy.array(index, dtype=numpy.int32)
        return (l_key,l_results,index)

事实证明,在算法的早期,我已经不得不访问每个子字典的大小。利用这一点,我开始累积这个值大小变量,在测试新方法后它会稍微快一些。测试结果如下:

#Each Test was executed on the different data and ran 1000 times
Test#1 | Flatten        6.422301292419434   | Flatten_numpy     4.761376142501831
Test#2 | Flatten        5.212526082992554   | Flatten_numpy     4.901215553283691
Test#3 | Flatten        5.2060017585754395  | Flatten_numpy     5.266955852508545
Test#4 | Flatten        6.079436302185059   | Flatten_numpy     4.803238153457642
Test#5 | Flatten        5.059106349945068   | Flatten_numpy     4.565468788146973

【问题讨论】:

  • A SortedDict 不是原生 Python 数据类型,因此您也需要在问题中包含它的定义。
  • 嗯,val.t. 是做什么的? calculation_dict 是什么?
  • @Crux 那个人不知道他们在说什么。列表推导和“lambdas”不是为了性能,你是为了风格/可读性。特别是lamdba 很傻,至少列表推导做了一些小的优化,但通常是边缘化的。
  • 如果有人说“你应该使用 lambda 函数,因为它会更有效率”,你几乎可以忽略它
  • 字典访问是一一对应的,所以除了使用keysitemsvalues 来获取列表之外,没有太多可以加快速度的方法。列表到数组很简单。您最内部的 dicts 很小,只有 1 或 2 个键,因此您无法加快速度。

标签: python performance numpy data-structures flatten


【解决方案1】:

您的方法在算法上是正确的,它是 O(n+m) 它是线性的,没有其他方法。 如果你知道 haom 很多 dict 将从集群到达,那么创建空的 numpy 数据结构并在运行时填充它会更方便,避免列表追加。

最后,t 计算:

l_results.append(t["t"] * calculation_dict[key])

可以在收集阶段的底部使用数组快速完成

【讨论】:

  • 2) 我能想到的只有两种方法可以知道大小:一种是有一个持久变量来跟踪总数键或“t-values”,因为它们是添加到系统中;另一种方法是在展平数据之前预先扫描数据,这意味着累积每个子字典的 len() 。我不确定执行这两种方法中的任何一种是否会比将列表合并到 numpy 数组中获得任何性能提升。但也许你知道得更好?
  • 3) 关于 t 计算,当你说它可以在收集阶段的底部更有效地完成时,我不确定你指的是什么。我将它添加到这部分的原因是因为必须迭代/检索每个 t 值和键值才能将其添加到展平数组中。此外,由于指针在存储在两个不同数组中的键和值之间追逐,因此尝试在扁平化、numpy 数组上执行此计算的成本会很高。也许您的意思有所不同,因此非常感谢您提供说明或示例。
  • 1) 我同意渐近复杂度为 O(n+m),其中 n 介于 1 和 1000 之间,而 m 介于 1 和 1M 之间。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-01-16
  • 1970-01-01
相关资源
最近更新 更多