<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 Introduction to Python
(via xkcd)
What is Python?
Python is a modern, open source, object-oriented programming language, created by a Dutch programmer, Guido van Rossum. Officially, it is an interpreted scripting language (meaning that it is not compiled until it is run) for the C programming language; in fact, Python itself is coded in C. Frequently, it is compared to languages like Perl and Ruby. It offers the power and flexibility of lower level (i.e. compiled) languages, without the steep learning curve, and without most of the associated debugging pitfalls. The language is very clean and readable, and it is available for almost every modern computing platform.
Why use Python for scientific programming?
Python offers a number of advantages to scientists, both for experienced and novice programmers alike
Step1:  Notice that, rather than using parentheses or brackets to enclose units of code (such as loops or conditional statements), python simply uses indentation. This relieves the programmer from worrying about a stray bracket causing her program to crash. Also, it forces programmers to code in neat blocks, making programs easier to read. So, for the following snippet of code
Step2:  The first line initializes a variable to hold the sum, and the second initiates a loop, where each element in the data list is given the name x, and is used in the code that is indented below. The first line of subsequent code that is not indented signifies the end of the loop. It takes some getting used to, but works rather well.
Now lets call the function
Step3:  Our specification of mean and var are by no means the most efficient implementations. Python provides some syntax and built-in functions to make things easier, and sometimes faster
Step4:  In the new implementation of mean, we use the built-in function sum to reduce the function to a single line. Similarly, var employs a list comprehension syntax to make a more compact and efficient loop.
An alternative looping construct involves the map function. Suppose that we had a number of datasets, for each which we want to calculate the mean
Step5:  This can be done using a classical loop
Step6:  Or, more succinctly using map
Step7:  Similarly we did not have to code these functions to get means and variances; the numpy package that we imported at the beginning of the module has similar methods
Step9:  Data Types and Data Structures
In the introduction above, you have already seen some of the important Python data structures, including integers, floating-point numbers, lists and tuples. It is worthwhile, however, to quickly introduce all of the built-in data structures relevant to everyday Python programming.
Literals
The simplest data structure are literals, which appear directly in programs, and include most simple strings and numbers
Step10:  There are a handful of constants that exist in the built-in-namespace. Importantly, there are boolean values True and False
Step11:  Either of these can be negated using not.
Step12:  In addition, there is a None type that represents the absence of a value.
Step13:  All the arithmetic operators are available in Python
Step14:  Compatibility Corner
Step15:  There are several Python data structures that are used to encapsulate several elements in a set or sequence.
Tuples
The first sequence data structure is the tuple, which simply an immutable, ordered sequence of elements. These elements may be of arbitrary and mixed types. The tuple is specified by a comma-separated sequence of items, enclosed by parentheses
Step16:  Individual elements in a tuple can be accessed by indexing. This amounts to specifying the appropriate element index enclosed in square brackets following the tuple name
Step17:  Notice that the index is zero-based, meaning that the first index is zero, rather than one (in contrast to R). So above, 5 retrieves the sixth item, not the fifth.
Two or more sequential elements can be indexed by slicing
Step18:  This retrieves the third, fourth and fifth (but not the sixth!) elements -- i.e., up to, but not including, the final index. One may also slice or index starting from the end of a sequence, by using negative indices
Step19:  As you can see, this returns all elements except the final two. 
You can add an optional third element to the slice, which specifies a step value. For example, the following returns every other element of foo, starting with the second element of the tuple.
Step20:  The elements of a tuple, as defined above, are immutable. Therefore, Python takes offense if you try to change them
Step21:  The TypeError is called an exception, which in this case indicates that you have tried to perform an action on a type that does not support it. We will learn about handling exceptions further along.
Finally, the tuple() function can create a tuple from any sequence
Step22:  Why does this happen? Because in Python, strings are considered a sequence of characters.
Lists
Lists complement tuples in that they are a mutable, ordered sequence of elements. To distinguish them from tuples, they are enclosed by square brackets
Step23:  Elements of a list can be arbitrarily substituted by assigning new values to the associated index
Step24:  Operations on lists are somewhat unusual. For example, multiplying a list by an integer does not multiply each element by that integer, as you might expect, but rather
Step25:  Which is simply three copies of the list, concatenated together. This is useful for generating lists with identical elements
Step26:  (incidentally, this works with tuples as well)
Step27:  Since lists are mutable, they retain several methods, some of which mutate the list. For example
Step28:  Some methods, however, do not change the list
Step29:  Dictionaries
One of the more flexible built-in data structures is the dictionary. A dictionary maps a collection of values to a set of associated keys. These mappings are mutable, and unlike lists or tuples, are unordered. Hence, rather than using the sequence index to return elements of the collection, the corresponding key must be used. Dictionaries are specified by a comma-separated sequence of keys and values, which are separated in turn by colons. The dictionary is enclosed by curly braces. 
For example
Step30:  Notice that a indexes an integer, b a tuple, and foo a string (now you know what foo means). Hence, a dictionary is a sort of associative array. Some languages refer to such a structure as a hash or key-value store.
As with lists, being mutable, dictionaries have a variety of methods and functions that take dictionary arguments. For example, some dictionary functions include
Step31:  Some useful dictionary methods are
Step32:  When we try to index a value that does not exist, it raises a KeyError.
Step33:  If we would rather not get the error, we can use the get method, which returns None if the value is not present.
Step34:  Custom return values can be specified with a second argument.
Step35:  It is easy to remove items from a dictionary.
Step36:  Sets
If we don't require labels for our unordered collection of values, we can use a set. Sets store unique collections of values.
Step37:  We can also use the set constructor.
Step38:  As we would expect, we can perform set operations.
Step39:  The set function is useful for returning the unique elements of a data structure. For example, recall bar
<ASSISTANT_TASK:>
Python Code:
# Import modules you might use
import numpy as np
# Some data, in a list
my_data = [12, 5, 17, 8, 9, 11, 21]
# Function for calulating the mean of some data
def mean(data):
    # Initialize sum to zero
    sum_x = 0.0
    # Loop over data
    for x in data:
        # Add to sum
        sum_x += x 
    
    # Divide by number of elements in list, and return
    return sum_x / len(data)
