Group data in nested dictionary Python - python

I have a dictionary like this,
data = {'04-01-2012': [{1: 0.93}, {2: 0.9195000000000001}, {3: 0.9090000000000001}, {4: 0.8985000000000002},
{5: 0.8880000000000002}, {6: 0.8775000000000003}, {7: 0.8670000000000003},
{8: 0.8565000000000004}, {9: 0.8460000000000004}],
'12-01-2012': [{1: 0.96}],
'07-01-2012': [{1: 0.96}, {2: 0.95}, {3: 0.94}, {4: 0.9299999999999999}, {5: 0.9199999999999999},
{6: 0.9099999999999999}],
'06-01-2012': [{1: 0.945}, {2: 0.9365}, {3: 0.928}, {4: 0.9195000000000001}, {5: 0.9110000000000001},
{6: 0.9025000000000002}, {7: 0.8940000000000002}],
'10-01-2012': [{1: 0.93}, {2: 0.9244}, {3: 0.9188}],
'05-01-2012': [{1: 0.935}, {2: 0.926}, {3: 0.917}, {4: 0.908}, {5: 0.899}, {6: 0.89}, {7: 0.881}, {8: 0.872}],
'11-01-2012': [{1: 0.945}, {2: 0.9325}],
'02-01-2012': [{1: 0.94}, {2: 0.9299999999999999}, {3: 0.9199999999999999}, {4: 0.9099999999999999},
{5: 0.8999999999999999}, {6: 0.8899999999999999}, {7: 0.8799999999999999},
{8: 0.8699999999999999}, {9: 0.8599999999999999}, {10: 0.8499999999999999},
{11: 0.8399999999999999}],
'03-01-2012': [{1: 0.955}, {2: 0.9455}, {3: 0.936}, {4: 0.9265000000000001}, {5: 0.9170000000000001},
{6: 0.9075000000000002}, {7: 0.8980000000000002}, {8: 0.8885000000000003},
{9: 0.8790000000000003}, {10: 0.8695000000000004}],
'08-01-2012': [{1: 0.94}, {2: 0.9295}, {3: 0.919}, {4: 0.9085000000000001}, {5: 0.8980000000000001}],
'01-01-2012': [{1: 0.95}, {2: 0.94}, {3: 0.9299999999999999}, {4: 0.9199999999999999}, {5: 0.9099999999999999},
{6: 0.8999999999999999}, {7: 0.8899999999999999}, {8: 0.8799999999999999},
{9: 0.8699999999999999}, {10: 0.8599999999999999}, {11: 0.8499999999999999},
{12: 0.8399999999999999}],
'09-01-2012': [{1: 0.92}, {2: 0.91}, {3: 0.9}, {4: 0.89}]}
I need to iterate over the dictionary values and group all the 1's, 2's and so on.
This is my code so far
from collections import defaultdict
final = defaultdict(list)
for k, v in data.items():
new_data = next(iter(v))
for m, n in new_data.items():
final[m].append(n)
print(final)
# defaultdict(<class 'list'>, {1: [0.935, 0.92, 0.955, 0.96, 0.94, 0.93, 0.95, 0.96, 0.945, 0.94, 0.945, 0.93]})
It groups all 1's only, not 2's and so on. What wrong I am doing?

You forgot to iterate over the many tiny dictionaries:
from collections import defaultdict
final = defaultdict(list)
for k, v in data.items():
for d in v: # <-- this was missing
for m, n in d.items():
final[m].append(n)
print(final)
(You only called next(...), which yields the first item only.)
Output:
defaultdict(, {1: [0.96, 0.935, 0.93, 0.945, 0.96, 0.95, 0.93, 0.94, 0.945, 0.955, 0.94, 0.92], 2: [0.926, 0.9244, 0.9365, 0.95, 0.94, 0.9195000000000001, 0.9299999999999999, 0.9325, 0.9455, 0.9295, 0.91], 3: [0.917, 0.9188, 0.928, 0.94, 0.9299999999999999, 0.9090000000000001, 0.9199999999999999, 0.936, 0.919, 0.9], 4: [0.908, 0.9195000000000001, 0.9299999999999999, 0.9199999999999999, 0.8985000000000002, 0.9099999999999999, 0.9265000000000001, 0.9085000000000001, 0.89], 5: [0.899, 0.9110000000000001, 0.9199999999999999, 0.9099999999999999, 0.8880000000000002, 0.8999999999999999, 0.9170000000000001, 0.8980000000000001], 6: [0.89, 0.9025000000000002, 0.9099999999999999, 0.8999999999999999, 0.8775000000000003, 0.8899999999999999, 0.9075000000000002], 7: [0.881, 0.8940000000000002, 0.8899999999999999, 0.8670000000000003, 0.8799999999999999, 0.8980000000000002], 8: [0.872, 0.8799999999999999, 0.8565000000000004, 0.8699999999999999, 0.8885000000000003], 9: [0.8699999999999999, 0.8460000000000004, 0.8599999999999999, 0.8790000000000003], 10: [0.8599999999999999, 0.8499999999999999, 0.8695000000000004], 11: [0.8499999999999999, 0.8399999999999999], 12: [0.8399999999999999]})

