Tornadoes in Canada from 1980 to 2009

Goals

  • To look at the Government of Canada Dataset on Tornadoes from 1980 and 2009 and their impact on the Canadian population.
  • To attempt to better understand where tornadoes are more likely and when.
  • To attempt to understand the financial impact on Canadians of tornadoes.

Limitations of Dataset

  • The only data available from the Government of Canada covers the 1980 to 2009 period.
  • This only captures tornadoes that were recorded. It would not take into account tornadoes that hit non populated areas. Therefore I always qualify findings as 'tornadoes in populated communities'. No data can really be discerned on the amount of activity country wide.
  • As this is a learning exercise only, no attempt is being made to add extra data from other sources or the periods of 2010-2019. The goal is to see what this government provided dataset actually tells us.

Assumptions

  • Human/Animal Death/Injuries often show -999. This can either mean no deaths or unsure. I will assume 0 deaths
  • Damage to housing is an ambiguous column. Assumption made that 000 is 000(000) based on the amount of deaths and injuries
  • House Damage data often shows -999. This number either signifies no significant damage or unknown. I will assume 0 damage.

Take Aways

While the data is not complete, it is obvious that tornadoes have an interesting history in Canada. As I stumbled upon what we're obviously some of the most devastating tornadoes like the big one in Edmonton, it was interesting to research old news articles about the events. While the data itself is very analytical, there are also many human stories behind it. One can only put themselves in the shoes of the people who faced these events at the time.

I never gave tornadoes much thought as they are such rare events, but they are always a threat and in an instant can change lives forever.

Interesting work happening today to study tornado activity in Canada

The data provided by the OpenData portal is seriously lacking. It appears a team of researchers have taken on the task to better understand tornado activity in Canada.

The following link from the Weather Network provides a brief synopsis of the work happening.

In [1]:
%matplotlib inline
import pandas as pd
import folium
import matplotlib.style as style
style.use('seaborn-poster') #sets the size of the charts
style.use('ggplot')
In [2]:
from IPython.core.display import HTML
css = open('../css/style-table.css').read() + open('../css/style-notebook.css').read()
HTML('<style>{}</style>'.format(css))
Out[2]:
In [3]:
df = pd.read_csv('../data/tornadoes.csv', encoding = "ISO-8859-1")
In [4]:
df.head()
Out[4]:
YYYY_LOCAL MM_LOCAL DD_LOCAL HHMM_LOCAL YYYYMMDDHH YYYY_SOLAR MM_SOLAR DD_SOLAR HHMM_SOLAR NEAR_CMMTY ... END_LON_W LENGTH_M MOTION_DEG WIDTH_MAX_ HUMAN_FATA HUMAN_INJ ANIMAL_FAT ANIMAL_INJ DMG_THOUS FORECAST_R
0 1980.0 4.0 6.0 1920.0 19800407 0020 1980.0 4.0 6.0 1847.0 Altona ... -999.000000 -999 -999 -999 -999 -999 -999 -999 -999.0 Morden - Winkler - Altona - Emerson - Morris
1 1980.0 5.0 5.0 2000.0 19800506 2300 1980.0 5.0 5.0 1839.0 Stratford ... -80.963823 4190 265 30 -999 -999 -999 -999 -999.0 Huron - Perth
2 1980.0 5.0 25.0 1750.0 19800525 2350 1980.0 5.0 25.0 1559.0 Creelman ... -999.000000 -999 -999 -999 -999 -999 -999 -999 -999.0 Estevan - Weyburn - Radville - Milestone
3 1980.0 5.0 28.0 1700.0 19800528 2200 1980.0 5.0 28.0 1530.0 16 km S of Morden ... -999.000000 -999 -999 -999 -999 -999 -999 -999 -999.0 Morden - Winkler - Altona - Emerson - Morris
4 1980.0 5.0 31.0 1334.0 19800531 1734 1980.0 5.0 31.0 1217.0 Georgetown to Woodbridge ... -79.643235 26300 245 490 0 0 0 0 900.0 Halton - Peel

5 rows × 25 columns

In [5]:
df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 1839 entries, 0 to 1838
Data columns (total 25 columns):
YYYY_LOCAL    1839 non-null float64
MM_LOCAL      1839 non-null float64
DD_LOCAL      1839 non-null float64
HHMM_LOCAL    1839 non-null float64
YYYYMMDDHH    1714 non-null object
YYYY_SOLAR    1839 non-null float64
MM_SOLAR      1839 non-null float64
DD_SOLAR      1839 non-null float64
HHMM_SOLAR    1839 non-null float64
NEAR_CMMTY    1839 non-null object
PROVINCE      1839 non-null object
FUJITA        1839 non-null int64
START_LAT_    1839 non-null float64
START_LON_    1839 non-null float64
END_LAT_N     1839 non-null float64
END_LON_W     1839 non-null float64
LENGTH_M      1839 non-null int64
MOTION_DEG    1839 non-null int64
WIDTH_MAX_    1839 non-null int64
HUMAN_FATA    1839 non-null int64
HUMAN_INJ     1839 non-null int64
ANIMAL_FAT    1839 non-null int64
ANIMAL_INJ    1839 non-null int64
DMG_THOUS     1839 non-null float64
FORECAST_R    1839 non-null object
dtypes: float64(13), int64(8), object(4)
memory usage: 359.3+ KB
In [6]:
columns_of_interest = ['YYYY_LOCAL', 'MM_LOCAL', 'DD_LOCAL', 'HHMM_LOCAL', 
                       'NEAR_CMMTY','PROVINCE', 'FUJITA', 'START_LAT_', 'START_LON_', 'END_LAT_N',
                       'END_LON_W', 'LENGTH_M', 'MOTION_DEG', 'WIDTH_MAX_', 'HUMAN_FATA', 
                       'HUMAN_INJ', 'ANIMAL_FAT', 'ANIMAL_INJ', 'DMG_THOUS']
df = df[columns_of_interest].copy()
In [7]:
df.head(1)
Out[7]:
YYYY_LOCAL MM_LOCAL DD_LOCAL HHMM_LOCAL NEAR_CMMTY PROVINCE FUJITA START_LAT_ START_LON_ END_LAT_N END_LON_W LENGTH_M MOTION_DEG WIDTH_MAX_ HUMAN_FATA HUMAN_INJ ANIMAL_FAT ANIMAL_INJ DMG_THOUS
0 1980.0 4.0 6.0 1920.0 Altona MB 0 49.105 -97.568 -999.0 -999.0 -999 -999 -999 -999 -999 -999 -999 -999.0
In [8]:
df.columns=['year', 'month', 'day', 'hhmm', 'community', 
            'province', 'ef','start_lat_n', 'start_lon_w', 'end_lat_n', 
            'end_lon_w', 'length', 'motion_deg', 'width_max', 
            'human_deaths', 'human_injuries', 'animal_deaths', 'animal_injuries',
             'house_damage']