Explanation: Introduction to Python
(via xkcd)
What is Python?
Python is a modern, open source, object-oriented programming language, created by a Dutch programmer, Guido van Rossum. Officially, it is an interpreted scripting language (meaning that it is not compiled until it is run) for the C programming language; in fact, Python itself is coded in C. Frequently, it is compared to languages like Perl and Ruby. It offers the power and flexibility of lower level (i.e. compiled) languages, without the steep learning curve, and without most of the associated debugging pitfalls. The language is very clean and readable, and it is available for almost every modern computing platform.
Why use Python for scientific programming?
Python offers a number of advantages to scientists, both for experienced and novice programmers alike:
Powerful and easy to use
Python is simultaneously powerful, flexible and easy to learn and use (in general, these qualities are traded off for a given programming language). Anything that can be coded in C, FORTRAN, or Java can be done in Python, almost always in fewer lines of code, and with fewer debugging headaches. Its standard library is extremely rich, including modules for string manipulation, regular expressions, file compression, mathematics, profiling and debugging (to name only a few). Unnecessary language constructs, such as END statements and brackets are absent, making the code terse, efficient, and easy to read. Finally, Python is object-oriented, which is an important programming paradigm particularly well-suited to scientific programming, which allows data structures to be abstracted in a natural way.
Interactive
Python may be run interactively on the command line, in much the same way as Octave or S-Plus/R. Rather than compiling and running a particular program, commands may entered serially followed by the Return key. This is often useful for mathematical programming and debugging.
Extensible
Python is often referred to as a “glue” language, meaning that it is a useful in a mixed-language environment. Frequently, programmers must interact with colleagues that operate in other programming languages, or use significant quantities of legacy code that would be problematic or expensive to re-code. Python was designed to interact with other programming languages, and in many cases C or FORTRAN code can be compiled directly into Python programs (using utilities such as f2py or weave). Additionally, since Python is an interpreted language, it can sometimes be slow relative to its compiled cousins. In many cases this performance deficit is due to a short loop of code that runs thousands or millions of times. Such bottlenecks may be removed by coding a function in FORTRAN, C or Cython, and compiling it into a Python module.
Third-party modules
There is a vast body of Python modules created outside the auspices of the Python Software Foundation. These include utilities for database connectivity, mathematics, statistics, and charting/plotting. Some notables include:
NumPy: Numerical Python (NumPy) is a set of extensions that provides the ability to specify and manipulate array data structures. It provides array manipulation and computational capabilities similar to those found in Matlab or Octave. 
SciPy: An open source library of scientific tools for Python, SciPy supplements the NumPy module. SciPy gathering a variety of high level science and engineering modules together as a single package. SciPy includes modules for graphics and plotting, optimization, integration, special functions, signal and image processing, genetic algorithms, ODE solvers, and others.
Matplotlib: Matplotlib is a python 2D plotting library which produces publication-quality figures in a variety of hardcopy formats and interactive environments across platforms. Its syntax is very similar to Matlab. 
Pandas: A module that provides high-performance, easy-to-use data structures and data analysis tools. In particular, the DataFrame class is useful for spreadsheet-like representation and mannipulation of data. Also includes high-level plotting functionality.
IPython: An enhanced Python shell, designed to increase the efficiency and usability of coding, testing and debugging Python. It includes both a Qt-based console and an interactive HTML notebook interface, both of which feature multiline editing, interactive plotting and syntax highlighting.
Free and open
Python is released on all platforms under the GNU public license, meaning that the language and its source is freely distributable. Not only does this keep costs down for scientists and universities operating  under a limited budget, but it also frees programmers from licensing concerns for any software they may develop. There is little reason to buy expensive licenses for software such as Matlab or Maple, when Python can provide the same functionality for free!
Sample code: mean and standard deviation
Here is a quick example of a Python program. We will call it stats.py, because Python programs typically end with the .py suffix. This code consists of some fake data, and two functions mean and var which calculate mean and variance, respectively. Python can be internally documented by adding lines beginning with the # symbol, or with simple strings enclosed in quotation marks. Here is the code:
End of explanation
sum_x = 0
# Loop over data
for x in my_data:
    
    # Add to sum
    sum_x += x 
