【问题标题】:Python np.append does not work on dictionary value which is of type numpy.ndarrayPython np.append 不适用于 numpy.ndarray 类型的字典值
【发布时间】:2020-07-23 09:04:14
【问题描述】:

我有一个函数,它给定两个 numpy 数组,将它们转换为字典,如下所示

def seggregate_based_on_y(X,y):
    dictionary={}
    for index in range(len(y)):
        if y[index] in dictionary.keys():
            np.append(dictionary[y[index]],X[index])
        else:
            dictionary[y[index]]=np.array([X[index]])
    return dictionary

用于以下输入

X=np.array([[1,1],[2,2],[3,3],[4,4],[5,5]])
y=np.array([2,3,2,3,4])
d=seggregate_based_on_y(X,y)
print(d)

我希望 'd' 为 {2: array([[1, 1],[3,3]]), 3: array([[2, 2],[4,4]]), 4: array([[5, 5]])},但我得到的 'd' 为 {2: array([[1, 1]]), 3: array([[2, 2]]), 4: array([[5, 5]])},即 if 语句不起作用。应该怎么做?

【问题讨论】:

标签: python arrays numpy append


【解决方案1】:

首先,就像 cmets 所说,您必须为字典分配新值。请参阅以下修复:

def seggregate_based_on_y(X,y):
    dictionary={}
    for index in range(len(y)):
        if y[index] in dictionary.keys():
            dictionary[y[index]] = np.append(dictionary[y[index]],X[index])
        else:
            dictionary[y[index]]=np.array([X[index]])
    return dictionary

使用给定的数据输出:

{2: array([1, 1, 3, 3]), 3: array([2, 2, 4, 4]), 4: array([[5, 5]])}

这与您的预期结果不同,因为np.append 将附加到同一个向量。要获得所需的输出,请使用np.vstack

def seggregate_based_on_y(X,y):
    dictionary={}
    for index in range(len(y)):
        if y[index] in dictionary.keys():
            dictionary[y[index]] = np.vstack((dictionary[y[index]],X[index]))
        else:
            dictionary[y[index]]=np.array([X[index]])
    return dictionary

这里的输出是:

{2: array([[1, 1],
       [3, 3]]), 3: array([[2, 2],
       [4, 4]]), 4: array([[5, 5]])}

我希望这会有所帮助。

【讨论】:

    【解决方案2】:

    你可以使用内置函数zip:

    def seggregate_based_on_y(X,y):
        d = {}
        for k, v in zip(y, X):
            if k in d:
                d[k] = np.append(d[k], v.reshape(1, 2), axis=0)
            else:
                d[k] = v.reshape(1, 2)
    
        return d
    
    
    X=np.array([[1,1],[2,2],[3,3],[4,4],[5,5]])
    y=np.array([2,3,2,3,4])
    print(seggregate_based_on_y(X,y))
    

    输出:

    {2: array([[1, 1],
            [3, 3]]), 3: array([[2, 2],
            [4, 4]]), 4: array([[5, 5]])}
    

    【讨论】:

      【解决方案3】:

      试试这个

      import numpy as np
      
      def seggregate_based_on_y(X,y):
          dictionary={}
          for index in range(len(y)):
              if y[index] in dictionary.keys():
                  z = np.append(dictionary[y[index]], X[index])
                  dictionary[y[index]] = z.reshape(z.size // 2, 2)
      
              else:
                  dictionary[y[index]]=np.array([X[index]])
          return dictionary
      
      X=np.array([[1,1],[2,2],[3,3],[4,4],[5,5]])
      y=np.array([2,3,2,3,4])
      d=seggregate_based_on_y(X,y)
      print(d)
      

      输出:

      {2: array([[1, 1],[3, 3]]), 3: array([[2, 2],[4, 4]]), 4: array([[5, 5]])}
      

      【讨论】:

        【解决方案4】:

        defaultdict 可以轻松完成此类收集:

        In [268]: from collections import defaultdict                                                          
        In [269]: x = [[1,1],[2,2],[3,3],[4,4],[5,5]]                                                          
        In [270]: y = [2,3,2,3,4]                                                                              
        In [271]: dd = defaultdict(list)                                                                       
        In [272]: for i,j in zip(y, x): 
             ...:     dd[i].append(j) 
             ...:                                                                                              
        In [273]: dd                                                                                           
        Out[273]: defaultdict(list, {2: [[1, 1], [3, 3]], 3: [[2, 2], [4, 4]], 4: [[5, 5]]})
        

        如果结果必须是数组而不是列表,则可以转换为:

        In [274]: d = {k: np.array(dd[k]) for k in dd}                                                         
        In [275]: d                                                                                            
        Out[275]: 
        {2: array([[1, 1],
                [3, 3]]), 3: array([[2, 2],
                [4, 4]]), 4: array([[5, 5]])}
        

        列表追加比np.append(或任何numpyconcatenate 系列函数)快。列表追加就地操作。

        defaultdict 可以直接构建一个数组(但我希望这会更慢):

        In [280]: dd = defaultdict(lambda:np.zeros((0,2),int))                                                 
        In [281]: for i,j in zip(y, x): 
             ...:     dd[i] = np.vstack((dd[i],j)) 
             ...:                                                                                              
        In [282]: dd                                                                                           
        Out[282]: 
        defaultdict(<function __main__.<lambda>()>, {2: array([[1, 1],
                            [3, 3]]), 3: array([[2, 2],
                            [4, 4]]), 4: array([[5, 5]])})
        

        【讨论】:

          猜你喜欢
          • 2018-09-29
          • 1970-01-01
          • 1970-01-01
          • 2019-03-22
          • 2017-10-26
          • 2014-07-24
          • 1970-01-01
          • 2021-02-23
          • 1970-01-01
          相关资源
          最近更新 更多