0

I have a (normal, unordered) dictionary that is holding my data and I extract some of the data into a numpy array to do some linear algebra. Once that's done I want to put the resulting ordered numpy vector data back into the dictionary with all of data. What's the best, most Pythonic, way to do this?

Joe Kington suggests in his answer to "Writing to numpy array from dictionary" that two solutions include:

  1. Using Ordered Dictionaries
  2. Storing the sorting order in another data structure, such as a dictionary

Here are some (possibly useful) details:

My data is in nested dictionaries. The outer is for groups: {groupKey: groupDict} and group keys start at 0 and count up in order to the total number of groups. groupDict contains information about items: (itemKey: itemDict}. itemDict has keys for the actual data and these keys typically start at 0, but can skip numbers as not all "item locations" are populated. itemDict keys include things like 'name', 'description', 'x', 'y', ...

Getting to the data is easy, dictionaries are great: data[groupKey][itemKey]['x'] = 0.12

Then I put data such as x and y into a numpy vectors and arrays, something like this:

 xVector = numpy.empty( xLength )
 vectorIndex = 0
 for groupKey, groupDict in dataDict.items()
      for itemKey, itemDict in groupDict.items()
           xVector[vectorIndex] = itemDict['x']
           vectorIndex += 1

Then I go off and do my linear algebra and calculate a z vector that I want to add back into dataDict. The issue is that dataDict is unordered, so I don't have any way of getting the proper index.

The Ordered Dict method would allow me to know the order and then index through the dataDict structure and put the data back in.

Alternatively, I could create another dictionary while inside the inner for loop above that stores the relationship between vectorIndex, groupKey and itemKey:

 sortingDict[vectorIndex]['groupKey'] = groupKey
 sortingDict[vectorIndex]['itemKey'] = itemKey

Later, when it's time to put the data back, I could just loop through the vectors and add the data:

 vectorIndex = 0
 for z in numpy.nditer(zVector):
      dataDict[sortingDict[vectorIndex]['groupKey']][sortingDict[vectorIndex]['itemKey']]['z'] = z

Both methods seem equally straight forward to me. I'm not sure if changing dataDict to an ordered dictionary will have any other effects elsewhere in my code, but probably not. Adding the sorting dictionary also seems pretty easy as it will get created at the same time as the numpy arrays and vectors. Left on my own I think I would go with the sortingDict method.

Is one of these methods better than the others? Is there a better way I'm not thinking of? My data structure works well for me, but if there's a way to change that to improve everything else I'm open to it.

Casey
  • 475
  • 6
  • 19
  • 1
    It is helpful if you give concrete examples of what you are working with. – juanpa.arrivillaga Oct 13 '17 at 18:45
  • 2
    If you're in Python 3.6, [dictionaries are ordered](https://stackoverflow.com/questions/39980323/dictionaries-are-ordered-in-python-3-6) -it's considered an implementation detail for now, but I read somewhere that it's popular enough to become spec in future. – toonarmycaptain Oct 13 '17 at 18:59
  • Welcome to SO. Please take the time to read [ask] and the links it contains. – wwii Oct 13 '17 at 19:01
  • 2
    I imagine the `most Pythonic` way would be one that works. – wwii Oct 13 '17 at 19:02
  • @wwii: Thanks for the welcome. I've read the How to Ask, and aside from the lack of concrete examples, what are the other problems you see with my question? I don't have a specific example because I haven't tried it yet. I think both ways will work fine, I was just hoping for some specific thoughts on why one might be better than the other. From my perspective they have minor differences, none of which make one better than the other. I tried to lay this out in the question, but clearly I didn't do a very good job. I'm going to try ordered dictionaries first – Casey Oct 23 '17 at 23:34
  • Nothing specific, I see the low points and invite the poster to read that, maybe not for the current question but keep it mind for future posts - mcve especially. Had I taken the time to see that you've been *here* five months, I might not have commented that. – wwii Oct 24 '17 at 02:42

1 Answers1

0

I ended up going with option #2 and it works quite well.

Casey
  • 475
  • 6
  • 19