print(sum_x)
Explanation: Notice that, rather than using parentheses or brackets to enclose units of code (such as loops or conditional statements), python simply uses indentation. This relieves the programmer from worrying about a stray bracket causing her program to crash. Also, it forces programmers to code in neat blocks, making programs easier to read. So, for the following snippet of code:
End of explanation
mean(my_data)
Explanation: The first line initializes a variable to hold the sum, and the second initiates a loop, where each element in the data list is given the name x, and is used in the code that is indented below. The first line of subsequent code that is not indented signifies the end of the loop. It takes some getting used to, but works rather well.
Now lets call the function:
End of explanation
# Function for calulating the mean of some data
def mean(data):
    # Call sum, then divide by the numner of elements
    return sum(data)/len(data)
# Function for calculating variance of data
def var(data):
    # Get mean of data from function above
    x_bar = mean(data)
    # Do sum of squares in one line
    sum_squares = sum([(x - x_bar)**2 for x in data])
    # Divide by n-1 and return
    return sum_squares/(len(data)-1)
Explanation: Our specification of mean and var are by no means the most efficient implementations. Python provides some syntax and built-in functions to make things easier, and sometimes faster:
End of explanation
x = (45, 95, 100, 47, 92, 43)
y = (65, 73, 10, 82, 6, 23)
z = (56, 33, 110, 56, 86, 88) 
datasets = (x,y,z)
datasets
Explanation: In the new implementation of mean, we use the built-in function sum to reduce the function to a single line. Similarly, var employs a list comprehension syntax to make a more compact and efficient loop.
An alternative looping construct involves the map function. Suppose that we had a number of datasets, for each which we want to calculate the mean:
End of explanation
means = []
for d in datasets:
    means.append(mean(d))
