import numpy as np
import pandas as pd

"""
Explanation: Notes on Numpy Arrays and Panda's Series and DataFrames
We need to import the numpy and pandas libraries before using them in this notebook
End of explanation
"""


array = np.array([1,2,3,4],float)
array

"""
Explanation: Intro to Numpy Arrays
Here create a 1-dimension array with floating numbers.  Note we did not have to type print before array if it is the last line of code
End of explanation
"""


two_dimen_array = np.array([[1,2,3],[4,5,6]], float)
two_dimen_array

"""
Explanation: Here we create an 2x3 array
End of explanation
"""


array[2:]

"""
Explanation: Now let us show how to perform certain slicing and indexing operations on numpy Arrays.If we want to print from the 3rd element until the end on a vector array
End of explanation
"""


two_dimen_array[0][1:]

"""
Explanation: In this line of code, we print all elements from the 2nd element until the end of the 1st row.
End of explanation
"""


two_dimen_array[1, :]

"""
Explanation: In this line, we print the 2nd row of the matrix
End of explanation
"""


two_dimen_array[:,1]

"""
Explanation: In this line, we print the 2nd column
End of explanation
"""


array[:3] - two_dimen_array[1,:]

"""
Explanation: In this line,  I wanted to experiment a bit with slicing operations with the arithmetic operations.  Here I print out the results of subtracting the 2nd row of the matrix from 1st three elements of the vector array
End of explanation
"""


two_by_two_array = np.array([[1,4],[2,5]],float)
two_by_two_array

array[:2]

"""
Explanation: Here we create a 2x2 array display it's output.  Next, we print out the results of the 1st two elements from the vector array
End of explanation
"""


two_by_two_array * array[:2]

"""
Explanation: This operation I found to be kind of weird since I would have assumed the multiplication of two arrays to be the dot product, but that is not what occurs here.  In this operation, The first element of array is multiplied by each element of the first column in two_by_two_array  and the 2nd element of the array is multiplied by each element of the 2nd column of two_by_two_array.
End of explanation
"""


array2 = np.array([1,2],float)
array2

np.dot(array2,two_by_two_array)

"""
Explanation: If we want to compute the dot product, you have to use the dot member function of the numpy library.  Here, we create a new array and perform the dot product on two_by_two_array
End of explanation
"""


series = pd.Series(['Ransford', "Hyman Sr.", 'January', 1941], index=['First Name', 'Last Name', 'Birth Month', 'Birth Year'])
series

"""
Explanation: Intro to Panda Series and DataFrames
The Panda Series allows you to create a Panda Column in which you can put elements of any type within the same column.  Here I create Panda Series with information about my father.  I have modified the index so that it will print out the standard number indices
End of explanation
"""


family = {'name': ['Ransford','Denzel'],
         'Birth year': [1984, 2004],
         'favorite subject': ['Math','Science']}
family

df = pd.DataFrame(family)
df

"""
Explanation: Here we create a Python Dictionary and then convert that into a Panda DataFrame.  Here we create a dictionary named family and create dataframe df from family.
End of explanation
"""


frank_grades = {'subject':['Math','English','Social Studies','Science','Music','Art'],
               'grades': [95,87,80,96,98,70]}
df2 = pd.DataFrame(frank_grades)
df2

"""
Explanation: Notice that when we print out the dictionary it prints out in regular text, But when we print out the dataframe, it gives us a nice table in IPython. Pretty cool!!!
Now we are going to create a seperate dataframe and play around with some of it's member functions.
End of explanation
"""


df2['grades'].describe()

"""
Explanation: Notice here that we can index Dataframes by the index name just like in Python dictionaries.  Panda's dataframes have a function called describe which generates some interesting statiscal information.  This function is very helpful for doing some initial sanity checking on the dataframe's columns.  Here we are given the number of entries (given by the count row), the mean, standard deviation and the Interquartile Range (IQR).
End of explanation
"""


print df2['subject'].head(2)
df2.head()

"""
Explanation: Here is a way to examine the DataFrame without printing the entire thing.  The printout shows the printing of the first 2 rows of the subject column.  Note that you can specify how rows you would like to print by passing the number as a parameter to the head function.  The second printout shows the function being called on the entire dataframe object.
End of explanation
"""


print df2['grades'].tail()
df2.tail


"""
Explanation: Here we perform the tail on the DataFrame object.
End of explanation
"""


