Homework 9

We’re going to make a Lil’ QuakeBot!!!! Please write this code as a .py file, not a Notebook.

First, tips:

Be careful that you’re doing all of your math with ints or floats instead of strings that look like ints or floats. When you write your functions, you can pass either the entire dictionary to the function OR just the part you’re curious about (e.g., when you’re getting the day you could send the whole earthquake dictionary or just what’s in the ‘time’ key.)

Writing empty functions that always return the same thing are a great way to start off. You can start saying every earthquake is shallow and then fill in the actual code later.

Find out what each column name in the database means by visiting http://earthquake.usgs.gov/earthquakes/feed/v1.0/csv.php and clicking the links for each column.

PART ZERO: Overall description

Given an earthquake defined like this…

earthquake = {
  'rms': '1.85',
  'updated': '2014-06-11T05:22:21.596Z',
  'type': 'earthquake',
  'magType': 'mwp',
  'longitude': '-136.6561',
  'gap': '48',
  'depth': '10',
  'dmin': '0.811',
  'mag': '5.7',
  'time': '2014-06-04T11:58:58.200Z',
  'latitude': '59.0001',
  'place': '73km WSW of Haines, Alaska',
  'net': 'us',
  'nst': '',
  'id': 'usc000rauc'}

I want to be able to run

print(eq_to_sentence(earthquake))

and get the following:

A DEPTH POWER, MAGNITUDE earthquake was reported DAY TIME_OF_DAY on DATE LOCATION.

So, for example, “A deep, huge 4.5 magnitude earthquake was reported Monday morning on June 22 73km WSW of Haines, Alaska”.

DEPTH, POWER, MAGNITUDE, DAY, and TIME_OF_DAY should all come from separate functions. More details are in PART ONE and PART TWO.

# Start by saving the sample earthquake
earthquake = {
  'rms': '1.85',
  'updated': '2014-06-11T05:22:21.596Z',
  'type': 'earthquake',
  'magType': 'mwp',
  'longitude': '-136.6561',
  'gap': '48',
  'depth': '10',
  'dmin': '0.811',
  'mag': '5.7',
  'time': '2014-06-04T11:58:58.200Z',
  'latitude': '59.0001',
  'place': '73km WSW of Haines, Alaska',
  'net': 'us',
  'nst': '',
  'id': 'usc000rauc'}

PART ONE: Write your few tiny functions

First you’ll need to write a few functions to help describe an earthquake. Try out each of these functions individually. You will probably require:

  • depth_to_words will describe the earthquake’s depth
  • magnitude_to_words will describe the earthquake’s power
  • day_in_words should be the day of the week
  • time_in_words should be “morning”, “afternoon”, “evening” or “night”
  • date_in_words should be “Monthname day”, e.g. “June 22”
  • Any other functions as necessary

DEPTH can be determined from the USGS website - http://earthquake.usgs.gov/learn/topics/seismology/determining_depth.php - it should be either ‘shallow’, ‘intermediate’ or ‘deep’

POWER should be evocative words like like ‘easily ignored’ or ‘huge’ or ‘very destructive’ (feel free to pick your own) - look on Google Image Search for “richter scale” to see some possible descriptors.

MAGNITUDE should be the actual numerical magnitude.

DAY should be the day of the week.

TIME_OF_DAY should be morning, afternoon, evening or night.

DATE should be “Monthname day”, e.g. “June 22”.

TIP: You probably (a.k.a. definitely) need to convert ‘time’ - which is a string - into a Python datetime object which can do .hour, .day, .strftime("%Y %b %d") and other fun things. Convert it and test the conversion like this:

import dateutil.parser
timestring = '2014-06-04T11:58:58.200Z'
yourdate = dateutil.parser.parse(timestring)
print("The hour is", yourdate.hour)
print("We can do things with strftime like", yourdate.strftime("%Y %b"))

You’ll need to pip install dateutils.

# I hate running command line tools in the notebook, but let's do it anyway...
!pip install dateutils
import dateutils

Our first function: depth_to_words

There are a few different ways to build depth_to_words. Let’s take a look at a few.

  • depth_to_words will describe the earthquake’s depth
  • DEPTH can be determined from the USGS website - http://earthquake.usgs.gov/learn/topics/seismology/determining_depth.php - it should be either ‘shallow’, ‘intermediate’ or ‘deep’

From that URL:

Shallow earthquakes are between 0 and 70 km deep; intermediate earthquakes, 70 - 300 km deep; and deep earthquakes, 300 - 700 km deep.

Attempt One

We’ll take an integer, and just follow what the text says.

def depth_to_words(depth):
    if depth > 0 and depth < 70:
        return "shallow"
    elif depth > 70 and depth < 300:
        return "intermediate"
    elif depth > 300 and depth < 700:
        return "shallow"

# You would call it like this
depth_to_words(70)

# Now let's test it with some sample values
test_values = [30, 100, 70, 0, 1000, -1]
for value in test_values:
    print(value, "gives us", depth_to_words(value))
30 gives us shallow
100 gives us intermediate
70 gives us None
0 gives us None
1000 gives us None
-1 gives us None

70, 0, 1000 and -1 all give us None as our depth! This is because we listened a little too closely to the description given to us by USGS.

  • Shallow: ABOVE 0 and BELOW 70
  • Intermediate: ABOVE 70 and BELOW 300
  • Deep: ABOVE 300 and BELOW 700

Unfortunately 70 slipped through the cracks (we looked for BELOW 70 and ABOVE 70) as did values outside of 0-700. Should a 70km earthquake be shallow or intermediate? Should a 1000km earthquake be considered deep, or should it encounter an error? How about 0km, or negative values?

Sometimes decisions like this take more research, and sometimes it takes you making a decision.

  • 0km and negative-km earthquakes are generally explosions at the surface, but there can also be slight errors in measurement. I think making them shallow isn’t a big deal.
  • Is the 70km cutoff for shallow/intermediate an official term? I’m going to say no (even though I didn’t check!), so we can count it as either.
  • 1000km earthquakes seem deep to me, so let’s consider them deep.

