1

I am trying to iterate over nested Ordered Dictionaries in Python. I know that I can do something like this:

food = OrderedDict([('Fruits', OrderedDict([('Apple', 50), ('Banana', 100), ('Pear', 200)])), 
                    ('Vegetables', OrderedDict([('Carrot', 10), ('Broccoli', 5), ('Corn', 40)]))])
for value in food.itervalues():
    for key in value.iterkeys():
        print key

to get the key (or value) using nested for loops. However, how can I do this in one line? I am trying to save only the String keys (i.e. the fruit names) to a pandas dataframe (the numbers are not used). Here was my attempt:

food_df = pd.DataFrame({'Food': key for key in value.iterkeys() for value in food.itervalues()})

Which raises the error:

File "C:\Python27\lib\site-packages\pandas\core\frame.py", line 397, in __init__
    mgr = self._init_dict(data, index, columns, dtype=dtype)
File "C:\Python27\lib\site-packages\pandas\core\frame.py", line 528, in _init_dict
    dtype=dtype)
File "C:\Python27\lib\site-packages\pandas\core\frame.py", line 5670, in _arrays_to_mgr
    index = extract_index(arrays)
File "C:\Python27\lib\site-packages\pandas\core\frame.py", line 5708, in extract_index
    raise ValueError('If using all scalar values, you must must pass'
    ValueError: If using all scalar values, you must must pass an index

Any ideas? Thanks!

KidSudi
  • 460
  • 2
  • 7
  • 19
  • Please edit your question to included your desired output. I'm not sure whether you want to throw away the information about whether something is a fruit or a vegetable. – DSM Mar 12 '14 at 15:07

1 Answers1

3
[item for sublist in map(lambda a: a.keys(), food.itervalues()) for item in sublist]

This returns

['Apple', 'Banana', 'Pear', 'Carrot', 'Broccoli', 'Corn']

in your case.

You can then create a DataFrame as usual.

food_pd = pd.DataFrame([item for sublist in map(lambda a: a.keys(), food.itervalues()) for item in sublist], columns=["Food"])
Sudeep Juvekar
  • 4,898
  • 3
  • 29
  • 35
  • 1
    upvote and accept please :). There are in fact other ways of `flatten` ing lists of lists: http://stackoverflow.com/questions/952914/making-a-flat-list-out-of-list-of-lists-in-python so this `implicit` double loop that we are using also has alternatives. But for concise one line, it is good enough – Sudeep Juvekar Mar 12 '14 at 15:18
  • Can't upvote at the moment (need reputation score of 15)! And thanks for the info! – KidSudi Mar 12 '14 at 15:22
  • Is there a reason why I can't do this for the values (i.e. 50, 100, 200, 10, 5, 40)? I tried replacing a.keys() with a.values(), but it returns an empty list. – KidSudi Mar 12 '14 at 23:58
  • Sorry, one last thing, is there a way to get both the keys and values in one line? Something like: food_pd = pd.DataFrame([item for sublist in map(lambda a: a.keys(), a.values(), food.itervalues()) for item in sublist], columns=["Food"]). Note this doesn't work. – KidSudi Mar 13 '14 at 00:26
  • 1
    use `(a.keys(), a.values())` (with brackets) inside `map`. This returns a tuple of key value pairs, e.g. `('Apple', 50)`. – Sudeep Juvekar Mar 13 '14 at 00:45