CAOS Workshop Series: Introduction to Python Programming

Chris McCray - 21 February 2018

Basic Python syntax (from https://www.stavros.io/tutorials/python/)

  • Python has no mandatory statement termination characters (i.e. semicolons)
  • Single-line comments start with a #
  • Variable values are assigned using =
  • Python automatically sets the data type (i.e. int, float, str)
  • Basic data structures: lists, tuples, dictionaries (index of the first item is 0)

Python allows for a great deal of freedom, but does have a style guide (PEP 8) to make your code generally cleaner and more user-friendly: https://www.python.org/dev/peps/pep-0008/

Many good intro to Python resources can be found online (check them out for more detail than we can go through here) - e.g., Python tutorial: https://docs.python.org/3/tutorial/

Python code can be run in scripts, with an IDE (see Spyder), in Jupyter notebooks like this one

Jupyter Notebook:

  • Allows code to be run in blocks/"cells"
  • Allows for easy presentation of figures and code
  • Can be hosted remotely (i.e. on a server, closer to your data)

Variables, data types, and printing

Variable types are automatically assigned - no type declarations needed

Variable names

  • Can start with lowercase or uppercase letters (but not numbers or symbols!)
  • Can contain numbers and certain symbols
  • Words should be separated by underscores

Printing

  • In Python 3, printing output requires parentheses: print(variable_name)
  • In Python 2, parentheses are not required (but can be included): print variable_name
In [1]:
#Integers
my_integer = 3
print(type(my_integer))

#Floats
my_float = 1.23
print(type(my_float))

#Strings
string_1 = 'This is a string.'
string_2 = "This is also a string!"
print(type(string_1))
<class 'int'>
<class 'float'>
<class 'str'>
In [2]:
print(my_integer)
print('Test')
print('Test',my_integer)
3
Test
Test 3
In [3]:
print(string_1+my_integer)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-3-3085dcc10b55> in <module>()
----> 1 print(string_1+my_integer)

TypeError: must be str, not int
In [ ]:
print(string_1+' '+str(my_integer))
In [4]:
print(string_1, my_integer)
This is a string. 3

Lists and dictionaries

Lists
In [5]:
list_one = ['a','b','c','d','e','f']
print(list_one[0])
print(list_one[-1])
a
f

image.png

Dictionaries
In [6]:
ages = {'Jim': 23, 
        'Sarah': 25,
        'Tom': 30}


print(ages['Jim'])
23

Control Flow Tools/Loops

While loop
In [7]:
b = 10
while b <= 20:
    print (b)
    b+=1
10
11
12
13
14
15
16
17
18
19
20
If statements
In [9]:
x = int(input("Please enter an integer:"))
if x < 0:
    print(x,'is less than 0.')
elif x == 0:
    print(x,'is 0.')
else:
    print(x,'is greater than 0.')
Please enter an integer:11
11 is greater than 0.
For loop
In [10]:
words = ['cat', 'horse', 'chicken']
for w in words:
    print(w, len(w))
cat 3
horse 5
chicken 7

Modules and functions

  • Python source files (ending in .py) are known as modules
  • Modules contain functions, which can be called separated from the module
  • Below is an example of what's inside the module welcome.py (modified from https://developers.google.com/edu/python/introduction)
  • Try running welcome.py by typing python hello.py and your name, in your command line
#!/usr/bin/env python

# import modules used here -- sys is a very standard one
import sys

# Gather our code in a main() function
def main():
    print('Hello there', sys.argv[1])
    # Command line args are in sys.argv[1], sys.argv[2] ...
    # sys.argv[0] is the script name itself and can be ignored

def string_information(string):
    num_characters = len(string)
    num_no_whitespace = (len(string.replace(" ", "")))
    print('This string has',num_characters,'characters including \\
    whitespace and',num_no_whitespace,'without whitespace.')

# Standard boilerplate to call the main() function to begin
# the program.
if __name__ == '__main__':
    main()

Functions can be imported into other modules: (welcome.py can be downloaded at https://github.com/mccrayc/tutorials/blob/master/1_intro/welcome.py)

In [ ]:
from welcome import string_information
In [ ]:
string = 'This Is a Test'
string_information(string)

Basic Math

In [13]:
print( 3.1 + 3.6 )
print( 3.1/392   )
print( 3.1*3.2   )
print( 4**2  )
6.7
0.007908163265306122
9.920000000000002
16
In [14]:
import math
from math import cos
print( cos(2*math.pi) )
print( math.sqrt(4) )
1.0
2.0

Warning: In Python 2, integer division is "floor division"

  • 5/6 = 0
  • 6/5 = 1

NumPy

From http://www.numpy.org/

NumPy is the fundamental package for scientific computing with Python. It contains among other things

  • a powerful N-dimensional array object
  • sophisticated (broadcasting) functions
  • tools for integrating C/C++ and Fortran code
  • useful linear algebra, Fourier transform, and random number capabilities "
In [15]:
import numpy as np
In [16]:
a = np.array([[1,2,3,4],[5,6,7,8]])
print(a)
[[1 2 3 4]
 [5 6 7 8]]
In [17]:
#Subtract 3 from each array element
print( a-3 )
# Get the cosine of each array element
print( np.cos(a) )
# Calculate e^x for each array element x
print (np.exp(a))
# Transpose a
print( a.T )
[[-2 -1  0  1]
 [ 2  3  4  5]]
[[ 0.54030231 -0.41614684 -0.9899925  -0.65364362]
 [ 0.28366219  0.96017029  0.75390225 -0.14550003]]
[[  2.71828183e+00   7.38905610e+00   2.00855369e+01   5.45981500e+01]
 [  1.48413159e+02   4.03428793e+02   1.09663316e+03   2.98095799e+03]]
[[1 5]
 [2 6]
 [3 7]
 [4 8]]

NumPy is a very important part of scientific Python, and forms an integral part of nearly all other scientific packages. You should look through https://docs.scipy.org/doc/numpy-dev/user/quickstart.html to get some background in how it works.

Plotting with matplotlib

The most common plotting library with Python is currently matplotlib, which provides a MATLAB-style interface

  • There are many ways to create figures and subplots with matplotlib, but here we'll just go over a basic example using the pyplot interface.
  • Pyplot provides MATLAB-like functionality
In [18]:
import matplotlib.pyplot as plt
In [19]:
'''
This allows for an interactive figure interface within the jupyter notebook. 
If you just want to show the figure without interactivity, use %matplotlib inline
'''
%matplotlib notebook
In [20]:
x = np.arange(0,100,0.01)
y1 = np.cos(x)
y2 = np.sin(x)
In [21]:
plt.plot(x,y1, label='cos(x)')
plt.plot(x,y2, label='sin(x)')
plt.axhline(y=0, color='k')
Out[21]:
<matplotlib.lines.Line2D at 0x7f8bcc028f60>
In [22]:
#Zoom in on the plot
plt.xlim([0,10])
Out[22]:
(0, 10)
In [ ]:
#Add labels to the axes
plt.xlabel("x")
plt.ylabel("y")
#Add a title
plt.title("$sin(x)$ and $cos(x)$")
#Add a grid
plt.grid()
In [23]:
#Plot a basic legend
plt.legend()
Out[23]:
<matplotlib.legend.Legend at 0x7f8bc0e6d518>
In [24]:
plt.close()

Exercise: Working with real data (CSV format) in Pandas

  • There are many ways to read CSV data. Python's standard library includes the "csv" package
  • "Pandas" (https://pandas.pydata.org/) is one of the key packages in scientific Python and data science
  • Pandas makes reading CSVs easy, handles missing data well, and allows for quick calculations and plotting
In [25]:
import pandas as pd

We'll read in a CSV file that contains daily weather data for each day in 2017 from Environment and Climate Change Canada for CYUL (Montreal-Trudeau Airport)

In [26]:
cyul_2017 = pd.read_csv('http://www.cdmccray.com/python_tutorial/eng-daily-01012017-12312017.csv')
In [27]:
cyul_2017
Out[27]:
Date Year Month Day Data Quality Tmax Max Temp Flag Tmin Min Temp Flag Tmean ... Snow Total Snow Flag Precip Total Precip Flag Snow on Grnd (cm) Snow on Grnd Flag Dir of Max Gust (10s deg) Dir of Max Gust Flag Max_gust Spd of Max Gust Flag
0 2017-01-01 2017 1 1 -2.4 NaN -8.7 NaN -5.6 ... 2.8 NaN 2.4 NaN 12.0 NaN 28.0 NaN 54 NaN
1 2017-01-02 2017 1 2 1.8 NaN -10.2 NaN -4.2 ... 0.0 NaN 0.0 NaN 6.0 NaN NaN NaN <31 NaN
2 2017-01-03 2017 1 3 0.5 NaN -5.8 NaN -2.7 ... 3.6 NaN 17.4 NaN 6.0 NaN 5.0 NaN 43 NaN
3 2017-01-04 2017 1 4 2.5 NaN -5.6 NaN -1.6 ... 9.0 NaN 8.0 NaN 12.0 NaN 24.0 NaN 85 NaN
4 2017-01-05 2017 1 5 -5.3 NaN -10.7 NaN -8.0 ... 0.0 T 0.0 T 13.0 NaN 24.0 NaN 76 NaN
5 2017-01-06 2017 1 6 -7.7 NaN -16.4 NaN -12.1 ... 0.0 T 0.0 T 13.0 NaN 10.0 NaN 41 NaN
6 2017-01-07 2017 1 7 -9.6 NaN -18.9 NaN -14.3 ... 0.0 NaN 0.0 NaN 13.0 NaN NaN NaN <31 NaN
7 2017-01-08 2017 1 8 -10.9 NaN -20.3 NaN -15.6 ... 0.0 NaN 0.0 NaN 12.0 NaN 30.0 NaN 37 NaN
8 2017-01-09 2017 1 9 -7.0 NaN -21.9 NaN -14.5 ... 0.4 NaN 0.4 NaN 11.0 NaN 15.0 NaN 41 NaN
9 2017-01-10 2017 1 10 1.3 NaN -8.3 NaN -3.5 ... 1.0 NaN 2.2 NaN 11.0 NaN 15.0 NaN 63 NaN
10 2017-01-11 2017 1 11 5.7 NaN 1.2 NaN 3.5 ... 0.0 NaN 3.0 NaN 10.0 NaN 22.0 NaN 93 NaN
11 2017-01-12 2017 1 12 5.0 NaN -0.9 NaN 2.1 ... 0.0 NaN 10.0 NaN 4.0 NaN 26.0 NaN 57 NaN
12 2017-01-13 2017 1 13 -0.4 NaN -14.9 NaN -7.7 ... 0.0 T 0.4 NaN 2.0 NaN 28.0 NaN 70 NaN
13 2017-01-14 2017 1 14 -7.1 NaN -17.2 NaN -12.2 ... 0.0 T 0.0 T 1.0 NaN 18.0 NaN 33 NaN
14 2017-01-15 2017 1 15 -7.4 NaN -11.3 NaN -9.4 ... 0.0 T 0.0 T 1.0 NaN NaN NaN <31 NaN
15 2017-01-16 2017 1 16 2.7 NaN -9.0 NaN -3.2 ... 0.0 NaN 0.0 NaN 1.0 NaN 23.0 NaN 59 NaN
16 2017-01-17 2017 1 17 -0.4 NaN -5.3 NaN -2.9 ... 1.4 NaN 1.4 NaN 1.0 NaN 4.0 NaN 44 NaN
17 2017-01-18 2017 1 18 -1.3 NaN -5.3 NaN -3.3 ... 6.8 NaN 7.0 NaN 3.0 NaN 4.0 NaN 37 NaN
18 2017-01-19 2017 1 19 2.0 NaN -1.3 NaN 0.4 ... 0.0 NaN 0.0 T 4.0 NaN 26.0 NaN 33 NaN
19 2017-01-20 2017 1 20 2.2 NaN 0.2 NaN 1.2 ... 0.0 NaN 0.0 NaN 3.0 NaN NaN NaN <31 NaN
20 2017-01-21 2017 1 21 2.1 NaN 0.3 NaN 1.2 ... 0.0 NaN 0.6 NaN 2.0 NaN NaN NaN <31 NaN
21 2017-01-22 2017 1 22 2.1 NaN -2.6 NaN -0.3 ... 0.0 T 0.0 T 1.0 NaN 4.0 NaN 54 NaN
22 2017-01-23 2017 1 23 -0.1 NaN -3.8 NaN -2.0 ... 0.0 NaN 0.0 T 0.0 T 5.0 NaN 50 NaN
23 2017-01-24 2017 1 24 -2.3 NaN -3.8 NaN -3.1 ... 7.0 NaN 12.4 NaN 0.0 T 3.0 NaN 65 NaN
24 2017-01-25 2017 1 25 0.3 NaN -2.4 NaN -1.1 ... 3.2 NaN 2.6 NaN 4.0 NaN 24.0 NaN 39 NaN
25 2017-01-26 2017 1 26 1.4 NaN 0.1 NaN 0.8 ... 2.2 NaN 1.6 NaN 5.0 NaN 25.0 NaN 46 NaN
26 2017-01-27 2017 1 27 0.8 NaN -3.1 NaN -1.2 ... 3.6 NaN 2.6 NaN 4.0 NaN 25.0 NaN 63 NaN
27 2017-01-28 2017 1 28 0.2 NaN -3.0 NaN -1.4 ... 0.2 NaN 0.2 NaN 5.0 NaN 26.0 NaN 46 NaN
28 2017-01-29 2017 1 29 -0.3 NaN -6.5 NaN -3.4 ... 1.0 NaN 1.0 NaN 5.0 NaN 22.0 NaN 37 NaN
29 2017-01-30 2017 1 30 -6.4 NaN -13.7 NaN -10.1 ... 0.0 T 0.0 T 5.0 NaN 23.0 NaN 35 NaN
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
335 2017-12-02 2017 12 2 3.2 NaN -0.9 NaN 1.2 ... 0.0 NaN 0.0 NaN NaN NaN 10.0 NaN 17 NaN
336 2017-12-03 2017 12 3 2.3 NaN -1.7 NaN 0.3 ... 0.0 NaN 0.0 NaN NaN NaN 5.0 NaN 26 NaN
337 2017-12-04 2017 12 4 5.9 NaN -3.0 NaN 1.5 ... 0.0 NaN 0.0 T NaN NaN 15.0 NaN 57 NaN
338 2017-12-05 2017 12 5 10.0 NaN 5.6 NaN 7.8 ... 0.0 NaN 9.8 NaN NaN NaN 26.0 NaN 59 NaN
339 2017-12-06 2017 12 6 5.7 NaN -0.3 NaN 2.7 ... 0.0 T 0.0 T NaN NaN 22.0 NaN 65 NaN
340 2017-12-07 2017 12 7 1.4 NaN -1.7 NaN -0.2 ... 0.2 NaN 0.2 NaN 0.0 T 23.0 NaN 41 NaN
341 2017-12-08 2017 12 8 1.0 NaN -2.9 NaN -1.0 ... 0.0 T 0.0 T 0.0 T 20.0 NaN 54 NaN
342 2017-12-09 2017 12 9 0.5 NaN -4.5 NaN -2.0 ... 0.0 T 0.0 T NaN NaN 22.0 NaN 44 NaN
343 2017-12-10 2017 12 10 -1.4 NaN -5.1 NaN -3.3 ... 1.8 NaN 1.6 NaN 0.0 T 27.0 NaN 48 NaN
344 2017-12-11 2017 12 11 -3.8 NaN -12.7 NaN -8.3 ... 0.8 NaN 0.4 NaN 2.0 NaN 2.0 NaN 33 NaN
345 2017-12-12 2017 12 12 -6.8 NaN -10.7 NaN -8.8 ... 18.6 NaN 17.2 NaN 4.0 NaN 3.0 NaN 48 NaN
346 2017-12-13 2017 12 13 -7.2 NaN -16.3 NaN -11.8 ... 2.4 NaN 1.6 NaN 9.0 NaN 27.0 NaN 61 NaN
347 2017-12-14 2017 12 14 -14.5 NaN -19.0 NaN -16.8 ... 0.0 NaN 0.0 NaN 4.0 NaN 24.0 NaN 50 NaN
348 2017-12-15 2017 12 15 -9.4 NaN -20.1 NaN -14.8 ... 0.4 NaN 0.4 NaN 3.0 NaN NaN NaN <31 NaN
349 2017-12-16 2017 12 16 -8.0 NaN -15.0 NaN -11.5 ... 1.8 NaN 1.8 NaN 5.0 NaN 27.0 NaN 32 NaN
350 2017-12-17 2017 12 17 -12.4 NaN -21.0 NaN -16.7 ... 0.2 NaN 0.2 NaN 5.0 NaN NaN NaN <31 NaN
351 2017-12-18 2017 12 18 -10.1 NaN -14.1 NaN -12.1 ... 4.8 NaN 4.4 NaN 5.0 NaN NaN NaN <31 NaN
352 2017-12-19 2017 12 19 3.3 NaN -10.2 NaN -3.5 ... 4.4 NaN 7.1 NaN 9.0 NaN 25.0 NaN 61 NaN
353 2017-12-20 2017 12 20 1.0 NaN -12.2 NaN -5.6 ... 0.0 NaN 0.0 T 8.0 NaN 29.0 NaN 63 NaN
354 2017-12-21 2017 12 21 -10.5 NaN -16.2 NaN -13.4 ... 0.0 NaN 0.0 NaN 6.0 NaN NaN NaN <31 NaN
355 2017-12-22 2017 12 22 -11.6 NaN -15.2 NaN -13.4 ... 1.4 NaN 1.2 NaN 5.0 NaN 4.0 NaN 43 NaN
356 2017-12-23 2017 12 23 -5.2 NaN -12.0 NaN -8.6 ... 9.4 NaN 14.4 NaN 5.0 NaN 24.0 NaN 41 NaN
357 2017-12-24 2017 12 24 -5.5 NaN -9.7 NaN -7.6 ... 0.0 T 0.0 T 12.0 NaN 4.0 NaN 43 NaN
358 2017-12-25 2017 12 25 -6.4 NaN -10.1 NaN -8.3 ... 13.4 NaN 12.6 NaN 18.0 NaN 26.0 NaN 52 NaN
359 2017-12-26 2017 12 26 -7.0 NaN -18.9 NaN -13.0 ... 0.0 T 0.0 T 19.0 NaN 27.0 NaN 54 NaN
360 2017-12-27 2017 12 27 -18.3 NaN -24.5 NaN -21.4 ... 0.0 NaN 0.0 NaN 11.0 NaN 27.0 NaN 37 NaN
361 2017-12-28 2017 12 28 -20.5 NaN -26.6 NaN -23.6 ... 0.0 NaN 0.0 NaN 10.0 NaN 27.0 NaN 44 NaN
362 2017-12-29 2017 12 29 -18.4 NaN -24.8 NaN -21.6 ... 1.6 NaN 1.6 NaN 10.0 NaN 26.0 NaN 30 NaN
363 2017-12-30 2017 12 30 -17.4 NaN -24.9 NaN -21.2 ... 0.2 NaN 0.2 NaN 10.0 NaN NaN NaN <31 NaN
364 2017-12-31 2017 12 31 -18.9 NaN -23.8 NaN -21.4 ... 0.0 T 0.0 T 10.0 NaN 27.0 NaN 37 NaN

365 rows × 27 columns

In [28]:
#Set the index of the Pandas DataFrame to Date
cyul_2017.set_index('Date', inplace=True)
In [29]:
cyul_2017
Out[29]:
Year Month Day Data Quality Tmax Max Temp Flag Tmin Min Temp Flag Tmean Mean Temp Flag ... Snow Total Snow Flag Precip Total Precip Flag Snow on Grnd (cm) Snow on Grnd Flag Dir of Max Gust (10s deg) Dir of Max Gust Flag Max_gust Spd of Max Gust Flag
Date
2017-01-01 2017 1 1 -2.4 NaN -8.7 NaN -5.6 NaN ... 2.8 NaN 2.4 NaN 12.0 NaN 28.0 NaN 54 NaN
2017-01-02 2017 1 2 1.8 NaN -10.2 NaN -4.2 NaN ... 0.0 NaN 0.0 NaN 6.0 NaN NaN NaN <31 NaN
2017-01-03 2017 1 3 0.5 NaN -5.8 NaN -2.7 NaN ... 3.6 NaN 17.4 NaN 6.0 NaN 5.0 NaN 43 NaN
2017-01-04 2017 1 4 2.5 NaN -5.6 NaN -1.6 NaN ... 9.0 NaN 8.0 NaN 12.0 NaN 24.0 NaN 85 NaN
2017-01-05 2017 1 5 -5.3 NaN -10.7 NaN -8.0 NaN ... 0.0 T 0.0 T 13.0 NaN 24.0 NaN 76 NaN
2017-01-06 2017 1 6 -7.7 NaN -16.4 NaN -12.1 NaN ... 0.0 T 0.0 T 13.0 NaN 10.0 NaN 41 NaN
2017-01-07 2017 1 7 -9.6 NaN -18.9 NaN -14.3 NaN ... 0.0 NaN 0.0 NaN 13.0 NaN NaN NaN <31 NaN
2017-01-08 2017 1 8 -10.9 NaN -20.3 NaN -15.6 NaN ... 0.0 NaN 0.0 NaN 12.0 NaN 30.0 NaN 37 NaN
2017-01-09 2017 1 9 -7.0 NaN -21.9 NaN -14.5 NaN ... 0.4 NaN 0.4 NaN 11.0 NaN 15.0 NaN 41 NaN
2017-01-10 2017 1 10 1.3 NaN -8.3 NaN -3.5 NaN ... 1.0 NaN 2.2 NaN 11.0 NaN 15.0 NaN 63 NaN
2017-01-11 2017 1 11 5.7 NaN 1.2 NaN 3.5 NaN ... 0.0 NaN 3.0 NaN 10.0 NaN 22.0 NaN 93 NaN
2017-01-12 2017 1 12 5.0 NaN -0.9 NaN 2.1 NaN ... 0.0 NaN 10.0 NaN 4.0 NaN 26.0 NaN 57 NaN
2017-01-13 2017 1 13 -0.4 NaN -14.9 NaN -7.7 NaN ... 0.0 T 0.4 NaN 2.0 NaN 28.0 NaN 70 NaN
2017-01-14 2017 1 14 -7.1 NaN -17.2 NaN -12.2 NaN ... 0.0 T 0.0 T 1.0 NaN 18.0 NaN 33 NaN
2017-01-15 2017 1 15 -7.4 NaN -11.3 NaN -9.4 NaN ... 0.0 T 0.0 T 1.0 NaN NaN NaN <31 NaN
2017-01-16 2017 1 16 2.7 NaN -9.0 NaN -3.2 NaN ... 0.0 NaN 0.0 NaN 1.0 NaN 23.0 NaN 59 NaN
2017-01-17 2017 1 17 -0.4 NaN -5.3 NaN -2.9 NaN ... 1.4 NaN 1.4 NaN 1.0 NaN 4.0 NaN 44 NaN
2017-01-18 2017 1 18 -1.3 NaN -5.3 NaN -3.3 NaN ... 6.8 NaN 7.0 NaN 3.0 NaN 4.0 NaN 37 NaN
2017-01-19 2017 1 19 2.0 NaN -1.3 NaN 0.4 NaN ... 0.0 NaN 0.0 T 4.0 NaN 26.0 NaN 33 NaN
2017-01-20 2017 1 20 2.2 NaN 0.2 NaN 1.2 NaN ... 0.0 NaN 0.0 NaN 3.0 NaN NaN NaN <31 NaN
2017-01-21 2017 1 21 2.1 NaN 0.3 NaN 1.2 NaN ... 0.0 NaN 0.6 NaN 2.0 NaN NaN NaN <31 NaN
2017-01-22 2017 1 22 2.1 NaN -2.6 NaN -0.3 NaN ... 0.0 T 0.0 T 1.0 NaN 4.0 NaN 54 NaN
2017-01-23 2017 1 23 -0.1 NaN -3.8 NaN -2.0 NaN ... 0.0 NaN 0.0 T 0.0 T 5.0 NaN 50 NaN
2017-01-24 2017 1 24 -2.3 NaN -3.8 NaN -3.1 NaN ... 7.0 NaN 12.4 NaN 0.0 T 3.0 NaN 65 NaN
2017-01-25 2017 1 25 0.3 NaN -2.4 NaN -1.1 NaN ... 3.2 NaN 2.6 NaN 4.0 NaN 24.0 NaN 39 NaN
2017-01-26 2017 1 26 1.4 NaN 0.1 NaN 0.8 NaN ... 2.2 NaN 1.6 NaN 5.0 NaN 25.0 NaN 46 NaN
2017-01-27 2017 1 27 0.8 NaN -3.1 NaN -1.2 NaN ... 3.6 NaN 2.6 NaN 4.0 NaN 25.0 NaN 63 NaN
2017-01-28 2017 1 28 0.2 NaN -3.0 NaN -1.4 NaN ... 0.2 NaN 0.2 NaN 5.0 NaN 26.0 NaN 46 NaN
2017-01-29 2017 1 29 -0.3 NaN -6.5 NaN -3.4 NaN ... 1.0 NaN 1.0 NaN 5.0 NaN 22.0 NaN 37 NaN
2017-01-30 2017 1 30 -6.4 NaN -13.7 NaN -10.1 NaN ... 0.0 T 0.0 T 5.0 NaN 23.0 NaN 35 NaN
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
2017-12-02 2017 12 2 3.2 NaN -0.9 NaN 1.2 NaN ... 0.0 NaN 0.0 NaN NaN NaN 10.0 NaN 17 NaN
2017-12-03 2017 12 3 2.3 NaN -1.7 NaN 0.3 NaN ... 0.0 NaN 0.0 NaN NaN NaN 5.0 NaN 26 NaN
2017-12-04 2017 12 4 5.9 NaN -3.0 NaN 1.5 NaN ... 0.0 NaN 0.0 T NaN NaN 15.0 NaN 57 NaN
2017-12-05 2017 12 5 10.0 NaN 5.6 NaN 7.8 NaN ... 0.0 NaN 9.8 NaN NaN NaN 26.0 NaN 59 NaN
2017-12-06 2017 12 6 5.7 NaN -0.3 NaN 2.7 NaN ... 0.0 T 0.0 T NaN NaN 22.0 NaN 65 NaN
2017-12-07 2017 12 7 1.4 NaN -1.7 NaN -0.2 NaN ... 0.2 NaN 0.2 NaN 0.0 T 23.0 NaN 41 NaN
2017-12-08 2017 12 8 1.0 NaN -2.9 NaN -1.0 NaN ... 0.0 T 0.0 T 0.0 T 20.0 NaN 54 NaN
2017-12-09 2017 12 9 0.5 NaN -4.5 NaN -2.0 NaN ... 0.0 T 0.0 T NaN NaN 22.0 NaN 44 NaN
2017-12-10 2017 12 10 -1.4 NaN -5.1 NaN -3.3 NaN ... 1.8 NaN 1.6 NaN 0.0 T 27.0 NaN 48 NaN
2017-12-11 2017 12 11 -3.8 NaN -12.7 NaN -8.3 NaN ... 0.8 NaN 0.4 NaN 2.0 NaN 2.0 NaN 33 NaN
2017-12-12 2017 12 12 -6.8 NaN -10.7 NaN -8.8 NaN ... 18.6 NaN 17.2 NaN 4.0 NaN 3.0 NaN 48 NaN
2017-12-13 2017 12 13 -7.2 NaN -16.3 NaN -11.8 NaN ... 2.4 NaN 1.6 NaN 9.0 NaN 27.0 NaN 61 NaN
2017-12-14 2017 12 14 -14.5 NaN -19.0 NaN -16.8 NaN ... 0.0 NaN 0.0 NaN 4.0 NaN 24.0 NaN 50 NaN
2017-12-15 2017 12 15 -9.4 NaN -20.1 NaN -14.8 NaN ... 0.4 NaN 0.4 NaN 3.0 NaN NaN NaN <31 NaN
2017-12-16 2017 12 16 -8.0 NaN -15.0 NaN -11.5 NaN ... 1.8 NaN 1.8 NaN 5.0 NaN 27.0 NaN 32 NaN
2017-12-17 2017 12 17 -12.4 NaN -21.0 NaN -16.7 NaN ... 0.2 NaN 0.2 NaN 5.0 NaN NaN NaN <31 NaN
2017-12-18 2017 12 18 -10.1 NaN -14.1 NaN -12.1 NaN ... 4.8 NaN 4.4 NaN 5.0 NaN NaN NaN <31 NaN
2017-12-19 2017 12 19 3.3 NaN -10.2 NaN -3.5 NaN ... 4.4 NaN 7.1 NaN 9.0 NaN 25.0 NaN 61 NaN
2017-12-20 2017 12 20 1.0 NaN -12.2 NaN -5.6 NaN ... 0.0 NaN 0.0 T 8.0 NaN 29.0 NaN 63 NaN
2017-12-21 2017 12 21 -10.5 NaN -16.2 NaN -13.4 NaN ... 0.0 NaN 0.0 NaN 6.0 NaN NaN NaN <31 NaN
2017-12-22 2017 12 22 -11.6 NaN -15.2 NaN -13.4 NaN ... 1.4 NaN 1.2 NaN 5.0 NaN 4.0 NaN 43 NaN
2017-12-23 2017 12 23 -5.2 NaN -12.0 NaN -8.6 NaN ... 9.4 NaN 14.4 NaN 5.0 NaN 24.0 NaN 41 NaN
2017-12-24 2017 12 24 -5.5 NaN -9.7 NaN -7.6 NaN ... 0.0 T 0.0 T 12.0 NaN 4.0 NaN 43 NaN
2017-12-25 2017 12 25 -6.4 NaN -10.1 NaN -8.3 NaN ... 13.4 NaN 12.6 NaN 18.0 NaN 26.0 NaN 52 NaN
2017-12-26 2017 12 26 -7.0 NaN -18.9 NaN -13.0 NaN ... 0.0 T 0.0 T 19.0 NaN 27.0 NaN 54 NaN
2017-12-27 2017 12 27 -18.3 NaN -24.5 NaN -21.4 NaN ... 0.0 NaN 0.0 NaN 11.0 NaN 27.0 NaN 37 NaN
2017-12-28 2017 12 28 -20.5 NaN -26.6 NaN -23.6 NaN ... 0.0 NaN 0.0 NaN 10.0 NaN 27.0 NaN 44 NaN
2017-12-29 2017 12 29 -18.4 NaN -24.8 NaN -21.6 NaN ... 1.6 NaN 1.6 NaN 10.0 NaN 26.0 NaN 30 NaN
2017-12-30 2017 12 30 -17.4 NaN -24.9 NaN -21.2 NaN ... 0.2 NaN 0.2 NaN 10.0 NaN NaN NaN <31 NaN
2017-12-31 2017 12 31 -18.9 NaN -23.8 NaN -21.4 NaN ... 0.0 T 0.0 T 10.0 NaN 27.0 NaN 37 NaN

365 rows × 26 columns

In [30]:
cyul_2017.loc['2017-05-29']
Out[30]:
Year                         2017
Month                           5
Day                            29
Data Quality                    ‡
Tmax                         19.6
Max Temp Flag                 NaN
Tmin                         12.7
Min Temp Flag                 NaN
Tmean                        16.2
Mean Temp Flag                NaN
Heat Deg Days (°C)            1.8
Heat Deg Days Flag            NaN
Cool Deg Days (°C)              0
Cool Deg Days Flag            NaN
Rain                            8
Total Rain Flag               NaN
Snow                            0
Total Snow Flag               NaN
Precip                          8
Total Precip Flag             NaN
Snow on Grnd (cm)             NaN
Snow on Grnd Flag             NaN
Dir of Max Gust (10s deg)      14
Dir of Max Gust Flag          NaN
Max_gust                       52
Spd of Max Gust Flag          NaN
Name: 2017-05-29, dtype: object

Let's see what the warmest and coldest temperatures of 2017 were:

In [31]:
cyul_2017['Tmax'].nlargest(5)
Out[31]:
Date
2017-06-18    32.1
2017-09-25    31.5
2017-06-12    31.4
2017-09-27    31.2
2017-09-24    30.6
Name: Tmax, dtype: float64
In [32]:
cyul_2017['Tmin'].nsmallest(5)
Out[32]:
Date
2017-12-28   -26.6
2017-12-30   -24.9
2017-12-29   -24.8
2017-12-27   -24.5
2017-12-31   -23.8
Name: Tmin, dtype: float64

Now, let's try plotting some of this data

First, we'll grab the individual columns we want for our x and y data

In [33]:
max_temps = cyul_2017['Tmax']
In [34]:
max_temps
Out[34]:
Date
2017-01-01    -2.4
2017-01-02     1.8
2017-01-03     0.5
2017-01-04     2.5
2017-01-05    -5.3
2017-01-06    -7.7
2017-01-07    -9.6
2017-01-08   -10.9
2017-01-09    -7.0
2017-01-10     1.3
2017-01-11     5.7
2017-01-12     5.0
2017-01-13    -0.4
2017-01-14    -7.1
2017-01-15    -7.4
2017-01-16     2.7
2017-01-17    -0.4
2017-01-18    -1.3
2017-01-19     2.0
2017-01-20     2.2
2017-01-21     2.1
2017-01-22     2.1
2017-01-23    -0.1
2017-01-24    -2.3
2017-01-25     0.3
2017-01-26     1.4
2017-01-27     0.8
2017-01-28     0.2
2017-01-29    -0.3
2017-01-30    -6.4
              ... 
2017-12-02     3.2
2017-12-03     2.3
2017-12-04     5.9
2017-12-05    10.0
2017-12-06     5.7
2017-12-07     1.4
2017-12-08     1.0
2017-12-09     0.5
2017-12-10    -1.4
2017-12-11    -3.8
2017-12-12    -6.8
2017-12-13    -7.2
2017-12-14   -14.5
2017-12-15    -9.4
2017-12-16    -8.0
2017-12-17   -12.4
2017-12-18   -10.1
2017-12-19     3.3
2017-12-20     1.0
2017-12-21   -10.5
2017-12-22   -11.6
2017-12-23    -5.2
2017-12-24    -5.5
2017-12-25    -6.4
2017-12-26    -7.0
2017-12-27   -18.3
2017-12-28   -20.5
2017-12-29   -18.4
2017-12-30   -17.4
2017-12-31   -18.9
Name: Tmax, Length: 365, dtype: float64
In [35]:
plt.figure(figsize=[7,4])
plt.plot(max_temps)
Out[35]:
[<matplotlib.lines.Line2D at 0x7f8bace53630>]

Pandas has many convenience functions that allow us to quickly plot our data in a much prettier way!

In [36]:
plt.close()
plt.figure()
cyul_2017['Tmax'].plot(color='red', figsize=[8,5])
cyul_2017['Tmin'].plot(color='blue')
Out[36]:
<matplotlib.axes._subplots.AxesSubplot at 0x7f8baca98eb8>

Let's add a 30-day rolling average to the plot so that we smooth out the variations

In [38]:
cyul_2017['Tmean'].rolling(30,min_periods=2,center=True).mean().plot(c='k', label='30-day avg. Tmean')

plt.grid()

Now, add a title, axis labels, and legend

In [39]:
plt.title('Montreal Daily Temperatures - 2017')
plt.ylabel('Temperature (deg C)')
plt.legend()
Out[39]:
<matplotlib.legend.Legend at 0x7f8baba858d0>

With pandas, you can do quick statistics/calculations as well. This is what makes it really powerful for data analysis

In [40]:
cyul_2017.describe()
Out[40]:
Year Month Day Tmax Tmin Tmean Heat Deg Days (°C) Cool Deg Days (°C) Rain Snow Precip Snow on Grnd (cm) Dir of Max Gust (10s deg)
count 365.0 365.000000 365.000000 362.000000 365.000000 362.000000 362.000000 362.000000 360.000000 361.000000 362.000000 119.000000 336.000000
mean 2017.0 6.526027 15.720548 12.009116 3.234795 7.606354 11.205249 0.811602 2.843611 0.633795 3.459392 6.865546 18.928571
std 0.0 3.452584 8.808321 12.471745 11.354032 11.812289 10.873452 1.749120 6.758139 2.761052 7.166166 7.004749 9.289102
min 2017.0 1.000000 1.000000 -20.500000 -26.600000 -23.600000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000
25% 2017.0 4.000000 8.000000 1.900000 -5.300000 -1.900000 0.225000 0.000000 0.000000 0.000000 0.000000 1.000000 12.000000
50% 2017.0 7.000000 16.000000 14.150000 5.000000 9.300000 8.700000 0.000000 0.000000 0.000000 0.000000 5.000000 22.000000
75% 2017.0 10.000000 23.000000 23.325000 13.200000 17.775000 19.900000 0.000000 1.600000 0.000000 2.800000 10.000000 26.000000
max 2017.0 12.000000 31.000000 32.100000 21.300000 26.700000 41.600000 8.700000 42.400000 31.600000 42.400000 29.000000 36.000000
In [41]:
cyul_2017[cyul_2017.Month==12].describe()
Out[41]:
Year Month Day Tmax Tmin Tmean Heat Deg Days (°C) Cool Deg Days (°C) Rain Snow Precip Snow on Grnd (cm) Dir of Max Gust (10s deg)
count 31.0 31.0 31.000000 31.000000 31.000000 31.000000 31.000000 31.0 31.000000 31.000000 31.000000 24.000000 26.000000
mean 2017.0 12.0 16.000000 -5.612903 -12.064516 -8.858065 26.858065 0.0 0.409677 1.980645 2.409677 7.083333 20.076923
std 0.0 0.0 9.092121 8.416006 8.786526 8.493675 8.493675 0.0 1.808932 4.290876 4.692430 5.012304 9.142967
min 2017.0 12.0 1.000000 -20.500000 -26.600000 -23.600000 10.200000 0.0 0.000000 0.000000 0.000000 0.000000 2.000000
25% 2017.0 12.0 8.500000 -11.050000 -18.950000 -14.100000 19.500000 0.0 0.000000 0.000000 0.000000 4.000000 16.250000
50% 2017.0 12.0 16.000000 -6.400000 -12.200000 -8.600000 26.600000 0.0 0.000000 0.000000 0.200000 5.500000 24.000000
75% 2017.0 12.0 23.500000 1.200000 -3.750000 -1.500000 32.100000 0.0 0.000000 1.700000 1.600000 10.000000 27.000000
max 2017.0 12.0 31.000000 10.000000 5.600000 7.800000 41.600000 0.0 9.800000 18.600000 17.200000 19.000000 29.000000

Try making a plot of one of the other fields in cyul_2017

In [ ]:
plt.close()
#######
  • Xarray - reading, analyzing, editing, creating NetCDF files
  • Cartopy - http://scitools.org.uk/cartopy/
    • Plotting data on maps
    • Note that you'll come across matplotlib basemap - this is no longer developed and Cartopy is currently the successor to basemap