Version Two: Taking care with edge cases

def depth_to_words(depth):
    if depth < 70:
        return "shallow"
    elif depth < 300:
        return "intermediate"
    else:
        return "shallow"

# You would call it like this
depth_to_words(70)

# Now let's test it with some sample values
test_values = [30, 100, 70, 0, 1000, -1]
for value in test_values:
    print(value, "gives us", depth_to_words(value))
30 gives us shallow
100 gives us intermediate
70 gives us intermediate
0 gives us shallow
1000 gives us shallow
-1 gives us shallow

That looks a little better. Opening up the ends instead of being firm gives us a little flexibility with our input. Whether that’s a good or bad idea depends on what your data is!

We do have one big problem, though, and it shows up when we start working with our real data

depth_to_words(earthquake['depth'])
---------------------------------------------------------------------------

TypeError                                 Traceback (most recent call last)

<ipython-input-19-68eff4faf19b> in <module>()
----> 1 depth_to_words(earthquake['depth'])


<ipython-input-18-44d0f6dabc90> in depth_to_words(depth)
      1 def depth_to_words(depth):
----> 2     if depth < 70:
      3         return "shallow"
      4     elif depth < 300:
      5         return "intermediate"


TypeError: unorderable types: str() < int()

Uh oh, turns out earthquake['depth'] is actually a string, which you can’t compare to an integer. Guess we need to convert that.

Attempt Three: Preparing our input

def depth_to_words(str_depth):
    depth = int(str_depth)
    if depth < 70:
        return "shallow"
    elif depth < 300:
        return "intermediate"
    else:
        return "shallow"

# You would call it like this
depth_to_words(70)

# Now let's test it with some sample values
test_values = [30, 100, 70, 0, 1000, -1]
for value in test_values:
    print(value, "gives us", depth_to_words(value))
30 gives us shallow
100 gives us intermediate
70 gives us intermediate
0 gives us shallow
1000 gives us shallow
-1 gives us shallow

Luckily there isn’t a problem with converting an integer into an integer: int(70) just becomes 70 - it doesn’t have to be int(“70”). Now let’s try it with our data.

depth_to_words(earthquake['depth'])
'shallow'

Attempt three: Passing a dictionary

Now you get to make an executive decision. Which one of the following looks better to you?

  • depth_to_words(earthquake['depth'])
  • depth_to_words(earthquake)

I like the second one, it moves more of the “magic” out into the function. So let’s rewrite our function to accept a dictionary instead of a number.

def depth_to_words(earthquake):
    depth = int(earthquake['depth'])
    if depth < 70:
        return "shallow"
    elif depth < 300:
        return "intermediate"
    else:
        return "shallow"

# You would call it like this
depth_to_words(earthquake)
'shallow'

This looks far nicer, but is also much more difficult to test.

Before we could just try things out by sending integers (or even strings) to the function. But now if we wanted to test a bunch of different depths, we need to create a bunch of fake earthquakes.

At least we only need to give them the depth key, since that’s the only key we use in our function.

test_earthquakes = [{'depth': 30}, {'depth': 100}, {'depth': 70}, {'depth': 0}, {'depth': 1000}, {'depth': 0}]
for test_earthquake in test_earthquakes:
    print(test_earthquake['depth'], "gives us", depth_to_words(test_earthquake))
30 gives us shallow
100 gives us intermediate
70 gives us intermediate
0 gives us shallow
1000 gives us shallow
0 gives us shallow

We could also create the dictionary just at the moment we’re calling the function, which is a little cleaner-looking.

test_values = [30, 100, 70, 0, 1000, -1]
for value in test_values:
    print(value, "gives us", depth_to_words({'depth': value}))
30 gives us shallow
100 gives us intermediate
70 gives us intermediate
0 gives us shallow
1000 gives us shallow
-1 gives us shallow

I personally think testing with real data is the way to go - I’d give a few tests myself, then plug it into the real data that comes in Part Two.

Function two: magnitude_in_words

  • magnitude_to_words will describe the earthquake’s power
  • POWER should be evocative words like like ‘easily ignored’ or ‘huge’ or ‘very destructive’ (feel free to pick your own) - look on Google Image Search for “richter scale” to see some possible descriptors.

I’m going to use this image: http://wiki.ubc.ca/images/e/ea/Richterscale.png

Range Description
0-2 Never felt
2-3 Minor
3-4 Minor
4-5 Light
5-6 Moderate
6-7 Strong
7-8 Major
8-9 Great
9-10 Great
10+ Epic

It doesn’t seem like the best set of descriptions, but we’ll go with it.

After the lessons learned with the last function, we’re going to make sure to convert to a float (not an integer, since the decimals matter) and accept a dictionary.

def magnitude_in_words(earthquake):
    mag = float(earthquake['mag'])
    if mag < 2:
        return "unnoticeable"
    elif mag < 4:
        return "minor"
    elif mag < 5:
        return "light"
    elif mag < 6:
        return "moderate"
    elif mag < 7:
        return "strong"
    elif mag < 8:
        return "major"
    elif mag < 10:
        return "great"
    else:
        return "epic"

# And we'll test it with our sample
print(earthquake['mag'], "registers as", magnitude_in_words(earthquake))
5.7 registers as moderate

Looks good to me, on to the next one.

Function Three: Day of the Week

  • day_in_words should be the day of the week
  • DAY should be the day of the week.
  • TIP: You probably (a.k.a. definitely) need to convert ‘time’ - which is a string - into a Python datetime object which can do .hour, .day, .strftime(“%Y %b %d”) and other fun things. Convert it and test the conversion like this:
import dateutil.parser
timestring = '2014-06-04T11:58:58.200Z'
yourdate = dateutil.parser.parse(timestring)
print("The hour is", yourdate.hour)
print("We can do things with strftime like", yourdate.strftime("%Y %b"))

Let’s look at our earthquake’s time

