create a dictionary from a list with a function - python

I'm working on a premier league dataset and I need to create a dictionary where the keys are the teams and the values are their relative points. I have a list for the teams and a function that takes the results from the matches and transform them into the points for the teams. I got everything good but the problem is that instead of creating one dictionary with all the teams and their scores, it prints 20 dictionaries for each of the team. What is wrong?

You are creating a new dictionary at each iteration. Instead you should make the dictionary before the loop and then add a new entry at each iteration:
def get_team_points(df, teams):
team_points = {}
for team_name in teams:
num_points = ... # as you have it but since you posted an image I'm not rewriting it
team_points[team_name] = num_points
return team_points
A neater solution is to use a dictionary comprehension
def get_team_points(df, teams):
team_points = {team: get_num_points(team, df) for team in teams}
return team_points
where get_num_points is a function of your num_points = ... line, which again I would type out if you had posted the code as text :)
Also - please start using better variable names ;) your life will improve if you do. Names like List and Dict are really bad since:
they're not descriptive
they shadow build-in classes from the typing module (which you should use)
they violate pep8 naming conventions
and speaking of the typing module, here it is in action:
def get_team_points(df: pd.DataFrame, teams: List[str]) -> Dict[str, int]:
team_points = {team: get_num_points(team, df) for team in teams}
return team_points
now you can use a tool like mypy to catch errors before they occur. If you use an IDE instead of jupyter, it will highlight errors as you go. And also your code becomes much clearer for other developers (including future you) to understand and use.

I think perhaps you want this:
def get_team_points(df, teams):
Dict = {}
for team_name in List:
num_points = TeamPoints(...)
Dict[team_name] = num_points
print(Dict)

In TeamsPointDict() method, you are creating dictionaries for each team member in the list.
To insert all of them in one dictionary, declare the dictionary outside the for loop.

You want to take the sum of HP for Home teams, and AP for Away teams and add them together by team. Instead of manually separating, you can use two groupby operations and sum the results.
The return of each groupby will be a Series that we can then add together as pandas aligns on the index (teams in this case). Then with Series.to_dict() we get the entire dictionary at once.
import pandas as pd
df = pd.DataFrame({'HomeTeam': list('AABCDA'), 'AwayTeam': list('CBAAAB'),
'HP': [4,5,6,7,8,10], 'AP': [0,0,10,11,4,7]})
HomeTeam AwayTeam HP AP
0 A C 4 0
1 A B 5 0
2 B A 6 10
3 C A 7 11
4 D A 8 4
5 A B 10 7
# Fill value so addition works if a team has exclusively home/away games.
s = df.groupby('HomeTeam')['HP'].sum().add(df.groupby('AwayTeam')['AP'].sum(),
fill_value=0).astype(int)
s.to_dict()
{'A': 44, 'B': 13, 'C': 7, 'D': 8}

you should define your dictionary before the function then add your values.
dic = {}
for team_name in List:
dic[team_name] = num_points

Related

Outputing single strings in python

