简体   繁体   中英

Convert dictionary with integer keys to numpy array

I have a dictionary defined as follows:

>>> mydict = {0:obj0,5:obj1,4:obj3,7:obj4}

The dictionary has integer as keys.

I am trying to convert this dict to a numpy array.

so that:

>>> nparray[[4,0]] = [obj3,obj0]
>>> nparray[[7,4]] = [obj4,obj3]

I am aware of numpy structured arrays but unfortunately it seems like integer indexes must correspond to the position in the array as opposed to the key. Is there a way to change this behavior.

I was considering a way to "trick" the numpy array. For example instead of reading [4,0] it reads the rows corresponding to those keys.

My end goal is to have some sort of custom class that inherits from np.ndarray, if there isn't another alternative.

UPDATE

A bit more background, I originally solved this problem by using the class below, which stores the objects:

class MyArray (dict):
    def __init__ (self,*args):
        dict.__init__(self,*args)
    def __getitem__ (self, key):
        if not hasattr (key, '__iter__'):
            return dict.__getitem__ (self,key)
        return List([dict.__getitem__ (self,k) for k in key])

Which allows multi-key indexes. The key array can be very huge (1000000+), and so for k in key can take a long time and/or be expensive. I wanted to use numpy arrays to take advantage of it's speed, lower memory etc.. and wouldn't have to use that for loop. Is it still warranted?

Lets make the dictionary; here my obj are tuples (just for convenience):

In [563]: mydict={0:(0,),5:(1,),4:(3,),7:(4,)}
In [564]: mydict
Out[564]: {0: (0,), 4: (3,), 5: (1,), 7: (4,)}

Initial an array that's big enough and dtype=object:

In [565]: A=np.empty((8,),dtype=object)    
In [566]: A
Out[566]: array([None, None, None, None, None, None, None, None], dtype=object)

copy values from mydict to A , using the key as the array index:

In [567]: for k in mydict:
   .....:     A[k]=mydict[k]
   .....:     

In [568]: A
Out[568]: array([(0,), None, None, None, (3,), (1,), None, (4,)], dtype=object)

In [574]: A[[4,0]]
Out[574]: array([(3,), (0,)], dtype=object)
In [575]: A[[7,4]]
Out[575]: array([(4,), (3,)], dtype=object)

Items defined in the dictionary now appear in the corresponding slots in the array. I won't make any claims about this being useful.


I could mask the nones .

In [581]: Am=np.ma.masked_array(A)
In [582]: Am.mask=[False,True,True,True,False,False,True,False]

In [583]: Am
Out[583]: 
masked_array(data = [(0,) -- -- -- (3,) (1,) -- (4,)],
             mask = [False  True  True  True False False  True False],
       fill_value = ?)

The nones are still there, just 'hidden'. I don't know if masking does anything useful with object types.


Subclass dict

From comments it sounds like the main thing you want is the ability to select multiple items from a dictionary, something akin to the array A[[0,3,5]] indexing.

It might be easier to subclass dict than to expand or subclass np.ndarray .

scipy.sparse has a sparse matrix format which is a subclass of dict. It's __getitem__ may give ideas on how to extend your own dict. I'll try to come up with a simpler version.

In mean time, one way to fetch a group of keys is with an expression like:

In [646]: {k:mydict[k] for k in mydict if k in {0,4}}
Out[646]: {0: (0,), 4: (3,)}

or simpler

In [647]: {k:mydict[k] for k in [0,4]}
Out[647]: {0: (0,), 4: (3,)}

but more robust:

In [649]: {k:mydict.get(k,None) for k in [0,4,5,10]}
Out[649]: {0: (0,), 4: (3,), 5: (1,), 10: None}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM