# Iterating over set
animals = {'cat', 'dog', 'fish', 'monkey'}
for animal in animals:
    print('{}'.format(animal))

# Iterating over set (and generating an index)
animals = {'cat', 'dog', 'fish', 'monkey'}
for idx, animal in enumerate(animals):
    print('{}: {}'.format(idx,animal))

"""
Explanation: Data Exploration - My data exploration lab notes
Code Like a Pythonista
Iterating over list/set/dict
End of explanation
"""


#List comprehension
list1 = [x**2 for x in range(10)]
print(list1)

list2 = [x for x in list1 if x % 2 == 0]
print(list2)

#Set comprehension
nums = {x for x in range(10)}
print(nums)  # Prints "{0, 1, 2, 3, 4, 5}"

#Dict comprehension
mcase = {'a':10, 'b': 34, 'A': 7, 'Z':3}
mcase_frequency = { k.lower() : mcase.get(k.lower(), 0) + mcase.get(k.upper(), 0) for k in mcase.keys() }
print(mcase_frequency)

#Set comprehension from list
names = [ 'Bob', 'JOHN', 'alice', 'bob', 'ALICE', 'J', 'Bob' ]
names_set = { name[0].upper() + name[1:].lower() for name in names if len(name) > 1 }
print(names_set)

#Nested list comprehension
matrix = [ [ 1 if item_idx == row_idx else 0 for item_idx in range(0, 3) ] for row_idx in range(0, 3) ]
print(matrix)

"""
Explanation: List/Set/Dict Comprehensions
Python supports list comprehensions, that can be used to construct lists in a very natural way, similar to mathematic construction.
[ output_expression() for(set of values to iterate) if(conditional filtering) ]
End of explanation
"""


numbers = range(20)

numbers_doubled_odds = []
for n in numbers:
    if n%2 == 1:
        numbers_doubled_odds.append(n*2)
        
print(numbers_doubled_odds)

#vs

numbers_doubled_odds = [n*2 for n in numbers if n%2==1]
print(numbers_doubled_odds)

# Calculating prime numbers
noprimes = [j for i in range(2, 8) for j in range(i*2, 100, i)]
primes = [x for x in range(2, 100) if x not in noprimes]
print(primes)

"""
Explanation: The power of comprehension
End of explanation
"""


import numpy as np

array1D = np.array([1,2,3,4,5,6,7,8, 9, 10])

#Standard print
print('Data in arr1D:\n', array1D)

#The last line is evaluated
array1D

array2D = np.array([[1,2,3,4],[5,6,7,8]])

print('Data in arr2D:\n', array2D)

array2D

# Slicing works the same as in standard Python

array2D = np.array([[1,2,3,4],[5,6,7,8]])
print(array2D)

mini_array2D = array2D[:2, 1:3]
print(mini_array2D)

"""
Explanation: Basic Numpy data structures
End of explanation
"""


array2D = np.zeros((2,4))
print(array2D)

array2D = np.ones((2,4))
print(array2D)

array2D = np.full((2,4),0.8)
print(array2D)

array2D = np.random.random((2,4))
print(array2D)

print(type(array2D))
print(array2D.shape)

"""
Explanation: Creating arrays
End of explanation
"""


array1D = np.arange(12)
print(array1D,'\n')

array2D = array1D.reshape(2,6) 
print(array2D,'\n')

array2D = array1D.reshape(6,2) 
print(array2D,'\n')

array3D = array1D.reshape(2,2,3) 
print(array3D,'\n')

array3D = array1D.reshape(3,2,2) 
print(array3D,'\n')

"""
Explanation: Changing the shape of arrays
End of explanation
"""


print('\n Numpy 2-dim array')
tab10n5 = np.random.randn(10,5)

print(tab10n5)
print('\n Standard deviation of array')
print(np.std(tab10n5))

#TODO Statistics functions

"""
Explanation: Statistics
End of explanation
"""


#TODO stacking arrays

"""
Explanation: Stacking together different arrays
Take a quick look at tutorial
and fill the next cell
End of explanation
"""


%matplotlib inline

import numpy as np
import matplotlib.pyplot as plt

x = np.linspace(0, 3*np.pi, 50)
plt.plot(x, np.sin(x**2))
plt.title('A simple chirp');

"""
Explanation: Plotting
End of explanation
"""


import csv
import numpy as np

data = np.genfromtxt('country-of-birth-london-min.csv', skip_header=1, delimiter=';')
print(data[:5,:])

raw_data = np.genfromtxt('country-of-birth-london-min.csv', delimiter=';', dtype=None)
names = raw_data[:5,:1].astype(str)
print(names)

#TODO - Calculate summary statistics

#TODO - Visualize summary using matplotlib charts

"""
Explanation: Importing data
End of explanation
"""