means
Explanation: This can be done using a classical loop:
End of explanation
list(map(mean, datasets))
Explanation: Or, more succinctly using map:
End of explanation
np.mean(datasets, axis=1)
Explanation: Similarly we did not have to code these functions to get means and variances; the numpy package that we imported at the beginning of the module has similar methods:
End of explanation
42              # Integer
0.002243        # Floating-point
5.0J            # Imaginary
'foo'
"bar"           # Several string types
s = Multi-line
string
Explanation: Data Types and Data Structures
In the introduction above, you have already seen some of the important Python data structures, including integers, floating-point numbers, lists and tuples. It is worthwhile, however, to quickly introduce all of the built-in data structures relevant to everyday Python programming.
Literals
The simplest data structure are literals, which appear directly in programs, and include most simple strings and numbers:
End of explanation
type(True)
Explanation: There are a handful of constants that exist in the built-in-namespace. Importantly, there are boolean values True and False
End of explanation
not False
Explanation: Either of these can be negated using not.
End of explanation
x = None
print(x)
Explanation: In addition, there is a None type that represents the absence of a value.
End of explanation
15/4
Explanation: All the arithmetic operators are available in Python:
End of explanation
(14 - 5) * 4
Explanation: Compatibility Corner: Note that when using Python 2, you would get a different answer! Dividing an integer by an integer will yield another integer. Though this is "correct", it is not intuitive, and hence was changed in Python 3.
Operator precendence can be enforced using parentheses:
End of explanation
(34,90,56) # Tuple with three elements
(15,) # Tuple with one element
(12, 'foobar') # Mixed tuple
Explanation: There are several Python data structures that are used to encapsulate several elements in a set or sequence.
Tuples
The first sequence data structure is the tuple, which simply an immutable, ordered sequence of elements. These elements may be of arbitrary and mixed types. The tuple is specified by a comma-separated sequence of items, enclosed by parentheses:
End of explanation
foo = (5,7,2,8,2,-1,0,4)
foo[0]
Explanation: Individual elements in a tuple can be accessed by indexing. This amounts to specifying the appropriate element index enclosed in square brackets following the tuple name:
End of explanation
foo[2:5]
Explanation: Notice that the index is zero-based, meaning that the first index is zero, rather than one (in contrast to R). So above, 5 retrieves the sixth item, not the fifth.
Two or more sequential elements can be indexed by slicing:
End of explanation
foo[:-2]
Explanation: This retrieves the third, fourth and fifth (but not the sixth!) elements -- i.e., up to, but not including, the final index. One may also slice or index starting from the end of a sequence, by using negative indices:
End of explanation
foo[1::2]
Explanation: As you can see, this returns all elements except the final two. 
You can add an optional third element to the slice, which specifies a step value. For example, the following returns every other element of foo, starting with the second element of the tuple.
End of explanation
a = (1,2,3)
a[0] = 6
Explanation: The elements of a tuple, as defined above, are immutable. Therefore, Python takes offense if you try to change them:
End of explanation
tuple('foobar')
Explanation: The TypeError is called an exception, which in this case indicates that you have tried to perform an action on a type that does not support it. We will learn about handling exceptions further along.
Finally, the tuple() function can create a tuple from any sequence:
End of explanation
# List with five elements
[90, 43.7, 56, 1, -4]
# Tuple with one element
[100]    
# Empty list
[]       
Explanation: Why does this happen? Because in Python, strings are considered a sequence of characters.
Lists
Lists complement tuples in that they are a mutable, ordered sequence of elements. To distinguish them from tuples, they are enclosed by square brackets:
End of explanation
bar = [5,8,4,2,7,9,4,1]
bar[3] = -5
bar
Explanation: Elements of a list can be arbitrarily substituted by assigning new values to the associated index:
End of explanation
bar * 3
Explanation: Operations on lists are somewhat unusual. For example, multiplying a list by an integer does not multiply each element by that integer, as you might expect, but rather:
End of explanation
[0]*10
Explanation: Which is simply three copies of the list, concatenated together. This is useful for generating lists with identical elements:
End of explanation
(3,)*10
Explanation: (incidentally, this works with tuples as well)
End of explanation
bar.extend(foo) # Adds foo to the end of bar (in-place)
bar
bar.append(5) # Appends 5 to the end of bar
bar
bar.insert(0, 4) # Inserts 4 at index 0
bar
bar.remove(7) # Removes the first occurrence of 7
bar
bar.remove(100) # Oops! Doesn’t exist
bar.pop(4) # Removes and returns indexed item
bar.reverse() # Reverses bar in place
bar
bar.sort() # Sorts bar in place
bar
Explanation: Since lists are mutable, they retain several methods, some of which mutate the list. For example:
End of explanation
bar.count(7) # Counts occurrences of 7 in bar
bar.index(7) # Returns index of first 7 in bar
Explanation: Some methods, however, do not change the list:
End of explanation
my_dict = {'a':16, 'b':(4,5), 'foo':'''(noun) a term used as a universal substitute 
           for something real, especially when discussing technological ideas and 
           problems'''}
