Arithmetic operations on List of Dictionaries in Python - python-3.x

I am currently using Python 3.5.2.
I have a dataset comprising of a list of dictionaries such as below (actual dataset has over 100 such entries):
MyList = [{"Class":1, "ID":123, "Name":"Sam", "Marks":90},
{"Class":1, "ID":124, "Name":"Jack", "Marks":91},
{"Class":1, "ID":125, "Name":"Dan", "Marks":92},
{"Class":2, "ID":234, "Name":"Sammy", "Marks":82},
{"Class":2, "ID":235, "Name":"Jacky", "Marks":85}]
I wanted to get the summary comprising as below:
ClassSummary = [{"Class":1, "TotalStudents": 3, "AvgMarks":91},
{"Class":2, "TotalStudents": 2, "AvgMarks":83.5}]
where TotalStudents refer to count of "Name" in each Class
and AvgMarks refer to Average of "Marks" in each Class.
I am fairly new to list of dictionaries, so any leads on how to approach this would be of great help.
[Edit] Here is what I have tried so far:
class_set = set()
for dict in MyList:
class_set.add(dict["Class"])
This gives me list of different classes available in my List. But I am not sure how to proceed further for subsequent arithmetic operations.
Thanks

It's a bit messy, but here is my solution that works fine:
ClassSummary = []
cls = 0
for d in MyList:
if d["Class"] != cls:
ClassSummary.append({"Class": d["Class"], "TotalStudents": 1, "AvgMarks": d["Marks"]})
cls = d["Class"]
else:
ClassSummary[d["Class"]-1]["TotalStudents"] += 1
ClassSummary[d["Class"]-1]["AvgMarks"] += d["Marks"]
for s in ClassSummary:
s["AvgMarks"] /= s["TotalStudents"]
which gives ClassSummary as:
[{'TotalStudents': 3, 'AvgMarks': 91.0, 'Class': 1}, {'TotalStudents': 2, 'AvgMarks': 83.5, 'Class': 2}]
as you asked for!

Related

How to Convert 'dict_items' Object to List

I am loading data from json files using load method and then putting the items in a new python object.
obj_1 = json.load(file)
obj_2 = obj_1.items()
When I run the code in python2, type(obj_2) is list. But when I run in python 3, type(obj_2) is 'dict_items'. Because of that when I run following code:
sorted_items = sorted (obj_2[1][1]['string'])
I'm getting this error in python 3:
TypeError: 'dict_items' object does not support indexing
In python 2 it runs fine. How can I solve this issue in python 3? I have found some related questions about this but the answers doesn't solve my particular case. I have tried to use list(obj_2) but it causes key error.
json file format is something like this:
{
"item_1": {
"item_2": {
"string": 111111,
"string": 222222,
"string": 333333,
................
................
},
},
}
I want to sort the "item_2" contents according to the keys in ascending order.
simply
d = { .... }
l = list(d.items())
making a for loop here is the best option i can think of.
object_list = []
for key, value in obj_2:
entry = [key, value]
object_list.append(entry)
that would store the key and value in a list that is inside another list.
EDIT
Found a better way to do it!
my_dict = {"hello": "there", "how": "are you?"}
my_list = [[x, y] for x, y in my_dict.items()]
# out => [['hello', 'there'], ['how', 'are you?']]
Convert dict items (keys and values) to a list with one line of code. Example:
example_dictionary = {"a": 1, "b": 2, "c": 3}
dict_items_to_list = [*foo.keys(), *foo.values()]
print(dict_items_to_list)
>>> ['a', 'b', 'c', 1, 2, 3]

Create dictionary with count of values from list