I'm in need of some assistance in this code problem from a MOOC on python programming that I'm taking. This is just for self-learning, and not for any graded coursework. Could you please provide some guidance. I am stuck. Thanks in advance for your help.
The problem statement is:
One of the confusing things about dictionaries is that they are unordered: the keys have no internal ordering to them. Sometimes though, you want to look through the keys in a
particular order, such as printing them alphabetically if they represent something like artist names.
For example, imagine if a forum tool used for a course exported its data as a dictionary. The keys of the dictionary are students' names, and the values are days of activity. Your goal is to return a list of students in the class in alphabetical order, followed by their days of activity, like this:
Chopra, Deepak: 22
Joyner, David: 14
Winfrey, Oprah: 17
Write a function named alphabetical_keys. alphabetical_keys should take as input a dictionary, and return a single string. The keys of the dictionary will be names and the values will be integers. The output should be a single string made of multiple
lines, following the format above: the name (the key), a colon and space, then the number of days of activity (the value), sorted alphabetically by key.
Remember, you are returning this as a single string: you're going to need to put the \n character after each line.
To convert a dictionary's keys into a list, use this line
of code:
keys_as_list = list(the_dict.keys)
From there, you could sort keys_as_list like any normal list.
Add your code here!
def alphabetical_keys(dictionary):
keys_as_list = list(dictionary.keys())
return keys_as_list + dictionary[keys]
Below are some lines of code that will test your function. You can change the value of the variable(s) to test your function with different inputs.
If your function works correctly, this will originally
print:
Chopra, Deepak: 22
Joyner, David: 14
Winfrey, Oprah: 17
the_dictionary = {"Joyner, David": 14, "Chopra, Deepak": 22, "Winfrey, Oprah": 17}
print(alphabetical_keys(the_dictionary))
While dictionaries may seem like they should be ordered, it's best not to think about them that way. It's a mapping from one thing to another.
You already have a way to get a list of the names in the dict:
keys_as_list = list(dictionary.keys())
After a quick Google search on "how to sort python list":
# sort list in place
keys_as_list.sort() # reverse=True would give reverse alpha order
Now you just need to loop through the sorted name as a way to access the dictionary keys:
return_str = "" # start with an empty string
for name in keys_as_list:
# add to the string -- get the name and the dict value for that name
return_str += f"{name}: {dictionary[name]}\n"
All together:
def alphabetical_keys(dictionary):
keys_as_list = list(dictionary.keys())
keys_as_list.sort()
return_str = ""
for name in keys_as_list:
return_str += f"{name}: {dictionary[name]}\n"
return return_str
d = {
"Chopra, Deepak": 22,
"Joyner, David": 14,
"Winfrey, Oprah": 17,
"Gump, Forrest": 9,
"Obama, Barack": 19,
}
string = alphabetical_keys(d)
print(string)
Output:
Chopra, Deepak: 22
Gump, Forrest: 9
Joyner, David: 14
Obama, Barack: 19
Winfrey, Oprah: 17

Python: Running function to append values to an empty list returns no values

This is probably a very basic question but I haven't been able to figure this out.
I'm currently using the following to append values to an empty list
shoes = {'groups':['running','walking']}
df_shoes_group_names = pd.DataFrame(shoes)
shoes_group_name=[]
for type in df_shoes_group_names['groups']:
shoes_group_name.append(type)
shoes_group_name
['running', 'walking']
I'm trying to accomplish the same using a for loop, however, when I execute the loop the list comes back as blank
shoes_group_name=[]
def list_builder(dataframe_name):
if 'shoes' in dataframe_name:
for type in df_shoes_group_names['groups']:
shoes_group_name.append(type)
list_builder(df_shoes_group_names)
shoes_group_name
[]
Reason for the function is that eventually I'll have multiple DF's with different product's so i'd like to just have if statements within the function to handle the creation of each list
so for example future examples could look like this:
df_shoes_group_names
df_boots_group_names
df_sandals_group_names
shoes_group_name=[]
boots_group_name=[]
sandals_group_name=[]
def list_builder(dataframe_name):
if 'shoes' in dataframe_name:
for type in df_shoes_group_names['groups']:
shoes_group_name.append(type)
elif 'boots' in dataframe_name:
for type in df_boots_group_names['groups']:
boots_group_name.append(type)
elif 'sandals' in dataframe_name:
for type in df_sandals_group_names['groups']:
sandals_group_name.append(type)
list_builder(df_shoes_group_names)
list_builder(df_boots_group_names)
list_builder(df_sandals_group_names)
Not sure if I'm approaching this the right way so any advice would be appreciated.
Best,
You should never call or search a variable name as if it were a string.
Instead, use a dictionary to store a variable number of variables.
Bad practice
# dataframes
df_shoes_group_names = pd.DataFrame(...)
df_boots_group_names = pd.DataFrame(...)
df_sandals_group_names = pd.DataFrame(...)
def foo(x):
if shoes in df_shoes_group_names: # <-- THIS WILL NOT WORK
# do something with x
Good practice
# dataframes
df_shoes_group_names = pd.DataFrame(...)
df_boots_group_names = pd.DataFrame(...)
df_sandals_group_names = pd.DataFrame(...)
dfs = {'shoes': df_shoes_group_names,
'boots': df_boots_group_names,
'sandals': df_sandals_group_names}
def foo(key):
if 'shoes' in key: # <-- THIS WILL WORK
# do something with dfs[key]