In [9]:
df.head(2)
Out[9]:
year month day hhmm community province ef start_lat_n start_lon_w end_lat_n end_lon_w length motion_deg width_max human_deaths human_injuries animal_deaths animal_injuries house_damage
0 1980.0 4.0 6.0 1920.0 Altona MB 0 49.105000 -97.568000 -999.0000 -999.000000 -999 -999 -999 -999 -999 -999 -999 -999.0
1 1980.0 5.0 5.0 2000.0 Stratford ON 0 43.385625 -81.012735 43.3897 -80.963823 4190 265 30 -999 -999 -999 -999 -999.0
In [10]:
# Over 80% of readings don't provide end lon/lat
df.end_lon_w.value_counts().head()
Out[10]:
-999.000    1580
-79.545        2
-80.823        2
-79.305        1
-84.017        1
Name: end_lon_w, dtype: int64
In [11]:
# Number of tornadoes recorded in Canada from 1980 to 2009
len(df)
Out[11]:
1839
In [12]:
df.dtypes
Out[12]:
year               float64
month              float64
day                float64
hhmm               float64
community           object
province            object
ef                   int64
start_lat_n        float64
start_lon_w        float64
end_lat_n          float64
end_lon_w          float64
length               int64
motion_deg           int64
width_max            int64
human_deaths         int64
human_injuries       int64
animal_deaths        int64
animal_injuries      int64
house_damage       float64
dtype: object
In [13]:
df['year'] = df.year.astype(int)
df['month'] = df.month.astype(int)
df['day'] = df.day.astype(int)
df['hhmm'] = df.hhmm.astype(int)
df.head(2)
Out[13]:
year month day hhmm community province ef start_lat_n start_lon_w end_lat_n end_lon_w length motion_deg width_max human_deaths human_injuries animal_deaths animal_injuries house_damage
0 1980 4 6 1920 Altona MB 0 49.105000 -97.568000 -999.0000 -999.000000 -999 -999 -999 -999 -999 -999 -999 -999.0
1 1980 5 5 2000 Stratford ON 0 43.385625 -81.012735 43.3897 -80.963823 4190 265 30 -999 -999 -999 -999 -999.0
In [14]:
df['date'] = pd.to_datetime(df[['year', 'month', 'day']], errors='coerce')
In [15]:
df.head()
Out[15]:
year month day hhmm community province ef start_lat_n start_lon_w end_lat_n end_lon_w length motion_deg width_max human_deaths human_injuries animal_deaths animal_injuries house_damage date
0 1980 4 6 1920 Altona MB 0 49.105000 -97.568000 -999.000000 -999.000000 -999 -999 -999 -999 -999 -999 -999 -999.0 1980-04-06
1 1980 5 5 2000 Stratford ON 0 43.385625 -81.012735 43.389700 -80.963823 4190 265 30 -999 -999 -999 -999 -999.0 1980-05-05
2 1980 5 25 1750 Creelman SK 1 49.840000 -103.630000 -999.000000 -999.000000 -999 -999 -999 -999 -999 -999 -999 -999.0 1980-05-25
3 1980 5 28 1700 16 km S of Morden MB 0 49.190000 -98.100000 -999.000000 -999.000000 -999 -999 -999 -999 -999 -999 -999 -999.0 1980-05-28
4 1980 5 31 1334 Georgetown to Woodbridge ON 0 43.652990 -79.930887 43.762647 -79.643235 26300 245 490 0 0 0 0 900.0 1980-05-31
In [16]:
df.dtypes
Out[16]:
year                        int64
month                       int64
day                         int64
hhmm                        int64
community                  object
province                   object
ef                          int64
start_lat_n               float64
start_lon_w               float64
end_lat_n                 float64
end_lon_w                 float64
length                      int64
motion_deg                  int64
width_max                   int64
human_deaths                int64
human_injuries              int64
animal_deaths               int64
animal_injuries             int64
house_damage              float64
date               datetime64[ns]
dtype: object
In [17]:
df['hour'] = df['hhmm'].apply(lambda x: str(x)[:-2])
In [18]:
df.head(2)
Out[18]:
year month day hhmm community province ef start_lat_n start_lon_w end_lat_n ... length motion_deg width_max human_deaths human_injuries animal_deaths animal_injuries house_damage date hour
0 1980 4 6 1920 Altona MB 0 49.105000 -97.568000 -999.0000 ... -999 -999 -999 -999 -999 -999 -999 -999.0 1980-04-06 19
1 1980 5 5 2000 Stratford ON 0 43.385625 -81.012735 43.3897 ... 4190 265 30 -999 -999 -999 -999 -999.0 1980-05-05 20

2 rows × 21 columns

In [19]:
df.dtypes
Out[19]:
year                        int64
month                       int64
day                         int64
hhmm                        int64
community                  object
province                   object
ef                          int64
start_lat_n               float64
start_lon_w               float64
end_lat_n                 float64
end_lon_w                 float64
length                      int64
motion_deg                  int64
width_max                   int64
human_deaths                int64
human_injuries              int64
animal_deaths               int64
animal_injuries             int64
house_damage              float64
date               datetime64[ns]
hour                       object
dtype: object
In [20]:
#Most Active years for tornodoes
df.year.value_counts().head(10)
Out[20]:
1991    94
1999    92
1984    76
1986    73
1990    72
1988    70
1982    69
1983    67
2000    67
1996    67
Name: year, dtype: int64
In [21]:
# Graph the most active years
df.year.value_counts().head(10).plot(kind='bar')
Out[21]:
<matplotlib.axes._subplots.AxesSubplot at 0x7f2dec3ae128>
In [22]:
# Average number of tornadoes per year
df.year.value_counts().mean()
Out[22]:
61.3
In [23]:
# The sample size is too small but already we can see a normal distribution taking shape.  The following 
# graph shows a distibution of tornadoes per year.
df.year.value_counts().plot(kind='hist', bins=5)
Out[23]:
<matplotlib.axes._subplots.AxesSubplot at 0x7f2dea2de7b8>
In [24]:
#most active hours of the day
df.hour.value_counts().plot(kind='bar')
Out[24]:
<matplotlib.axes._subplots.AxesSubplot at 0x7f2de9c02080>

Data looks off. It is unlikely that midnight sees the highest frequency. More likely that no hour is recorded but still assigned hour 0 based on the amounts later in the night and early morning.

Late afternoon / Early evening (between 3pm-6pm) appears to be most likely time for a tornado

In [25]:
#Top 10 cities have the highest tornado activity
df.community.value_counts().head(10).plot(kind='barh')
Out[25]:
<matplotlib.axes._subplots.AxesSubplot at 0x7f2de9b878d0>

cities in western canada see the highest tornado activity (Top 4)