I'm trying to figure out how to create a dictionary with the key as the school and values the wins-losses-draws, based on each item in the list. For example, calling my_dict['Clemson'] would return the string "1-1-1"
"
team_score_list =[['Georgia', 'draw'], ['Duke', 'loss'], ['Virginia Tech', 'win'], ['Virginia', 'loss'], ['Clemson', 'loss'], ['Clemson', 'win'], ['Clemson', 'draw']]
The output for the above list should be the following dictionary:
{'Georgia': 0-0-1, 'Duke': 0-1-0, 'Virginia Tech': 1-0-0, 'Virginia': 0-1-0, 'Clemson': 1-1-1}
For context, the original data comes from a CSV, where each line is in the form of Date,Opponent,Location,Points For,Points Against.
For example: 2016-12-31,Kentucky,Neutral,33,18.
I've managed to wrangle the data into the above list (albeit probably not in the most efficient manner), however just not exactly sure how to get this into the format above.
Any help would be greatly appreciated!
Not beautiful but this should work.
team_score_list = [
["Georgia", "draw"],
["Duke", "loss"],
["Virginia Tech", "win"],
["Virginia", "loss"],
["Clemson", "loss"],
["Clemson", "win"],
["Clemson", "draw"],
]
def gen_dict_lst(team_score_list):
"""Generates dict of list based on team record"""
team_score_dict = {}
for team_record in team_score_list:
if team_record[0] not in team_score_dict.keys():
team_score_dict[team_record[0]] = [0, 0, 0]
if team_record[1] == "win":
team_score_dict[team_record[0]][0] += 1
elif team_record[1] == "loss":
team_score_dict[team_record[0]][1] += 1
elif team_record[1] == "draw":
team_score_dict[team_record[0]][2] += 1
return team_score_dict
def convert_format(score_dict):
"""formats list to string for output validation"""
output_dict = {}
for key, value in score_dict.items():
new_val = []
for index, x in enumerate(value):
if index == 2:
new_val.append(str(x))
else:
new_val.append(str(x) + "-")
new_str = "".join(new_val)
output_dict[key] = new_str
return output_dict
score_dict = gen_dict_lst(team_score_list)
out_dict = convert_format(score_dict)
print(out_dict)
You can first make a dictionary and insert/increment values of wins,loss and draw while iterating over the dictionary values. Here I have shown a way using variable name same as the string used for win,loss and draw and then increased corresponding value in dictionary using global()['str'] (from another answer)
dct={}
for i in team_score_list:
draw=2
win=0
loss=1
if i[0] in dct:
dct[i[0]][globals()[i[1]]]+=1
else:
dct[i[0]]=[0,0,0]
dct[i[0]][globals()[i[1]]]=1
You can then convert your list to string by using '-'.join(...) to get it in a format you want in the dictionary.
I now get what you mean:
You could do
a = dict()
f = lambda x,s: str(int(m[x]=='1' or j==s))
for (i,j) in team_score_list:
m = a.get(i,'0-0-0')
a[i] = f"{f(0,'win')}-{f(2,'draw')}-{f(4,'loss')}"
{'Georgia': '0-1-0',
'Duke': '0-0-1',
'Virginia Tech': '1-0-0',
'Virginia': '0-0-1',
'Clemson': '1-1-1'}
Now this is an answer only for this example. If you had many data, it would be good to use a list then join at the end. Eg
b = dict()
g = lambda x,s: str(int(m[x]) + (j==s))
for (i,j) in team_score_list:
m = b.get(i,[0,0,0])
b[i] =[g(0,"win"),g(1,"draw"),g(2,"loss")]
{key:'-'.join(val) for key,val in b.items()}
{'Georgia': '0-1-0',
'Duke': '0-0-1',
'Virginia Tech': '1-0-0',
'Virginia': '0-0-1',
'Clemson': '1-1-1'}

Python: logarithm to base 2 in nested lists

I have this list:
mylist = [['A',5,6,7],['C',3,90,5.3],['G',5,4,6]]
How I can get the logarithm to base 2 in such nested lists?
This is my approach:
from math import log
print([log(x,2) for x in mylist2[1:]])
Outputs should be like:
[['A',2.321928094887362, 2.584962500721156, 2.807354922057604],['C',1.5849625007211563, 6.491853096329675, 2.4059923596758366],['G',2.321928094887362, 2.0, 2.584962500721156]]
Not exactly clear on how you want your output to be formatted. But if you want to keep it in the same "format" as the input, here's a quick one-liner:
In [6]: list(map(lambda row: [row[0]] + [log(item, 2) for item in row[1:]], mylist))
Out[6]:
[['A', 2.321928094887362, 2.584962500721156, 2.807354922057604],
['C', 1.5849625007211563, 6.491853096329675, 2.4059923596758366],
['G', 2.321928094887362, 2.0, 2.584962500721156]]
If you just want the log values without the "key" to start each list, leave off the [row[0]] + part.
HTH.
The fastest approach (not in computational terms obviously) is a naive solution like this:
from math import log
mylist = [['A',5,6,7],['C',3,90,5.3],['G',5,4,6]]
for numbers in mylist:
for number in numbers[1:]:
print log(number,2) #or assign to something

Making a dictionary of from a list and a dictionary