How can I store a list of C-like structures in Python?

Let me explain the problem by a simple example:
Let's say I want to store 100 people's name, and brand(s) of the car(s) they own (so there can be 1 or more).
I was thinking about using dictionary in Python, but is can only store 1 string attached to one name. Perhaps I can seperate the cars' names like this:
people_and_cars = {'Jack':'Opel Audi'}
and when I need them, I can seperate it into 'Opel' and 'Audi by the split() function, but it seems a bit silly solution.
Is there a better way to do this?
You can store your data in a dictionary:
people_and_cars = {}
Jack has an Opel car, but he might buy another one later, so I store this one in a list like this:
people_and_cars['Jack'] = ['Opel']
print(people_and_cars) # Output: {'Jack': ['Opel']}
Now, Jack buys a new Audi car, so I add it as follows:
people_and_cars['Jack'].append('Audi')
print(people_and_cars) # Output: {'Jack': ['Opel', 'Audi']}
You may need to check first whether a person exists in your dictionary or not, you can do that like below:
if person in people_and_cars:
people_and_cars[person].append(car)
else:
people_and_cars[person] = [car]
Store the list of the cars for each person as a list. The list will be then the values of the keys (people) in your dictionary.
For your example:
people_and_cars = dict()
people_and_cars['Jack'] = ["Opel", "Audi"]

What does ChainMap.new_child() return?

I'm reading David Beazley & Brian K. Jones 's book "Python Cookbook" (Ed 3). In pg 35 there's an example of ChainMap. I don't quite understand the values jumping up and down, pls see my understanding and questions below:
>>> values = ChainMap()
>>> values['x'] = 1
I suppose now values is ChainMap({'x': 1})
>>> # Add a new mapping
>>> values = values.new_child()
>>> values['x'] = 2
At the end of these 3 lines, what is values now? the ChainMap or the dictionary inside?
I'm really a bit lost, the codes here meant to me is the ChainMap added a new child, which shall be a new dictionary; so values becomes a dictionary item linked by the ChainMap; then values is assigned to the new dictionary .
>>> # Add a new mapping
>>> values = values.new_child()
>>> values['x'] = 3
But now values' start to callnew_child()again! Isnt'new_child()can only be called by aChainMap, not a particulardictionary` it links?
That's a great book, I suppose every Python developer should read at least chapters 1 and 4
Concerning your question:
At the end of these 3 lines, what is values now?
values is ChainMap object with 2 dictionaries mapped:
values = ChainMap({'x': 1}, {'x': 2})
The confusing thing is that the (mutated) object itself is returned from new_child() and not the real child.
But now values' start to callnew_child()again!
Of course you can call new_child() as many times as you want, values would be always ChainMap object with defined method new_child()

Can a value in a Python Dictionary have two values?

For a test program I'm making a simple model of the NFL. I'd like to assign a record (wins and losses) to a team as a value in a dictionary? Is that possible?
For example:
afcNorth = ["Baltimore Ravens", "Pittsburgh Steelers", "Cleveland Browns", "Cincinatti Bengals"]
If the Ravens had 13 wins and 3 loses, can the dictionary account for both of those values? If so, how?
sure, just make the value a list or tuple:
afc = {'Baltimore Ravens': (10,3), 'Pb Steelers': (3,4)}
If it gets more complicated, you might want to make a more complicated structure than a tuple - for example if you like dictionaries, you can put a dictionary in your dictionary so you can dictionary while you dictionary.
afc = {'Baltimore Ravens': {'wins':10,'losses': 3}, 'Pb Steelers': {'wins': 3,'losses': 4}}
But eventually you might want to move up to classes...
The values in the dictionary can be tuples or, maybe better in this case, lists:
d = {"Baltimore Ravens": [13, 3]}
d["Baltimore Ravens"][0] += 1
print d
# {"Baltimore Ravens": [14, 3]}
Well, you can use a tuple (or a list):
records = {}
records["Baltimore Ravens"] = (13, 3)
Or you could be fancy and make a Record class with Record.wins and record.losses, but that's probably overkill.
(As another answer points out, using a list means that you can do arithmetic on the values, which might be useful.)

Categories