In [26]:
# Graph activity frequency by Province
df.province.value_counts().head(10).plot(kind='bar')
Out[26]:
<matplotlib.axes._subplots.AxesSubplot at 0x7f2de9b0a4a8>
In [27]:
# Looking at Canada's largent province by population
df_on = df[df.province == 'ON']
df_on.head()
Out[27]:
year month day hhmm community province ef start_lat_n start_lon_w end_lat_n ... length motion_deg width_max human_deaths human_injuries animal_deaths animal_injuries house_damage date hour
1 1980 5 5 2000 Stratford ON 0 43.385625 -81.012735 43.389700 ... 4190 265 30 -999 -999 -999 -999 -999.0 1980-05-05 20
4 1980 5 31 1334 Georgetown to Woodbridge ON 0 43.652990 -79.930887 43.762647 ... 26300 245 490 0 0 0 0 900.0 1980-05-31 13
5 1980 6 9 1115 Whitby ON 0 43.883971 -78.971305 43.883653 ... 50 315 -999 -999 -999 -999 -999 1.0 1980-06-09 11
10 1980 7 15 1505 Wellesley ON 0 43.489469 -80.767201 43.494084 ... 1500 250 -999 -999 -999 -999 -999 50.0 1980-07-15 15
11 1980 7 16 936 LaSalle ON 1 42.244189 -83.100691 42.229000 ... 6350 285 -999 -999 -999 10 -999 500.0 1980-07-16 9

5 rows × 21 columns

In [28]:
# Top 10 communities in Ontario for tornado activity
df_on.community.value_counts().head(10).plot(kind='barh')
Out[28]:
<matplotlib.axes._subplots.AxesSubplot at 0x7f2de9a243c8>
In [29]:
# Looking at Cochrane specifically as it was mentioned in the national top 10 earlier.
df[df.community == 'Cochrane']
Out[29]:
year month day hhmm community province ef start_lat_n start_lon_w end_lat_n ... length motion_deg width_max human_deaths human_injuries animal_deaths animal_injuries house_damage date hour
127 1982 8 8 1545 Cochrane ON 0 49.038 -81.388 49.126 ... 9820 180 -999 0 0 0 0 100.0 1982-08-08 15
333 1985 6 28 1800 Cochrane AB 1 51.180 -114.470 -999.000 ... -999 -999 -999 -999 -999 -999 -999 40.0 1985-06-28 18
403 1986 7 13 1530 Cochrane AB 0 51.180 -114.470 -999.000 ... -999 -999 -999 -999 -999 -999 -999 -999.0 1986-07-13 15
1265 1999 0 0 0 Cochrane AB 0 51.180 -114.470 -999.000 ... -999 -999 -999 -999 -999 -999 -999 -999.0 NaT
1553 2005 6 4 2030 Cochrane AB 0 51.180 -114.430 -999.000 ... -999 -999 -999 -999 -999 -999 -999 -999.0 2005-06-04 20

5 rows × 21 columns

The Top 10 cities had Cochrane listed. I assumed Cochrane Ontario had 5 tornadoes but they did not show up in Ontario top 10. Turns out there is a Cochrane Alberta

In [30]:
len(df.date.unique())
Out[30]:
938

Most active tornado days are most likely the same tornado systems hitting communities that are in proximity

In [31]:
# most active community days for tornadoes
df.date.value_counts().head(10).plot(kind='barh')
Out[31]:
<matplotlib.axes._subplots.AxesSubplot at 0x7f2dec3ddf28>
In [32]:
#Who had tornadoes on the most active day
df20090820 = df[df.date == '2009-08-20']
In [33]:
# Ontario communities that got hit on 2009-08-20
df20090820
Out[33]:
year month day hhmm community province ef start_lat_n start_lon_w end_lat_n ... length motion_deg width_max human_deaths human_injuries animal_deaths animal_injuries house_damage date hour
1811 2009 8 20 1600 Durham ON 2 44.077300 -80.934400 44.427500 ... 48000 215 400 1 0 0 0 0.0 2009-08-20 16
1812 2009 8 20 1640 The Blue Mountains ON 2 44.454800 -80.482500 44.537000 ... 12500 225 400 0 0 0 0 0.0 2009-08-20 16
1813 2009 8 20 1730 New Lowell ON 1 44.352600 -79.974200 44.453900 ... 12600 210 70 0 0 0 0 10.0 2009-08-20 17
1814 2009 8 20 1730 Arnstein ON 1 45.885061 -79.955382 45.889943 ... 1340 245 -999 0 0 0 0 0.0 2009-08-20 17
1815 2009 8 20 1750 Newmarket ON 1 44.077358 -79.355971 44.094693 ... 2470 220 300 0 0 0 0 0.0 2009-08-20 17
1816 2009 8 20 1805 Woodbridge ON 2 43.761134 -79.628703 43.827064 ... 9620 230 -999 0 0 0 0 0.0 2009-08-20 18
1817 2009 8 20 1810 Moonstone ON 0 44.629400 -79.679291 44.652118 ... 3220 220 -999 0 0 0 0 0.0 2009-08-20 18
1818 2009 8 20 1830 Dollars Lake ON 1 45.934887 -80.224121 45.942346 ... 1100 220 -999 0 0 0 0 0.0 2009-08-20 18
1819 2009 8 20 1830 Milton ON 1 43.514084 -79.881796 43.518936 ... 1090 240 200 0 0 0 0 0.0 2009-08-20 18
1820 2009 8 20 1830 North Bay ON 0 46.310000 -79.470000 -999.000000 ... -999 -999 -999 0 0 0 0 0.0 2009-08-20 18
1821 2009 8 20 1830 Gravenhurst ON 1 44.840500 -79.417000 44.950200 ... 14300 210 900 0 0 0 0 0.0 2009-08-20 18
1822 2009 8 20 1832 Maple ON 2 43.855294 -79.544134 43.872731 ... 2710 225 -999 0 0 0 0 0.0 2009-08-20 18
1823 2009 8 20 2000 Ril Lake ON 1 45.162849 -79.028522 45.166453 ... 580 225 -999 0 0 0 0 0.0 2009-08-20 20
1824 2009 8 20 2000 Near Kennisis Lake ON 1 45.259200 -78.673200 45.350000 ... 10000 205 300 0 0 0 0 0.0 2009-08-20 20
1825 2009 8 20 2000 Redstone Lake ON 0 45.185000 -78.526977 45.195028 ... 1420 220 -999 0 0 0 0 0.0 2009-08-20 20
1826 2009 8 20 2005 Orono ON 0 44.045085 -78.542112 44.063913 ... 3150 230 200 0 0 0 0 0.0 2009-08-20 20
1827 2009 8 20 2030 Rice Lake to Otonabee-South Monaghan ON 1 44.211456 -78.150194 44.302278 ... 10300 190 -999 0 0 0 0 0.0 2009-08-20 20
1828 2009 8 20 2145 Carlow Mayo ON 1 44.998258 -77.683351 45.132401 ... 19100 220 -999 0 0 0 0 0.0 2009-08-20 21
1829 2009 8 20 2145 Buckshot Lake ON 1 45.005316 -77.060822 45.021398 ... 2030 210 30 0 0 0 0 0.0 2009-08-20 21

19 rows × 21 columns

In [34]:
# Ontario communities that got hit on 2006-08-02
df20060802 = df[df.date == '2006-08-02']
df20060802
Out[34]:
year month day hhmm community province ef start_lat_n start_lon_w end_lat_n ... length motion_deg width_max human_deaths human_injuries animal_deaths animal_injuries house_damage date hour
1637 2006 8 2 1525 Morriston ON 0 43.450000 -80.083300 -999.000 ... -999 -999 -999 0 0 0 0 0.0 2006-08-02 15
1638 2006 8 2 1815 Jackson’s Cove ON 0 44.942000 -81.122000 44.945 ... 1500 240 200 0 0 0 0 0.0 2006-08-02 18
1639 2006 8 2 1925 Uffington ON 0 44.955000 -79.167000 44.954 ... 250 290 50 0 0 0 0 0.0 2006-08-02 19
1640 2006 8 2 1930 Marsden Lake ON 1 45.230000 -78.525000 45.232 ... 6200 270 200 0 1 0 0 0.0 2006-08-02 19
1641 2006 8 2 1940 Head Lake ON 0 44.750000 -78.900000 -999.000 ... -999 -999 -999 0 0 0 0 0.0 2006-08-02 19
1642 2006 8 2 1940 Kashwakamak Lake ON 0 44.825000 -77.115000 44.826 ... 6860 270 100 0 0 0 0 0.0 2006-08-02 19
1643 2006 8 2 1945 Minden Hills ON 1 45.027000 -78.782000 44.965 ... 17100 300 100 0 0 0 0 0.0 2006-08-02 19
1644 2006 8 2 1950 Drag Lake ON 1 45.100000 -78.494000 45.081 ... 11500 285 500 0 0 0 0 0.0 2006-08-02 19
1645 2006 8 2 1950 West Guilford ON 1 45.071000 -78.704000 45.123 ... 13300 245 800 0 0 0 0 0.0 2006-08-02 19
1646 2006 8 2 2000 Catchacoma ON 0 44.729000 -78.341000 44.730 ... 4450 270 300 0 0 0 0 0.0 2006-08-02 20
1647 2006 8 2 2005 Anstruther Lake ON 1 44.729000 -78.233000 44.730 ... 1020 260 90 0 0 0 0 0.0 2006-08-02 20
1648 2006 8 2 2010 Coxvale ON 0 44.858000 -76.911000 44.864 ... 1220 240 100 0 0 0 0 0.0 2006-08-02 20
1649 2006 8 2 2010 Big Mink Lake ON 1 45.204612 -78.084658 45.200 ... 1500 290 200 0 0 0 0 0.0 2006-08-02 20
1650 2006 8 2 2010 Combermere ON 2 45.370000 -77.640000 45.367 ... 28800 275 400 0 0 0 0 0.0 2006-08-02 20
1651 2006 8 2 2030 Near Clayton ON 0 45.179000 -76.453000 -999.000 ... -999 -999 100 0 0 0 0 0.0 2006-08-02 20
1652 2006 8 2 2045 Near Bancroft ON 2 45.096000 -77.653000 45.107 ... 8000 260 250 0 0 0 0 0.0 2006-08-02 20
1653 2006 8 2 2100 Ferguson Corners ON 1 45.078503 -77.299030 45.083 ... 1000 240 180 0 0 0 0 0.0 2006-08-02 21

17 rows × 21 columns

Map of all communities where a tornado touched down between 1980 and 2009 in Canada

In [35]:
# Get a list of tuples for geo coordinates to be used in plotting a tornado map
def locations(lat, lon, community, province, ef, year, deaths):
    startlat = [la for la in lat]
    startlon = [lo for lo in lon]
    community_ = [c for c in community]
    province_ = [p for p in province]
    cat = [e for e in ef]
    year_ = [y for y in year]
    death_ = [d for d in deaths]
    return list(zip(startlat, startlon, community_, province_, cat, year_, death_))
        
coordinates = locations(df.start_lat_n, df.start_lon_w, df.community, df.province, df.ef, df.year, df.human_deaths)
In [36]:
def tornado_map(coordinates, mapname):
    #tornado_map = folium.Map(location=[49.641438,-97.389353], zoom_start=4)
    tornado_map = folium.Map(location=[56.0,-96.0], zoom_start=4)
    for coord in coordinates:
        folium.CircleMarker(location=[
            coord[0], coord[1]], 
            popup=coord[2]+coord[3]+','+str(coord[5])+'\n'+str(coord[6])+' '+'Deaths'+'\n'+'F'+str(coord[4]),
            radius=3).add_to(tornado_map)
    tornado_map.save(f'{mapname}.html')

tornado_map(coordinates, 'map')

What can we learn from the data

We see that the bulk of recorded tornado activity is centred in the Alberta, Saskatchewan, Manitoba, Southern Ontario and Southern Quebec.

Populated coastal areas see less tornado activity. Also, tornadoes probably hit remote areas but may not hit any areas with population centres and are therefore not recorded.

In [37]:
from IPython.display import IFrame
IFrame('map.html', width=960, height=530)
Out[37]:

What went on in 1991, the most active tornado year

In [38]:
df_1991 = df[df['year'] == 1991]
In [39]:
df_1991.head()
Out[39]:
year month day hhmm community province ef start_lat_n start_lon_w end_lat_n ... length motion_deg width_max human_deaths human_injuries animal_deaths animal_injuries house_damage date hour
695 1991 3 10 1330 Pitt Meadows BC 0 49.241944 -122.671944 -999.0 ... -999 -999 -999 -999 -999 -999 -999 3.5 1991-03-10 13
696 1991 4 5 1245 Lac la Hache BC 1 51.816667 -121.466667 -999.0 ... -999 -999 -999 -999 -999 -999 -999 16.0 1991-04-05 12
697 1991 5 12 1630 Maryfield SK 0 49.835000 -101.415000 -999.0 ... -999 -999 -999 -999 -999 -999 -999 -999.0 1991-05-12 16
698 1991 5 21 2230 Oungre SK 2 49.150000 -103.800000 -999.0 ... -999 -999 -999 -999 -999 -999 -999 -999.0 1991-05-21 22
699 1991 5 28 1246 Whitecourt AB 0 54.150000 -115.672000 -999.0 ... -999 -999 -999 -999 -999 -999 -999 -999.0 1991-05-28 12

5 rows × 21 columns

In [40]:
# The most active year was 1991 and recorded 94 tornadoes
len(df_1991)
Out[40]:
94
In [41]:
# Tornadoes by Province
df_1991['province'].value_counts().plot('bar')
Out[41]:
<matplotlib.axes._subplots.AxesSubplot at 0x7f2de85712e8>

Map locations of tornadoes in 1991

In [42]:
coordinates91 = locations(df_1991.start_lat_n, df_1991.start_lon_w, df_1991.community, df_1991.province, df_1991.ef, df_1991.year, df_1991.human_deaths)
tornado_map(coordinates91, 'map1991')
IFrame('map1991.html', width=960, height=530)
Out[42]:

Map of Ontario's busiest tornado day, August 8, 2009