new_data = next(iter(v))`
This is the line where it goes wrong. This just returns the next value in your iterable, which in this case is the key-value pair bound to key: 1.
you can see this by adding a print statement:
from collections import defaultdict
final = defaultdict(list)
print final
for k, v in data.items():
new_data = next(iter(v))
for m, n in new_data.items():
print new_data
final[m].append(n)
#{1: 0.96}
#{1: 0.935}
#{1: 0.93}
#{1: 0.945}
#{1: 0.96}
#{1: 0.95}
#{1: 0.93}
#{1: 0.94}
#{1: 0.945}
#{1: 0.955}
#{1: 0.94}
#{1: 0.92}
Then the solution is to actually grab all items, instead of just the first, which can be done in a lot of ways, the simplest and ugliest of which is to nest another loop.
from collections import defaultdict
final = defaultdict(list)
for k, v in data.items():
iterable = iter(v)
for i in range(len(v)):
new_data = iterable.next()
for m, n in new_data.items():
final[m].append(n)
print(final)

Related

How to create a dictionary using python list comprehension from 2 list

This is my code:
a=[1,2,3,4,5,6,7]
b=[8,9,10,11,12,13,14]
c=[{i:j} for i in a for j in b]
print(c)
Output is
[{1: 8}, {1: 9}, {1: 10}, {1: 11}, {1: 12}, {1: 13}, {1: 14}, {2: 8}, {2: 9}, {2: 10}, {2: 11}, {2: 12}, {2: 13}, {2: 14}, {3: 8}, {3: 9}, {3: 10}, {3: 11}, {3: 12}, {3: 13}, {3: 14}, {4: 8}, {4: 9}, {4: 10}, {4: 11}, {4: 12}, {4: 13}, {4: 14}, {5: 8}, {5: 9}, {5: 10}, {5: 11}, {5: 12}, {5: 13}, {5: 14}, {6: 8}, {6: 9}, {6: 10}, {6: 11}, {6: 12}, {6: 13}, {6: 14}, {7: 8}, {7: 9}, {7: 10}, {7: 11}, {7: 12}, {7: 13}, {7: 14}]
But I want like:
[{1: 8, 2: 9, 3: 10, 4: 11, 5: 12, 6: 13, 7: 14}]
How to achieve this?
To pair several list together you need to use zip operation zip(a, b),
You may use dict comprehension notation or dict constructor
Wrap in an array if needed
c = dict(zip(a, b)) # {1: 8, 2: 9, 3: 10, 4: 11, 5: 12, 6: 13, 7: 14}
c = [dict(zip(a, b))] # [{1: 8, 2: 9, 3: 10, 4: 11, 5: 12, 6: 13, 7: 14}]
c = {i: j for i, j in zip(a, b)} # {1: 8, 2: 9, 3: 10, 4: 11, 5: 12, 6: 13, 7: 14}
c = [{i: j for i, j in zip(a, b)}] # [{1: 8, 2: 9, 3: 10, 4: 11, 5: 12, 6: 13, 7: 14}]
Your notation [{:} for _ in _] was creating a dict for each iteration, resulting in mulitple dicts in a list [{}, {}, {}]
Use dict with zip
Ex:
a=[1,2,3,4,5,6,7]
b=[8,9,10,11,12,13,14]
print(dict(zip(a, b)))
# --> {1: 8, 2: 9, 3: 10, 4: 11, 5: 12, 6: 13, 7: 14}

i want to create a dictionary of list of dictionaries

i want to create a dictionary of an array of dictionaries from a list of node pairs and their weight.
nets = pd.read_table('data/nodes.txt', header = None)
bb = np.array(nets).tolist()
graph = collections.defaultdict(dict)
for row in bb:
graph[row[0]][row[1]]=row[2]
graph[row[1]][row[0]] = row[2]
print(dict(graph))
which resulted in this dictionary
{0: {1: 2, 2: 3, 3: 6, 7: 8}, 1: {0: 2, 2: 5, 4: 7}, 2: {0: 3, 1: 5, 11: 5, `5: 4}, 3: {0: 6, 11: 4, 6: 2}, 4: {1: 7}, 5: {8: 3, 2: 4}, 6: {9: 3, 3: 2}, 7: {0: 8}, 8: {5: 3}, 9: {10: 6, 6: 3}, 10: {9: 6}, 11: {2: 5, 3: 4}}`
and want a it in this form.
{0: [{1: 2}, {2: 3}, {3: 6}, {7: 8}],
1: [{0: 2}, {2: 5}, {4: 7}],
2: [{0: 3}, {1: 5}, {11: 5}, {5: 4}],
3: [{0: 6}, {11: 4}, {6: 2}],
4: [{1: 7}],
5: [{8: 3}, {2: 4}],
6: [{9: 3}, {3: 2}],
7: [{0: 8}, 8: {5: 3}],
9: [{10: 6}, {6: 3}],
10: [{9: 6}],
11: [{2: 5}, {3: 4}]}
You can do this pretty easily if you really want to, though I'd look carefully at where you're going to use this data structure to see if your existing more logical structure could be made to work instead.
Anyway, here's a quick implementation that should do what you want:
graph = collections.defaultdict(list)
for row in bb:
graph[row[0]].append({row[1]: row[2]})
graph[row[1]].append({row[0]: row[2]})

How do i create a nested dictionary iteratively?

I want to create a dictionary from a given list, nesting elements as shown below. For instance, given:
lst = range(1, 11)
how do I create a function to create a nested dictionary from this list:
dic = {1: {2: {3: {4: {5: {6: {7: {8: {9: 10}}}}}}}}}
Reverse your list (or better range object). Take the last (now first) element as start value and create a new dict in each iteration through the rest of the reversed list:
>>> r = reversed(range(1, 11))
... d = next(r)
... for x in r:
... d = {x: d}
... d
...
{1: {2: {3: {4: {5: {6: {7: {8: {9: 10}}}}}}}}}
You could use functools.reduce.
import functools
lst = range(1, 11)
functools.reduce(lambda x, y: {y: x}, reversed(lst))
# {1: {2: {3: {4: {5: {6: {7: {8: {9: 10}}}}}}}}}
You can build it from inside out:
result = {9: 10}
for i in range(8, 0, -1):
temp = {i: result}
result = temp
print(result)
# outputs {1: {2: {3: {4: {5: {6: {7: {8: {9: 10}}}}}}}}}
Start from the innermost value, working outward.
At each step, use the previous step's dict as the new val.
def nest_dict(lst):
my_dict = lst[-1]
for val in lst[-2::-1]:
my_dict = {val: my_dict}
return my_dict
print nest_dict(range(1, 11))
Output:
{1: {2: {3: {4: {5: {6: {7: {8: {9: 10}}}}}}}}}

Finding 3 biggest value in dictionaries contained within a list

my_list = [{0: 0}, {1: 4.2}, {2: 3.7}, {3: 5.0}, {4: 4.0}, {5: 3.3}, {6: 4.3}, {7: 4.0}, {8: 3.9}, 0, {10: 4.0}]
What I want my program to do is go through the list, record the highest value (as in the value from a key-value pair) once it's scanned through the entire thing, append that key-pair value to a new list, remove that key-pair value from the original list [my_list], and repeat the process twice more. So the desired output would look like this:
desired output: [{3: 5.0},{6: 4.3},{1: 4.2}]
I'm not sure how to achieve the desired output.
I'm assuming that the single integer in your my_list is a typo.
Use the heapq module to get the three largest items. This has slightly better complexity and memory efficiency than sorting the whole list and then extracting the last three elements.
>>> from heapq import nlargest
>>> my_list = [{0: 0}, {1: 4.2}, {2: 3.7}, {3: 5.0}, {4: 4.0}, {5: 3.3}, {6: 4.3}, {7: 4.0}, {8: 3.9}, {10: 4.0}]
>>> nlargest(3, my_list, key=lambda d: d.values()[0])
[{3: 5.0}, {6: 4.3}, {1: 4.2}]
The key function specifies the criterion by which the items from your list are to be ordered, it simply fetches the only value any individual dictionary has.

How to change value for item in a list of dict in python in a simple way?

Suppose a list composed by several dict in python:
a = [{1: u'100'}, {2: u'200'}, {3: u'300'}]
I'd like to change the datatype of items of the dict from unicode to float, i.e.,
a = [{1: 100.0}, {2: 200.0}, {3: 300.0}]
The following are my current codes:
for i in a:
for j in i.keys():
if type(i[j]) == unicode:
i[j] = float(i[j])
It works but I hate this stupid expression.
There must be some much more elegant expression.
Please help.
>>> a = [{1: u'100'}, {2: u'200'}, {3: u'300'}]
>>> [{k:float(v) for k,v in d.iteritems()} for d in a]
[{1: 100.0}, {2: 200.0}, {3: 300.0}]
If you need to add a Unicode type check, you can, but then arguably a nested list/dict comprehension isn't all that readable any more:
>>> a = [{1: u'100'}, {2: u'200'}, {3: u'300', 4: "not unicode"}]
>>> [{k:float(v) if isinstance(v, unicode) else v for k,v in d.iteritems()} for d in a]
[{1: 100.0}, {2: 200.0}, {3: 300.0, 4: 'not unicode'}]

Categories

Resources