【问题标题】:Python: Concatenate many dicts of numpy arrays with same keys and sizePython:连接许多具有相同键和大小的numpy数组字典
【发布时间】:2017-11-06 19:51:50
【问题描述】:

我有一个在循环中调用的函数,它返回一个包含大约 50 个变量的 dict (dsst_mean)。所有变量都是长度为 10 的 numpy 数组。

循环大约迭代 3000 次。我目前在每个循环结束时进行连接,这样我就有一个在每次迭代中都会变大的 'dsst_mean_all' dict。

source = [dsst_mean_all, dsst_mean]                
for key in source[0]:                    
    dsst_mean_all[key] = np.concatenate([d[key] for d in source])

它有效,但我知道这不是有效的。我也有初始化“dsst_mean_all”字典的问题。 (我目前正在使用 dict.fromkeys() 来执行此操作。)

我的问题是:有哪些选择可以更有效地做到这一点?我想我可以将 dsst_mean 字典存储在一个列表中,然后在最后进行一个连接。但我不确定在内存中保存 3000 多个 numpy 数组字典是否是个好主意。我知道这取决于大小,但不幸的是,现在我无法估计每个 'dsst_mean' 字典的大小。

谢谢。

【问题讨论】:

  • 不仅效率不高:它非常不安全:您更改了正在迭代的字典。您的程序可以跳过键、迭代键两次,甚至陷入无限循环。
  • 那您有什么建设性的建议吗?
  • 将它们存储为一个列表很好,直到您知道这是一个内存问题。它不应该在内存方面增加太多开销,并且比每次迭代创建 numpy 数组效率更高。

标签: python numpy dictionary concatenation


【解决方案1】:

通常我们建议在列表中收集值,并在最后创建一次数组。这里的新东西是我们需要迭代字典的键来完成这个集合。

例如:

制作个人字典的函数:

In [804]: def foo(i):
     ...:     return {k:np.arange(5) for k in ['A','B','C']}
     ...: 
In [805]: foo(0)
Out[805]: 
{'A': array([0, 1, 2, 3, 4]),
 'B': array([0, 1, 2, 3, 4]),
 'C': array([0, 1, 2, 3, 4])}

收集器字典:

In [806]: dd = {k:[] for k in ['A','B','C']}

迭代,收集列表中的数组:

In [807]: for _ in range(3):
     ...:     x = foo(None)
     ...:     for k,v in dd.items():
     ...:         v.append(x[k])
     ...:         
In [808]: dd
Out[808]: 
{'A': [array([0, 1, 2, 3, 4]), array([0, 1, 2, 3, 4]), array([0, 1, 2, 3, 4])],
 'B': [array([0, 1, 2, 3, 4]), array([0, 1, 2, 3, 4]), array([0, 1, 2, 3, 4])],
 'C': [array([0, 1, 2, 3, 4]), array([0, 1, 2, 3, 4]), array([0, 1, 2, 3, 4])]}

字典上的另一个迭代将列表转换为某种数组(stackconcatenate,您的选择):

In [810]: for k,v in dd.items():
     ...:     dd[k]=np.stack(v,axis=0)
     ...:     
In [811]: dd
Out[811]: 
{'A': array([[0, 1, 2, 3, 4],
        [0, 1, 2, 3, 4],
        [0, 1, 2, 3, 4]]), 'B': array([[0, 1, 2, 3, 4],
        [0, 1, 2, 3, 4],
        [0, 1, 2, 3, 4]]), 'C': array([[0, 1, 2, 3, 4],
        [0, 1, 2, 3, 4],
        [0, 1, 2, 3, 4]])}

一个包含 3000 个长度为 10 的数组的列表将比一个包含 30,000 个数字的数组占用更多的内存,但不会更多。

您可以在第一次将整个字典收集在一个列表中,但您仍然需要像这样将它们组合到字典中。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-01-18
    • 2023-03-30
    • 1970-01-01
    • 1970-01-01
    • 2014-04-27
    • 1970-01-01
    • 1970-01-01
    • 2014-12-24
    相关资源
    最近更新 更多