<jupyter_start><jupyter_text><NAME>  W37Mon: Flow Control and More - ExerciseBuilds on exercises provided with Programming with Python for Social Science by <NAME> and from Social Data Science 2019 by <NAME>.  1. Conditional Flow Control (aka If Statements)If statements are a form of flow control. _Flow control_ means writing code that controls the way data or information flows through the program. These are fundamental structures to programming. Recall that they also have a long history in how programming languages have been designed. The concepts of flow control should be recognizable outside of coding as well. For example when you go shopping you might want to buy ice cream, but only **if** it's sunny and warm outside. **else** you will buy hot chocolate. These kinds of logic come up everywhere in coding; self driving cars should go forward only **if** the light is green, items should be listed for sale in a web shop only **if** they are in stock. Recall that in Python the conditional flow control can use three conditional statements: `if`, `elif` (else if) and `else`. The `if` and `elif` statements should be followed by a logical statement or condition that is either `True` or `False`. The code that should be executed `if` the logic is `True` is written on the lines below the `if`, and should be indented one TAB (or 4 spaces). Finally all flow control statements must end with a colon. >**Task 1.1:** Write a __pseudocode__ workflow that includes conditions, for a daily activity. >> *Note*: No coding is needed here.<jupyter_code>#if hungry:
#    check the fridge
#    if "food in the fridge" == True:
#        cook
#    else:
#        go to the supermarket
#        buy food
#        cook
#    eat the food
#else:
#    pass<jupyter_output><empty_output><jupyter_text>> **Task 1.2**: Imagine that we have a car that can fit 5 passengers, and we want to know, if the car can fit more passengers. Using `if` and `else`, write code that prints out "The car is full" if passengers is 5 or more, and "The car is not full yet" if passengers are less than 5.<jupyter_code># Number of passengers
passengers = 5

# Include your solution in a new cell below.
# You can test your solution by changing the value of passengers, running this cell, 
# and then running your solution with the new value
if passengers >= 5:
    print("The car is full")
elif passengers < 5:
    print("The car is not full yet")<jupyter_output>The car is full<jupyter_text>>**Task 1.3**: Write a conditional flow logic which produces statements about numbers that you give it, with the following conditions:- if the number is over 100 print "Phew, that's a big number."- if the number is even, print "This one is even."- if the number is even and over 100 print "Stop. I can't even."- if the number doesn't satisfy any of these conditions, print the number.>*Recall: Multiple conditions can be inserted with elif statement(s). And remember to think through your solution first before jumping to write your code!*>*Hint: The different if statements are executed in a given order. Think carefully about the different options you have and what they imply.*<jupyter_code>number = 102
# Most complex condition first
if (number > 100) & ((number % 2) == 0):
    print("Stop. I can't even.")
# I chose to have 'larger than 100' first
elif number > 100:
    print("Phew, that's a big number.")
# Even number
elif (number % 2) == 0:
    print("This one is even.")
else:
    print(number)<jupyter_output>Stop. I can't even.<jupyter_text>2. ListsRecall that lists are a type of container. They are declared using square brackets e.g. `[x,y,z]` and lists can change, as in you can add elements to lists, you can change the value of a specific element, or you can remove elements. You access elements by their index, which starts at 0.We have defined in the next cell a list that contains the the population of Denmark from 1901 - 2020 (population in 1000s). The data is from here: https://www.statbank.dk/10021.<jupyter_code># Data from https://www.statbank.dk/10021