In [43]:
# All tornadoes recorded on August 8 2009
df20090820
Out[43]:
year month day hhmm community province ef start_lat_n start_lon_w end_lat_n ... length motion_deg width_max human_deaths human_injuries animal_deaths animal_injuries house_damage date hour
1811 2009 8 20 1600 Durham ON 2 44.077300 -80.934400 44.427500 ... 48000 215 400 1 0 0 0 0.0 2009-08-20 16
1812 2009 8 20 1640 The Blue Mountains ON 2 44.454800 -80.482500 44.537000 ... 12500 225 400 0 0 0 0 0.0 2009-08-20 16
1813 2009 8 20 1730 New Lowell ON 1 44.352600 -79.974200 44.453900 ... 12600 210 70 0 0 0 0 10.0 2009-08-20 17
1814 2009 8 20 1730 Arnstein ON 1 45.885061 -79.955382 45.889943 ... 1340 245 -999 0 0 0 0 0.0 2009-08-20 17
1815 2009 8 20 1750 Newmarket ON 1 44.077358 -79.355971 44.094693 ... 2470 220 300 0 0 0 0 0.0 2009-08-20 17
1816 2009 8 20 1805 Woodbridge ON 2 43.761134 -79.628703 43.827064 ... 9620 230 -999 0 0 0 0 0.0 2009-08-20 18
1817 2009 8 20 1810 Moonstone ON 0 44.629400 -79.679291 44.652118 ... 3220 220 -999 0 0 0 0 0.0 2009-08-20 18
1818 2009 8 20 1830 Dollars Lake ON 1 45.934887 -80.224121 45.942346 ... 1100 220 -999 0 0 0 0 0.0 2009-08-20 18
1819 2009 8 20 1830 Milton ON 1 43.514084 -79.881796 43.518936 ... 1090 240 200 0 0 0 0 0.0 2009-08-20 18
1820 2009 8 20 1830 North Bay ON 0 46.310000 -79.470000 -999.000000 ... -999 -999 -999 0 0 0 0 0.0 2009-08-20 18
1821 2009 8 20 1830 Gravenhurst ON 1 44.840500 -79.417000 44.950200 ... 14300 210 900 0 0 0 0 0.0 2009-08-20 18
1822 2009 8 20 1832 Maple ON 2 43.855294 -79.544134 43.872731 ... 2710 225 -999 0 0 0 0 0.0 2009-08-20 18
1823 2009 8 20 2000 Ril Lake ON 1 45.162849 -79.028522 45.166453 ... 580 225 -999 0 0 0 0 0.0 2009-08-20 20
1824 2009 8 20 2000 Near Kennisis Lake ON 1 45.259200 -78.673200 45.350000 ... 10000 205 300 0 0 0 0 0.0 2009-08-20 20
1825 2009 8 20 2000 Redstone Lake ON 0 45.185000 -78.526977 45.195028 ... 1420 220 -999 0 0 0 0 0.0 2009-08-20 20
1826 2009 8 20 2005 Orono ON 0 44.045085 -78.542112 44.063913 ... 3150 230 200 0 0 0 0 0.0 2009-08-20 20
1827 2009 8 20 2030 Rice Lake to Otonabee-South Monaghan ON 1 44.211456 -78.150194 44.302278 ... 10300 190 -999 0 0 0 0 0.0 2009-08-20 20
1828 2009 8 20 2145 Carlow Mayo ON 1 44.998258 -77.683351 45.132401 ... 19100 220 -999 0 0 0 0 0.0 2009-08-20 21
1829 2009 8 20 2145 Buckshot Lake ON 1 45.005316 -77.060822 45.021398 ... 2030 210 30 0 0 0 0 0.0 2009-08-20 21

19 rows × 21 columns

In [44]:
# We can see that it was very windy in Southern Ontario right up to as far north as North Bay
d = df20090820
coords_on_09 = locations(d.start_lat_n, d.start_lon_w, d.community, d.province, d.ef, d.year, d.human_deaths)
tornado_map(coords_on_09, 'on2009')
IFrame('on2009.html', width=960, height=530)
Out[44]:

Canada's worst tornadoes

The data provides information on human and animal deaths and injuries as well as damage to housing.

In [45]:
# Assuming -999 has no information recorded or there were no deaths
df['human_deaths'].unique()
Out[45]:
array([-999,    0,    1,    4,    8,   27,   12,    3])
In [46]:
df.dtypes
Out[46]:
year                        int64
month                       int64
day                         int64
hhmm                        int64
community                  object
province                   object
ef                          int64
start_lat_n               float64
start_lon_w               float64
end_lat_n                 float64
end_lon_w                 float64
length                      int64
motion_deg                  int64
width_max                   int64
human_deaths                int64
human_injuries              int64
animal_deaths               int64
animal_injuries             int64
house_damage              float64
date               datetime64[ns]
hour                       object
dtype: object
In [47]:
# Remove the -999 value and assume 0 deaths.
df.replace(-999, 0, inplace=True)
In [48]:
df['human_injuries'].unique()
Out[48]:
array([  0,   1,  13,  10,   7,   5,  40,   4,  33,   3,  69, 155, 300,
         2,  15,   6, 130,  19])
In [49]:
df.head()
Out[49]:
year month day hhmm community province ef start_lat_n start_lon_w end_lat_n ... length motion_deg width_max human_deaths human_injuries animal_deaths animal_injuries house_damage date hour
0 1980 4 6 1920 Altona MB 0 49.105000 -97.568000 0.000000 ... 0 0 0 0 0 0 0 0.0 1980-04-06 19
1 1980 5 5 2000 Stratford ON 0 43.385625 -81.012735 43.389700 ... 4190 265 30 0 0 0 0 0.0 1980-05-05 20
2 1980 5 25 1750 Creelman SK 1 49.840000 -103.630000 0.000000 ... 0 0 0 0 0 0 0 0.0 1980-05-25 17
3 1980 5 28 1700 16 km S of Morden MB 0 49.190000 -98.100000 0.000000 ... 0 0 0 0 0 0 0 0.0 1980-05-28 17
4 1980 5 31 1334 Georgetown to Woodbridge ON 0 43.652990 -79.930887 43.762647 ... 26300 245 490 0 0 0 0 900.0 1980-05-31 13

5 rows × 21 columns

Fatalities and Injuries

In [50]:
len(df.date.unique())
Out[50]:
938
In [51]:
df['human_deaths'].unique()
Out[51]:
array([ 0,  1,  4,  8, 27, 12,  3])
In [52]:
df.head()
Out[52]:
year month day hhmm community province ef start_lat_n start_lon_w end_lat_n ... length motion_deg width_max human_deaths human_injuries animal_deaths animal_injuries house_damage date hour
0 1980 4 6 1920 Altona MB 0 49.105000 -97.568000 0.000000 ... 0 0 0 0 0 0 0 0.0 1980-04-06 19
1 1980 5 5 2000 Stratford ON 0 43.385625 -81.012735 43.389700 ... 4190 265 30 0 0 0 0 0.0 1980-05-05 20
2 1980 5 25 1750 Creelman SK 1 49.840000 -103.630000 0.000000 ... 0 0 0 0 0 0 0 0.0 1980-05-25 17
3 1980 5 28 1700 16 km S of Morden MB 0 49.190000 -98.100000 0.000000 ... 0 0 0 0 0 0 0 0.0 1980-05-28 17
4 1980 5 31 1334 Georgetown to Woodbridge ON 0 43.652990 -79.930887 43.762647 ... 26300 245 490 0 0 0 0 900.0 1980-05-31 13

5 rows × 21 columns

