【问题标题】:How to apply a masked array to a very large JSON fast如何快速将屏蔽数组应用于非常大的 JSON
【发布时间】:2020-07-02 03:51:09
【问题描述】:

数据

我目前正在处理这样格式的非常大的 JSON 文件

{key: [1000+ * arrays of length 241],
 key2: [1000+ * arrays of length 241],
 (...repeat 5-8 times...)}

数据的结构方式是每个键的数组中的第 n 个元素属于第 n 个实体。将其视为每个键都是一个描述符,例如“高度”或“压力”。因此,要获取实体的“高度”和“压力”,您将访问所有数组中的实体索引 n。因此所有键的数组都是相同的长度Z

正如您可以想象的那样,这是一个整体工作的痛苦。因此,每当我执行任何数据操作时,我都会返回一个长度为 Z 的掩码数组,其中填充了 1 和 0。 1 表示要保留每个键中该索引中的数据,0 表示应省略)


问题

执行完所有数据操作后,我需要将掩码数组应用于数据以返回原始 JSON 数据的副本,但每个键的数组 Z 的长度等于掩码数组中 1 的数量(如果掩码数组中索引 n 处的元素为 0,则索引 n 中的元素将从所有 json 键的数组中删除,反之亦然)


我的尝试

# mask: masked array
# d: data to apply the mask to
 def apply_mask(mask, d):
    keys = d.keys()
    print(keys)
    rem = [] #List of index to remove
    for i in range(len(mask)):
        if mask[i] == 0:
            rem.append(i) #Populate 'rem'

        for k in keys:
            d[k] = [elem for elem in d[k] if not d[k].index(elem) in rem]

    return d

这按预期工作,但需要一段时间处理如此大的 JSON 数据


问题

我希望以上所有内容都清楚并帮助您理解我的问题:

是否有更优化/更快的方法将屏蔽数组应用于如上所示的数据?

干杯

【问题讨论】:

    标签: python arrays json list performance


    【解决方案1】:

    这会很慢,因为

    d[k] = [elem for elem in d[k] if not d[k].index(elem) in rem]
    

    每次都完全重新创建内部列表。

    由于您已经在原地修改 d,您可以删除相应的元素:

    def apply_mask(mask, d):
        for i, keep in enumerate(mask):
            if not keep:
                for key in d:
                    del d[key][i - len(mask)]
        return d
    

    (正在使用负索引i - len(mask),因为如果列表由于先前删除的元素而已经改变了它的长度,正索引将不再起作用。)

    【讨论】:

      【解决方案2】:

      问题来自代码的高算法复杂性。可以设计一个更快的算法。

      K 为字典d(即len(d))中的键数。让Z 为掩码的大小(即len(mask)),这也是d 中数组值的典型大小(即,对于任何keylen(d[key]))。

      初始代码的算法复杂度为O(Z^3 * K)。这是因为rem 是一个列表,而in rem 是在线性时间内完成的,还因为d[k].index(elem)d[k] 中搜索elem 也是在线性时间内。

      finefoot 提出的解决方案速度更快。事实上,他的代码的复杂度是 O(Z^2 * K)(因为 del 在 CPython 列表上是线性时间完成的)。

      但是,可以在线性时间内进行计算:O(K * Z)。方法如下:

      def apply_mask(mask, d):
          for key in d:
              d[key] = [e for i,e in enumerate(d[key]) if mask[i]!=0]
          return d
      

      这段代码应该快几个数量级。

      PS:关于问题的描述,我认为初始算法是不正确的。事实上,由于rem 在迭代之间没有被清理(因此索引被累积),因此可以删除一些应该保留的项目。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-08-11
        • 2021-01-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-01-01
        相关资源
        最近更新 更多