I am trying to create a dictionary of codes that I can use for queries and selections. Let's say I have a dictionary of state names and corresponding FIPS codes:
statedict ={'Alabama': '01', 'Alaska':'02', 'Arizona': '04',... 'Wyoming': '56'}
And then I have a list of FIPS codes that I have pulled in from a Map Server request:
fipslist = ['02121', '01034', '56139', '04187', '02003', '04023', '02118']
I want to sort of combine the key from the dictionary (based on the first 2 characters of the value of that key) with the list items (also, based on the first 2 characters of the value of that key. Ex. all codes beginning with 01 = 'Alabama', etc...). My end goal is something like this:
fipsdict ={'Alabama': ['01034'], 'Alaska':['02121', '02003','02118'], 'Arizona': ['04187', '04023'],... 'Wyoming': ['56139']}
I would try to set it up similar to this, but it's not working quite correctly. Any suggestions?
fipsdict = {}
tempList = []
for items in fipslist:
for k, v in statedict:
if item[:2] == v in statedict:
fipsdict[k] = statedict[v]
fipsdict[v] = tempList.extend(item)
A one liner with nested comprehensions:
>>> {k:[n for n in fipslist if n[:2]==v] for k,v in statedict.items()}
{'Alabama': ['01034'],
'Alaska': ['02121', '02003', '02118'],
'Arizona': ['04187', '04023'],
'Wyoming': ['56139']}
You will have to create a new list to hold matching fips codes for each state. Below is the code that should work for your case.
for state,two_digit_fips in statedict.items():
matching_fips = []
for fips in fipslist:
if fips[:2] == two_digit_fips:
matching_fips.append(fips)
state_to_matching_fips_map[state] = matching_fips
>>> print(state_to_matching_fips_map)
{'Alabama': ['01034'], 'Arizona': ['04187', '04023'], 'Alaska': ['02121', '02003', '02118'], 'Wyoming': ['56139']}
For both proposed solutions I need a reversed state dictionary (I assume that each state has exactly one 2-digit code):
reverse_state_dict = {v: k for k,v in statedict.items()}
An approach based on defaultdict:
from collections import defaultdict
fipsdict = defaultdict(list)
for f in fipslist:
fipsdict[reverse_state_dict[f[:2]]].append(f)
An approach based on groupby and dictionary comprehension:
from itertools import groupby
{reverse_state_dict[k]: list(v) for k,v
in (groupby(sorted(fipslist), key=lambda x:x[:2]))}

Nested dictionaries in Python: how to make them and how to use them?

I'm still trying to figure it out how nested dictionaries in python really works.
I know that when you're using [] it's a list, () it's a tuple and {} a dict.
But when you want to make a nested dictionaries like this structure (that's what a i want) :
{KeyA :
{ValueA :
[KeyB : ValueB],
[Keyc : ValueC],
[KeyD : ValueD]},
{ValueA for each ValueD]}}
For now I have a dict like:
{KeyA : {KeyB : [ValueB],
KeyC : [ValueC],
KeyD : [ValueD]}}
Here's my code:
json_file = importation()
dict_guy = {}
for key, value in json_file['clients'].items():
n_customerID = normalization(value['shortname'])
if n_customerID not in dict_guy:
dict_guy[n_customerID] = {
'clientsName':[],
'company':[],
'contacts':[], }
dict_guy[n_customerID]['clientsName'].append(n_customerID)
dict_guy[n_customerID]['company'].append(normalization(value['name']))
dict_guy[n_customerID]['contacts'].extend([norma_email(item) for item in v\
alue['contacts']])
Can someone please, give me more informations or really explain to me how a nested dict works?
So, I hope I get it right from our conversation in the comments :)
json_file = importation()
dict_guy = {}
for key, value in json_file['clients'].items():
n_customerID = normalization(value['shortname'])
if n_customerID not in dict_guy:
dict_guy[n_customerID] = {
'clientsName':[],
'company':[],
'contacts':{}, } # Assign empty dict, not list
dict_guy[n_customerID]['clientsName'].append(n_customerID)
dict_guy[n_customerID]['company'].append(normalization(value['name']))
for item in value['contacts']:
normalized_email = norma_email(item)
# Use the contacts dictionary like every other dictionary
dict_guy[n_customerID]['contacts'][normalized_email] = n_customerID
There is no problem to simply assign a dictionary to a key inside another dictionary. That's what I do in this code sample. You can create dictionaries nested as deep as you wish.
How that this helped you. If not, we'll work on it further :)
EDIT:
About list/dict comprehensions. You are almost right that:
I know that when you're using [] it's a list, () it's a tuple and {} a dict.
The {} brackets are a little tricky in Python 3. They can be used to create a dictionary as well as a set!
a = {} # a becomes an empty dictionary
a = set() # a becomes an empty set
a = {1,2,3} # a becomes a set with 3 values
a = {1: 1, 2: 4, 3: 9} # a becomes a dictionary with 3 keys
a = {x for x in range(10)} # a becomes a set with 10 elements
a = {x: x*x for x in range(10)} # a becomes a dictionary with 10 keys
Your line dict_guy[n_customerID] = { {'clientsName':[], 'company':[], 'contacts':[]}} tried to create a set with a single dictionary in it and because dictionaries are not hashable, you got the TypeError exception informing you that something is not hashable :) (sets can store only ements that are hashable)
Check out this page.
example = {'app_url': '', 'models': [{'perms': {'add': True, 'change': True,
'delete': True}, 'add_url': '/admin/cms/news/add/', 'admin_url': '/admin/cms/news/',
'name': ''}], 'has_module_perms': True, 'name': u'CMS'}

Resources