In [53]:
print('Human Deaths = {}'.format(df['human_deaths'].sum()))
print('Human Injuries = {}'.format(df['human_injuries'].sum()))
print('Animal Deaths = {}'.format(df['animal_deaths'].sum()))
print('Animal Injuries = {}'.format(df['animal_injuries'].sum()))
Human Deaths = 60
Human Injuries = 887
Animal Deaths = 110157
Animal Injuries = 2039
In [54]:
# All Tornadoes with deaths recorded between 1980 and 2009
c = df
c = c[c['human_deaths'] > 0].sort_values('human_deaths', ascending=False)
c
Out[54]:
year month day hhmm community province ef start_lat_n start_lon_w end_lat_n ... length motion_deg width_max human_deaths human_injuries animal_deaths animal_injuries house_damage date hour
460 1987 7 31 1503 Edmonton #1 AB 4 53.364000 -113.377000 53.639679 ... 30800 185 1300 27 300 0 0 260000.0 1987-07-31 15
1299 2000 7 14 1900 Pine Lake AB 3 52.087500 -113.597900 52.055000 ... 27300 280 1600 12 130 0 0 12000.0 2000-07-14 19
319 1985 5 31 1700 Barrie ON 4 44.339000 -79.738000 44.400000 ... 15000 240 600 8 155 0 0 150000.0 1985-05-31 17
314 1985 5 31 1615 Grand Valley to Tottenham ON 4 43.837000 -80.589000 44.133000 ... 115000 250 600 4 69 0 0 2500.0 1985-05-31 16
1799 2009 7 9 2035 Near Ear Falls / Lac Seul #1 ON 2 50.439900 -93.153000 50.539800 ... 22900 240 100 3 5 0 0 0.0 2009-07-09 20
269 1984 6 29 1753 Big Coulee AB 3 54.881500 -113.281500 0.000000 ... 0 0 0 1 1 0 0 0.0 1984-06-29 17
282 1984 7 15 1620 Sheenboro to Bouchette QC 3 45.971062 -77.232548 46.203250 ... 102000 255 80 1 40 0 0 2000.0 1984-07-15 16
678 1990 8 12 2100 Norwich Township ON 2 42.990000 -80.600000 0.000000 ... 0 0 0 1 2 0 0 0.0 1990-08-12 21
983 1995 7 15 315 Bridgenorth ON 2 44.390000 -78.384000 44.389000 ... 400 285 0 1 0 0 0 2600.0 1995-07-15 3
1656 2006 8 5 1719 Patricia Beach MB 2 50.421000 -96.646000 50.425000 ... 18900 265 300 1 7 0 0 0.0 2006-08-05 17
1811 2009 8 20 1600 Durham ON 2 44.077300 -80.934400 44.427500 ... 48000 215 400 1 0 0 0 0.0 2009-08-20 16

11 rows × 21 columns

In [55]:
c[c['province'] == 'AB'].sort_values('human_deaths', ascending=False)
Out[55]:
year month day hhmm community province ef start_lat_n start_lon_w end_lat_n ... length motion_deg width_max human_deaths human_injuries animal_deaths animal_injuries house_damage date hour
460 1987 7 31 1503 Edmonton #1 AB 4 53.3640 -113.3770 53.639679 ... 30800 185 1300 27 300 0 0 260000.0 1987-07-31 15
1299 2000 7 14 1900 Pine Lake AB 3 52.0875 -113.5979 52.055000 ... 27300 280 1600 12 130 0 0 12000.0 2000-07-14 19
269 1984 6 29 1753 Big Coulee AB 3 54.8815 -113.2815 0.000000 ... 0 0 0 1 1 0 0 0.0 1984-06-29 17

3 rows × 21 columns

In [73]:
# The worst tornadoes for death, injuries
c.loc[c['human_deaths'] > 0, ['date', 'community', 'province', 'human_deaths', 'ef']]
Out[73]:
date community province human_deaths ef
460 1987-07-31 Edmonton #1 AB 27 4
1299 2000-07-14 Pine Lake AB 12 3
319 1985-05-31 Barrie ON 8 4
314 1985-05-31 Grand Valley to Tottenham ON 4 4
1799 2009-07-09 Near Ear Falls / Lac Seul #1 ON 3 2
269 1984-06-29 Big Coulee AB 1 3
282 1984-07-15 Sheenboro to Bouchette QC 1 3
678 1990-08-12 Norwich Township ON 1 2
983 1995-07-15 Bridgenorth ON 1 2
1656 2006-08-05 Patricia Beach MB 1 2
1811 2009-08-20 Durham ON 1 2
In [78]:
# graph it
c.loc[c['human_deaths'] > 0, ['community','human_deaths']].set_index('community').plot(kind='barh')
Out[78]:
<matplotlib.axes._subplots.AxesSubplot at 0x7f2de95c2cc0>

The big Edmonton tornado of 1987

I found the following video on youtube that is like a documentary on this historic event.

In [58]:
IFrame('https://www.youtube.com/embed/L-98xXnyWbQ', width=960, height=530)
Out[58]:

Map of all tornadoes that caused human death from 1980 - 2009

Click on the marker for details

In [59]:
coords_death = locations(c.start_lat_n, c.start_lon_w, c.community, c.province, c.ef, c.year, c.human_deaths)
tornado_map(coords_death, 'deaths')
IFrame('deaths.html', width=960, height=530)
Out[59]:
In [60]:
# Total of all deaths from 1980 to 2009
c['human_deaths'].sum()
Out[60]:
60

Look at injuries suffered from tornadoes from 1980 to 2009