earthquake['time']
'2014-06-04T11:58:58.200Z'

Now let’s try out the sample code from up above with our earthquake’s time

import dateutil.parser
yourdate = dateutil.parser.parse(earthquake['time'])
print("The hour is", yourdate.hour)
print("We can do things with strftime like", yourdate.strftime("%Y %b"))
The hour is 11
We can do things with strftime like 2014 Jun

If we’re trying to get the day, and we can use .hour, can we use… .day?

yourdate.day
4

Uh, not really, I guess. This is where strftime comes into play. It will convert a Python representation of time into a string. We can use the handy reference on strftime.org to know what the secret codes are when using .strftime.

yourdate.strftime("%A")
'Wednesday'

Worked like a charm, so now all we need to do is make a function that accepts the earthquake dictionary and returns the day name.

def day_in_words(earthquake):
    parsed_date = dateutil.parser.parse(earthquake['time'])
    return parsed_date.strftime("%A")

day_in_words(earthquake)
'Wednesday'

Beautiful! On to the next one.

Function Four: time_in_words

  • time_in_words should be “morning”, “afternoon”, “evening” or “night”

Unfortunately we can’t use strftime for this. What we can do, though, is think about what makes morning, afternoon, evening and night?

The hour. And we have the hour!

yourdate = dateutil.parser.parse(earthquake['time'])
print("The hour is", yourdate.hour)
The hour is 11

Time for some decisions. Morning is probably before 12pm, afternoon is before 6pm, evening is 6-8, and night is after that.

We won’t see this unless we test specific times, but what about 2am? You could either have been out all night (still nighttime) or waking up early for a flight (which seems like morning). What do you pick?

In this case, it’s really your choice. Decisions like this are what make computer-generated stories seem independent but show that they’re really just as human-being-written as any other story. I’m going to say 3am is the beginning of morning.

def time_in_words(earthquake):
    parsed_date = dateutil.parser.parse(earthquake['time'])
    hour = parsed_date.hour
    if hour < 3:
        return "night"
    elif hour < 12:
        return "morning"
    elif hour < 6:
        return "afternoon"
    elif hour < 8:
        return "evening"
    else:
        return "night"
        
print(earthquake['time'])
time_in_words(earthquake)
2014-06-04T11:58:58.200Z





'morning'

Yup, 11AM is morning, so that sounds good.

I made a choice to have two separate returns for night. I could have done if hour < 3 or hour >= 8 but I felt that keeping the times in order was important. It also would have been easy to do if hour < 3 or hour > 8 and accidentally miss out on 8pm.

Function Five: date_in_words

  • date_in_words should be “Monthname day”, e.g. “June 22”

This is easy, it’s just another strftime one! Hop on over to strftime.org and we’ll be good to go. You’ll just want to be careful you don’t use %d, which would give “04” instead of %-d, which gives “4”.

def date_in_words(earthquake):
    parsed_date = dateutil.parser.parse(earthquake['time'])
    return parsed_date.strftime("%B %-d")

date_in_words(earthquake)
'June 4'

PART TWO: Write the eq_to_sentence function

Write a function called eq_to_sentence that, when called, returns the whole sentence mentioned above, “A DEPTH, POWER MAGNITUDE earthquake was reported DAY TIME_OF_DAY on DATE LOCATION.”

Print out the result for the sample earthquake.

def eq_to_sentence(earthquake):
    print("A", depth_to_words(earthquake), magnitude_in_words(earthquake), earthquake['mag'], "earthquake was reported", day_in_words(earthquake), time_in_words(earthquake), "on", date_in_words(earthquake), earthquake['place'])

eq_to_sentence(earthquake)
A shallow moderate 5.7 earthquake was reported Wednesday morning on June 4 73km WSW of Haines, Alaska

This isn’t what I asked for, though! I asked for something that returns a string, and then the string gets printed. It’s just a matter of moving print, maybe?

def eq_to_sentence(earthquake):
    return "A", depth_to_words(earthquake), magnitude_in_words(earthquake), earthquake['mag'], "earthquake was reported", day_in_words(earthquake), time_in_words(earthquake), "on", date_in_words(earthquake), earthquake['place']

print(eq_to_sentence(earthquake))
('A', 'shallow', 'moderate', '5.7', 'earthquake was reported', 'Wednesday', 'morning', 'on', 'June 4', '73km WSW of Haines, Alaska')

Hmmm, doesn’t look beautiful. Now, what you could do is use the + to stick all of those together, or maybe treat them as a list and use ' '.join to join them all together with spaces. I’m going to show you a secret trick, though, called .format!

name = "Smushface"
animal = "cat"
"My name is {} and I am a {}".format(name, animal)
'My name is Smushface and I am a cat'

.format allows you to do a “fill in the blanks” with variables when creating a string. It’s pretty useful!

depthwords = depth_to_words(earthquake)
magwords = magnitude_in_words(earthquake)
daywords = day_in_words(earthquake)
timewords = time_in_words(earthquake)
datewords = date_in_words(earthquake)
"A {} {} {} earthquake was reported {} {} on {}, {}".format(depthwords, magwords, earthquake['mag'], daywords, timewords, datewords, earthquake['place'])
'A shallow moderate 5.7 earthquake was reported Wednesday morning on June 4, 73km WSW of Haines, Alaska'

If we want to get even crazier, you can use a dictionary with .format so that you don’t have to pay attention to order.

eq_words = {
    'depthwords': depth_to_words(earthquake),
    'magwords': magnitude_in_words(earthquake),
    'daywords': day_in_words(earthquake),
    'timewords': time_in_words(earthquake),
    'datewords': date_in_words(earthquake),
    'location': earthquake['place'],
    'magnitude': earthquake['mag']
}
"A {depthwords} {magwords} {magnitude} earthquake was reported {daywords} {timewords} on {location}, {magnitude}".format(**eq_words)
'A shallow moderate 5.7 earthquake was reported Wednesday morning on 73km WSW of Haines, Alaska, 5.7'

Whichever version you choose, now you can pop it into a function.

def eq_to_words(earthquake):
    eq_words = {
        'depthwords': depth_to_words(earthquake),
        'magwords': magnitude_in_words(earthquake),
        'daywords': day_in_words(earthquake),
        'timewords': time_in_words(earthquake),
        'datewords': date_in_words(earthquake),
        'location': earthquake['place'],
        'magnitude': earthquake['mag']
    }
    return "A {depthwords} {magwords} {magnitude} earthquake was reported {daywords} {timewords} on {location}, {magnitude}".format(**eq_words)

eq_to_words(earthquake)
'A shallow moderate 5.7 earthquake was reported Wednesday morning on 73km WSW of Haines, Alaska, 5.7'

Looking good!

PART THREE: Doing it in bulk

Read in the csv of the past 30 days of 1.0+ earthquke activity from http://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/1.0_month.csv (tip: read_csv works with URLs!)

Because we haven’t covered looping through pandas, use the following code to convert a pandas DataFrame into a list of dictionaries that you can loop through.

earthquakes_df = pd.read_csv(“../1.0_month.csv”) earthquakes = earthquakes_df.to_dict(‘records’)

(If you really want to do it with pandas, it’s for index, row in earthquakes_df.iterrows():)

Loop through each earthquake, printing sentence descriptions for the ones that are above or equal to 4.0 on the Richter scale.

import pandas as pd
earthquakes_df = pd.read_csv("http://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/1.0_month.csv")
earthquakes_df.head()
time latitude longitude depth mag magType nst gap dmin rms ... updated place type horizontalError depthError magError magNst status locationSource magSource
0 2016-06-26T11:55:51.850Z 37.506168 -118.797333 -1.19 1.47 md 10.0 219.0 0.06295 0.03 ... 2016-06-26T12:18:03.754Z 22km SE of Mammoth Lakes, California earthquake 0.72 2.26 0.080 10.0 automatic nc nc
1 2016-06-26T11:50:06.540Z 34.832000 -118.922167 13.50 1.99 ml 43.0 36.0 0.05095 0.25 ... 2016-06-26T12:00:31.920Z 2km ENE of Frazier Park, CA earthquake 0.34 0.57 0.196 26.0 automatic ci ci
2 2016-06-26T11:41:38.920Z 38.793167 -122.759163 1.09 1.13 md 17.0 69.0 0.02014 0.02 ... 2016-06-26T12:07:02.715Z 1km N of The Geysers, California earthquake 0.19 0.53 0.100 6.0 automatic nc nc
3 2016-06-26T11:17:11.690Z 39.486700 73.325200 15.50 6.40 mww NaN 57.0 1.17600 1.17 ... 2016-06-26T12:18:32.170Z 27km SSE of Sary-Tash, Kyrgyzstan earthquake 5.80 1.80 NaN NaN reviewed us us
4 2016-06-26T11:13:00.970Z 33.009667 -116.485000 10.52 1.10 ml 34.0 77.0 0.11830 0.17 ... 2016-06-26T11:24:18.280Z 13km SE of Julian, CA earthquake 0.21 0.45 0.204 27.0 automatic ci ci

5 rows × 22 columns

Now all we need to do is convert the dataframe into a list of dictionaries and pass them to our function, and suddenly we have a hundred sentences without doing much more work at all!

earthquakes = earthquakes_df.to_dict('records')
# I'm just going to slice off the first 100
for earthquake in earthquakes[0:100]:
    print(eq_to_words(earthquake))