DK_population =[2447,2477,2506,2532,2560,2589,2621,2652,2687,2722,
                2757,2788,2820,2851,2886,2921,2958,2991,3027,3061,
                3265,3306,3340,3372,3406,3439,3467,3487,3510,3531,
                3557,3590,3620,3651,3683,3711,3738,3765,3794,3826,
                3849,3882,3926,3973,4023,4075,4123,4168,4211,4252,
                4285,4315,4349,4389,4424,4454,4479,4501,4532,4566,
                4601,4630,4666,4703,4741,4779,4820,4855,4879,4907,
                4951,4976,5008,5036,5054,5065,5080,5097,5112,5122,
                5124,5119,5116,5112,5111,5116,5125,5129,5130,5135,
                5146,5162,5181,5197,5216,5251,5275,5295,5314,5330,
                5349,5368,5384,5398,5411,5427,5447,5476,5511,5535,
                5561,5581,5603,5627,5660,5707,5749,5781,5806,5823]<jupyter_output><empty_output><jupyter_text>>**Task 2.1**: Take the list above. Use list methods and indices to answer the following: > - How many elements are in the list? > - What is the range (e.g. the max - min) of the first 10 items? > - What is the range (e.g. the max - min) for elements between indices 80 and 90 (i.e. 1981 to 1991)? > - What was the population in 1904 (Hint: This is the fourth element in the list)> Bonus: Can you make the cell return full length responses to each of the questions?<jupyter_code># How many elements are in the list?
length = len(DK_population) # 120
print(f"There are {length} elements in the list")
# What is the range (e.g. the max - min) of the first 10 items?
first_10 = DK_population[0:9]
Range = max(first_10) - min(first_10) # 240
print(f"The range of the first 10 items is {Range}.")
# What is the range (e.g. the max - min) for elements between indices 80 and 90 (i.e. 1981 to 1991)?
second_sub = DK_population[80:90]
max(second_sub) - min(second_sub) # 24
print(f"The range between 1981 and 1991 is {Range}.")
# What was the population in 1904 (Hint: This is the fourth element in the list)
print(f"The population in 1904 was {DK_population[3]}.")<jupyter_output>The population in 1904 was 2532.<jupyter_text>>**Task 2.2**: Run the cell below, which loads the SODAS DataFrame. Then, retrieve the names of the people at SODAS and turn them into a list. > _Hint: You will want to identify the column in the DataFrame that contains the names and then use a Pandas Series method to transform it into a list. You can find the documentation for Series [here](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.html)_<jupyter_code># Loading the pandas module
import pandas as pd

# Loading the SODAS dataframe

url = 'https://dl.dropboxusercontent.com/s/9war4suj1s5j1ah/sodas_people_twitter_scholar.csv?dl=1'

sodas_people_df = pd.read_csv(url)

sodas_people_df.head(2)
sodas_people = sodas_people_df['name'].tolist()
sodas_people<jupyter_output><empty_output><jupyter_text>>**Task 2.3**: How many people are in SODAS based on this list?<jupyter_code>len(sodas_people) # 51<jupyter_output><empty_output><jupyter_text>> **Task 2.4**: What is the index of '<NAME>' in `sodas_people`? >*Hint: one way is to just look at the list and count, but this is an impractical solution for long lists and doesn't work if your program needs to know the answer. There is also a list method that helps find the index of a specific element - you can search Google or look up Python documentation to find it.*<jupyter_code>sodas_people.index("<NAME>")
# Index 1<jupyter_output><empty_output><jupyter_text>>**Task 2.5**: Sometimes in lists you want to access only a few specific elements and put them in a new list. Create a list called `some_sodas_people` that contains only the 8th, 9th, and 10th elements of `sodas_people`.<jupyter_code>some_sodas_people = sodas_people[7:10]
some_sodas_people<jupyter_output><empty_output><jupyter_text>> **Task 2.6**: Say we want to make a broader list of people related to SDS, which then includes SODAS members and SDS students like your group. First make a new list, `sds_group` with the names of your group members, including you. Note that each name should be a string.<jupyter_code>sds_group = ["Silvia", "Korbinian", "Isha", "Aske"]<jupyter_output><empty_output><jupyter_text>> **Task 2.7:** Now make a list called `SDS` which consist of first `sodas_people`, then `sds_group`. >>*Hint: You might be inclined to use a list method here, but don't forget that there are also operators that might be suitable.*<jupyter_code>SDS = sodas_people + sds_group<jupyter_output><empty_output><jupyter_text>> **Task 2.8**: Create a list called `groups` that contains nested lists `sds_group` and a new list `sds_group2` with the names of the group beside you.<jupyter_code>sds_group2 = ["Anton", "Annika"]
groups = [sds_group, sds_group2]<jupyter_output><empty_output><jupyter_text>> **Task 2.9:** How would you access the element with your own name? >> *Hint: Here, we just want you to think about how indices in nested lists work. You can count the correct indices. Take as example the following code:*<jupyter_code>xy = ['x','y']
letters = [['x','y'],['z','w']]
# counting here the xy list is inside list letters
print(letters.index(xy))
print(letters[0].index('x'))<jupyter_output>0<jupyter_text>First index the list inside the bigger list and subsequently do whatever you want with the chosen list.<jupyter_code># Print my name based on location
print(groups[0][3])