In [61]:
# Total number of injuries suffered from 1980 to 2009
i = df
i['human_injuries'].sum()
Out[61]:
887
In [62]:
# Average number of people injured per year in Canada from 1980 to 2009
round(i['human_injuries'].sum() / len(i.year.unique()), 1)
Out[62]:
29.6
In [63]:
# The most injuries suffered in one year
i['human_injuries'].max()
Out[63]:
300
In [64]:
# Some years saw no injuries recorded
i['human_injuries'].min()
Out[64]:
0
In [65]:
# the top injury days in the last 30 years
# All Tornadoes with deaths recorded between 1980 and 2009
ij = i[i['human_injuries'] > 0].sort_values('human_injuries', ascending=False)
ij
Out[65]:
year month day hhmm community province ef start_lat_n start_lon_w end_lat_n ... length motion_deg width_max human_deaths human_injuries animal_deaths animal_injuries house_damage date hour
460 1987 7 31 1503 Edmonton #1 AB 4 53.364000 -113.377000 53.639679 ... 30800 185 1300 27 300 0 0 260000.0 1987-07-31 15
319 1985 5 31 1700 Barrie ON 4 44.339000 -79.738000 44.400000 ... 15000 240 600 8 155 0 0 150000.0 1985-05-31 17
1299 2000 7 14 1900 Pine Lake AB 3 52.087500 -113.597900 52.055000 ... 27300 280 1600 12 130 0 0 12000.0 2000-07-14 19
314 1985 5 31 1615 Grand Valley to Tottenham ON 4 43.837000 -80.589000 44.133000 ... 115000 250 600 4 69 0 0 2500.0 1985-05-31 16
282 1984 7 15 1620 Sheenboro to Bouchette QC 3 45.971062 -77.232548 46.203250 ... 102000 255 80 1 40 0 0 2000.0 1984-07-15 16
293 1984 9 2 1920 London ON 2 42.945000 -81.249000 42.929000 ... 3630 300 120 0 33 0 0 5000.0 1984-09-02 19
1657 2006 8 5 1815 McArthur Falls MB 2 50.400000 -96.000000 50.365000 ... 58700 275 500 0 19 0 0 0.0 2006-08-05 18
755 1991 8 27 0 Maskinongé QC 3 46.226616 -73.016550 0.000000 ... 1500 0 150 0 15 0 0 17000.0 1991-08-27
167 1983 5 2 1300 Reeces Corners ON 4 42.905000 -82.238000 43.041000 ... 30000 240 400 0 13 10000 0 20000.0 1983-05-02 13
182 1983 7 1 1200 Dolbeau-Mistanssini QC 2 48.815192 -72.313609 0.000000 ... 0 0 0 0 10 0 0 300.0 1983-07-01 12
208 1983 10 28 1200 Saint-Polycarpe QC 2 45.288944 -74.266077 0.000000 ... 0 0 0 0 7 0 0 1000.0 1983-10-28 12
1656 2006 8 5 1719 Patricia Beach MB 2 50.421000 -96.646000 50.425000 ... 18900 265 300 1 7 0 0 0.0 2006-08-05 17
1773 2008 8 26 1240 Spruce Home SK 1 53.400000 -105.960000 0.000000 ... 0 0 0 0 6 0 0 0.0 2008-08-26 12
1002 1996 4 20 1750 Williamsford ON 3 44.356000 -80.915000 44.527500 ... 37000 230 450 0 6 3 7 1500.0 1996-04-20 17
1405 2002 7 28 1000 Halfway Lake Prov. Park ON 2 46.892770 -81.687440 46.914747 ... 5400 240 1120 0 6 0 0 0.0 2002-07-28 10
685 1990 8 28 1630 Frome to Port Stanley ON 3 42.770000 -81.310000 42.660000 ... 13000 340 0 0 5 0 19 20000.0 1990-08-28 16
1799 2009 7 9 2035 Near Ear Falls / Lac Seul #1 ON 2 50.439900 -93.153000 50.539800 ... 22900 240 100 3 5 0 0 0.0 2009-07-09 20
277 1984 7 8 1605 St. Claude to Haywood MB 3 49.670000 -98.350000 49.628155 ... 12100 295 0 0 5 0 0 0.0 1984-07-08 16
945 1994 8 4 1500 Aylmer QC 2 45.404000 -75.843600 45.409600 ... 2000 250 100 0 5 0 0 8000.0 1994-08-04 15
1606 2005 11 9 1645 Hamilton to Stoney Creek ON 1 43.207500 -79.886000 43.236000 ... 16000 260 350 0 4 0 0 1000.0 2005-11-09 16
289 1984 8 14 1940 Downsview ON 1 43.745000 -79.517000 43.717000 ... 3980 35 150 0 4 0 0 2000.0 1984-08-14 19
1601 2005 8 19 1330 Salem to Lake Belwood ON 2 43.679010 -80.511620 43.755260 ... 19200 245 300 0 3 2 0 0.0 2005-08-19 13
1600 2005 8 19 1240 Milverton to Conestogo Lake ON 2 43.623000 -80.906000 43.691000 ... 17100 245 300 0 3 0 0 0.0 2005-08-19 12
326 1985 6 18 0 St-Sylvère QC 3 46.233218 -72.224165 0.000000 ... 0 0 0 0 3 0 0 1000.0 1985-06-18
596 1989 7 28 1915 Lumsden Beach SK 2 50.734000 -105.016000 50.764000 ... 0 0 0 0 3 0 0 0.0 1989-07-28 19
1003 1996 4 20 1810 Arthur to Violet Hill ON 3 43.816500 -80.587500 44.127000 ... 63000 230 500 0 3 3 3 6500.0 1996-04-20 18
311 1985 5 25 1700 Ste. Genevieve MB 1 49.740000 -96.520000 0.000000 ... 0 0 0 0 3 0 0 0.0 1985-05-25 17
932 1994 7 10 1905 Birtle MB 4 50.361000 -101.037000 50.396000 ... 29200 260 0 0 2 0 0 0.0 1994-07-10 19
678 1990 8 12 2100 Norwich Township ON 2 42.990000 -80.600000 0.000000 ... 0 0 0 1 2 0 0 0.0 1990-08-12 21
872 1993 7 29 1940 Holden AB 2 53.235000 -112.230000 53.347370 ... 17000 225 250 0 2 0 0 0.0 1993-07-29 19
658 1990 7 6 1610 25 km S of Youngstown AB 0 51.320000 -111.220000 0.000000 ... 0 0 0 0 2 0 0 0.0 1990-07-06 16
490 1988 5 15 2100 Shelburne ON 1 43.988000 -80.334000 44.129000 ... 32000 250 500 0 1 1 0 500.0 1988-05-15 21
166 1983 5 2 1300 Walpole Island ON 2 42.542000 -82.615000 42.608739 ... 15000 240 0 0 1 0 0 1000.0 1983-05-02 13
269 1984 6 29 1753 Big Coulee AB 3 54.881500 -113.281500 0.000000 ... 0 0 0 1 1 0 0 0.0 1984-06-29 17
283 1984 7 21 1245 Herronton AB 0 50.630000 -113.420000 0.000000 ... 0 0 0 0 1 0 0 0.0 1984-07-21 12
1640 2006 8 2 1930 Marsden Lake ON 1 45.230000 -78.525000 45.232000 ... 6200 270 200 0 1 0 0 0.0 2006-08-02 19
351 1985 0 0 0 Dalemead AB 0 50.870000 -113.630000 0.000000 ... 0 0 0 0 1 0 0 0.0 NaT
369 1986 6 16 1430 Brady Lake to Maynooth ON 2 45.042826 -78.877949 45.230637 ... 76700 240 0 0 1 0 0 4000.0 1986-06-16 14
432 1987 6 6 120 Arcola SK 1 49.630000 -102.480000 0.000000 ... 0 0 0 0 1 0 0 0.0 1987-06-06 1
1391 2002 6 23 1715 Fallowfield ON 2 45.265500 -75.829500 45.258500 ... 1000 315 500 0 1 0 0 1000.0 2002-06-23 17
981 1995 7 15 230 Kennisis Lake ON 1 45.224000 -78.700000 45.218000 ... 8700 275 700 0 1 0 0 2000.0 1995-07-15 2
1369 2001 7 31 635 Morson ON 1 49.097500 -94.325500 0.000000 ... 0 0 0 0 1 0 0 8.0 2001-07-31 6
1303 2000 7 17 2012 Guelph ON 2 43.541500 -80.236500 43.466500 ... 13000 315 600 0 1 0 0 2000.0 2000-07-17 20
584 1989 7 8 1710 Odessa to Peebles SK 2 50.252514 -103.783879 50.170000 ... 60000 280 0 0 1 0 0 0.0 1989-07-08 17
1130 1998 6 2 1600 Fergus ON 0 43.700000 -80.370000 0.000000 ... 0 0 0 0 1 0 0 18.0 1998-06-02 16
1024 1996 6 27 1420 High River AB 1 50.580000 -113.870000 0.000000 ... 0 0 0 0 1 0 0 0.0 1996-06-27 14
111 1982 6 30 2100 Dovercourt AB 3 52.250000 -114.850000 0.000000 ... 0 0 0 0 1 0 0 500.0 1982-06-30 21
17 1980 8 8 1615 Le Petit-Aigle QC 2 46.240263 -76.303648 0.000000 ... 0 0 0 0 1 0 0 0.0 1980-08-08 16