A shallow unnoticeable 1.47 earthquake was reported Sunday morning on 22km SE of Mammoth Lakes, California, 1.47
A shallow unnoticeable 1.99 earthquake was reported Sunday morning on 2km ENE of Frazier Park, CA, 1.99
A shallow unnoticeable 1.13 earthquake was reported Sunday morning on 1km N of The Geysers, California, 1.13
A shallow strong 6.4 earthquake was reported Sunday morning on 27km SSE of Sary-Tash, Kyrgyzstan, 6.4
A shallow unnoticeable 1.1 earthquake was reported Sunday morning on 13km SE of Julian, CA, 1.1
A shallow unnoticeable 1.2 earthquake was reported Sunday morning on 27km ENE of Cantwell, Alaska, 1.2
A shallow unnoticeable 1.04 earthquake was reported Sunday morning on 8km E of Mammoth Lakes, California, 1.04
A shallow unnoticeable 1.9 earthquake was reported Sunday morning on 83km E of Sutton-Alpine, Alaska, 1.9
A shallow unnoticeable 1.0 earthquake was reported Sunday morning on 81km NNW of Valdez, Alaska, 1.0
A intermediate minor 2.2 earthquake was reported Sunday morning on 25km NNE of Culebra, Puerto Rico, 2.2
A shallow unnoticeable 1.0 earthquake was reported Sunday morning on 20km E of Julian, CA, 1.0
A shallow unnoticeable 1.8 earthquake was reported Sunday morning on 5km E of Espino, Puerto Rico, 1.8
A shallow light 4.6 earthquake was reported Sunday morning on 126km NNW of Dobo, Indonesia, 4.6
A shallow unnoticeable 1.1 earthquake was reported Sunday morning on 118km W of Cantwell, Alaska, 1.1
A intermediate minor 2.9 earthquake was reported Sunday morning on 84km NE of Chignik Lake, Alaska, 2.9
A shallow unnoticeable 1.1 earthquake was reported Sunday morning on 103km WNW of Talkeetna, Alaska, 1.1
A intermediate moderate 5.0 earthquake was reported Sunday morning on 20km E of Farkhar, Afghanistan, 5.0
A shallow unnoticeable 1.8 earthquake was reported Sunday morning on 46km N of Sterling, Alaska, 1.8
A shallow unnoticeable 1.0 earthquake was reported Sunday morning on 68km SSW of Tok, Alaska, 1.0
A shallow light 4.9 earthquake was reported Sunday morning on Reykjanes Ridge, 4.9
A shallow unnoticeable 1.6 earthquake was reported Sunday morning on 22km S of Charlotte Amalie, U.S. Virgin Islands, 1.6
A shallow unnoticeable 1.2 earthquake was reported Sunday morning on 59km SSE of Cantwell, Alaska, 1.2
A shallow moderate 5.0 earthquake was reported Sunday morning on West of Macquarie Island, 5.0
A intermediate light 4.3 earthquake was reported Sunday morning on 145km NNE of Tobelo, Indonesia, 4.3
A intermediate light 4.3 earthquake was reported Sunday morning on 77km SSW of Calama, Chile, 4.3
A shallow unnoticeable 1.0 earthquake was reported Sunday morning on 36km ESE of Bridgeport, California, 1.0
A shallow unnoticeable 1.3 earthquake was reported Sunday morning on 60km WNW of Willow, Alaska, 1.3
A intermediate minor 2.0 earthquake was reported Sunday morning on 53km NNE of Redoubt Volcano, Alaska, 2.0
A shallow light 4.2 earthquake was reported Sunday morning on 93km S of Kuh Sefid, Iran, 4.2
A shallow unnoticeable 1.42 earthquake was reported Sunday morning on 18km E of Big Bear City, CA, 1.42
A shallow moderate 5.1 earthquake was reported Sunday morning on 253km ESE of Yigo Village, Guam, 5.1
A shallow light 4.8 earthquake was reported Sunday morning on West of Macquarie Island, 4.8
A shallow minor 3.0 earthquake was reported Sunday morning on 69km N of Charlotte Amalie, U.S. Virgin Islands, 3.0
A shallow unnoticeable 1.0 earthquake was reported Sunday morning on 61km NW of Ester, Alaska, 1.0
A intermediate light 4.0 earthquake was reported Sunday morning on 94km W of Willow, Alaska, 4.0
A shallow minor 2.8 earthquake was reported Sunday morning on 54km NNE of Road Town, British Virgin Islands, 2.8
A shallow minor 2.72 earthquake was reported Sunday night on 9km WNW of Cobb, California, 2.72
A intermediate light 4.9 earthquake was reported Sunday night on 241km NW of Saumlaki, Indonesia, 4.9
A shallow unnoticeable 1.86 earthquake was reported Sunday night on 20km NNE of Upper Lake, California, 1.86
A shallow minor 2.5 earthquake was reported Sunday night on 86km N of Road Town, British Virgin Islands, 2.5
A shallow unnoticeable 1.01 earthquake was reported Sunday night on 12km SSW of Ocotillo Wells, CA, 1.01
A intermediate minor 2.6 earthquake was reported Sunday night on 52km N of Charlotte Amalie, U.S. Virgin Islands, 2.6
A shallow unnoticeable 1.98 earthquake was reported Sunday night on 4km ENE of San Marcos, CA, 1.98
A shallow unnoticeable 1.3 earthquake was reported Sunday night on 26km N of Yucca Valley, CA, 1.3
A shallow unnoticeable 1.9 earthquake was reported Sunday night on 120km NNW of Kodiak Station, Alaska, 1.9
A shallow unnoticeable 1.9 earthquake was reported Sunday night on 110km NNW of Kodiak Station, Alaska, 1.9
A shallow unnoticeable 1.5 earthquake was reported Sunday night on 114km W of Cantwell, Alaska, 1.5
A shallow unnoticeable 1.82 earthquake was reported Sunday night on 8km ESE of Mammoth Lakes, California, 1.82
A shallow light 4.8 earthquake was reported Sunday night on West of Macquarie Island, 4.8
A shallow minor 2.9 earthquake was reported Sunday night on 84km N of Road Town, British Virgin Islands, 2.9
A shallow minor 2.88 earthquake was reported Sunday night on 26km ESE of Hawaiian Ocean View, Hawaii, 2.88
A shallow unnoticeable 1.34 earthquake was reported Sunday night on 5km NW of The Geysers, California, 1.34
A shallow unnoticeable 1.28 earthquake was reported Sunday night on 4km WSW of Banning, CA, 1.28
A shallow unnoticeable 1.67 earthquake was reported Sunday night on 16km N of Morgan Hill, California, 1.67
A shallow minor 2.69 earthquake was reported Saturday night on 27km NE of Ucluelet, Canada, 2.69
A shallow unnoticeable 1.3 earthquake was reported Saturday night on 18km NE of Fairbanks, Alaska, 1.3
A shallow unnoticeable 1.52 earthquake was reported Saturday night on 6km NE of Little Lake, CA, 1.52
A shallow minor 2.33 earthquake was reported Saturday night on 26km SE of Hawaiian Ocean View, Hawaii, 2.33
A shallow minor 3.4 earthquake was reported Saturday night on 181km WNW of Haines Junction, Canada, 3.4
A shallow unnoticeable 1.97 earthquake was reported Saturday night on 2km NE of Lakeland South, Washington, 1.97
A shallow minor 2.6 earthquake was reported Saturday night on 8km SSW of Cheney, Kansas, 2.6
A shallow unnoticeable 1.2 earthquake was reported Saturday night on 70km S of Deltana, Alaska, 1.2
A shallow unnoticeable 1.8 earthquake was reported Saturday night on 92km N of Redoubt Volcano, Alaska, 1.8
A shallow unnoticeable 1.0 earthquake was reported Saturday night on 41km N of Cold Springs, Nevada, 1.0
A shallow minor 2.1 earthquake was reported Saturday night on 74km NNE of Kiska Volcano, Alaska, 2.1
A shallow unnoticeable 1.09 earthquake was reported Saturday night on 10km NNE of Trabuco Canyon, CA, 1.09
A shallow minor 2.3 earthquake was reported Saturday night on 16km E of Y, Alaska, 2.3
A shallow minor 2.9 earthquake was reported Saturday night on 141km SE of Akutan, Alaska, 2.9
A shallow light 4.7 earthquake was reported Saturday night on Reykjanes Ridge, 4.7
A intermediate unnoticeable 1.9 earthquake was reported Saturday night on 12km SSW of Adak, Alaska, 1.9
A shallow minor 2.2 earthquake was reported Saturday night on 59km NE of Road Town, British Virgin Islands, 2.2
A shallow minor 2.04 earthquake was reported Saturday night on 5km E of Pahala, Hawaii, 2.04
A shallow minor 2.0 earthquake was reported Saturday night on 49km E of Lazy Mountain, Alaska, 2.0
A intermediate unnoticeable 1.0 earthquake was reported Saturday night on 43km SSW of Cantwell, Alaska, 1.0
A shallow unnoticeable 1.0 earthquake was reported Saturday night on 24km S of Gerlach-Empire, Nevada, 1.0
A shallow unnoticeable 1.7 earthquake was reported Saturday night on 9km SSE of Volcano, Hawaii, 1.7
A shallow unnoticeable 1.62 earthquake was reported Saturday night on 3km SSE of North Tustin, CA, 1.62
A shallow light 4.6 earthquake was reported Saturday night on Reykjanes Ridge, 4.6
A shallow unnoticeable 1.66 earthquake was reported Saturday night on 4km NE of Hollywood, CA, 1.66
A shallow minor 2.9 earthquake was reported Saturday night on 152km SE of Akutan, Alaska, 2.9
A shallow moderate 5.1 earthquake was reported Saturday night on 143km SSW of Merizo Village, Guam, 5.1
A shallow unnoticeable 1.06 earthquake was reported Saturday night on 8km ESE of Mammoth Lakes, California, 1.06
A shallow minor 3.1 earthquake was reported Saturday night on 91km N of Road Town, British Virgin Islands, 3.1
A shallow minor 2.7 earthquake was reported Saturday night on 105km N of Vieques, Puerto Rico, 2.7
A shallow minor 2.04 earthquake was reported Saturday night on 25km E of Honaunau-Napoopoo, Hawaii, 2.04
A shallow minor 2.5 earthquake was reported Saturday night on 89km N of Redoubt Volcano, Alaska, 2.5
A shallow minor 2.6 earthquake was reported Saturday night on 20km NW of Hawthorne, Nevada, 2.6
A shallow minor 2.9 earthquake was reported Saturday night on 148km SE of Akutan, Alaska, 2.9
A shallow minor 2.14 earthquake was reported Saturday night on 6km NE of Little Lake, CA, 2.14
A shallow unnoticeable 1.3 earthquake was reported Saturday night on 31km WNW of Anchorage, Alaska, 1.3
A shallow unnoticeable 1.94 earthquake was reported Saturday night on 4km SSW of Volcano, Hawaii, 1.94
A shallow minor 3.1 earthquake was reported Saturday night on 8km SSE of Caldwell, Kansas, 3.1
A shallow moderate 5.1 earthquake was reported Saturday night on Reykjanes Ridge, 5.1
A shallow minor 2.3 earthquake was reported Saturday night on 19km S of Indios, Puerto Rico, 2.3
A shallow minor 2.8 earthquake was reported Saturday night on 21km WSW of Mendota, California, 2.8
A shallow unnoticeable 1.65 earthquake was reported Saturday night on 13km SSE of Manila, Arkansas, 1.65
A shallow unnoticeable 1.06 earthquake was reported Saturday night on 4km NW of The Geysers, California, 1.06
A shallow unnoticeable 1.32 earthquake was reported Saturday night on 8km E of Mammoth Lakes, California, 1.32
A shallow minor 2.2 earthquake was reported Saturday night on 76km NW of New Allakaket, Alaska, 2.2
A intermediate minor 3.3 earthquake was reported Saturday night on 94km WSW of Cantwell, Alaska, 3.3

