Introduction to and using
Python is a powerful and easy to use programming language. It has a large community of developers and given its open source nature, you can find many solutions, scripts, and help all over the web. It is easy to learn and code, and faster than other high-level programming languages...and did I mention it is free because it is open-source
IPython is a very powerful extension to Python that provides: Powerful interactive shells (terminal, Qt-based and Notebooks based on Jupyter).
- A browser-based notebook with support for code, text, mathematical expressions, inline plots and other rich media.
- Support for interactive data visualization and use of GUI toolkits.
- Flexible, embeddable interpreters to load into your own projects.
- Easy to use, high performance tools for parallel computing.
Jupyter is an open-source project that provides open-standards, and services for interactive computing across dozens of programming languages, including Python
, R
, Stata
and many others used by economists.
Getting Python, IPython, R, and Jupyter¶
You can download and install Python
and its packages for free for your computer from Python.org. While this is the official site, which offers the basic installer and you can try do add any packages you require yourself, a much easier approach, which is almost foolproof is to use Continuum Anaconda or Enthought Canopy. Both of these distributions offer academic licenses (Canopy), which allow you to use a larger set of packages. Similarly, you can download R
from the r-project website.
I personally have switched to using Continuum Anaconda since it make installing all the packages and software I use much easier. You can follow the instructions below or better yet follow the instructions on the Computation Page of my Economic Growth and Comparative Development Course.
Installing (I)Python & Jupyter¶
The easiest and most convenient way to install a working version of IPython with all the required packages and tools is using Continuum's Anaconda Distribution. You can install following the instructions in that website, or if you can just run this script (Mac/Linux). After installing the latest version of Anaconda, add the Anaconda/bin
directory to your PATH
variable.
To create an environment useful for these notebooks, in your terminal execute
conda create --name GeoPython3env -c conda-forge -c r -c mro --override-channels python=3.9 georasters geopandas pandas spatialpandas statsmodels xlrd networkx ipykernel ipyparallel ipython ipython_genutils ipywidgets jupyter jupyterlab kiwisolver matplotlib-base matplotlib scikit-image scikit-learn scipy seaborn geoplot geopy geotiff pycountry nb_conda_kernels stata_kernel nltk
This should create an environment with most of the packages we need. We can always install others down the road.
To start using one of the environment you will need to exectute the following command
source activate GeoPython3env
Note¶
I assume you have followed the steps above and have installed Anaconda
. Everything that is done should work on any distribution that has the required packages, since the Python scripts should run (in principle) on any of these distributions.
We will use IPython as our computing environment.
Let's get started¶
Once you have your Python distribution installed you'll be ready to start working. You have various options:
- Open the
Canopy
program and work there - Open
Anaconda Navigator
and open one of the apps from there (python
,ipython
,jupyter console
,jupyter notebook
,jupyter lab
,R
,Stata
- From the Terminal prompt (command-line in Windows) execute one of the following commands:
ipython
jupyter console
jupyter qtconsole
jupyter notebook
jupyter lab
While theses last are all using IPython, each has its advantages and disadvantages. You should play with them to get a better feeling of which you want to use for which purpose. In my own research I usually use a text editor (TextMate, Atom, Sublime) and the jupyter qtconsole
or the jupyter notebook
. To see the power of Jupter notebooks
(see this excellent and in-depth presentation by its creators). As you will see, this might prove an excellent environment to do research, homework, replicate papers, etc.
Note¶
You can pass some additional commands to ipython
in order to change colors and rendering of plots. I usually use jupyter qtconsole --color=linux --pylab=inline
. You can create profiles to manage many options within IPython
and JuPyter
.
First steps¶
Let's start by running some simple commands at the prompt to do some simple computations.
1+1-2
3*2
3**2
-1**2
3*(3-2)
3*3-2
Notice that Python obeys the usual orders for operators, so exponentiation before multiplication/division, etc.
1/2
If you are in Python 2.7
you will notice that this answer is wrong if $1,2\in\mathbb{R}$, but Python thinks they are integers, so it forces and integer. In order to have a more natural behavior of division we need
from __future__ import division
1/2
Note¶
It is a good idea to include this among the packages to be imported by default
Getting help¶
So what else can we do? Where do we start if we are new? You can use ?
or help()
to get help.
?
help()
If you want information about a command, say mycommand
you can use help(mycommand)
, mycommand?
or mycommand??
to get information about how it is used or even see its code.
help(sum)
sum?
sum??
Variables, strings, and other objects¶
We can print information
print('Hello World!')
We can also create variables, which can be of various types
a = 1
b = 2
a+b
a
and b
now hold numerical values we can use for computing
c = [1, 2]
d = [[1, 2], [3, 4]]
print('c=%s' % c)
print('d=%s' % d)
Notice that we have used %s
and %
to let Python know we are passing a string to the print function.
What kind of variables are c
and d
? They look like vectors and matrices, but...
print(' a * c = %s' % (a * c))
print(' b * d = %s' % (b * d))
c*d
Actually, Python does not have vectors or matrices directly available. Instead it has lists, sets, arrays, etc., each with its own set of operations. We defined c
and d
as list objects
type(c)
type(d)
type(a)
Luckily Python has a powerful package for numerical computing called Numpy.
Extending Python's Functionality with Packages¶
In order to use a package in Python or IPython, say mypackage
, you need to import it, by executing
import mypackage
After executing this command, you will have access to the functions and objects defined in mypackage
. For example, if mypackage
has a function squared
that takes a real number x
and computes its square, we can use this function by calling mypackage.squared(x)
. Since the name of some packages might be too long, your can give them a nickname by importing them instead as
import mypackage as myp
so now we could compute the square of x
by calling myp.squared(x)
.
We will see various packages that will be useful to do computations, statistics, plots, etc.
IPython has a command that imports Numpy and Matplotlib (Python's main plotting package). Numpy is imported as np
and Matplotlib as plt
. One could import these by hand by executing
import numpy as np
import matplotlib as plt
but the creators of IPython have optimized the interaction between these packages by running the following command:
%pylab
%pylab?
I do recommend using the --no-import-all
option in order to ensure you do not contaminate the namespace. Instead it might be best to use
%pylab --no-import-all
%matplotlib
%matplotlib?
%pylab --no-import-all
%matplotlib inline
np?
Let us now recreate c
and d
, but as Numpy arrays instead.
ca = np.array(c)
da = np.array(d)
print('c = %s' % c)
print('d = %s' % d)
print('ca = %s' % ca)
print('da = %s' % da)
We could have created them as matrices intead. Again how you want to cerate them depends on what you will be doing with them. See here for an explanation of the differences between Numpy arrays and matrices.
cm = np.matrix(c)
dm = np.matrix(d)
print('cm = %s' % cm)
print('dm = %s' % dm)
Let's see some information about these...(this is a good moment to show tab completion...a wonderful feature of IPython, which is not avalable if Python)
cm.shape
ca.shape
dm.diagonal()
da.cumsum()
Let's try again some operations on our new arrays and matrices
cm*dm
ca
da
ca*da
ca.dot(da)
We can create special matrices using Numpy's functions and classes
print(np.ones((3,4)))
print(np.zeros((2,2)))
print(np.eye(2))
print(np.ones_like(cm))
np.random.uniform(-1,1,10)
#np.random.seed(123456)
x0 = 0
x = [x0]
[x.append(x[-1] + np.random.normal() ) for i in range(500)]
plt.plot(x)
plt.title('A simple random walk')
plt.xlabel('Period')
plt.ylabel('Log Income')
plt.show()
Extending Capabilities with Functions¶
We have used some of the functions in Python, Numpy and Matplotlib. But what if we wanted to create our own functions? It is very easy to do so in Python. There are two ways to define functions. Let's use them to define the CRRA utility function $u(c)=\frac{c^{1-\sigma}-1}{1-\sigma}$ and the production function $f(k)=Ak^\alpha$.
The first method is as follows:
def u(c, sigma):
'''This function returns the value of utility when the CRRA
coefficient is sigma. I.e.
u(c,sigma)=(c**(1-sigma)-1)/(1-sigma) if sigma!=1
and
u(c,sigma)=ln(c) if sigma==1
Usage: u(c,sigma)
'''
if sigma!=1:
u = (c**(1-sigma) - 1) / (1-sigma)
else:
u = np.log(c)
return u
This defined the utility function. Let's plot it for $0< c\le5$ and $\sigma\in\{0.5,1,1.5\}$
# Create vector
c = np.linspace(0.1, 5, 100)
# Evaluate utilities for different CRRA parameters
u1 = u(c, .5)
u2 = u(c, 1)
u3 = u(c, 1.5)
# Plot
plt.plot(c, u1, label=r'$\sigma=.5$')
plt.plot(c, u2, label=r'$\sigma=1$')
plt.plot(c, u3, label=r'$\sigma=1.5$')
plt.xlabel(r'$c_t$')
plt.ylabel(r'$u(c_t)$')
plt.title('CRRA Utility function')
plt.legend(loc=4)
plt.savefig('./CRRA.jpg', dpi=150)
plt.savefig('./CRRA.pdf', dpi=150)
plt.savefig('./CRRA.png', dpi=150)
plt.show()
While this is nice, it requires us to always have to put a value for the CRRA coefficient. Furthermore, we need to remember if $c$ is the first or second argument. Since we tend to use log-utilities a lot, let us change the definition of the utility function so that it has a default value for $\sigma$ equal to 1
def u(c, sigma=1):
'''This function returns the value of utility when the CRRA
coefficient is sigma. I.e.
u(c,sigma)=(c**(1-sigma)-1)/(1-sigma) if sigma!=1
and
u(c,sigma)=ln(c) if sigma==1
Usage: u(c,sigma=value), where sigma=1 is the default
'''
if sigma!=1:
u = (c**(1-sigma) - 1) / (1-sigma)
else:
u = np.log(c)
return u
sigma1 = .25
sigma3 = 1.25
u1 = u(c, sigma=sigma1)
u2 = u(c)
u3 = u(c, sigma=sigma3)
plt.plot(c, u1, label=r'$\sigma='+str(sigma1)+'$')
plt.plot(c, u2, label=r'$\sigma=1$')
plt.plot(c, u3, label=r'$\sigma='+str(sigma3)+'$')
plt.xlabel(r'$c_t$')
plt.ylabel(r'$u(c_t)$')
plt.title('CRRA Utility function')
plt.legend(loc=4)
plt.show()
Exercise¶
Write the function for the Cobb-Douglas production function. Can you generalize it so that we can use it for aggregate, per capita, and per efficiency units without having to write a function for each?
Remember aggregate production is $$ Y = F(K, AL) = K^\alpha (A L)^{1-\alpha}, $$
per capita is
$$ \hat y=\frac{F(K, AL)}{L} = \frac{K^\alpha (A L)^{1-\alpha}}{L} = Ak^\alpha, $$and per effective worker
$$ y = \frac{F(K, AL)}{AL} = \frac{K^\alpha (A L)^{1-\alpha}}{AL} = k^\alpha, $$where $k=K/AL$.
The second method is to use the lambda
notation, which allows you to define functions in one line or without giving the function a name.
squared = lambda x: x**2
squared(2)
Our first script¶
Let's write a script that prints "Hello World!"
%%file?
%%file helloworld.py
#!/usr/bin/env python
# coding=utf-8
'''
My First script in Python
Author: Me
E-mail: me@me.com
Website: http://me.com
GitHub: https://github.com/me
Date: Today
This code computes Random Walks and graphs them
'''
'''
from __future__ import division
import numpy as np
import matplotlib.pyplot as plt
'''
print('Hello World!')
Let's run that script
%run helloworld.py
Exercise¶
Write a simple script randomwalk.py
that simulates and plots random walks. In particular, create a function randomwalk(x0, T, mu, sigma)
that simulates the random walk starting at $x_0=x0$ until $t=T$ where the shock is distributed $\mathcal{N}(\mu,\sigma^2)$
import randomwalk as rw
rw.randomwalk(0, 500, 0, 1)
from randomwalk import randomwalk
randomwalk??
import time
time.sleep(10)
print("It's time")
Notebook written by Ömer Özak for his Ph.D. students in Economics at Southern Methodist University. Feel free to use, distribute, or contribute.