# Or find the index within the nested list
print(groups[0].index("Aske"))<jupyter_output>Aske
3<jupyter_text>> **Task 2.10**: Maybe sometime in the future you become the Head of Studies of the SDS program and take over from <NAME>. Replace Andreas's name with your name (as a string) in `sodas_people`. >> *Hint: First find the index with Andreas's name*<jupyter_code>sodas_people.index("<NAME>")
sodas_people[7] = "<NAME>"
sodas_people[0:8]<jupyter_output><empty_output><jupyter_text>> **Task 2.11**: What are the values of `SDS`? Where is your name and why?<jupyter_code>print(SDS)
SDS.index("Aske") # at index 54 as I appended our names to the end of the list<jupyter_output>['<NAME>', '<NAME>', '<NAME>', '<NAME>', '<NAME>', '<NAME>', '<NAME>', '<NAME>', '<NAME>', '<NAME>', '<NAME>', '<NAME>', '<NAME>', '<NAME>', '<NAME>', '<NAME>', '<NAME>', '<NAME>', '<NAME>', '<NAME>', '<NAME>', '<NAME>', '<NAME>', '<NAME>', '<NAME>', '<NAME>', '<NAME>', '<NAME>', '<NAME>', '<NAME>', '<NAME>', '<NAME>', '<NAME>', '<NAME>', '<NAME>', '<NAME>', '<NAME>', '<NAME>', '<NAME>', '<NAME>', '<NAME>', '<NAME>', '<NAME>', '<NAME>', 'Asg[...]<jupyter_text>3. Conditional Flow Control in PracticeThere are a variety of applications of conditional logic when working in Python, such as when you are collecting data or conducting quality assurance on existing data. Next, we'll have two tasks that introduce potential applications to give you an opportunity to practice more meaningful uses and think through when you might want to use flow control.When trying to load files in your own computer into a pandas dataframe in python you may encounter different types of errors. In the following task, you will be using `if` statements and booleans to check whether a file is present in an existing folder, specifically in the one you have stored your Jupyter Notebook in. To set up for the task, run the next cell which returns a boolean value indicating whether a file called "file_name_to_check.txt" is present in the directory where your Jupyter Notebook is stored. If the file is present in the folder a `True` value will be stored in the variable called `boolean`. Otherwise, a `False` value will be stored.<jupyter_code>import os.path
fname = "file_name_to_check.txt"
boolean = os.path.isfile(fname) 
boolean<jupyter_output><empty_output><jupyter_text>> **Task 3.1:** Use the `boolean` variable you just created and write a flow control logic that prints a message to describing whether the file exists in your folder or not. >> _Note: If you are uncertain about the code above or are having problems with it, you can also just imagine that the file does not exists and make defining the variable `boolean` part of your solution._<jupyter_code>if boolean == True:
    print(f"The file {fname} exists in the folder.")