PART FOUR: The other bits

If the earthquake is anything other than an earthquake (e.g. explosion or quarry blast), print

There was also a magnitude MAGNITUDE TYPE_OF_EVENT on DATE LOCATION.

For example,

There was also a magnitude 1.29 quarry blast on June 19 12km SE of Tehachapi, California.

with TYPE_OF_EVENT being explosion, quarry blast, etc and LOCATION being ‘place’ - e.g. ‘0km N of The Geysers, California’.

# Just add in an 'if' statement - we COULD make another function to build that string... but I'm not doing it.

earthquakes = earthquakes_df.to_dict('records')
for earthquake in earthquakes:
    if earthquake['type'] != 'earthquake':
        print("There was also a magnitude", earthquake['mag'], earthquake['type'], "at", earthquake['place'])
    else:
        # I'm going to comment out the earthquakes just so we can make sure quarry blasts etc show up
        #print(eq_to_words(earthquake))
        pass
There was also a magnitude 1.58 quarry blast at 45km NNW of Los Algodones, B.C., MX
There was also a magnitude 1.73 explosion at 3km SSE of Princeton, Canada
There was also a magnitude 1.19 quarry blast at 8km SSW of Mojave, CA
There was also a magnitude 1.78 quarry blast at 10km NNW of Big Bear Lake, CA
There was also a magnitude 1.25 explosion at 13km NE of Abbotsford, Canada
There was also a magnitude 1.84 explosion at 5km E of White Salmon, Washington
There was also a magnitude 1.11 quarry blast at 1km SE of Quarry near Aromas, CA
There was also a magnitude 1.31 quarry blast at 13km SE of Tehachapi, CA
There was also a magnitude 1.22 quarry blast at 11km E of Quarry near Portola Valley, CA
There was also a magnitude 1.34 quarry blast at 11km E of Quarry near Portola Valley, CA
There was also a magnitude 1.08 explosion at 2km ENE of Eatonville, Washington
There was also a magnitude 1.94 quarry blast at 5km ENE of Butte, Montana
There was also a magnitude 1.27 explosion at 7km SSE of Eatonville, Washington
There was also a magnitude 1.62 explosion at 3km S of Princeton, Canada
There was also a magnitude 1.64 explosion at 30km ESE of Florence, Oregon
There was also a magnitude 1.87 quarry blast at 6km W of Colonial Heights, Tennessee
There was also a magnitude 1.8 explosion at 15km S of Princeton, Canada
There was also a magnitude 1.44 explosion at 5km SE of Gold Bar, Washington
There was also a magnitude 1.06 quarry blast at 6km SSW of Mojave, CA
There was also a magnitude 1.92 quarry blast at 11km N of Oroville, California
There was also a magnitude 1.98 explosion at 4km NNW of Bend, Oregon
There was also a magnitude 1.44 quarry blast at 46km NE of Holtville, CA
There was also a magnitude 1.71 explosion at 3km WSW of Sweet Home, Oregon
There was also a magnitude 1.33 quarry blast at 11km E of Quarry near Portola Valley, CA
There was also a magnitude 1.85 explosion at 2km E of Granite Falls, Washington
There was also a magnitude 1.23 quarry blast at 13km W of Mojave, CA
There was also a magnitude 1.77 quarry blast at 7km SSE of Home Gardens, CA
There was also a magnitude 1.25 quarry blast at 4km ENE of Tehachapi, CA
There was also a magnitude 1.29 other event at 10km SW of Bridgeport, Washington
There was also a magnitude 1.95 explosion at 1km SSW of Princeton, Canada
There was also a magnitude 1.36 other event at 10km SW of Bridgeport, Washington
There was also a magnitude 1.27 other event at 30km ESE of Sweet Home, Oregon
There was also a magnitude 1.74 explosion at 9km S of Princeton, Canada
There was also a magnitude 1.22 explosion at 8km E of Yacolt, Washington
There was also a magnitude 1.99 explosion at 26km WSW of Cheney, Washington
There was also a magnitude 1.57 explosion at 8km WNW of Junction City, Oregon
There was also a magnitude 1.48 quarry blast at 4km SE of Home Gardens, CA
There was also a magnitude 1.66 explosion at 14km NNW of Philomath, Oregon
There was also a magnitude 1.85 quarry blast at 4km ENE of Butte, Montana
There was also a magnitude 1.63 quarry blast at 0km E of Quarry near Salinas, CA
There was also a magnitude 1.27 quarry blast at 10km NNW of Big Bear City, CA
There was also a magnitude 1.36 quarry blast at 2km SE of Home Gardens, CA
There was also a magnitude 1.24 quarry blast at 11km E of Quarry near Portola Valley, CA
There was also a magnitude 1.48 quarry blast at 0km SE of Quarry near Vallejo, CA
There was also a magnitude 1.35 explosion at 28km SW of Morton, Washington
There was also a magnitude 1.16 quarry blast at 6km SSW of Mojave, CA
There was also a magnitude 1.09 explosion at 28km SW of Morton, Washington
There was also a magnitude 2.08 quarry blast at 16km SW of Kemmerer, Wyoming
There was also a magnitude 1.15 explosion at 25km SW of Morton, Washington
There was also a magnitude 1.3 explosion at 25km SW of Morton, Washington
There was also a magnitude 1.07 quarry blast at 13km WNW of Searles Valley, CA
There was also a magnitude 1.33 quarry blast at 12km WNW of Whitehall, Montana
There was also a magnitude 2.14 explosion at 5km S of Princeton, Canada
There was also a magnitude 1.56 quarry blast at 1km NW of Quarry near Salinas, CA
There was also a magnitude 1.29 quarry blast at 4km SSE of Home Gardens, CA
There was also a magnitude 1.25 quarry blast at 5km ENE of Butte, Montana
There was also a magnitude 1.12 quarry blast at 2km SW of Quarry near San Rafael, CA
There was also a magnitude 1.35 explosion at 14km WSW of Cashmere, Washington
There was also a magnitude 1.1 explosion at 4km N of Fern Prairie, Washington
There was also a magnitude 1.57 quarry blast at 46km NE of Holtville, CA
There was also a magnitude 1.44 quarry blast at 11km E of Quarry near Portola Valley, CA
There was also a magnitude 1.33 quarry blast at 3km SSE of Quarry near Aromas, CA
There was also a magnitude 1.35 quarry blast at 4km ENE of Rancho San Diego, CA
There was also a magnitude 1.03 quarry blast at 10km ESE of Coto De Caza, CA
There was also a magnitude 1.17 quarry blast at 6km SSW of Mojave, CA
There was also a magnitude 1.36 quarry blast at 13km SE of Tehachapi, CA
There was also a magnitude 1.05 explosion at 5km E of Yoncalla, Oregon
There was also a magnitude 1.11 quarry blast at 5km NNW of Boron, CA
There was also a magnitude 1.13 explosion at 10km NNW of Philomath, Oregon
There was also a magnitude 2.18 quarry blast at 46km NE of Holtville, CA
There was also a magnitude 2.38 explosion at 1km WNW of Princeton, Canada
There was also a magnitude 1.65 quarry blast at 1km W of Tijuana, B.C., MX
There was also a magnitude 1.26 explosion at 13km S of Morton, Washington
There was also a magnitude 1.09 quarry blast at 5km S of Mojave, CA
There was also a magnitude 1.75 quarry blast at 5km E of Butte, Montana
There was also a magnitude 1.53 quarry blast at 9km NNW of Big Bear Lake, CA
There was also a magnitude 2.02 explosion at 2km NNE of Princeton, Canada
There was also a magnitude 1.48 quarry blast at 4km SE of Home Gardens, CA
There was also a magnitude 2.01 explosion at 9km S of Princeton, Canada
There was also a magnitude 1.19 quarry blast at 13km SE of Tehachapi, CA
There was also a magnitude 1.41 quarry blast at 44km NNW of Los Algodones, B.C., MX
There was also a magnitude 1.45 quarry blast at 11km E of Quarry near Portola Valley, CA
There was also a magnitude 1.11 quarry blast at 13km W of Mojave, CA
There was also a magnitude 1.9 explosion at 1km S of Princeton, Canada
There was also a magnitude 1.42 quarry blast at 7km SSW of Mojave, CA
There was also a magnitude 1.45 quarry blast at 1km SSE of Quarry near Aromas, CA
There was also a magnitude 1.55 quarry blast at 28km SE of Virginia City, Montana
There was also a magnitude 1.63 explosion at 23km NNW of Baker City, Oregon
There was also a magnitude 1.72 quarry blast at 47km NE of Holtville, CA
There was also a magnitude 1.93 explosion at 6km SSW of Princeton, Canada
There was also a magnitude 1.3 quarry blast at 11km E of Quarry near Portola Valley, CA
There was also a magnitude 1.0 explosion at 16km ESE of Enumclaw, Washington
There was also a magnitude 1.57 explosion at 5km SW of Napavine, Washington
There was also a magnitude 1.8 quarry blast at 7km SSE of Home Gardens, CA
There was also a magnitude 1.55 quarry blast at 0km N of Quarry near Portola Valley, CA
There was also a magnitude 1.28 explosion at 3km E of West Side Highway, Washington
There was also a magnitude 2.1 explosion at 1km WSW of Princeton, Canada
There was also a magnitude 1.95 explosion at 32km E of Shady Cove, Oregon
There was also a magnitude 1.44 quarry blast at 0km E of Quarry near Atascadero, CA
There was also a magnitude 1.6 quarry blast at 8km W of Townsend, Montana
There was also a magnitude 1.63 quarry blast at 43km NNW of Los Algodones, B.C., MX
There was also a magnitude 1.35 quarry blast at 5km NNW of Boron, CA
There was also a magnitude 1.47 quarry blast at 11km E of Quarry near Portola Valley, CA
There was also a magnitude 1.77 quarry blast at 4km E of Butte, Montana
There was also a magnitude 1.1 quarry blast at 2km SW of Quarry near San Rafael, CA
There was also a magnitude 1.09 quarry blast at 13km SE of Tehachapi, CA
There was also a magnitude 2.0 explosion at 6km SSE of Princeton, Canada
There was also a magnitude 1.93 explosion at 3km S of Princeton, Canada
There was also a magnitude 1.09 explosion at 5km N of Fern Prairie, Washington
There was also a magnitude 1.76 quarry blast at 46km NNW of Los Algodones, B.C., MX
There was also a magnitude 1.82 explosion at 0km SW of Dundee, Oregon
There was also a magnitude 1.52 quarry blast at 4km SE of Home Gardens, CA
There was also a magnitude 1.38 quarry blast at 13km W of Mojave, CA
There was also a magnitude 1.84 quarry blast at 5km ENE of Butte, Montana
There was also a magnitude 1.24 quarry blast at 2km WSW of Quarry near Clayton, CA
There was also a magnitude 1.53 explosion at 22km NNE of Pasco, Washington
There was also a magnitude 1.07 quarry blast at 6km ENE of Tehachapi, CA
There was also a magnitude 1.37 quarry blast at 11km E of Quarry near Portola Valley, CA
There was also a magnitude 2.0 explosion at 25km SW of Cheney, Washington
There was also a magnitude 2.08 explosion at 2km NE of Coos Bay, Oregon
There was also a magnitude 1.02 quarry blast at 3km SSE of San Marcos, CA
There was also a magnitude 1.05 quarry blast at 6km SSW of Mojave, CA
There was also a magnitude 1.53 quarry blast at 20km S of Quarry near Atascadero, CA
There was also a magnitude 1.33 quarry blast at 7km ESE of Butte, Montana
There was also a magnitude 1.35 explosion at 5km E of Buckley, Washington
There was also a magnitude 1.34 quarry blast at 12km SE of Tehachapi, CA
There was also a magnitude 1.56 quarry blast at 5km NNW of Boron, CA
There was also a magnitude 1.42 explosion at 14km S of Leavenworth, Washington
There was also a magnitude 1.34 quarry blast at 3km SSE of Home Gardens, CA
There was also a magnitude 1.81 explosion at 12km S of Princeton, Canada
There was also a magnitude 1.01 quarry blast at 7km E of Lebec, CA
There was also a magnitude 1.4 quarry blast at 7km SE of Bonita, CA
There was also a magnitude 2.3 quarry blast at 17km N of Orofino, Idaho
There was also a magnitude 1.26 quarry blast at 4km SE of Home Gardens, CA
There was also a magnitude 1.35 quarry blast at 6km SSE of Valley Center, CA
There was also a magnitude 1.21 explosion at 16km W of Winston, Oregon
There was also a magnitude 1.18 explosion at 3km E of Kelso, Washington
There was also a magnitude 1.56 quarry blast at 8km ESE of Bonita, CA
There was also a magnitude 1.41 quarry blast at 45km NE of Holtville, CA
There was also a magnitude 1.23 quarry blast at 12km E of Quarry near Portola Valley, CA
There was also a magnitude 1.57 explosion at 2km SSW of Princeton, Canada
There was also a magnitude 1.41 quarry blast at 4km N of Norco, CA
There was also a magnitude 2.04 quarry blast at 28km N of Orofino, Idaho
There was also a magnitude 1.2 quarry blast at 7km SSW of Mojave, CA
There was also a magnitude 2.23 explosion at 10km S of Princeton, Canada
There was also a magnitude 1.66 explosion at 2km S of Princeton, Canada
There was also a magnitude 1.84 explosion at 7km NE of Abbotsford, Canada
There was also a magnitude 1.55 explosion at 3km SW of Drain, Oregon
There was also a magnitude 1.2 quarry blast at 0km S of Quarry near Vallejo, CA
There was also a magnitude 1.79 explosion at 5km SSE of Princeton, Canada
There was also a magnitude 1.37 quarry blast at 7km SSW of Mojave, CA
There was also a magnitude 1.48 quarry blast at 6km ESE of Butte, Montana
There was also a magnitude 1.31 quarry blast at 11km E of Quarry near Portola Valley, CA