my_dict
my_dict['b']
Explanation: Dictionaries
One of the more flexible built-in data structures is the dictionary. A dictionary maps a collection of values to a set of associated keys. These mappings are mutable, and unlike lists or tuples, are unordered. Hence, rather than using the sequence index to return elements of the collection, the corresponding key must be used. Dictionaries are specified by a comma-separated sequence of keys and values, which are separated in turn by colons. The dictionary is enclosed by curly braces. 
For example:
End of explanation
len(my_dict)
# Checks to see if ‘a’ is in my_dict
'a' in my_dict
Explanation: Notice that a indexes an integer, b a tuple, and foo a string (now you know what foo means). Hence, a dictionary is a sort of associative array. Some languages refer to such a structure as a hash or key-value store.
As with lists, being mutable, dictionaries have a variety of methods and functions that take dictionary arguments. For example, some dictionary functions include:
End of explanation
# Returns a copy of the dictionary
my_dict.copy() 
# Returns key/value pairs as list
my_dict.items() 
# Returns list of keys
my_dict.keys() 
# Returns list of values
my_dict.values() 
Explanation: Some useful dictionary methods are:
End of explanation
my_dict['c']
Explanation: When we try to index a value that does not exist, it raises a KeyError.
End of explanation
my_dict.get('c')
Explanation: If we would rather not get the error, we can use the get method, which returns None if the value is not present.
End of explanation
my_dict.get('c', -1)
Explanation: Custom return values can be specified with a second argument.
End of explanation
my_dict.popitem() 
# Empties dictionary
my_dict.clear()
my_dict
Explanation: It is easy to remove items from a dictionary.
End of explanation
my_set = {4, 5, 5, 7, 8}
my_set
Explanation: Sets
If we don't require labels for our unordered collection of values, we can use a set. Sets store unique collections of values.
End of explanation
empty_set = set()
empty_set
empty_set.add(-5)
another_set = empty_set
another_set
Explanation: We can also use the set constructor.
End of explanation
my_set | another_set
my_set & another_set
my_set - {4}
Explanation: As we would expect, we can perform set operations.
End of explanation
bar
set(bar)
Explanation: The set function is useful for returning the unique elements of a data structure. For example, recall bar:
End of explanation
<END_TASK>