This question already has answers here:
How do I sort a dictionary by value?
(34 answers)
Closed 1 year ago.
{'KRW-SOL': {'count': 3, 'tradeAmount': 437540},
'KRW-LOOM': {'count': 78, 'tradeAmount': 21030768},
'KRW-ONT': {'count': 14, 'tradeAmount': 947009},
'KRW-FCT2': {'count': 1, 'tradeAmount': 491935},
'KRW-DKA': {'count': 30, 'tradeAmount': 12053758}
I want to sort by count or tradeAmount
i want like this
{'KRW-LOOM': {'count': 78, 'tradeAmount': 21030768},
'KRW-DKA': {'count': 30, 'tradeAmount': 12053758}
'KRW-ONT': {'count': 14, 'tradeAmount': 947009},
'KRW-SOL': {'count': 3, 'tradeAmount': 437540},
'KRW-FCT2': {'count': 1, 'tradeAmount': 491935}}
sorted(cdDict.items(), key=lambda item: item[1]['tradeAmount'], reverse=True)
you can do something like below
x = {'KRW-SOL': {'count': 3, 'tradeAmount': 437540},
'KRW-LOOM': {'count': 78, 'tradeAmount': 21030768},
'KRW-ONT': {'count': 14, 'tradeAmount': 947009},
'KRW-FCT2': {'count': 1, 'tradeAmount': 491935},
'KRW-DKA': {'count': 30, 'tradeAmount': 12053758}} #input
# new dict sorted by count
y = {k: v for k, v in sorted(x.items(), key=lambda item: item[1]['count'],reverse=True)}
print(y)
If you want sort by tradeAmount then,
y = {k: v for k, v in sorted(x.items(), key=lambda item: item[1]['tradeAmount'],reverse=True)}
print(y)
Related
I need some help with some code where it needs to go into the log file and it should look like this:
I have the dictonary which holds the count value and the keys which is the event id, but I want to display it like that but I do not know how to since it comes out all at once and it does not print individually instead of 1 by 1 and I have used a nested dictionary to do this.
This is an example of the dictionary which holds the count vals and keys which need to be printed.
eventIDs = {1102: {'count': 0}, 4611: {'count': 0}, 4624: {'count': 0}, 4634: {'count': 0}, 4648: {'count': 0}, 4661: {'count': 0},
4662: {'count': 0}, 4663: {'count': 0}, 4672: {'count': 0}, 4673: {'count': 0}, 4688: {'count': 0}, 4698: {'count': 0},
4699: {'count': 0}, 4702: {'count': 0}, 4703: {'count': 0}, 4719: {'count': 0}, 4732: {'count': 0}, 4738: {'count': 0},
4742: {'count': 0}, 4776: {'count': 0}, 4798: {'count': 0}, 4799: {'count': 0}, 4985: {'count': 0}, 5136: {'count': 0},
5140: {'count': 0}, 5142: {'count': 0}, 5156: {'count': 0}, 5158: {'count': 0}}
This is the code I have tried:
def log_output():
with open('path' + timeStamp + '.txt', 'a') as VisualiseLog:
event_id = list{eventIDs.keys()}
event_count = list(eventIDs.values)
for item in eventIDs:
print(f'Event ID: {event_id}')
VisualiseLog.write('Event ID: {event_id}')
print(f'Event Count: {event_count}')
VisualiseLog.write(f'Event Count: {event_count}')
Try this code:
eventIDs = {
1102: {'count': 0},
4611: {'count': 0}
}
timeStamp = "1234"
def log_output():
with open('path' + timeStamp + '.txt', 'a') as VisualiseLog:
for id in eventIDs:
count = eventIDs[id]['count']
print(f'Event ID: {id}')
VisualiseLog.write(f'Event ID: {id}\n')
print(f'Event Count: {count}')
VisualiseLog.write(f'Event Count: {count}\n\n')
log_output()
# Outputs:
# Event ID: 1102
# Event Count: 0
#
# Event ID: 4611
# Event Count: 0
Every loop in this function:
def sum_total(files, local_dir):
final_dict = {}
for i in range(len(files)):
with open(local_dir+files[i], 'r') as f:
data = f.readlines()
res = find_by_tag(data)
print('res: ', res)
sum_values_from_several_dict_to_one(res)
Generates example output:
{'Critical Tests': {'failed': 1, 'passed': 2, 'total': 5}, 'All Tests': {'failed': 5, 'passed': 0, 'total': 5}}
{'Critical Tests': {'failed': 2, 'passed': 3, 'total': 5}, 'All Tests': {'failed': 10, 'passed': 12, 'total': 12}}
{'Critical Tests': {'failed': 3, 'passed': 4, 'total': 5}, 'All Tests': {'failed': 10, 'passed': 0, 'total': 10}}
EXPECTED OUTPUT:
I would like to sum those values into one dictionary to get output like:
{'Critical Tests': {'failed': 6, 'passed': 9, 'total': 15}, 'All Tests': {'failed': 25, 'passed': 12, 'total': 27}}
The problem is - how should the 'sum_values_from_several_dict_to_one' function looks like? Thats my code but it does not work.. What should be improved?
def sum_values_from_several_dict_to_one(d1):
final_dict = {}
for d in d1 <?>:
for test, results in d.items():
if test not in final_dict:
final_dict[test] = {}
for key, value in results.items():
if key in final_dict[test]:
final_dict[test][results] += value
else:
final_dict[test][key] = value
return final_dict
Here you have:
a = {'Critical Tests': {'failed': 1, 'passed': 2, 'total': 5}, 'All Tests': {'failed': 5, 'passed': 0, 'total': 5}}
b = {'Critical Tests': {'failed': 2, 'passed': 3, 'total': 5}, 'All Tests': {'failed': 10, 'passed': 12, 'total': 12}}
def sum_dicts (dict1, dict2):
res = {}
for key, val in dict1.items():
for k, v in dict2.items():
if k == key:
if type(val) is dict:
res.update({key: sum_dicts(val, v)})
else:
res.update({key: val + v})
break
return res
if __name__ == '__main__':
sol = sum_dicts(a, b)
print(sol)
Output:
{'All Tests': {'failed': 15, 'total': 17, 'passed': 12}, 'Critical Tests': {'failed': 3, 'total': 10, 'passed': 5}}
EDIT:
Assuming res is a dict you can use it like this:
def sum_total(files, local_dir):
final_dict = {}
for i in range(len(files)):
with open(local_dir+files[i], 'r') as f:
data = f.readlines()
res = find_by_tag(data)
print('res: ', res)
final_dict = sum_dicts(final_dict, res)
I have a dict which I have used Counter to get term frequencies for each key e.g. 'A' and 'B'.
dict = {'A': Counter({'food': 30, 'menu': 19, 'good': 15}), 'B': Counter({'one': 5, 'chicken': 10})}
I would like to be able to add a new field so that each term has another value.
I have tried:
for key, values in dict.items():
for it1, it2 in values:
dict[key][it1][it2] = 0
but I receive:
ValueError: too many values to unpack (expected 2)
Do I need to remove the Counter object? How do I create a new value and how do I access this value?
You're better off creating an entirely new dictionary, to have that extra nested dict:
dct = {key: {k: {v: 0} for k, v in values.items()} for key, values in dct.items()}
I hope I understood your question. You want to add one more item to the counter?. If that is the case, you could do by updating the counter object. the count will increase as you keep on updating it.
mydict = {'A': Counter({'food': 30, 'menu': 19, 'good': 15}), 'B': Counter({'one': 5, 'chicken': 10})}
mydict['A'].update(['price'])
mydict['B'].update(['cow'])
print mydict
{'A': Counter({'food': 30, 'menu': 19, 'good': 15, 'price': 1}), 'B': Counter({'chicken': 10, 'one': 5, 'cow': 1})}
if you do update again
mydict['A'].update(['price'])
mydict['B'].update(['cow'])
print mydict
will result in
{'A': Counter({'food': 30, 'menu': 19, 'good': 15, 'price': 2}), 'B': Counter({'chicken': 10, 'one': 5, 'cow': 2})}
Without creating a new dict you can manipulate your current dict with Counter inside.
You can print your current items like this way:
dct = {'A': Counter({'food': 30, 'menu': 19, 'good': 15}), 'B': Counter({'one': 5, 'chicken': 10})}
for k, v in dct.items():
print(k, v)
Output:
>>> A Counter({'food': 30, 'menu': 19, 'good': 15})
>>> B Counter({'chicken': 10, 'one': 5})
In order to modify values inside Counter dict, you can do something like this:
for k, v in dct:
if "food" in v:
v["food"] = 666
Output:
print(dct)
>>> {'A': Counter({'food': 666, 'menu': 19, 'good': 15}), 'B': Counter({'chicken': 10, 'one': 5})}
And if you want to add new elements to your Counter dict you can do something like this:
for k, v in dct.items():
if "food" in v:
v.update({"new_food":0})
print(dct)
Output:
>>> {'A': Counter({'food': 30, 'menu': 19, 'good': 15, 'new_food': 0}), 'B': Counter({'chicken': 10, 'one': 5})}
Otherwise if you want to have a new "regular" dict you can use dict comprehension:
new_dct = {k:{key:val for key,val in v.items()} for k,v in dct.items()}
print(new_dct)
>>> {'A': {'food': 30, 'menu': 19, 'good': 15}, 'B': {'chicken': 10, 'one': 5}}
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I have a dictionary in the next format:
a = {'file': {'x': [1, 2, 3, 4], 'y': [23, 134, 571, 13]},
'file2': {'x': [1, 2, 3, 5], 'y': [123, 215, 21, 123]}}
Is it possible to convert this dictionary in this format (here keys are union between all x's):
{'1': {'file': 23, 'file2': 123}, '2': {'file': '134', 'file2': 215}, ...,
'4': {'file': 13, 'file2': '-'}, '5': {'file': '-', 'file2': '123'}}
I just cannot figure out how to do it.
Yes, of course it is possible. I think what you want is something like:
interim = {k: {x: y for x, y in zip(v['x'], v['y'])} for k, v in a.items()}
which creates a dictionary mapping the 'x's to the 'y's:
{'file2': {1: 123, 2: 215, 3: 21, 5: 123},
'file': {1: 23, 2: 134, 3: 571, 4: 13}}
then:
out_keys = set().union(*interim.values())
which creates the set of keys for the output:
set([1, 2, 3, 4, 5])
and finally:
output = {k: {k1: v1.get(k, "-") for k1, v1 in interim.items()} for k in keys}
which creates your output format:
{1: {'file2': 123, 'file': 23},
2: {'file2': 215, 'file': 134},
3: {'file2': 21, 'file': 571},
4: {'file2': '-', 'file': 13},
5: {'file2': 123, 'file': '-'}}
This is flexible such that any number of 'file's, 'x's and 'y's can be handled. Note that zip will truncate to whichever of the x's and 'y's is shorter if they aren't the same length.
Here's a one-liner, so to speak:
In [1]: %paste
a = {'file': {'x': [1, 2, 3, 4], 'y': [23, 134, 571, 13]},
'file2': {'x': [1, 2, 3, 5], 'y': [123, 215, 21, 123]}}
## -- End pasted text --
In [2]: {x: {fkey:
..: ([y for _, y in zip(fval['x'], fval['y']) if _ == x] or ['-'])[0]
..: for fkey, fval in a.items()}
..: for x in set().union(*[fval['x'] for fval in a.values()])}
Out[2]:
{1: {'file2': 123, 'file': 23},
2: {'file2': 215, 'file': 134},
3: {'file2': 21, 'file': 571},
4: {'file2': '-', 'file': 13},
5: {'file2': 123, 'file': '-'}}
Essentially it is equivalent to jonsharpe's answer, although it doesn't create an intermediate dict.
Taking this dictionary:
{'local': {'count': 7,
'dining-and-nightlife': {'count': 1,
'bar-clubs': {'count': 1}
},
'activities-events': {'count': 6,
'outdoor-adventures': {'count': 4},
'life-skill-classes': {'count': 2}
}
}}
How do I determine the most relevant match (within a 30% leeway)? For example, activities-events has a count of 6 so 6/7 = 85% and its child outdoor-adventures has a count of 4 out 6 (66%). So from this the most relevant category is outdoor-adventures.
In this example:
{'local': {'count': 11,
'dining-and-nightlife': {'count': 4,
'bar-clubs': {'count': 4}
},
'activities-events': {'count': 6,
'outdoor-adventures': {'count': 4},
'life-skill-classes': {'count': 2}
}
}}
Take both dining-and-nightlife (33%) with bar-clubs (100%) and activities-events (54%) with
outdoor-aventures (66%).
I was hoping the percentage cutoff to be determined by
cutoff = 0.3
The idea here is to determine which category is most relevant removing the smaller results (below a 30%) match.
#F.J answered this question below but now I wish to update the counts in the tree.
Inital Output:
{'local': {'activities-events': {'count': 6,
'life-skill-classes': {'count': 2},
'outdoor-adventures': {'count': 4}},
'count': 11,
'dining-and-nightlife': {'bar-clubs': {'count': 4}, 'count': 4}}}
Post output:
{'local': {'activities-events': {'count': 6,
'life-skill-classes': {'count': 2},
'outdoor-adventures': {'count': 4}},
'count': 10,
'dining-and-nightlife': {'bar-clubs': {'count': 4}, 'count': 4}}}
The following should work, note that this will modify your input dictionary in place:
def keep_most_relevant(d, cutoff=0.3):
for k, v in list(d.items()):
if k == 'count':
continue
if 'count' in d and v['count'] < d['count'] * cutoff:
del d[k]
else:
keep_most_relevant(v)
Examples:
>>> d1 = {'local': {'count': 7, 'dining-and-nightlife': {'count': 1, 'bar-clubs': {'count': 1}}, 'activities-events': {'count': 6, 'outdoor-adventures': {'count': 4}, 'life-skill-classes': {'count': 2}}}}
>>> keep_most_relevant(d1)
>>> pprint.pprint(d1)
{'local': {'activities-events': {'count': 6,
'life-skill-classes': {'count': 2},
'outdoor-adventures': {'count': 4}},
'count': 7}}
>>> d2 = {'local': {'count': 11, 'dining-and-nightlife': {'count': 4, 'bar-clubs': {'count': 4}}, 'activities-events': {'count': 6, 'outdoor-adventures': {'count': 4}, 'life-skill-classes': {'count': 2}}}}
>>> keep_most_relevant(d2)
>>> pprint.pprint(d2)
{'local': {'activities-events': {'count': 6,
'life-skill-classes': {'count': 2},
'outdoor-adventures': {'count': 4}},
'count': 11,
'dining-and-nightlife': {'bar-clubs': {'count': 4}, 'count': 4}}}
def matches(match, cutoff):
total = float(match['count'])
for k in match:
if k == 'count':
continue
score = match[k]['count'] / total
if score >= cutoff:
yield (k, score)
m = list(matches(match[k], cutoff))
if m: yield max(m, key=lambda (c, s): s)
def best_matches(d, cutoff):
for k in d:
for m in matches(d[k], cutoff):
yield m
Test 1
>>> d = {'local': {'count': 7,
'dining-and-nightlife': {'count': 1,
'bar-clubs': {'count': 1}
},
'activities-events': {'count': 6,
'outdoor-adventures': {'count': 4},
'life-skill-classes': {'count': 2}
}
}}
>>> print list(best_matches(d, 0.3))
[('activities-events', 0.8571428571428571), ('outdoor-adventures', 0.66666666666666663)]
Test 2
>>> d = {'local': {'count': 11,
'dining-and-nightlife': {'count': 4,
'bar-clubs': {'count': 4}
},
'activities-events': {'count': 6,
'outdoor-adventures': {'count': 4},
'life-skill-classes': {'count': 2}
}
}}
>>> print list(best_matches(d, 0.3))
[('dining-and-nightlife', 0.36363636363636365), ('bar-clubs', 1.0), ('activities-events', 0.54545454545454541), ('outdoor-adventures', 0.66666666666666663)]