48 rows × 21 columns

In [66]:
# Number of tornadoes that recorded human injuries
len(ij)
Out[66]:
48
In [67]:
# The worst tornadoes for injuries
ij.loc[ij['human_injuries'] > 0, ['date', 'community', 'province', 'human_injuries']]
Out[67]:
date community province human_injuries
460 1987-07-31 Edmonton #1 AB 300
319 1985-05-31 Barrie ON 155
1299 2000-07-14 Pine Lake AB 130
314 1985-05-31 Grand Valley to Tottenham ON 69
282 1984-07-15 Sheenboro to Bouchette QC 40
293 1984-09-02 London ON 33
1657 2006-08-05 McArthur Falls MB 19
755 1991-08-27 Maskinongé QC 15
167 1983-05-02 Reeces Corners ON 13
182 1983-07-01 Dolbeau-Mistanssini QC 10
208 1983-10-28 Saint-Polycarpe QC 7
1656 2006-08-05 Patricia Beach MB 7
1773 2008-08-26 Spruce Home SK 6
1002 1996-04-20 Williamsford ON 6
1405 2002-07-28 Halfway Lake Prov. Park ON 6
685 1990-08-28 Frome to Port Stanley ON 5
1799 2009-07-09 Near Ear Falls / Lac Seul #1 ON 5
277 1984-07-08 St. Claude to Haywood MB 5
945 1994-08-04 Aylmer QC 5
1606 2005-11-09 Hamilton to Stoney Creek ON 4
289 1984-08-14 Downsview ON 4
1601 2005-08-19 Salem to Lake Belwood ON 3
1600 2005-08-19 Milverton to Conestogo Lake ON 3
326 1985-06-18 St-Sylvère QC 3
596 1989-07-28 Lumsden Beach SK 3
1003 1996-04-20 Arthur to Violet Hill ON 3
311 1985-05-25 Ste. Genevieve MB 3
932 1994-07-10 Birtle MB 2
678 1990-08-12 Norwich Township ON 2
872 1993-07-29 Holden AB 2
658 1990-07-06 25 km S of Youngstown AB 2
490 1988-05-15 Shelburne ON 1
166 1983-05-02 Walpole Island ON 1
269 1984-06-29 Big Coulee AB 1
283 1984-07-21 Herronton AB 1
1640 2006-08-02 Marsden Lake ON 1
351 NaT Dalemead AB 1
369 1986-06-16 Brady Lake to Maynooth ON 1
432 1987-06-06 Arcola SK 1
1391 2002-06-23 Fallowfield ON 1
981 1995-07-15 Kennisis Lake ON 1
1369 2001-07-31 Morson ON 1
1303 2000-07-17 Guelph ON 1
584 1989-07-08 Odessa to Peebles SK 1
1130 1998-06-02 Fergus ON 1
1024 1996-06-27 High River AB 1
111 1982-06-30 Dovercourt AB 1
17 1980-08-08 Le Petit-Aigle QC 1
In [68]:
# Cities that have suffered the most injuries due to tornadoes
ij.loc[ij['human_injuries'] > 0, ['community',
                    'human_injuries', 'human_deaths']].set_index('community').head(10).plot(kind='barh')
Out[68]:
<matplotlib.axes._subplots.AxesSubplot at 0x7f2de98c8c88>

Animal Deaths and Injuries

A F1 tornado ripped through Paris, Ontario back on May 20, 1996 that caused significant animal deaths. Google searches point to the tornado ripping through barns in the area but further searches came up empty. Apparently many residents took video of the tornado as it passed the area but I could not find any posted.

The record does not show any human deaths and injuries for that particular tornado but the financial fallout to farmers would can be extensive.

Paris, Ontario, May 20, 1996

"Residents film F1 tornado as it leaves trail of damage through north end of town

An excerpt from that day

This tornado was caught on video as it tracked for 1.5km on the north side of Paris at about 7:00pm. Several barns were torn apart, trees were snapped and uprooted and houses damaged. On one property, a number of antique cars were battered by debris and destroyed, and damage there was estimated at $500,000."

Reece's Corners, Ontario May 2, 1983

Reece's Corners hardest hit by devastating storm

In [69]:
# All Tornadoes with deaths recorded between 1980 and 2009
a = df
a = a[a['animal_deaths'] > 0].sort_values('animal_deaths', ascending=False)
a.head(1)
Out[69]:
year month day hhmm community province ef start_lat_n start_lon_w end_lat_n ... length motion_deg width_max human_deaths human_injuries animal_deaths animal_injuries house_damage date hour
1010 1996 5 20 1900 Paris ON 1 43.24 -80.43 0.0 ... 0 0 0 0 0 100000 2000 50.0 1996-05-20 19

1 rows × 21 columns

In [72]:
a.loc[a['animal_deaths'] > 0, ['community', 'province', 'date', 'hour',
                    'animal_deaths', 'house_damage', 'ef' ]].set_index('community').head(10)#.plot(kind='barh')
Out[72]:
province date hour animal_deaths house_damage ef
community
Paris ON 1996-05-20 19 100000 50.0 1
Reeces Corners ON 1983-05-02 13 10000 20000.0 4
Appin ON 2000-05-23 19 100 1000.0 1
Goodlands MB 2005-06-01 16 12 0.0 1
LaSalle ON 1980-07-16 9 10 500.0 1
Toutes Aides MB 1991-08-28 7 6 0.0 0
South Easthope ON 2005-08-19 15 4 50.0 1
Williamsford ON 1996-04-20 17 3 1500.0 3
Arthur to Violet Hill ON 1996-04-20 18 3 6500.0 3
Carp ON 1994-08-04 15 3 2000.0 2
In [71]:
a.loc[a['animal_injuries'] > 0, ['community', 'province', 'date',
                    'animal_injuries' ]].set_index('community')
Out[71]:
province date animal_injuries
community
Paris ON 1996-05-20 2000
Williamsford ON 1996-04-20 7
Arthur to Violet Hill ON 1996-04-20 3
Carp ON 1994-08-04 3
In [ ]:
 
In [ ]:
 
In [ ]:
 
In [ ]:
 
In [ ]:
 
In [ ]:
 
In [ ]:
 
In [ ]:
 
In [ ]:
 
In [ ]:
 
In [ ]:
 
In [ ]:
 
In [ ]:
 
In [ ]:
 
In [ ]: