【问题标题】:How to append vector to numpy matrix based on its string name?如何根据字符串名称将向量附加到 numpy 矩阵?
【发布时间】:2020-11-16 03:56:45
【问题描述】:

我有许多 numpy 数组的异步过程,它们的新值是任意出现的,需要附加。我为此苦苦挣扎了好几个小时,想得到这样的东西:

class nbAppend():
    def __init__(self):
         pass

    def append(self,varName,varValues):
          self.varName = np.append(self.varName,varValues,axis=0) # !!! not feasible

所以当一个 numpy 数组 x 新值出现时,它应该在 'x' = np.append('x',values,axis=0) 中更新。我知道有字典的解决方案,即

np_add_rows = {}
def process_row(d, key,_cache=np_add_rows):
    # keep the rows for each key separate.
    lst = _cache.setdefault(key, [])
    lst.append(d)

但是这种解决方法会使代码减慢 5-6 倍,这是不可接受的。那么,如何根据字符串名称将向量附加到 numpy 矩阵?感谢您的帮助。

【问题讨论】:

  • 你能举个例子来说明你想要完成的事情吗?
  • 由于异步过程,很难举个例子,但会尝试进一步支持它。假设我们有数百个变量,其中的值是任意推送给我们的。由于我们不知道会出现哪个变量,并且为每个变量编写x = np.append(x,values) 既不实用也不高效,因此根据名称“x”更新 x 变量的函数将很有用。希望现在更清楚一点。
  • 如果您可以访问变量名的字符串形式,我不明白为什么像defaultdict(list) 这样的东西在保持快速时不起作用。键查找和追加到列表是 O(1),而追加到数组则需要制作数组的完整副本
  • 问题是添加新值后,分析如下。我已经使用字典(也包括 pandas)以及列表测试了解决方案,但速度明显较慢(5-6x)。因此最好将新向量附加到 numpy 矩阵并立即对其进行分析。
  • 您是否对其进行了分析,以确切了解导致瓶颈的原因以及您在分析方面做了什么,因为随着数组变得越来越大,它会变得越来越慢,因为您必须分配越来越多记忆。如果你必须使用数组,设置一个最大大小的缓冲区,这样你就不必每次新数据进来时都复制,一旦不再需要旧数据就删除它

标签: python numpy dynamic append names


【解决方案1】:

在字典中收集数组:

collections.defaultdict:

In [85]: dd = defaultdict(lambda : np.zeros(0, int))                                                 
In [86]: for i in ['aa','bb','cc','dd','aa','cc']: 
    ...:     dd[i] = np.concatenate([dd[i], np.arange(3)]) 
    ...:                                                                                             
In [87]: dd                                                                                          
Out[87]: 
defaultdict(<function __main__.<lambda>()>,
            {'aa': array([0, 1, 2, 0, 1, 2]),
             'bb': array([0, 1, 2]),
             'cc': array([0, 1, 2, 0, 1, 2]),
             'dd': array([0, 1, 2])})

或使用常规字典:

In [88]: dd = {}                                                                                     
In [89]: for i in ['aa','bb','cc','dd','aa','cc']: 
    ...:     arr = dd.get(i, np.zeros(0,int)) 
    ...:     dd[i] = np.concatenate([arr, np.arange(3)]) 
    ...:      
    ...:                                                                                             
In [90]: dd                                                                                          
Out[90]: 
{'aa': array([0, 1, 2, 0, 1, 2]),
 'bb': array([0, 1, 2]),
 'cc': array([0, 1, 2, 0, 1, 2]),
 'dd': array([0, 1, 2])}

列表等价物:

In [93]: dd = defaultdict(list)                                                                      
In [94]: for i in ['aa','bb','cc','dd','aa','cc']: 
    ...:     dd[i].extend(np.arange(3)) 
    ...:                                                                                             
In [95]: dd                                                                                          
Out[95]: 
defaultdict(list,
            {'aa': [0, 1, 2, 0, 1, 2],
             'bb': [0, 1, 2],
             'cc': [0, 1, 2, 0, 1, 2],
             'dd': [0, 1, 2]})

通常这个列表版本会更快,但如果在每次迭代中我们都必须做类似的事情

acc.append(np.sum(dd[i])) 

它可以提示有利于数组累积的时间,因为它可以节省从列表到数组的重复转换。

【讨论】:

    猜你喜欢
    • 2018-06-13
    • 2018-03-28
    • 1970-01-01
    • 1970-01-01
    • 2011-05-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-25
    相关资源
    最近更新 更多