def square(): # <- function header
new_value = 4 ** 2 # <- function body
print(new_value)Python Data Science Toolkit
User-defined functions
- Defining a function
Right now, function does not have any parameters within the parentheses. Whenever called, it will print out new_value which is 16 (4 squared).
square()To input any number, we add a parameter in the parentheses
def square(value): # add parameter
new_value = value ** 2
print(new_value)square(5)- When you define a function, you write parameters into the function header
- When you call a function, you pass arguments into the function
- This function now accepts a single parameter and prints out its squared value.
- But what if instead we don’t want to print it out, instead we want to return the squared value and assign it to some variable:
def square(value):
"""Return the square of a value.""" # docstring
new_value = value ** 2
return new_value # return the square
num = square(4) # assign the result to num
print(num)- Docstrings placed immediate line below function header inside ““” triple quotes
It is important to remember that assigning a variable y2 to a function that prints a value but does not return a value will result in that variable y2 being of type NoneType.
# Define shout with the parameter, word
def shout(word):
"""Print a string with three exclamation marks"""
# Concatenate the strings: shout_word
shout_word = word + '!!!'
# Print shout_word
print(shout_word)
# Call shout with the string 'congratulations'
shout("congratulations")# Define shout with the parameter, word
def shout(word):
"""Return a string with three exclamation marks"""
# Concatenate the strings: shout_word
shout_word = word + "!!!"
# Replace print with return
return shout_word
# Pass 'congratulations' to shout: yell
yell = shout("congratulations")
# Print yell
print(yell)Great work! Here it made sense to assign the output of shout(‘congratulations’) to a variable yell because the function shout actually returns a value, it does not merely print one.
Multiple Parameters & Return Values
- Change our
square()function to raise to any power
def raise_to_power(value1, value2):
"""Raise value1 to the power of value2."""
new_value = value1 ** value2
return new_value
result = raise_to_power(2, 3)
print(result)Can return multiple values by constructing tuples in the function
- Tuple is like a list, can contain multiple values
- Tuple is immutable, cannot be changed!
- Constructed using ()
even_nums = (2, 4, 6)
print(type(even_nums))Can also unpack a tuple into several values
a, b, c = even_nums
print(a)
print(b)
print(c)Can access tuple elements like a list
print(even_nums[1])
second_num = even_nums[1]
print(second_num)uses zero-indexing like lists
def raise_both(value1, value2):
"""Raise value1 to the power of value2
and vice versa"""
new_value1 = value1 ** value2
new_value2 = value2 ** value1
new_tuple = (new_value1, new_value2)
return new_tuple
result = raise_both(2, 3)
print(result)# Define shout with parameters word1 and word2
def shout(word1, word2):
"""Concatenate strings with three exclamation marks"""
# Concatenate word1 with '!!!': shout1
shout1 = word1 + "!!!"
# Concatenate word2 with '!!!': shout2
shout2 = word2 + "!!!"
# Concatenate shout1 with shout2: new_shout
new_shout = shout1 + shout2
# Return new_shout
return new_shout
# Pass 'congratulations' and 'you' to shout(): yell
yell = shout('congratulations', 'you')
# Print yell
print(yell)nums = (3, 4 ,5)
# Unpack nums into num1, num2, and num3
num1 = nums[0]
num2 = nums[1]
num3 = nums[2]
# Construct even_nums
even_nums = (2, num2, num3)# Define shout_all with parameters word1 and word2
def shout_all(word1, word2):
# Concatenate word1 with '!!!': shout1
shout1 = word1 + "!!!"
# Concatenate word2 with '!!!': shout2
shout2 = word2 + "!!!"
# Construct a tuple with shout1 and shout2: shout_words
shout_words = (shout1, shout2)
# Return shout_words
return shout_words
# Pass 'congratulations' and 'you' to shout_all(): yell1, yell2
yell1, yell2 = shout_all("congratulations", "you")
# Print yell1 and yell2
print(yell1)
print(yell2)twitter data example
# Import pandas
import pandas as pd
# Import Twitter data as DataFrame: df
df = pd.read_csv("tweets.csv")
# Initialize an empty dictionary: langs_count
langs_count = {}
# Extract column from DataFrame: col
col = df['lang']
# Iterate over lang column in DataFrame
for entry in df['lang']:
# If the language is in langs_count, add 1
if entry in langs_count.keys():
langs_count[entry] += 1
# Else add the language to langs_count, set the value to 1
else:
langs_count[entry] = 1
# Print the populated dictionary
print(langs_count)# Define count_entries()
def count_entries(df, col_name):
"""Return a dictionary with counts of
occurrences as value for each key."""
# Initialize an empty dictionary: langs_count
langs_count = {}
# Extract column from DataFrame: col
col = df[col_name]
# Iterate over lang column in DataFrame
for entry in col:
# If the language is in langs_count, add 1
if entry in langs_count.keys():
langs_count[entry] += 1
# Else add the language to langs_count, set the value to 1
else:
langs_count[entry] = 1
# Return the langs_count dictionary
return langs_count
# Call count_entries(): result
result = count_entries(tweets_df, 'lang')
# Print the result
print(result)Scope
- Not all objects are accessible everywhere in a script
- Scope: part of the program where an object or name may be accessible
- Names: variables (e.g.
x) or objects like functions (e.g.sum()) - Three types of scopes
- Global - defined in the main body of a script
- Local - defined inside a function; when execution of function finishes, any name inside ceases to exist
- Built-in - names in pre-defined built-ins module python provides (like
print()andsum())
- Names: variables (e.g.
# consider our square function from before
def square(value):
"""Return the square of a value."""
new_val = value ** 2
return new_value
new_value # returns an error, since new_value is defined only in local scope of the functionAlternatively, what if new_val is defined globally
new_val = 10
def square(value):
"""Return the square of a value."""
new_val = value ** 2
return new_value
square(3)new_valNow any time we call the name that’s global in scope (new_val), it will be accessed.
When a name is called inside the local scope of a function, it first looks in the local scope (why square(3) results in 9 and not 10). If there is none, then and only then it searches the global scope.
If we redefine new_val and then call square() function, we see the new value is used
new_val = 20
square(new_val)What about altering a global name within a function call: use keyword global
new_val = 10
def square(value):
"""Return the square of a value."""
global new_val # access & alter new_val
new_val = value ** 2
return new_val
square(3)new_val# Create a string: team
team = "teen titans"
# Define change_team()
def change_team():
"""Change the value of the global variable team."""
# Use team in global scope
global team
# Change the value of team in global: team
team = "justice league"
# Print team
print(team)
# Call change_team()
change_team()
# Print team
print(team)nested functions
- Makes sense sometimes to nest functions, an “inner” function nested within an “outer” function
- Helps avoid unnecessary/wasteful repetition
def mo2dplus5(x1, x2, x3):
"""Returns the remainder plus 5 of three values."""
new_x1 = x1 % 2 + 5
new_x2 = x2 % 2 + 5
new_x3 = x3 % 2 + 5
return (new_x1, new_x2, new_x3)instead can nest an inner function
def mod2plus5(x1, x2, x3):
"""Returns the remainder plus 5 of three values."""
def inner(x):
"""Returns the remainder plus 5 of a value."""
return x % 2 + 5
return (inner(x1), inner(x2), inner(x3))
print(mod2plus5(1, 2, 3))def raise_val(n):
"""Return the inner function."""
def inner(x):
"""Raise x to the power of n."""
raised = x ** n
return raised
return inner
square = raise_val(2) # creates function to square numbers
cube = raise_val(3) # creates function to cube numbers
print(square(2), cube(4))Similar to global, in a nested function you can use nonlocal t ocreate and change names in an enclosing scope
def outer():
"""Prints the value of n."""
n = 1
def inner():
nonlocal n
n = 2
print(n)
inner()
print(n)
outer()Here we alter the value of n in the inner function, nonlocal also alters the value of n in the enclosing scope (the outer function).
Calling outer prints the value of n as determined by inner().
LEGB Rule for order of names searched (in order) - Local - Enclosing - Global - Built-in
Assigining names will only create or change local names, unless they are declared in global or nonlocal statemens using global or nonlocal
example
# Define three_shouts
def three_shouts(word1, word2, word3):
"""Returns a tuple of strings
concatenated with '!!!'."""
# Define inner
def inner(word):
"""Returns a string concatenated with '!!!'."""
return word + '!!!'
# Return a tuple of strings
return (inner(word1), inner(word2), inner(word3))
# Call three_shouts() and print
print(three_shouts('a', 'b', 'c'))# Define echo
def echo(n):
"""Return the inner_echo function."""
# Define inner_echo
def inner_echo(word1):
"""Concatenate n copies of word1."""
echo_word = word1 * n
return echo_word
# Return inner_echo
return inner_echo
# Call echo: twice
twice = echo(2)
# Call echo: thrice
thrice = echo(3)
# Call twice() and thrice() then print
print(twice('hello'), thrice('hello'))# Define echo_shout()
def echo_shout(word):
"""Change the value of a nonlocal variable"""
# Concatenate word with itself: echo_word
echo_word = word*2
# Print echo_word
print(echo_word)
# Define inner function shout()
def shout():
"""Alter a variable in the enclosing scope"""
# Use echo_word in nonlocal scope
nonlocal echo_word
# Change echo_word to echo_word concatenated with '!!!'
echo_word = echo_word + '!!!'
# Call function shout()
shout()
# Print echo_word
print(echo_word)
# Call function echo_shout() with argument 'hello'
echo_shout('hello')default arguments
- arguments with default values don’t need to have parameters passed to them
def power(number, pow=1):
"""Raise number to the power of pow."""
new_value = number ** pow
return new_valuepower(9,2)power(9) # by default, raised to 1st powerFlexible arguments *args where there are an unknown, arbitrary number of arguments
the function below adds up all arguments passed into it
def add_all(*args):
"""Sum all values in *args together."""
# Initialize sum
sum_all = 0
# Accumulate the sum
for num in args:
sum_all += num
return sum_all*args turns all arguments passed to a function call into a tuple caleld args in the function body
In the body, we initialize sum_all to 0, loop over the tuple args and then add each element of it successively to sum_all and then return it
add_all(1, 2, 5, 10)Can also use **kwargs to pass arbitrary number of keyword arguments, “kwargs” - arguments preceded by identifiers
print_all(name = "Ryan Safner", employer = "USCO")def print_all(*kwargs):
"""Print out key-value pairs in **kwargs."""
# Print out the key-value pairs
for key, value in kwargs.items():
print(key + ": " + value)**kwargs turns identifier-keyword pairs into a dictionary within the function body. Then in the body, just need to print all key-value pairs stored in the dictionary kwargs.
NOTE: the names “args” and “kwargs” are arbitrary, the important part is the * and **.
# Define shout_echo
def shout_echo(word1, echo = 1):
"""Concatenate echo copies of word1 and three
exclamation marks at the end of the string."""
# Concatenate echo copies of word1 using *: echo_word
echo_word = word1 * echo
# Concatenate '!!!' to echo_word: shout_word
shout_word = echo_word + '!!!'
# Return shout_word
return shout_word
# Call shout_echo() with "Hey": no_echo
no_echo = shout_echo("Hey")
# Call shout_echo() with "Hey" and echo=5: with_echo
with_echo = shout_echo("Hey", echo = 5)
# Print no_echo and with_echo
print(no_echo)
print(with_echo)# Define shout_echo
def shout_echo(word1, echo = 1, intense = False):
"""Concatenate echo copies of word1 and three
exclamation marks at the end of the string."""
# Concatenate echo copies of word1 using *: echo_word
echo_word = word1 * echo
# Make echo_word uppercase if intense is True
if intense is True:
# Make uppercase and concatenate '!!!': echo_word_new
echo_word_new = echo_word.upper() + '!!!'
else:
# Concatenate '!!!' to echo_word: echo_word_new
echo_word_new = echo_word + '!!!'
# Return echo_word_new
return echo_word_new
# Call shout_echo() with "Hey", echo=5 and intense=True: with_big_echo
with_big_echo = shout_echo("Hey", echo = 5, intense = True)
# Call shout_echo() with "Hey" and intense=True: big_no_echo
big_no_echo = shout_echo("Hey", intense = True)
# Print values
print(with_big_echo)
print(big_no_echo)# Define gibberish
def gibberish(*args):
"""Concatenate strings in *args together."""
# Initialize an empty string: hodgepodge
hodgepodge = ""
# Concatenate the strings in args
for word in args:
hodgepodge += word
# Return hodgepodge
return hodgepodge
# Call gibberish() with one string: one_word
one_word = gibberish("luke")
# Call gibberish() with five strings: many_words
many_words = gibberish("luke", "leia", "han", "obi", "darth")
# Print one_word and many_words
print(one_word)
print(many_words)# Define report_status
def report_status(**kwargs):
"""Print out the status of a movie character."""
print("\nBEGIN: REPORT\n")
# Iterate over the key-value pairs of kwargs
for key, value in kwargs.items():
# Print out the keys and values, separated by a colon ':'
print(key + ": " + value)
print("\nEND REPORT")
# First call to report_status()
report_status(name="luke", affiliation="jedi", status="missing")
# Second call to report_status()
report_status(name="anakin", affiliation="sith lord", status="deceased")examples
# Define count_entries()
def count_entries(df, col_name = 'lang'):
"""Return a dictionary with counts of
occurrences as value for each key."""
# Initialize an empty dictionary: cols_count
cols_count = {}
# Extract column from DataFrame: col
col = df[col_name]
# Iterate over the column in DataFrame
for entry in col:
# If entry is in cols_count, add 1
if entry in cols_count.keys():
cols_count[entry] += 1
# Else add the entry to cols_count, set the value to 1
else:
cols_count[entry] = 1
# Return the cols_count dictionary
return cols_count
# Call count_entries(): result1
result1 = count_entries(tweets_df, 'lang')
# Call count_entries(): result2
result2 = count_entries(tweets_df, 'source')
# Print result1 and result2
print(result1)
print(result2)# Define count_entries()
def count_entries(df, *args):
"""Return a dictionary with counts of
occurrences as value for each key."""
#Initialize an empty dictionary: cols_count
cols_count = {}
# Iterate over column names in args
for col_name in args:
# Extract column from DataFrame: col
col = df[col_name]
# Iterate over the column in DataFrame
for entry in col:
# If entry is in cols_count, add 1
if entry in cols_count.keys():
cols_count[entry] += 1
# Else add the entry to cols_count, set the value to 1
else:
cols_count[entry] = 1
# Return the cols_count dictionary
return cols_count
# Call count_entries(): result1
result1 = count_entries(tweets_df, 'lang')
# Call count_entries(): result2
result2 = count_entries(tweets_df, "lang", "source")
# Print result1 and result2
print(result1)
print(result2)Lambda Functions
- easier way to write functions on the fly using Lambda functions, using the keyword
lambda.- after
lambda, write names of arguments - after
:, an expression of what we want function to return
- after
raise_to_power = lambda x, y: x ** y
raise_to_power(2, 3)Anonymous functions
- function
map(func, seq)takes two arguments: a function and a sequence (such as a list) to apply the function over all elements - can pass lambda functions to
map()without even naming them, hence “anonymous” functions
nums = [48, 6, 9, 21, 1]
square_all = map(lambda num: num ** 2, nums)
print(square_all)created a map object, so to see its output, turn it into a list and then print
print(list(square_all))examples
# Define echo_word as a lambda function: echo_word
echo_word = (lambda word1, echo: word1 * echo)
# Call echo_word: result
result = echo_word('hey', 5)
# Print result
print(result)# Create a list of strings: spells
spells = ["protego", "accio", "expecto patronum", "legilimens"]
# Use map() to apply a lambda function over spells: shout_spells
shout_spells = map(lambda item: item + "!!!", spells)
# Convert shout_spells to a list: shout_spells_list
shout_spells_list = list(shout_spells)
# Print the result
print(shout_spells_list)# Create a list of strings: fellowship
fellowship = ['frodo', 'samwise', 'merry', 'pippin', 'aragorn', 'boromir', 'legolas', 'gimli', 'gandalf']
# Use filter() to apply a lambda function over fellowship: result
result = filter(lambda member: len(member) > 6, fellowship)
# Convert result to a list: result_list
result_list = list(result)
# Print result_list
print(result_list)# Import reduce from functools
from functools import reduce
# Create a list of strings: stark
stark = ['robb', 'sansa', 'arya', 'brandon', 'rickon']
# Use reduce() to apply a lambda function over stark: result
result = reduce(lambda item1, item2: item1 + item2, stark)
# Print the result
print(result)Error handling
- Exceptions - caught during execution
- Catch exceptions with
try-exceptclause - Python runs the code following
try; if it fails due to exception, then runs the code followingexcept
- Catch exceptions with
def sqrt(x):
"""Returns the square root of a number."""
try:
return x ** 0.5
except:
print('x must be an int or float.')sqrt(4)sqrt('hi')Alternatively we can focus just on TypeErrors and let other errors pass through, usign TypeError
def sqrt(x):
"""Returns the square root of a number."""
try:
return x ** 0.5
except TypeError:
print('x must be an int or float.')Other kinds of exceptions, e.g. - UnboundLocalError - reference to local variable with no value - UnicodeError - unicode related
Often instead of just print()ing an error, we’ll want to raise an error
sqrt(-9)Note it returns a complex number by default! Suppose we don’t want this
def sqrt(x):
"""Returns the square root of a number."""
if x < 0:
raise ValueError('x must be non-negative')
try:
return x ** 0.5
except TypeError:
print('x must be an int or float.')sqrt(-9)# Define shout_echo
def shout_echo(word1, echo=1):
"""Concatenate echo copies of word1 and three
exclamation marks at the end of the string."""
# Initialize empty strings: echo_word, shout_words
echo_word = ""
shout_words = ""
# Add exception handling with try-except
try:
# Concatenate echo copies of word1 using *: echo_word
echo_word = word1 * echo
# Concatenate '!!!' to echo_word: shout_words
shout_words = echo_word + "!!!"
except:
# Print error message
print("word1 must be a string and echo must be an integer.")
# Return shout_words
return shout_words
# Call shout_echo
shout_echo("particle", echo="accelerator")# Define shout_echo
def shout_echo(word1, echo=1):
"""Concatenate echo copies of word1 and three
exclamation marks at the end of the string."""
# Raise an error with raise
if echo < 0:
raise ValueError('echo must be greater than or equal to 0')
# Concatenate echo copies of word1 using *: echo_word
echo_word = word1 * echo
# Concatenate '!!!' to echo_word: shout_word
shout_word = echo_word + '!!!'
# Return shout_word
return shout_word
# Call shout_echo
shout_echo("particle", echo=5)putting it all together examples
# Select retweets from the Twitter DataFrame: result
result = filter(lambda x: x[0:2] == "RT", tweets_df['text'])
# Create list from filter object result: res_list
res_list = list(result)
# Print all retweets in res_list
for tweet in res_list:
print(tweet)# Define count_entries()
def count_entries(df, col_name='lang'):
"""Return a dictionary with counts of
occurrences as value for each key."""
# Initialize an empty dictionary: cols_count
cols_count = {}
# Add try block
try:
# Extract column from DataFrame: col
col = df[col_name]
# Iterate over the column in DataFrame
for entry in col:
# If entry is in cols_count, add 1
if entry in cols_count.keys():
cols_count[entry] += 1
# Else add the entry to cols_count, set the value to 1
else:
cols_count[entry] = 1
# Return the cols_count dictionary
return cols_count
# Add except block
except:
print('The DataFrame does not have a ' + col_name + ' column.')
# Call count_entries(): result1
result1 = count_entries(tweets_df, 'lang')
# Print result1
print(result1)# Define count_entries()
def count_entries(df, col_name='lang'):
"""Return a dictionary with counts of
occurrences as value for each key."""
# Raise a ValueError if col_name is NOT in DataFrame
if col_name not in df.columns:
raise ValueError('The DataFrame does not have a ' + col_name + ' column.')
# Initialize an empty dictionary: cols_count
cols_count = {}
# Extract column from DataFrame: col
col = df[col_name]
# Iterate over the column in DataFrame
for entry in col:
# If entry is in cols_count, add 1
if entry in cols_count.keys():
cols_count[entry] += 1
# Else add the entry to cols_count, set the value to 1
else:
cols_count[entry] = 1
# Return the cols_count dictionary
return cols_count
# Call count_entries(): result1
result1 = count_entries(tweets_df, 'lang')
# Print result1
print(result1)Part II
iterators
- a
forloop iterates over all elements of a list; can also iterate over characters in a string, over a sequence of numbers with a specialrange()object - these are all special objects called iterables, defined as an object having an associated
.iter()method- others include dictionaries and file connections
- when
.iter()is applied, creats an interator object and then iterates over it
- iterator: object that has an associated
next()method that produces consecutive values.- once iterator is defined, calling
next()on it returns the next value, until there are no more values and then it throws aStopIterationerror
- once iterator is defined, calling
word = 'Da'
it = iter(word)
next(it)next(it)Can print all values of an iterator with * (sometimes called “splat” operator)
word = "Data"
it = iter(word)
print(*it)
# once you do this, can't do it again since there's no more values to iterate throughexamples
# Create a list of strings: flash
flash = ['jay garrick', 'barry allen', 'wally west', 'bart allen']
# Print each list item in flash using a for loop
for i in flash:
print(i)
# Create an iterator for flash: superhero
superhero = iter(flash)
# Print each item from the iterator
print(next(superhero))
print(next(superhero))
print(next(superhero))
print(next(superhero))# Create an iterator for range(3): small_value
small_value = iter(range(3))
# Print the values in small_value
print(next(small_value))
print(next(small_value))
print(next(small_value))
# Loop over range(3) and print the values
for i in range(3):
print(i)
# Create an iterator for range(10 ** 100): googol
googol = iter(range(10 ** 100))
# Print the first 5 values from googol
print(next(googol))
print(next(googol))
print(next(googol))
print(next(googol))
print(next(googol))# Create a range object: values from 10 to 20
values = range(10,21)
# Print the range object
print(values)
# Create a list of integers: values_list
values_list = list(values)
# Print values_list
print(values_list)
# Get the sum of values: values_sum
values_sum = sum(values)
# Print values_sum
print(values_sum)enumerate()adds a counter to any iterable- takes any iterable as an argument
avengers = ['hawkeye', 'iron man', 'thor']
e = enumerate(avengers)
print(type(e)) # see that its an enumerate type object# turn into a list of tuples
e_list = list(e)
print(e_list)the enumerate object itself is also an iterable, can unpack it with a for loop using for index, value in enumerate()
for index, value in enumerate(avengers):
print(index, value)can alter the index with a second argument, start
for index, value in enumerate(avengers, start = 10):
print(index, value)zip()allows us to stitch together an arbitrary number of iterables and returns an iterator of tuples
names = ['barton', 'stark', 'odinson']
z = zip(avengers, names)
print(type(z)) # creates a zip object, an iterator of tuples# turn into a list
z_list = list(z)
print(z_list)
# first element is a tuple of the first element of each list; second element is tuple of the second element of each list, etc# use a for loop to print the tuples
for z1, z2 in zip(avengers, names):
print(z1, z2)# or could use the splat operator
print(*z)examples
# Create a list of strings: mutants
mutants = ['charles xavier',
'bobby drake',
'kurt wagner',
'max eisenhardt',
'kitty pryde']
# Create a list of tuples: mutant_list
mutant_list = list(enumerate(mutants))
# Print the list of tuples
print(mutant_list)
# Unpack and print the tuple pairs
for index1, value1 in enumerate(mutants):
print(index1, value1)
# Change the start index
for index2, value2 in enumerate(mutants, start = 1):
print(index2, value2)# Create a list of tuples: mutant_data
mutant_data = list(zip(mutants, aliases, powers))
# Print the list of tuples
print(mutant_data)
# Create a zip object using the three lists: mutant_zip
mutant_zip = zip(mutants, aliases, powers)
# Print the zip object
print(mutant_zip)
# Unpack the zip object and print the tuple values
for value1, value2, value3 in mutant_zip:
print(value1, value2, value3)# Create a zip object from mutants and powers: z1
z1 = zip(mutants, powers)
# Print the tuples in z1 by unpacking with *
print(*z1)
# Re-create a zip object from mutants and powers: z1
z1 = zip(mutants, powers)
# 'Unzip' the tuples in z1 by unpacking with * and zip(): result1, result2
result1, result2 = zip(*z1)
# Check if unpacked tuples are equivalent to original tuples
print(result1 == mutants)
print(result2 == powers)Loading Very Large Data in Chunks
- suppose file is too large to store in memory
- pandas
read_csv()function argumentchunksize
import pandas as pd
result = [] # preallocate empty list
# each chunk will be a DF
# take column called x from data, suppose we want the sum of x
for chunk in pd.read_csv("data.csv", chunksize = 1000):
result.append(sum(chunk['x']))
total = sum(result)
print(total)could do it not using a list instead:
import pandas as pd
total = 0 # preallocate empty variable
# take column called x from data, suppose we want the sum of x
for chunk in pd.read_csv("data.csv", chunksize = 1000):
total += sum(chunk['x'])
print(total)examples
# Initialize an empty dictionary: counts_dict
counts_dict = {}
# Iterate over the file chunk by chunk
for chunk in pd.read_csv("tweets.csv", chunksize = 100):
# Iterate over the column in DataFrame
for entry in chunk['lang']:
if entry in counts_dict.keys():
counts_dict[entry] += 1
else:
counts_dict[entry] = 1
# Print the populated dictionary
print(counts_dict)# Define count_entries()
def count_entries(csv_file, c_size, colname):
"""Return a dictionary with counts of
occurrences as value for each key."""
# Initialize an empty dictionary: counts_dict
counts_dict = {}
# Iterate over the file chunk by chunk
for chunk in pd.read_csv(csv_file, chunksize = c_size):
# Iterate over the column in DataFrame
for entry in chunk[colname]:
if entry in counts_dict.keys():
counts_dict[entry] += 1
else:
counts_dict[entry] = 1
# Return counts_dict
return counts_dict
# Call count_entries(): result_counts
result_counts = count_entries("tweets.csv",10, 'lang')
# Print result_counts
print(result_counts)List Comprehensions
- List comprehensions allow us to create lists from other lists, DF columns, etc.
- A single line of code, far more efficient than for loop
Suppose we wanted to populate a new list from an existing list, by adding 1 to each element
nums = [12, 8, 21, 3, 16]
# old way, using a for loop
new_nums = []
for num in nums:
new_nums.append(num + 1)
print(new_nums)- List comprehension syntax:
- inside [], the values_to_create (called “output expression”), followed by
forreferencing the original list - so:
- inside [], the values_to_create (called “output expression”), followed by
new_nums = [num + 1 for num in nums]
print(new_nums)- Can write a list comprehension over any iterable
- for example, a range object:
result = [num for num in range(11)]
print(result)- List comprehension requirements
- iterable
- iterator variable (represent members of iterable)
- output expression
- Can also use in place of nested for loops
- e.g. suppose we wanted to create a list of all pairs of integers where the first integer is between 0 and 1, and the second is between 6 and 7:
# using for loops
pairs_1 = []
for num1 in range(0,2):
for num2 in range(6,8):
pairs_1.append((num1, num2))
print(pairs_1)
# with list comprehensions
pairs_2 = [(num1, num2) for num1 in range(0, 2) for num2 in range(6, 8)]
print(pairs_2)We tradeoff readability
doctor = ['house', 'cuddy', 'chase', 'thirteen', 'wilson']
[doc[0] for doc in doctor]produces a list of the first character of each string in doctor look like? Note that the list comprehension uses doc as the iterator variable.
and produces the list [‘h’, ‘c’, ‘c’, ‘t’, ‘w’]
# Create list comprehension: squares
squares = [i**2 for i in range(0,10)] # squares integers 0 to 9# Create a 5 x 5 matrix using a list of lists: matrix
matrix = [[col for col in range(5)] for row in range(5)]
# Print the matrix
for row in matrix:
print(row)Advanced Comprehensions/conditions
Conditions on the iterable
# square numbers
[num ** 2 for num in range(10) if num % 2 == 0] # only iterate over even numbers
# condition on output expression, output square only for even numbers, otherwise output 0
[num ** 2 if num % 2 == 0 else 0 for num in range(10)]dict comprehensions - use {} instead of [] - key: value separated by colon
# create dictionary with keys of positive integers and corresponding values as negative integers
pos_neg = {num: -num for num in range(9)}
print(pos_neg)examples
You’ve been using list comprehensions to build lists of values, sometimes using operations to create these values.
An interesting mechanism in list comprehensions is that you can also create lists with values that meet only a certain condition. One way of doing this is by using conditionals on iterator variables. In this exercise, you will do exactly that!
Recall from the video that you can apply a conditional statement to test the iterator variable by adding an if statement in the optional predicate expression part after the for statement in the comprehension:
[ output expression
foriterator variableiniterableifpredicate expression ].
You will use this recipe to write a list comprehension for this exercise. You are given a list of strings fellowship and, using a list comprehension, you will create a list that only includes the members of fellowship that have 7 characters or more.
# Create a list of strings: fellowship
fellowship = ['frodo', 'samwise', 'merry', 'aragorn', 'legolas', 'boromir', 'gimli']
# Create list comprehension: new_fellowship
new_fellowship = [member for member in fellowship if len(member) >= 7]
# Print the new list
print(new_fellowship)You will work on the same list, fellowship and, using a list comprehension and an if-else conditional statement in the output expression, create a list that keeps members of fellowship with 7 or more characters and replaces others with an empty string. Use member as the iterator variable in the list comprehension.
# Create a list of strings: fellowship
fellowship = ['frodo', 'samwise', 'merry', 'aragorn', 'legolas', 'boromir', 'gimli']
# Create list comprehension: new_fellowship
new_fellowship = [member if len(member) >= 7 else '' for member in fellowship]
# Print the new list
print(new_fellowship)Comprehensions aren’t relegated merely to the world of lists. There are many other objects you can build using comprehensions, such as dictionaries, pervasive objects in Data Science. You will create a dictionary using the comprehension syntax for this exercise. In this case, the comprehension is called a dict comprehension.
Recall that the main difference between a list comprehension and a dict comprehension is the use of curly braces {} instead of []. Additionally, members of the dictionary are created using a colon :, as in <key> : <value>.
You are given a list of strings fellowship and, using a dict comprehension, create a dictionary with the members of the list as the keys and the length of each string as the corresponding values.
Create a dict comprehension where the key is a string in fellowship and the value is the length of the string. Remember to use the syntax <key> : <value> in the output expression part of the comprehension to create the members of the dictionary. Use member as the iterator variable.
# Create a list of strings: fellowship
fellowship = ['frodo', 'samwise', 'merry', 'aragorn', 'legolas', 'boromir', 'gimli']
# Create dict comprehension: new_fellowship
new_fellowship = {member: len(member) for member in fellowship}
# Print the new dictionary
print(new_fellowship)generator expressions
- replacing
[]with()creates a generator:
(num ** 2 for num in range(10))- unlike a comprehension, it doesn’t store the object in memory, but is an object we can iterate over to produce elements of the list as required
- list comprehension: returns a list
- generators: returns a generator object
# produce the elements of the list
result = (num for num in range(6))
for num in result:
print(num)can also pass generator to list() to create the list
result = (num for num in range(6))
print(list(result))and we can pass generator to next() to iterate through its elements
print(next(result))
print(next(result))- called “lazy evaluation” where evaluation of the expression is delayed until its value is needed
- this is useful for very large lists where comprehension would be stored in memory (and very costly), using a generator can generate elements of the list sequence on the fly
# this would crash
# [[num for num in range (10**1000000)]]
# but can easily use generatorwrite generator functions to produce generators: - produce generator objects when called - defined like a regular function with def - yields a sequence of values instead of returning a single value - generates a value with yield instead of return
def num_sequence(n):
"""Generate values from 0 to n."""
i = 0 # initialize to 0
while i < n:
yield i
i += 1 # add oneresult = num_sequence(5)
print(type(result)) # creates a generatorfor item in result:
print(item)examples
Now, you will start simple by creating a generator object that produces numeric values.
# Create generator object: result
result = (num for num in range(31))
# Print the first 5 values
print(next(result))
print(next(result))
print(next(result))
print(next(result))
print(next(result))
# Print the rest of the values
for value in result:
print(value)# Create a list of strings: lannister
lannister = ['cersei', 'jaime', 'tywin', 'tyrion', 'joffrey']
# Create a generator object: lengths
lengths = (len(person) for person in lannister)
# Iterate over and print the values in lengths
for value in lengths:
print(value)In this exercise, you will be using a list comprehension to extract the time from time-stamped Twitter data. You will add a conditional expression to the list comprehension so that you only select the times in which entry[17:19] is equal to ‘19’. The pandas package has been imported as pd and the file ‘tweets.csv’ has been imported as the df DataFrame for your use.
# Create a list of strings
lannister = ['cersei', 'jaime', 'tywin', 'tyrion', 'joffrey']
# Define generator function get_lengths
def get_lengths(input_list):
"""Generator function that yields the
length of the strings in input_list."""
# Yield the length of a string
for person in input_list:
yield len(person)
# Print the values generated by get_lengths()
for value in get_lengths(lannister):
print(value)Create a list comprehension that extracts the time from each row in tweet_time. Each row is a string that represents a timestamp, and you will access the 12th to 19th characters in the string to extract the time. Use entry as the iterator variable and assign the result to tweet_clock_time.
# Extract the created_at column from df: tweet_time
tweet_time = df["created_at"]
# Extract the clock time: tweet_clock_time
tweet_clock_time = [entry[11:19] for entry in tweet_time]
# Print the extracted times
print(tweet_clock_time)Additionally, add a conditional expression that checks whether entry[17:19] is equal to ‘19’.
# Extract the created_at column from df: tweet_time
tweet_time = df['created_at']
# Extract the clock time: tweet_clock_time
tweet_clock_time = [entry[11:19] for entry in tweet_time if entry[17:19] == '19']
# Print the extracted times
print(tweet_clock_time)Case Study
For this exercise, you’ll use what you’ve learned about the zip() function and combine two lists into a dictionary.
These lists are actually extracted from a bigger dataset file of world development indicators from the World Bank. For pedagogical purposes, we have pre-processed this dataset into the lists that you’ll be working with.
The first list feature_names contains header names of the dataset and the second list row_vals contains actual values of a row from the dataset, corresponding to each of the header names.
Create a zip object by calling zip() and passing to it feature_names and row_vals. Assign the result to zipped_lists.
Create a dictionary from the zipped_lists zip object by calling dict() with zipped_lists. Assign the resulting dictionary to rs_dict.
# Zip lists: zipped_lists
zipped_lists = zip(feature_names, row_vals)
# Create a dictionary: rs_dict
rs_dict = dict(zipped_lists)
# Print the dictionary
print(rs_dict){'CountryName': 'Arab World', 'CountryCode': 'ARB', 'IndicatorName': 'Adolescent fertility rate (births per 1,000 women ages 15-19)', 'IndicatorCode': 'SP.ADO.TFRT', 'Year': '1960', 'Value': '133.56090740552298'}Suppose you needed to repeat the same process done in the previous exercise to many, many rows of data. Rewriting your code again and again could become very tedious, repetitive, and unmaintainable.
In this exercise, you will create a function to house the code you wrote earlier to make things easier and much more concise. Why? This way, you only need to call the function and supply the appropriate lists to create your dictionaries! Again, the lists feature_names and row_vals are preloaded and these contain the header names of the dataset and actual values of a row from the dataset, respectively.
Define the function lists2dict() with two parameters: first is list1 and second is list2.
Return the resulting dictionary rs_dict in lists2dict().
Call the lists2dict() function with the arguments feature_names and row_vals. Assign the result of the function call to rs_fxn.
# Define lists2dict()
def lists2dict(list1, list2):
"""Return a dictionary where list1 provides
the keys and list2 provides the values."""
# Zip lists: zipped_lists
zipped_lists = zip(list1, list2)
# Create a dictionary: rs_dict
rs_dict = dict(zipped_lists)
# Return the dictionary
return rs_dict
# Call lists2dict: rs_fxn
rs_fxn = lists2dict(feature_names, row_vals)
# Print rs_fxn
print(rs_fxn){'CountryName': 'Arab World', 'CountryCode': 'ARB', 'IndicatorName': 'Adolescent fertility rate (births per 1,000 women ages 15-19)', 'IndicatorCode': 'SP.ADO.TFRT', 'Year': '1960', 'Value': '133.56090740552298'}This time, you’re going to use the lists2dict() function you defined in the last exercise to turn a bunch of lists into a list of dictionaries with the help of a list comprehension.
The lists2dict() function has already been preloaded, together with a couple of lists, feature_names and row_lists. feature_names contains the header names of the World Bank dataset and row_lists is a list of lists, where each sublist is a list of actual values of a row from the dataset.
Your goal is to use a list comprehension to generate a list of dicts, where the keys are the header names and the values are the row entries.
Inspect the contents of row_lists by printing the first two lists in row_lists.
Create a list comprehension that generates a dictionary using lists2dict() for each sublist in row_lists. The keys are from the feature_names list and the values are the row entries in row_lists. Use sublist as your iterator variable and assign the resulting list of dictionaries to list_of_dicts.
Look at the first two dictionaries in list_of_dicts by printing them out.
# Print the first two lists in row_lists
print(row_lists[0])
print(row_lists[1])
# Turn list of lists into list of dicts: list_of_dicts
list_of_dicts = [lists2dict(feature_names, sublist) for sublist in row_lists]
# Print the first two dictionaries in list_of_dicts
print(list_of_dicts[0])
print(list_of_dicts[1])['Arab World', 'ARB', 'Adolescent fertility rate (births per 1,000 women ages 15-19)', 'SP.ADO.TFRT', '1960', '133.56090740552298']
['Arab World', 'ARB', 'Age dependency ratio (% of working-age population)', 'SP.POP.DPND', '1960', '87.7976011532547']
{'CountryName': 'Arab World', 'CountryCode': 'ARB', 'IndicatorName': 'Adolescent fertility rate (births per 1,000 women ages 15-19)', 'IndicatorCode': 'SP.ADO.TFRT', 'Year': '1960', 'Value': '133.56090740552298'}
{'CountryName': 'Arab World', 'CountryCode': 'ARB', 'IndicatorName': 'Age dependency ratio (% of working-age population)', 'IndicatorCode': 'SP.POP.DPND', 'Year': '1960', 'Value': '87.7976011532547'}You’ve zipped lists together, created a function to house your code, and even used the function in a list comprehension to generate a list of dictionaries. That was a lot of work and you did a great job!
You will now use all of these to convert the list of dictionaries into a pandas DataFrame. You will see how convenient it is to generate a DataFrame from dictionaries with the DataFrame() function from the pandas package.
The lists2dict() function, feature_names list, and row_lists list have been preloaded for this exercise.
To use the DataFrame() function you need, first import the pandas package with the alias pd.
Create a DataFrame from the list of dictionaries in list_of_dicts by calling pd.DataFrame(). Assign the resulting DataFrame to df.
Inspect the contents of df printing the head of the DataFrame. Head of the DataFrame df can be accessed by calling df.head().
# Import the pandas package
import pandas as pd
# Turn list of lists into list of dicts: list_of_dicts
list_of_dicts = [lists2dict(feature_names, sublist) for sublist in row_lists]
# Turn list of dicts into a DataFrame: df
df = pd.DataFrame(list_of_dicts)
# Print the head of the DataFrame
print(df.head()) CountryName CountryCode IndicatorName IndicatorCode Year Value
0 Arab World ARB Adolescent fertility rate (births per 1,000 wo... SP.ADO.TFRT 1960 133.56090740552298
1 Arab World ARB Age dependency ratio (% of working-age populat... SP.POP.DPND 1960 87.7976011532547
2 Arab World ARB Age dependency ratio, old (% of working-age po... SP.POP.DPND.OL 1960 6.634579191565161
3 Arab World ARB Age dependency ratio, young (% of working-age ... SP.POP.DPND.YG 1960 81.02332950839141
4 Arab World ARB Arms exports (SIPRI trend indicator values) MS.MIL.XPRT.KD 1960 3000000.0Processing data in chunks (1)
Sometimes, data sources can be so large in size that storing the entire dataset in memory becomes too resource-intensive. In this exercise, you will process the first 1000 rows of a file line by line, to create a dictionary of the counts of how many times each country appears in a column in the dataset.
The csv file ‘world_dev_ind.csv’ is in your current directory for your use. To begin, you need to open a connection to this file using what is known as a context manager. For example, the command with open(‘datacamp.csv’) as datacamp binds the csv file ‘datacamp.csv’ as datacamp in the context manager. Here, the with statement is the context manager, and its purpose is to ensure that resources are efficiently allocated when opening a connection to a file.
If you’d like to learn more about context managers, refer to the DataCamp course on Importing Data in Python.
Use open() to bind the csv file 'world_dev_ind.csv' as file in the context manager.
Complete the for loop so that it iterates 1000 times to perform the loop body and process only the first 1000 rows of data of the file.
# Open a connection to the file
with open('world_dev_ind.csv') as file:
# Skip the column names
file.readline()
# Initialize an empty dictionary: counts_dict
counts_dict = {}
# Process only the first 1000 rows
for j in range(1000):
# Split the current line into a list: line
line = file.readline().split(',')
# Get the value for the first column: first_col
first_col = line[0]
# If the column value is in the dict, increment its value
if first_col in counts_dict.keys():
counts_dict[first_col] += 1
# Else, add to the dict and set value to 1
else:
counts_dict[first_col] = 1
# Print the resulting dictionary
print(counts_dict){'Arab World': 80, 'Caribbean small states': 77, 'Central Europe and the Baltics': 71, 'East Asia & Pacific (all income levels)': 122, 'East Asia & Pacific (developing only)': 123, 'Euro area': 119, 'Europe & Central Asia (all income levels)': 109, 'Europe & Central Asia (developing only)': 89, 'European Union': 116, 'Fragile and conflict affected situations': 76, 'Heavily indebted poor countries (HIPC)': 18}In the previous exercise, you processed a file line by line for a given number of lines. What if, however, you want to do this for the entire file?
In this case, it would be useful to use generators. Generators allow users to lazily evaluate data. This concept of lazy evaluation is useful when you have to deal with very large datasets because it lets you generate values in an efficient manner by yielding only chunks of data at a time instead of the whole thing at once.
In this exercise, you will define a generator function read_large_file() that produces a generator object which yields a single line from a file each time next() is called on it. The csv file ‘world_dev_ind.csv’ is in your current directory for your use.
Note that when you open a connection to a file, the resulting file object is already a generator! So out in the wild, you won’t have to explicitly create generator objects in cases such as this. However, for pedagogical reasons, we are having you practice how to do this here with the read_large_file() function. Go for it!
In the function read_large_file(), read a line from file_object by using the method readline(). Assign the result to data.
In the function read_large_file(), yield the line read from the file data.
In the context manager, create a generator object gen_file by calling your generator function read_large_file() and passing file to it.
Print the first three lines produced by the generator object gen_file using next().
# Define read_large_file()
def read_large_file(file_object):
"""A generator function to read a large file lazily."""
# Loop indefinitely until the end of the file
while True:
# Read a line from the file: data
data = file_object.readline()
# Break if this is the end of the file
if not data:
break
# Yield the line of data
yield data
# Open a connection to the file
with open('world_dev_ind.csv') as file:
# Create a generator object for the file: gen_file
gen_file = read_large_file(file)
# Print the first three lines of the file
print(next(gen_file))
print(next(gen_file))
print(next(gen_file))CountryName,CountryCode,IndicatorName,IndicatorCode,Year,Value
Arab World,ARB,"Adolescent fertility rate (births per 1,000 women ages 15-19)",SP.ADO.TFRT,1960,133.56090740552298
Arab World,ARB,Age dependency ratio (% of working-age population),SP.POP.DPND,1960,87.7976011532547Wonderful work! Note that since a file object is already a generator, you don’t have to explicitly create a generator object with your read_large_file() function. However, it is still good to practice how to create generators - well done!
Great! You’ve just created a generator function that you can use to help you process large files.
Now let’s use your generator function to process the World Bank dataset like you did previously. You will process the file line by line, to create a dictionary of the counts of how many times each country appears in a column in the dataset. For this exercise, however, you won’t process just 1000 rows of data, you’ll process the entire dataset!
The generator function read_large_file() and the csv file ‘world_dev_ind.csv’ are preloaded and ready for your use. Go for it!
Bind the file 'world_dev_ind.csv' to file in the context manager with open().
Complete the for loop so that it iterates over the generator from the call to read_large_file() to process all the rows of the file.
# Initialize an empty dictionary: counts_dict
counts_dict = {}
# Open a connection to the file
with open('world_dev_ind.csv') as file:
# Iterate over the generator from read_large_file()
for line in read_large_file(file):
row = line.split(',')
first_col = row[0]
if first_col in counts_dict.keys():
counts_dict[first_col] += 1
else:
counts_dict[first_col] = 1
# Print
print(counts_dict){'CountryName': 1, 'Arab World': 80, 'Caribbean small states': 77, 'Central Europe and the Baltics': 71, 'East Asia & Pacific (all income levels)': 122, 'East Asia & Pacific (developing only)': 123, 'Euro area': 119, 'Europe & Central Asia (all income levels)': 109, 'Europe & Central Asia (developing only)': 89, 'European Union': 116, 'Fragile and conflict affected situations': 76, 'Heavily indebted poor countries (HIPC)': 99, 'High income': 131, 'High income: nonOECD': 68, 'High income: OECD': 127, 'Latin America & Caribbean (all income levels)': 130, 'Latin America & Caribbean (developing only)': 133, 'Least developed countries: UN classification': 78, 'Low & middle income': 138, 'Low income': 80, 'Lower middle income': 126, 'Middle East & North Africa (all income levels)': 89, 'Middle East & North Africa (developing only)': 94, 'Middle income': 138, 'North America': 123, 'OECD members': 130, 'Other small states': 63, 'Pacific island small states': 66, 'Small states': 69, 'South Asia': 36}Another way to read data too large to store in memory in chunks is to read the file in as DataFrames of a certain length, say, 100. For example, with the pandas package (imported as pd), you can do pd.read_csv(filename, chunksize=100). This creates an iterable reader object, which means that you can use next() on it.
In this exercise, you will read a file in small DataFrame chunks with read_csv(). You’re going to use the World Bank Indicators data ‘ind_pop.csv’, available in your current directory, to look at the urban population indicator for numerous countries and years.
Use pd.read_csv() to read in 'ind_pop.csv' in chunks of size 10. Assign the result to df_reader.
Print the first two chunks from df_reader.
# Import the pandas package
import pandas as pd
# Initialize reader object: df_reader
df_reader = pd.read_csv('ind_pop.csv', chunksize = 10)
# Print two chunks
print(next(df_reader))
print(next(df_reader)) CountryName CountryCode IndicatorName IndicatorCode Year Value
0 Arab World ARB Urban population (% of total) SP.URB.TOTL.IN.ZS 1960 31.285
1 Caribbean small states CSS Urban population (% of total) SP.URB.TOTL.IN.ZS 1960 31.597
2 Central Europe and the Baltics CEB Urban population (% of total) SP.URB.TOTL.IN.ZS 1960 44.508
3 East Asia & Pacific (all income levels) EAS Urban population (% of total) SP.URB.TOTL.IN.ZS 1960 22.471
4 East Asia & Pacific (developing only) EAP Urban population (% of total) SP.URB.TOTL.IN.ZS 1960 16.918
5 Euro area EMU Urban population (% of total) SP.URB.TOTL.IN.ZS 1960 62.097
6 Europe & Central Asia (all income levels) ECS Urban population (% of total) SP.URB.TOTL.IN.ZS 1960 55.379
7 Europe & Central Asia (developing only) ECA Urban population (% of total) SP.URB.TOTL.IN.ZS 1960 38.066
8 European Union EUU Urban population (% of total) SP.URB.TOTL.IN.ZS 1960 61.213
9 Fragile and conflict affected situations FCS Urban population (% of total) SP.URB.TOTL.IN.ZS 1960 17.892
CountryName CountryCode IndicatorName IndicatorCode Year Value
10 Heavily indebted poor countries (HIPC) HPC Urban population (% of total) SP.URB.TOTL.IN.ZS 1960 12.236
11 High income HIC Urban population (% of total) SP.URB.TOTL.IN.ZS 1960 62.680
12 High income: nonOECD NOC Urban population (% of total) SP.URB.TOTL.IN.ZS 1960 56.108
13 High income: OECD OEC Urban population (% of total) SP.URB.TOTL.IN.ZS 1960 64.285
14 Latin America & Caribbean (all income levels) LCN Urban population (% of total) SP.URB.TOTL.IN.ZS 1960 49.285
15 Latin America & Caribbean (developing only) LAC Urban population (% of total) SP.URB.TOTL.IN.ZS 1960 44.863
16 Least developed countries: UN classification LDC Urban population (% of total) SP.URB.TOTL.IN.ZS 1960 9.616
17 Low & middle income LMY Urban population (% of total) SP.URB.TOTL.IN.ZS 1960 21.273
18 Low income LIC Urban population (% of total) SP.URB.TOTL.IN.ZS 1960 11.498
19 Lower middle income LMC Urban population (% of total) SP.URB.TOTL.IN.ZS 1960 19.811In the previous exercise, you used read_csv() to read in DataFrame chunks from a large dataset. In this exercise, you will read in a file using a bigger DataFrame chunk size and then process the data from the first chunk.
To process the data, you will create another DataFrame composed of only the rows from a specific country. You will then zip together two of the columns from the new DataFrame, ‘Total Population’ and ‘Urban population (% of total)’. Finally, you will create a list of tuples from the zip object, where each tuple is composed of a value from each of the two columns mentioned.
You’re going to use the data from ‘ind_pop_data.csv’, available in your current directory. pandas has been imported as pd.
Use pd.read_csv() to read in the file in 'ind_pop_data.csv' in chunks of size 1000. Assign the result to urb_pop_reader.
Get the first DataFrame chunk from the iterable urb_pop_reader and assign this to df_urb_pop.
Select only the rows of df_urb_pop that have a 'CountryCode' of 'CEB'. To do this, compare whether df_urb_pop['CountryCode'] is equal to 'CEB' within the square brackets in df_urb_pop[____].
Using zip(), zip together the 'Total Population' and 'Urban population (% of total)' columns of df_pop_ceb. Assign the resulting zip object to pops.
# Initialize reader object: urb_pop_reader
urb_pop_reader = pd.read_csv('ind_pop_data.csv', chunksize = 1000)
# Get the first DataFrame chunk: df_urb_pop
df_urb_pop = next(urb_pop_reader)
# Check out the head of the DataFrame
print(df_urb_pop.head())
# Check out specific country: df_pop_ceb
df_pop_ceb = df_urb_pop[df_urb_pop['CountryCode'] == 'CEB']
# Zip DataFrame columns of interest: pops
pops = zip(df_pop_ceb['Total Population'], df_pop_ceb['Urban population (% of total)'])
# Turn zip object into list: pops_list
pops_list = list(pops)
# Print pops_list
print(pops_list) CountryName CountryCode Year Total Population Urban population (% of total)
0 Arab World ARB 1960 9.250e+07 31.285
1 Caribbean small states CSS 1960 4.191e+06 31.597
2 Central Europe and the Baltics CEB 1960 9.140e+07 44.508
3 East Asia & Pacific (all income levels) EAS 1960 1.042e+09 22.471
4 East Asia & Pacific (developing only) EAP 1960 8.965e+08 16.918
[(91401583.0, 44.5079211390026), (92237118.0, 45.206665319194), (93014890.0, 45.866564696018), (93845749.0, 46.5340927663649), (94722599.0, 47.2087429803526)]Writing an iterator to load data in chunks (3)
You’re getting used to reading and processing data in chunks by now. Let’s push your skills a little further by adding a column to a DataFrame.
Starting from the code of the previous exercise, you will be using a list comprehension to create the values for a new column ‘Total Urban Population’ from the list of tuples that you generated earlier. Recall from the previous exercise that the first and second elements of each tuple consist of, respectively, values from the columns ‘Total Population’ and ‘Urban population (% of total)’. The values in this new column ‘Total Urban Population’, therefore, are the product of the first and second element in each tuple. Furthermore, because the 2nd element is a percentage, you need to divide the entire result by 100, or alternatively, multiply it by 0.01.
You will also plot the data from this new column to create a visualization of the urban population data.
The packages pandas and matplotlib.pyplot have been imported as pd and plt respectively for your use.
Write a list comprehension to generate a list of values from pops_list for the new column 'Total Urban Population'. The output expression should be the product of the first and second element in each tuple in pops_list. Because the 2nd element is a percentage, you also need to either multiply the result by 0.01 or divide it by 100. In addition, note that the column 'Total Urban Population' should only be able to take on integer values. To ensure this, make sure you cast the output expression to an integer with int().
Create a scatter plot where the x-axis are values from the 'Year' column and the y-axis are values from the 'Total Urban Population' column.
# Code from previous exercise
urb_pop_reader = pd.read_csv('ind_pop_data.csv', chunksize=1000)
df_urb_pop = next(urb_pop_reader)
df_pop_ceb = df_urb_pop[df_urb_pop['CountryCode'] == 'CEB']
pops = zip(df_pop_ceb['Total Population'],
df_pop_ceb['Urban population (% of total)'])
pops_list = list(pops)
# Use list comprehension to create new DataFrame column 'Total Urban Population'
df_pop_ceb['Total Urban Population'] = [int(tup[0] * tup[1] * 0.01) for tup in pops_list]
# Plot urban population data
df_pop_ceb.plot(kind='scatter', x='Year', y='Total Urban Population')
plt.show()In the previous exercises, you’ve only processed the data from the first DataFrame chunk. This time, you will aggregate the results over all the DataFrame chunks in the dataset. This basically means you will be processing the entire dataset now. This is neat because you’re going to be able to process the entire large dataset by just working on smaller pieces of it!
You’re going to use the data from ‘ind_pop_data.csv’, available in your current directory. The packages pandas and matplotlib.pyplot have been imported as pd and plt respectively for your use.
Initialize an empty DataFrame data using pd.DataFrame().
In the for loop, iterate over urb_pop_reader to be able to process all the DataFrame chunks in the dataset.
Concatenate data and df_pop_ceb by passing a list of the DataFrames to pd.concat().
# Initialize reader object: urb_pop_reader
urb_pop_reader = pd.read_csv('ind_pop_data.csv', chunksize=1000)
# Initialize empty DataFrame: data
data = pd.DataFrame()
# Iterate over each DataFrame chunk
for df_urb_pop in urb_pop_reader:
# Check out specific country: df_pop_ceb
df_pop_ceb = df_urb_pop[df_urb_pop['CountryCode'] == 'CEB']
# Zip DataFrame columns of interest: pops
pops = zip(df_pop_ceb['Total Population'],
df_pop_ceb['Urban population (% of total)'])
# Turn zip object into list: pops_list
pops_list = list(pops)
# Use list comprehension to create new DataFrame column 'Total Urban Population'
df_pop_ceb['Total Urban Population'] = [int(tup[0] * tup[1] * 0.01) for tup in pops_list]
# Concatenate DataFrame chunk to the end of data: data
data = pd.concat([data, df_pop_ceb])
# Plot urban population data
data.plot(kind='scatter', x='Year', y='Total Urban Population')
plt.show()This is the last leg. You’ve learned a lot about processing a large dataset in chunks. In this last exercise, you will put all the code for processing the data into a single function so that you can reuse the code without having to rewrite the same things all over again.
You’re going to define the function plot_pop() which takes two arguments: the filename of the file to be processed, and the country code of the rows you want to process in the dataset.
Because all of the previous code you’ve written in the previous exercises will be housed in plot_pop(), calling the function already does the following:
Loading of the file chunk by chunk,
Creating the new column of urban population values, and
Plotting the urban population data.
That’s a lot of work, but the function now makes it convenient to repeat the same process for whatever file and country code you want to process and visualize!
You’re going to use the data from ‘ind_pop_data.csv’, available in your current directory. The packages pandas and matplotlib.pyplot has been imported as pd and plt respectively for your use.
After you are done, take a moment to look at the plots and reflect on the new skills you have acquired. The journey doesn’t end here! If you have enjoyed working with this data, you can continue exploring it using the pre-processed version available on Kaggle.
Define the function plot_pop() that has two arguments: first is filename for the file to process and second is country_code for the country to be processed in the dataset.
Call plot_pop() to process the data for country code 'CEB' in the file 'ind_pop_data.csv'.
Call plot_pop() to process the data for country code 'ARB' in the file 'ind_pop_data.csv'.
# Define plot_pop()
def plot_pop(filename, country_code):
# Initialize reader object: urb_pop_reader
urb_pop_reader = pd.read_csv(filename, chunksize=1000)
# Initialize empty DataFrame: data
data = pd.DataFrame()
# Iterate over each DataFrame chunk
for df_urb_pop in urb_pop_reader:
# Check out specific country: df_pop_ceb
df_pop_ceb = df_urb_pop[df_urb_pop['CountryCode'] == country_code]
# Zip DataFrame columns of interest: pops
pops = zip(df_pop_ceb['Total Population'],
df_pop_ceb['Urban population (% of total)'])
# Turn zip object into list: pops_list
pops_list = list(pops)
# Use list comprehension to create new DataFrame column 'Total Urban Population'
df_pop_ceb['Total Urban Population'] = [int(tup[0] * tup[1] * 0.01) for tup in pops_list]
# Concatenate DataFrame chunk to the end of data: data
data = pd.concat([data, df_pop_ceb])
# Plot urban population data
data.plot(kind='scatter', x='Year', y='Total Urban Population')
plt.show()
# Set the filename: fn
fn = 'ind_pop_data.csv'
# Call plot_pop for country code 'CEB'
plot_pop('ind_pop_data.csv','CEB')
# Call plot_pop for country code 'ARB'
plot_pop('ind_pop_data.csv','ARB')