else:
    print(f"The file {fname} does not exist in the folder.")<jupyter_output>The file file_name_to_check.txt does not exist in the folder.<jupyter_text>Now let's get more practice with string methods and how to combine them with if statements. > **Task 3.2**: Define the string `string = "I-love-programming-in-python"` and use string methods to do the following:>>1. Replace the characters "-" with spaces (" ").>2. Convert the string to a title.<jupyter_code># Define string
string = "I-love-programming-in-python"
# Replace dashes with spaces
string = string.replace("-", " ")
# Change to title (all words start with a capital letter)
string = string.title()
string<jupyter_output><empty_output><jupyter_text>> **Task 3.3:** Combine string methods and conditional flow control into code that does the following:> - Check whether the string is a title and the number of "-" characters is equal to 0. > - If both conditions are met, store each word of the string into a separate element in a list. Plus, print the length of both the list and the string. Explain why they have the same lenght or not. > - If the conditions are not met, print "Something went wrong with the string methods."<jupyter_code>if (string.istitle() == True) & (string.count('-') == 0):
    words = string.split()
    print(f"the number of characters in the list 'string' is {len(string)}.")
    print(f"the number of words it contains is {len(words)}.")
else:
    print("Something went wrong with the string methods.")<jupyter_output>the number of characters in the list 'string' is 28.
the number of words it contains is 5.<jupyter_text>4. Practicing Python Built-in Functions and String MethodsAs you know by now, Python like any other language requires practice and repitition to acquire ease and fluency in using it. The next couple of tasks are intended to give you some opportunity to do just that with a specific focus on built-in functions and more string methods.>**Task 4.1**: Pick three built-in functions and apply them to an object of your choosing. For instance, you could try the following functions on lists: ```pythonlist_of_numbers = [0, 4, 3, -7] max(list_of_numbers)min(list_of_numbers)```> _Hint: You can find documentation on the built-in functions in Python [here](https://www.w3schools.com/python/python_ref_functions.asp)._<jupyter_code>sds_group = ["Silvia", "Korbinian", "Isha", "Aske"]

# first built-in function 
sds_group.append("Anders")
# second built-in function 
letters = "".join(sds_group)
print(f"the total number of letters in the list is {len(letters)}.")
# third built-in function b
print(f"The person with the longest name is {max(sds_group, key=len)}.")<jupyter_output>the total number of letters in the list is 41.
The person with the longest name is Korbinian.<jupyter_text>>**Task 4.2**: Next, check out the [String Methods documentation](https://www.w3schools.com/python/python_ref_string.asp). Then, define a string and try out at least two string methods that we haven't used in class before. As an example, you could use the replace method. ```pythonstring = "Hello"string.replace("ello", "i")```<jupyter_code># define string
string = "beast"
# first string method
string.replace("b", "f")

# second string method
string.upper()<jupyter_output><empty_output><jupyter_text>5. Tracing and DebuggingWhile you are getting steadly more at ease with working in Python, error messages will remain a constant companion. Therefore, dealing with error messages and resolving them is a key part of writing and working with code. While you will gain most of the knowledge and facility of how to do this tracing and debugging while practicing coding yourself, there are some best practices that can help you develop this facility. These are:1. Treat error messages like guide posts not stop signs–they are intended to help you solve an error not discourage you from coding.2. Read the guide posts carefully, starting from the last line describing the error, then looking at the last marker–`^` or `---->`–to identify the location of the error.3. Remember and make use of the layers of support in this class and the overall programming community:     1. Consult your readings, earlier notebooks, own comments, and [Python documentation](https://docs.python.org/3/index.html)    2. Look up error messages in only forums (such as [Stack Overflow](https://stackoverflow.com/questions) and the internet more broadly)    3. Involve your Base Camp group    4. Draw on the TAs during exercise sessions    5. Pose the problem to instructors on the [Absalon Discussion Forum](https://absalon.ku.dk/courses/45629/discussion_topics/282640)4. Sometimes running a section of code with an error will get stuck in the memory (cache) of your Python session. If you are confident that you have resolved the error in your code but it persists, try restarting your session by clicking 'Kernel' > 'Restart'. _Note:_ This will also clear everything you did in earlier cells from the memory (cache).5. Other times the errors will cause a process to run endlessly without actually raising an error. You can determine this by looking at the dot on the top right corner, if it is solid Python is busy, if it is hollow Python is idle. If Python is busy for an unreasonably long amount of time, you can interrupt the process by clicking 'Kernel' > 'Interrupt'. _Note:_ This will also likely require you to run everything you did so far over again.> **Task 5.1:** Look at the three cells and their error messages below. For each,     > - write out the error message    > - identify the location of the error    > - revise the code _in any way that resolves the error_ and rerun the cell    > - write a one to three sentence reflection on how you approached and resolved the error > **Task 5.1.1**<jupyter_code>10 * (1/0)
# It says devision by zero - that is not posssible<jupyter_output><empty_output><jupyter_text>> **Task 5.1.2**<jupyter_code>100 %% 3
# Invalid syntax - only one %
100%3<jupyter_output><empty_output><jupyter_text>> **Task 5.1.3**<jupyter_code>a_title = 'Honorable'

a_title.istitl()
# Nothing is called 'istitl' - an 'e' is lacking.
a_title.istitle()<jupyter_output><empty_output><jupyter_text>> **Task 5.1.4**<jupyter_code>a_list = ['first', 'second', 'last']

a_list[3]
# Out of range - index starts at 0.
a_list[2]<jupyter_output><empty_output><jupyter_text>> **Task 5.1.5**<jupyter_code>if a_list[-1] == 'last':
print('The last element is ' + a_list[-1] + '.')
else:
    print('The last element is not ' + a_list[-1] + '.')
# Expected an indented block
if a_list[-1] == 'last':
    print('The last element is ' + a_list[-1] + '.')
else:
    print('The last element is not ' + a_list[-1] + '.')<jupyter_output>The last element is last.<jupyter_text>6. Reflection>Write a brief paragraph reflecting on your experience learning programming today. What did you struggle with? What did you enjoy? What surprised you? I have done some coding in python before, so this was very basic :)  7. _If You Have Time_ Become a Python CEO and CFO>**Task 7.1**: Imagine you run you own company. You would like now to create a program that outputs if the average monthly income is as you expected it to be, greater or less and if applicable the difference between them. Moreover, assume your target monthly income is 40000 DKK, but your income fluctuates throughout the year in the following way: |Month|Income||---|---||January|45000||February|55000||March|65000||April|35000||May|45000||June|67000||July|23000||August|56000||September|30000||October|33000||November|32000||December|55000|> Now, try writing down out code that tests how your income compares to your goals and prints the results.>> *Note*: think about calculating the expected and real income first.<jupyter_code># Income
income = [45000, 55000,65000,35000,45000,67000,23000,56000,30000,33000,32000,55000]
income_avg = round(sum(income) / len(income),2)

# Expected
expected = 40000

# calculating the difference
abs(round(income_avg - expected,2))<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.10095821396819125, 'fraction_numerical': 0.04465079521880865, 'mean_word_length': 4.813092161929371, 'pattern_counts': {'":': 0, '<': 156, '<?xml version=': 0, '>': 221, 'https://': 9, 'lorem ipsum': 0, 'www.': 4, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '28', 'dir': 'jupyter-structured-clean-dedup', 'id': '317767', 'license': 'MIT', 'n_tokens_mistral': 6529, 'n_tokens_neox': 5944, 'n_words': 2650, 'path': 'Assignments/.ipynb_checkpoints/W37Mon-Exercises-FlowControl&More_AskeSvaneQvist-checkpoint.ipynb', 'repo_name': 'askesvane/BaseCamp', 'size': '20906'}