From 0f8a368a7a2c0850d6aa032edcd75d0209954f11 Mon Sep 17 00:00:00 2001 From: Rahul Dave Date: Wed, 2 Sep 2015 15:48:16 -0400 Subject: [PATCH] made copies of originals --- Lab1-babypython_original.ipynb | 1555 ++++++++++++++++ Lab1-git_original.ipynb | 2012 ++++++++++++++++++++ Lab1-pythonpandas_original.ipynb | 2946 ++++++++++++++++++++++++++++++ 3 files changed, 6513 insertions(+) create mode 100644 Lab1-babypython_original.ipynb create mode 100644 Lab1-git_original.ipynb create mode 100644 Lab1-pythonpandas_original.ipynb diff --git a/Lab1-babypython_original.ipynb b/Lab1-babypython_original.ipynb new file mode 100644 index 0000000..bb4814d --- /dev/null +++ b/Lab1-babypython_original.ipynb @@ -0,0 +1,1555 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Python and Friends\n", + "\n", + "This is a very quick run-through of some python syntax" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# The %... is an iPython thing, and is not part of the Python language.\n", + "# In this case we're just telling the plotting library to draw things on\n", + "# the notebook, instead of on a separate window.\n", + "%matplotlib inline \n", + "#this line above prepares IPython notebook for working with matplotlib\n", + "\n", + "# See all the \"as ...\" contructs? They're just aliasing the package names.\n", + "# That way we can call methods like plt.plot() instead of matplotlib.pyplot.plot().\n", + "\n", + "import numpy as np # imports a fast numerical programming library\n", + "import scipy as sp #imports stats functions, amongst other things\n", + "import matplotlib as mpl # this actually imports matplotlib\n", + "import matplotlib.cm as cm #allows us easy access to colormaps\n", + "import matplotlib.pyplot as plt #sets up plotting under plt\n", + "import pandas as pd #lets us handle data as dataframes\n", + "#sets up pandas table display\n", + "pd.set_option('display.width', 500)\n", + "pd.set_option('display.max_columns', 100)\n", + "pd.set_option('display.notebook_repr_html', True)\n", + "import seaborn as sns #sets up styles and gives us more plotting options" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "##The Python Language\n", + "\n", + "Lets talk about using Python as a calculator..." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "3" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "1+2" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Notice integer division and floating-point error below!" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "(0, 0.5, 9.600000000000001)" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "1/2,1.0/2.0,3*3.2" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Here is how we can print things. Something on the last line by itself is returned as the output value." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "4.0 \n", + "1.66666666667\n" + ] + }, + { + "data": { + "text/plain": [ + "1" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "print 1+3.0,\"\\n\",5/3.0\n", + "5/3" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We can obtain the type of a variable, and use boolean comparisons tontest these types." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0.833333333333\n", + "\n" + ] + } + ], + "source": [ + "a=5.0/6.0\n", + "print(a)\n", + "print type(a)" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "import types\n", + "type(a)==types.FloatType" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "False" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "type(a)==types.IntType" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Python and Iteration (and files)\n", + "\n", + "In working with python I always remember: a python is a duck.\n", + "\n", + "What I mean is, python has a certain way of doing things. For example lets call one of these ways listiness. Listiness works on lists, dictionaries, files, and a general notion of something called an iterator.\n", + "\n", + "But first, lets introduce the notion of a comprehension. Its a way of constructing a list" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[1, 4, 9, 16, 25]" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "alist=[1,2,3,4,5]\n", + "asquaredlist=[i*i for i in alist]\n", + "asquaredlist" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Python has some nifty functions like `enumerate` and `zip`. The former gives a list of tuples with each tuple of the form `(index, value)`, while the latter takes elements from each list and outs them together into a tuple, thus creating a list of tuples. The first is a duck, but the second isnt." + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "(, [(1, 1), (2, 4), (3, 9), (4, 16), (5, 25)])" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "enumerate(asquaredlist),zip(alist, asquaredlist)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Someone realized that design flaw and created izip." + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from itertools import izip\n", + "izip(alist, asquaredlist)" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n" + ] + } + ], + "source": [ + "print enumerate(asquaredlist)" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[(0, 1), (1, 4), (2, 9), (3, 16), (4, 25)]" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "[k for k in enumerate(asquaredlist)]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Open files behave like lists too! Here we get each line in the file and find its length, using the comprehension syntax to put these lengths into a big list." + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[9, 27, 2, 24, 2, 2, 2, 2, 22, 2, 28, 60, 29, 28, 27, 22, 22, 24, 25, 18, 24, 11, 21, 20, 22, 32, 10, 28, 31, 12, 22, 27, 2, 51, 32, 2, 67, 13, 2, 18, 2, 2, 2, 8, 2, 50, 2, 49, 2, 6, 14, 2, 7, 45, 2, 6, 21, 2, 7, 11, 2, 6, 5, 2, 7, 41, 2, 6, 53, 2, 7, 48, 25, 2, 6, 27, 2, 7, 23, 2, 6, 19, 39, 46, 2, 7, 48, 2, 32, 2, 6, 25, 2, 6, 27, 2, 7, 22, 2, 6, 30, 24, 2, 7, 24, 22, 2, 9, 2, 6, 18, 2, 6, 6, 25, 2, 6, 17, 2, 6, 45, 2, 6, 47, 2, 6, 22, 2, 6, 36, 42, 48, 38, 45, 37, 42, 2, 6, 32, 2, 6, 18, 41, 42, 31, 2, 6, 20, 41, 2, 6, 20, 51, 51, 43, 30, 2, 6, 51, 2, 23, 2, 6, 48, 2, 6, 43, 2, 6, 47, 2, 6, 49, 2, 6, 23, 2, 6, 23, 2, 6, 50, 42, 40, 54, 2, 6, 17, 2, 6, 22, 2, 6, 42, 2, 15, 2, 6, 33, 2, 6, 46, 42, 22, 2, 6, 41, 38, 19, 2, 6, 26, 2, 6, 25, 36, 40, 45, 42, 15, 2, 6, 48, 47, 2, 6, 48, 44, 48, 2, 6, 49, 47, 43, 43, 41, 50, 43, 46, 50, 30, 2, 6, 13, 47, 42, 44, 45, 53, 53, 53, 36, 50, 45, 39, 43, 35, 50, 39, 49, 36, 47, 41, 39, 48, 42, 39, 46, 45, 41, 50, 44, 2, 6, 37, 47, 49, 45, 2, 6, 41, 43, 41, 51, 45, 50, 43, 47, 43, 48, 42, 39, 45, 38, 46, 2, 19, 2, 53, 42, 14, 40, 44, 14, 42, 40, 11, 39, 41, 53, 19, 53, 2, 6, 40, 2, 6, 27, 2, 6, 12, 2, 6, 12, 2, 6, 12, 2, 15, 2, 38, 35, 38, 39, 2, 6, 44, 2, 6, 42, 38, 44, 48, 43, 42, 40, 41, 37, 2, 6, 38, 46, 44, 45, 49, 51, 48, 42, 2, 6, 45, 45, 47, 42, 42, 39, 45, 47, 44, 2, 6, 45, 44, 2, 11, 2, 2, 2, 52, 2, 63, 35, 2, 7, 47, 46, 52, 38, 47, 42, 41, 47, 47, 43, 42, 52, 45, 42, 45, 46, 47, 39, 46, 44, 46, 47, 40, 44, 49, 47, 47, 41, 43, 44, 46, 46, 43, 42, 45, 41, 48, 34, 49, 2, 16, 47, 2, 7, 41, 2, 35, 2, 45, 47, 41, 54, 45, 43, 42, 46, 34, 2, 7, 16, 44, 49, 37, 42, 50, 49, 2, 7, 51, 2, 6, 47, 37, 41, 41, 2, 7, 45, 45, 41, 2, 6, 54, 2, 7, 46, 2, 6, 44, 2, 8, 43, 50, 38, 40, 53, 37, 2, 6, 26, 2, 8, 11, 39, 2, 6, 45, 44, 38, 41, 40, 41, 49, 48, 45, 44, 47, 2, 7, 52, 47, 48, 53, 37, 43, 38, 46, 43, 40, 41, 44, 40, 43, 48, 46, 43, 48, 48, 48, 40, 45, 43, 35, 46, 41, 40, 38, 39, 43, 45, 2, 8, 46, 49, 2, 6, 41, 2, 7, 38, 41, 43, 45, 45, 48, 52, 41, 2, 26, 2, 6, 45, 38, 39, 49, 42, 40, 43, 53, 49, 50, 41, 46, 46, 47, 45, 38, 47, 55, 45, 47, 46, 48, 54, 49, 37, 44, 43, 46, 43, 40, 49, 2, 43, 2, 6, 24, 2, 6, 28, 34, 2, 6, 48, 2, 6, 54, 47, 12, 2, 6, 17, 2, 6, 47, 47, 2, 6, 37, 2, 6, 37, 40, 39, 45, 38, 47, 2, 6, 47, 2, 6, 43, 44, 2, 6, 41, 2, 6, 50, 47, 42, 41, 39, 2, 6, 17, 2, 6, 28, 2, 6, 39, 2, 6, 40, 39, 2, 6, 41, 2, 6, 10, 2, 6, 32, 2, 6, 21, 2, 6, 35, 41, 38, 21, 2, 6, 29, 2, 6, 42, 40, 43, 51, 35, 43, 49, 45, 55, 39, 46, 38, 49, 45, 50, 43, 32, 2, 6, 21, 2, 6, 46, 2, 6, 26, 2, 6, 17, 45, 39, 43, 43, 43, 30, 2, 6, 20, 2, 6, 44, 43, 24, 2, 6, 45, 30, 2, 15, 17, 2, 6, 17, 2, 7, 17, 2, 6, 18, 2, 7, 29, 2, 6, 28, 2, 6, 41, 2, 6, 29, 2, 6, 45, 2, 6, 14, 2, 6, 17, 2, 6, 30, 2, 6, 18, 2, 6, 27, 2, 6, 32, 2, 6, 39, 2, 6, 53, 2, 15, 17, 2, 6, 19, 2, 6, 30, 2, 6, 40, 19, 2, 6, 24, 30, 2, 6, 20, 2, 6, 40, 50, 43, 44, 42, 41, 42, 46, 46, 17, 2, 6, 26, 2, 6, 39, 2, 44, 2, 46, 52, 53, 53, 2, 9, 2, 2, 2, 40, 2, 30, 2, 7, 40, 40, 40, 27, 2, 6, 20, 2, 7, 45, 40, 40, 45, 41, 10, 2, 6, 17, 2, 7, 19, 43, 46, 41, 46, 42, 44, 49, 41, 37, 46, 44, 48, 42, 55, 42, 39, 47, 45, 46, 45, 50, 32, 44, 45, 39, 38, 39, 46, 44, 44, 41, 42, 41, 48, 2, 6, 45, 48, 40, 45, 47, 47, 29, 2, 7, 17, 45, 2, 19, 2, 38, 38, 2, 6, 47, 45, 56, 2, 38, 2, 38, 51, 41, 43, 52, 49, 45, 48, 42, 45, 46, 52, 40, 46, 40, 49, 45, 37, 44, 44, 45, 43, 42, 44, 2, 7, 42, 2, 6, 47, 2, 7, 38, 26, 2, 6, 27, 44, 2, 7, 11, 2, 9, 2, 6, 42, 2, 6, 52, 2, 6, 24, 39, 45, 53, 37, 46, 43, 45, 44, 2, 6, 45, 25, 2, 6, 47, 41, 47, 2, 6, 46, 2, 6, 47, 49, 54, 48, 45, 2, 6, 42, 24, 2, 6, 44, 2, 6, 52, 42, 2, 6, 45, 45, 48, 48, 45, 44, 47, 40, 44, 43, 38, 41, 50, 47, 39, 44, 43, 51, 40, 48, 42, 2, 6, 24, 2, 11, 2, 2, 2, 25, 2, 41, 2, 6, 42, 2, 6, 35, 2, 6, 16, 2, 6, 29, 2, 6, 19, 2, 6, 52, 43, 2, 57, 2, 31, 2, 6, 50, 52, 49, 43, 28, 2, 6, 17, 2, 6, 18, 43, 41, 50, 39, 47, 50, 42, 52, 39, 37, 48, 50, 42, 39, 50, 46, 50, 43, 45, 48, 35, 46, 46, 42, 21, 2, 6, 26, 2, 16, 2, 6, 44, 46, 55, 38, 42, 51, 41, 41, 44, 48, 39, 41, 44, 49, 43, 46, 38, 48, 49, 2, 25, 2, 6, 36, 37, 15, 2, 6, 33, 40, 24, 2, 6, 18, 2, 6, 43, 2, 6, 18, 2, 6, 31, 38, 42, 35, 43, 2, 6, 49, 40, 42, 43, 49, 41, 42, 39, 38, 28, 2, 6, 22, 26, 2, 6, 28, 2, 6, 22, 2, 6, 29, 2, 6, 20, 42, 40, 2, 18, 2, 45, 2, 28, 2, 53, 40, 2, 28, 2, 6, 38, 2, 6, 46, 2, 6, 44, 2, 6, 46, 2, 6, 24, 2, 6, 24, 2, 11, 2, 2, 2, 44, 2, 27, 2, 6, 55, 2, 8, 10, 2, 6, 9, 2, 8, 25, 44, 24, 2, 6, 19, 2, 8, 43, 25, 2, 6, 28, 2, 8, 47, 2, 6, 7, 2, 8, 27, 46, 44, 48, 49, 41, 43, 51, 58, 41, 42, 41, 37, 53, 43, 2, 6, 8, 2, 8, 45, 2, 6, 9, 2, 8, 41, 45, 2, 6, 49, 40, 26, 2, 8, 18, 47, 42, 51, 46, 49, 36, 44, 46, 22, 2, 6, 22, 13, 2, 8, 45, 54, 45, 41, 45, 41, 41, 45, 43, 45, 19, 40, 48, 44, 37, 22, 45, 47, 36, 38, 41, 40, 39, 40, 48, 43, 41, 43, 47, 41, 48, 21, 44, 50, 41, 37, 43, 39, 42, 43, 37, 39, 40, 47, 48, 46, 49, 42, 41, 36, 2, 9, 2, 6, 47, 51, 43, 41, 48, 42, 34, 42, 51, 42, 42, 41, 46, 26, 46, 39, 50, 47, 2, 12, 2, 43, 36, 17, 2, 6, 31, 2, 6, 26, 2, 6, 30, 2, 6, 11, 2, 6, 34, 2, 6, 39, 2, 32, 2, 6, 26, 2, 6, 21, 2, 6, 15, 2, 6, 24, 2, 6, 23, 2, 6, 28, 2, 6, 17, 2, 6, 55, 23, 2, 15, 25, 2, 6, 49, 27, 2, 6, 52, 18, 2, 6, 35, 43, 45, 54, 41, 43, 25, 2, 6, 49, 2, 6, 38, 23, 2, 6, 30, 2, 6, 47, 52, 46, 45, 49, 45, 27, 2, 6, 30, 2, 6, 47, 2, 15, 23, 2, 6, 19, 2, 6, 11, 17, 2, 6, 27, 2, 6, 16, 2, 6, 34, 2, 6, 32, 2, 8, 19, 2, 6, 58, 52, 19, 2, 6, 28, 2, 6, 44, 20, 2, 8, 19, 2, 6, 47, 25, 41, 45, 20, 2, 8, 19, 2, 6, 55, 51, 2, 6, 48, 2, 6, 46, 53, 40, 13, 44, 44, 45, 35, 49, 48, 44, 60, 62, 39, 48, 48, 8, 2, 8, 19, 2, 6, 47, 42, 37, 51, 53, 46, 44, 41, 31, 2, 11, 2, 2, 2, 9, 2, 38, 2, 32, 2, 6, 48, 2, 6, 18, 2, 6, 48, 39, 19, 2, 6, 27, 2, 6, 50, 46, 52, 45, 46, 48, 45, 53, 46, 47, 2, 6, 25, 2, 6, 50, 40, 43, 48, 42, 46, 40, 23, 2, 6, 21, 2, 6, 50, 31, 2, 6, 36, 2, 6, 48, 42, 34, 59, 43, 41, 36, 21, 2, 6, 22, 2, 6, 31, 2, 6, 14, 20, 2, 6, 30, 41, 43, 51, 11, 46, 44, 45, 41, 50, 41, 21, 2, 6, 21, 2, 6, 67, 64, 2, 6, 56, 13, 2, 6, 44, 50, 38, 56, 49, 45, 43, 39, 14, 50, 40, 42, 38, 38, 46, 2, 6, 18, 2, 6, 32, 2, 6, 15, 2, 6, 38, 2, 6, 19, 2, 6, 28, 2, 6, 16, 2, 6, 11, 2, 18, 2, 18, 2, 38, 2, 6, 43, 2, 6, 32, 2, 6, 41, 46, 45, 42, 51, 39, 38, 43, 2, 6, 19, 2, 6, 25, 25, 2, 6, 15, 2, 6, 44, 44, 45, 37, 41, 41, 48, 42, 40, 46, 45, 45, 46, 43, 2, 6, 44, 35, 40, 47, 36, 46, 50, 2, 6, 44, 36, 19, 2, 6, 25, 47, 51, 51, 34, 42, 38, 46, 57, 45, 2, 11, 2, 2, 2, 33, 2, 58, 2, 7, 45, 44, 41, 45, 43, 43, 43, 54, 44, 39, 51, 51, 48, 40, 45, 41, 50, 39, 2, 8, 45, 44, 48, 41, 40, 40, 43, 31, 2, 6, 21, 47, 44, 19, 2, 7, 15, 47, 41, 18, 2, 7, 46, 2, 8, 46, 38, 44, 44, 2, 7, 45, 30, 2, 8, 11, 2, 58, 2, 19, 2, 6, 44, 24, 2, 7, 47, 2, 6, 45, 36, 41, 45, 39, 43, 36, 2, 7, 43, 2, 6, 43, 49, 2, 7, 46, 2, 18, 2, 44, 50, 2, 8, 40, 48, 2, 7, 26, 2, 49, 2, 27, 47, 2, 7, 44, 41, 44, 41, 41, 50, 42, 47, 43, 44, 39, 49, 40, 48, 46, 42, 41, 18, 45, 45, 41, 26, 2, 7, 19, 45, 39, 50, 49, 20, 2, 35, 2, 6, 32, 38, 39, 51, 49, 46, 51, 42, 44, 43, 18, 2, 8, 29, 2, 6, 37, 49, 44, 41, 44, 44, 42, 43, 42, 10, 48, 39, 46, 10, 60, 13, 61, 35, 10, 44, 2, 8, 31, 2, 6, 46, 10, 35, 36, 30, 30, 63, 67, 12, 67, 15, 49, 39, 48, 24, 2, 7, 18, 20, 2, 6, 26, 2, 7, 38, 2, 6, 50, 46, 42, 47, 44, 41, 45, 45, 49, 43, 46, 50, 47, 41, 47, 44, 40, 44, 49, 40, 22, 2, 7, 25, 2, 8, 25, 2, 6, 52, 40, 27, 2, 7, 18, 2, 6, 44, 36, 39, 47, 20, 2, 7, 28, 2, 6, 48, 20, 2, 8, 20, 2, 6, 47, 36, 41, 43, 37, 30, 2, 7, 17, 2, 8, 53, 2, 6, 35, 46, 2, 39, 2, 26, 2, 31, 2, 6, 20, 2, 6, 26, 2, 6, 38, 2, 6, 17, 2, 6, 40, 2, 6, 18, 2, 6, 61, 29, 2, 6, 28, 2, 6, 65, 32, 2, 6, 18, 2, 6, 64, 52, 2, 6, 67, 64, 65, 65, 16, 2, 6, 22, 2, 6, 30, 2, 6, 14, 2, 6, 44, 2, 6, 63, 61, 61, 65, 67, 62, 64, 2, 6, 64, 40, 2, 6, 16, 2, 6, 65, 64, 64, 67, 67, 18, 2, 6, 57, 67, 7, 2, 6, 25, 2, 6, 26, 2, 39, 2, 6, 46, 2, 6, 35, 2, 18, 2, 7, 19, 2, 6, 20, 2, 6, 61, 41, 2, 6, 43, 2, 7, 38, 46, 2, 6, 28, 2, 6, 19, 2, 6, 56, 10, 2, 7, 25, 2, 6, 56, 28, 2, 6, 51, 2, 6, 58, 62, 64, 9, 2, 7, 18, 2, 6, 21, 2, 6, 24, 2, 6, 60, 43, 2, 6, 27, 2, 6, 62, 56, 2, 6, 65, 7, 2, 6, 61, 61, 2, 7, 63, 48, 2, 6, 33, 2, 6, 64, 30, 2, 6, 64, 64, 23, 2, 17, 22, 2, 6, 57, 62, 65, 23, 2, 6, 43, 2, 6, 62, 66, 58, 64, 2, 7, 30, 2, 6, 59, 67, 65, 20, 2, 6, 23, 2, 6, 63, 59, 64, 66, 38, 2, 6, 34, 2, 6, 65, 10, 2, 7, 28, 2, 6, 60, 60, 66, 64, 64, 67, 66, 64, 65, 60, 62, 64, 67, 66, 53, 2, 6, 50, 2, 6, 60, 2, 6, 59, 65, 62, 2, 6, 61, 67, 65, 63, 63, 63, 7, 2, 6, 56, 25, 2, 6, 54, 46, 2, 6, 57, 13, 2, 6, 61, 29, 2, 6, 27, 2, 6, 35, 2, 6, 62, 66, 65, 67, 65, 27, 2, 6, 58, 63, 57, 67, 66, 31, 2, 6, 64, 62, 66, 32, 2, 6, 16, 2, 7, 50, 2, 6, 28, 2, 6, 55, 2, 6, 62, 65, 67, 67, 31, 2, 32, 2, 7, 24, 2, 6, 63, 64, 63, 60, 64, 31, 2, 7, 24, 2, 6, 61, 29, 2, 19, 2, 6, 30, 2, 6, 67, 66, 2, 6, 64, 23, 2, 6, 67, 53, 2, 6, 35, 2, 6, 64, 9, 2, 6, 38, 2, 6, 13, 2, 6, 19, 2, 6, 36, 2, 6, 59, 59, 66, 64, 67, 15, 2, 6, 58, 2, 6, 32, 2, 6, 7, 37, 38, 2, 2, 6, 32, 2, 6, 38, 2, 6, 60, 20, 2, 6, 24, 2, 6, 30, 2, 6, 7, 26, 21, 45, 65, 28, 2, 31, 2, 64, 62, 60, 61, 63, 62, 67, 60, 64, 51, 2, 9, 23, 2, 6, 63, 65, 66, 67, 67, 64, 64, 61, 62, 67, 67, 64, 61, 2, 49, 2, 43, 2, 46, 49, 48, 53, 44, 44, 53, 50, 45, 54, 44, 51, 32, 2, 18, 2, 6, 60, 13, 2, 9, 23, 53, 48, 43, 51, 50, 53, 48, 49, 52, 42, 51, 44, 48, 17, 45, 52, 49, 48, 52, 44, 44, 47, 51, 26, 52, 43, 53, 53, 29, 2, 6, 19, 2, 6, 64, 65, 12, 2, 9, 49, 2, 6, 21, 2, 6, 38, 2, 9, 53, 46, 49, 45, 49, 53, 59, 49, 46, 51, 50, 49, 54, 29, 2, 6, 64, 27, 2, 6, 62, 62, 67, 65, 51, 2, 6, 53, 2, 6, 53, 64, 65, 28, 2, 6, 13, 2, 6, 51, 2, 55, 2, 60, 11, 2, 9, 14, 2, 6, 60, 66, 29, 2, 9, 14, 2, 6, 58, 2, 22, 2, 61, 37, 2, 6, 15, 2, 40, 2, 6, 24, 17, 41, 44, 42, 44, 45, 45, 48, 49, 13, 40, 48, 43, 50, 48, 42, 43, 38, 8, 40, 45, 41, 40, 42, 46, 46, 55, 48, 46, 40, 40, 43, 49, 56, 15, 44, 44, 44, 48, 38, 13, 49, 43, 39, 43, 42, 50, 53, 45, 44, 47, 47, 44, 46, 41, 43, 41, 48, 48, 2, 9, 2, 2, 2, 2, 10, 2, 32, 2, 57, 16, 2, 7, 43, 45, 42, 38, 2, 6, 46, 48, 2, 7, 43, 41, 47, 20, 2, 8, 26, 2, 6, 24, 2, 7, 43, 2, 6, 43, 25, 2, 8, 19, 17, 2, 6, 44, 50, 41, 42, 42, 32, 2, 6, 17, 47, 29, 2, 7, 48, 28, 42, 45, 2, 6, 20, 2, 40, 2, 7, 31, 45, 42, 18, 43, 48, 42, 38, 42, 27, 2, 8, 21, 39, 44, 52, 41, 23, 2, 6, 23, 2, 15, 2, 6, 51, 61, 42, 50, 52, 35, 20, 2, 7, 28, 55, 51, 45, 42, 17, 2, 6, 45, 2, 29, 2, 17, 2, 6, 47, 43, 45, 44, 49, 39, 48, 45, 45, 53, 50, 45, 41, 38, 50, 51, 46, 41, 43, 40, 51, 40, 48, 44, 42, 45, 41, 46, 39, 49, 43, 45, 45, 42, 28, 2, 6, 15, 43, 2, 6, 39, 2, 6, 39, 40, 31, 2, 6, 12, 25, 2, 6, 48, 49, 51, 41, 47, 17, 2, 6, 25, 2, 6, 10, 2, 6, 15, 2, 6, 27, 2, 6, 62, 27, 2, 6, 64, 2, 6, 58, 65, 66, 55, 2, 6, 42, 2, 6, 55, 64, 6, 2, 6, 26, 2, 6, 57, 65, 67, 66, 63, 67, 66, 60, 9, 2, 6, 19, 2, 6, 59, 39, 2, 6, 33, 2, 6, 65, 66, 64, 63, 63, 11, 2, 6, 33, 2, 6, 59, 67, 66, 67, 63, 66, 29, 2, 9, 2, 6, 42, 59, 44, 45, 52, 43, 42, 47, 50, 48, 37, 48, 2, 31, 2, 7, 44, 52, 53, 42, 43, 44, 31, 51, 42, 42, 36, 45, 48, 47, 2, 6, 40, 42, 48, 45, 46, 41, 44, 47, 47, 47, 43, 31, 2, 7, 17, 46, 2, 11, 2, 2, 2, 33, 2, 37, 2, 6, 58, 64, 65, 60, 62, 52, 65, 67, 67, 65, 67, 52, 2, 11, 24, 2, 6, 62, 66, 63, 66, 63, 64, 64, 66, 60, 62, 65, 65, 59, 64, 60, 64, 25, 2, 11, 58, 2, 6, 62, 63, 63, 64, 65, 64, 17, 2, 19, 2, 50, 2, 58, 2, 6, 40, 2, 6, 29, 2, 18, 2, 35, 2, 16, 19, 2, 25, 2, 6, 20, 2, 18, 2, 6, 36, 2, 6, 38, 39, 2, 6, 20, 2, 6, 30, 44, 45, 60, 46, 43, 50, 48, 44, 50, 49, 42, 52, 49, 47, 49, 50, 47, 46, 43, 46, 47, 47, 40, 43, 39, 41, 33, 44, 41, 45, 28, 2, 6, 16, 52, 44, 2, 6, 46, 18, 2, 66, 41, 2, 7, 30, 2, 6, 62, 45, 2, 7, 62, 7, 2, 6, 67, 21, 2, 6, 54, 2, 6, 21, 2, 6, 64, 12, 2, 6, 65, 20, 2, 6, 44, 2, 8, 41, 2, 6, 48, 2, 6, 41, 2, 6, 32, 33, 2, 6, 14, 2, 6, 32, 2, 6, 14, 2, 6, 39, 2, 6, 27, 2, 6, 51, 2, 6, 19, 2, 6, 10, 2, 6, 25, 2, 6, 9, 2, 6, 14, 2, 6, 60, 65, 22, 2, 6, 38, 2, 6, 62, 66, 66, 67, 62, 57, 2, 41, 2, 62, 60, 59, 57, 63, 66, 66, 61, 64, 67, 43, 2, 11, 2, 6, 27, 2, 6, 53, 2, 6, 52, 2, 19, 2, 6, 64, 19, 2, 6, 39, 2, 6, 61, 50, 2, 6, 53, 2, 6, 33, 36, 35, 2, 6, 44, 2, 6, 22, 2, 6, 18, 2, 29, 2, 10, 49, 47, 44, 50, 49, 39, 2, 11, 39, 44, 42, 47, 46, 43, 43, 36, 49, 41, 52, 56, 2, 10, 50, 48, 48, 42, 27, 2, 11, 23, 47, 38, 47, 2, 6, 30, 2, 11, 41, 48, 38, 39, 2, 10, 44, 40, 37, 38, 51, 40, 36, 45, 42, 44, 37, 46, 48, 47, 49, 54, 43, 50, 51, 45, 41, 46, 43, 33, 38, 40, 40, 52, 43, 51, 2, 11, 46, 46, 40, 42, 43, 46, 47, 35, 2, 6, 43, 2, 10, 49, 48, 29, 11, 2, 11, 23, 44, 2, 9, 2, 6, 32, 2, 8, 39, 2, 6, 30, 2, 7, 56, 2, 6, 61, 8, 2, 7, 28, 2, 6, 58, 63, 65, 61, 66, 14, 2, 19, 2, 43, 2, 6, 33, 2, 6, 61, 23, 2, 6, 38, 2, 6, 51, 2, 6, 26, 2, 6, 62, 64, 22, 2, 6, 58, 46, 49, 52, 37, 38, 2, 45, 2, 6, 64, 62, 66, 2, 6, 17, 2, 6, 33, 2, 8, 20, 2, 6, 21, 2, 7, 28, 2, 6, 25, 2, 38, 2, 6, 40, 30, 48, 32, 66, 62, 60, 2, 6, 15, 2, 6, 22, 38, 32, 41, 28, 2, 6, 24, 2, 6, 59, 24, 2, 6, 21, 2, 6, 35, 2, 6, 27, 2, 6, 51, 41, 45, 19, 2, 39, 2, 7, 45, 2, 6, 23, 2, 7, 17, 2, 6, 23, 2, 7, 48, 2, 6, 18, 2, 7, 34, 2, 6, 63, 62, 34, 2, 7, 61, 31, 2, 6, 29, 2, 7, 61, 22, 2, 6, 18, 2, 7, 61, 65, 62, 34, 2, 6, 16, 2, 7, 16, 2, 6, 64, 65, 65, 8, 2, 6, 57, 27, 2, 6, 65, 50, 2, 6, 64, 2, 6, 60, 24, 2, 6, 32, 2, 6, 51, 2, 6, 64, 63, 14, 2, 6, 26, 2, 6, 62, 33, 2, 6, 64, 8, 2, 41, 2, 67, 66, 14, 2, 7, 63, 2, 6, 62, 2, 7, 20, 2, 6, 13, 2, 7, 23, 2, 6, 19, 2, 7, 34, 2, 6, 56, 63, 63, 2, 7, 59, 21, 2, 6, 61, 64, 63, 64, 63, 65, 65, 26, 2, 19, 2, 21, 2, 6, 57, 2, 6, 60, 2, 6, 44, 2, 6, 31, 2, 6, 29, 2, 6, 18, 2, 6, 20, 2, 6, 63, 41, 2, 6, 16, 2, 9, 2, 6, 27, 2, 18, 2, 22, 2, 41, 2, 43, 53, 55, 40, 51, 44, 41, 33, 44, 45, 39, 45, 2, 9, 2, 2, 2, 34, 2, 46, 2, 7, 44, 50, 44, 41, 40, 39, 22, 2, 7, 28, 36, 37, 39, 2, 6, 40, 47, 45, 45, 41, 43, 46, 43, 49, 50, 42, 42, 46, 2, 7, 45, 41, 33, 2, 15, 19, 2, 25, 2, 19, 2, 6, 45, 37, 56, 43, 50, 50, 50, 39, 27, 2, 7, 23, 2, 18, 2, 45, 43, 38, 41, 45, 43, 45, 44, 50, 47, 48, 40, 48, 40, 44, 47, 49, 44, 48, 44, 45, 41, 45, 43, 42, 47, 49, 47, 45, 43, 41, 43, 44, 45, 57, 41, 18, 2, 23, 2, 17, 2, 6, 43, 47, 47, 42, 44, 12, 42, 43, 51, 50, 48, 48, 41, 46, 5, 46, 42, 43, 40, 41, 51, 46, 44, 43, 2, 9, 2, 32, 2, 7, 44, 44, 2, 9, 2, 2, 2, 39, 2, 29, 2, 6, 50, 55, 53, 47, 30, 2, 6, 35, 2, 8, 19, 44, 2, 35, 2, 17, 2, 6, 33, 2, 8, 45, 2, 6, 43, 2, 8, 45, 2, 6, 44, 2, 8, 23, 2, 6, 24, 2, 8, 21, 2, 6, 26, 51, 49, 2, 8, 50, 2, 6, 52, 38, 43, 2, 8, 47, 17, 2, 6, 39, 2, 6, 26, 25, 2, 35, 2, 6, 26, 2, 19, 2, 8, 28, 2, 6, 34, 2, 25, 2, 8, 41, 2, 6, 45, 44, 2, 8, 17, 2, 6, 28, 48, 16, 47, 47, 52, 46, 36, 40, 45, 2, 8, 51, 30, 2, 6, 13, 44, 44, 45, 47, 43, 40, 41, 47, 39, 44, 29, 2, 8, 18, 48, 2, 6, 45, 46, 43, 46, 44, 35, 39, 35, 43, 39, 52, 44, 48, 48, 45, 42, 48, 48, 54, 53, 42, 44, 41, 49, 46, 46, 48, 40, 20, 47, 43, 40, 45, 46, 43, 26, 2, 8, 26, 43, 46, 32, 2, 6, 18, 39, 48, 23, 2, 8, 25, 46, 24, 2, 6, 27, 46, 42, 40, 45, 27, 2, 8, 10, 2, 6, 33, 2, 16, 2, 44, 56, 2, 8, 17, 2, 6, 42, 46, 45, 9, 2, 8, 32, 44, 42, 46, 46, 23, 2, 6, 27, 2, 8, 26, 39, 48, 46, 45, 45, 42, 42, 46, 2, 6, 46, 52, 48, 43, 42, 51, 2, 8, 28, 2, 6, 27, 2, 8, 40, 2, 6, 27, 2, 8, 28, 2, 6, 47, 38, 50, 2, 15, 2, 8, 41, 32, 21, 2, 6, 10, 49, 49, 44, 46, 47, 46, 48, 47, 44, 45, 44, 45, 49, 41, 40, 45, 2, 8, 46, 2, 6, 38, 41, 45, 38, 46, 41, 42, 37, 41, 40, 45, 48, 45, 47, 41, 47, 25, 45, 43, 44, 41, 47, 35, 46, 27, 2, 8, 18, 2, 6, 43, 44, 49, 43, 51, 40, 39, 49, 48, 42, 46, 38, 38, 46, 41, 31, 2, 8, 46, 47, 28, 2, 6, 35, 2, 8, 8, 37, 2, 6, 53, 46, 47, 41, 40, 49, 45, 48, 46, 32, 46, 46, 49, 42, 46, 21, 2, 52, 2, 2, 2, 9, 2, 32, 2, 52, 2, 7, 54, 50, 20, 2, 8, 41, 2, 48, 2, 46, 2, 7, 34, 2, 8, 44, 43, 42, 45, 42, 26, 2, 7, 15, 44, 40, 39, 47, 41, 54, 46, 44, 40, 40, 45, 2, 8, 40, 43, 33, 47, 2, 7, 24, 45, 48, 40, 49, 2, 42, 2, 50, 40, 51, 49, 45, 2, 40, 2, 51, 43, 47, 42, 38, 51, 43, 40, 2, 11, 2, 39, 2, 17, 2, 6, 16, 2, 16, 32, 2, 6, 53, 2, 39, 2, 6, 50, 2, 6, 44, 2, 6, 49, 28, 2, 6, 20, 2, 6, 15, 2, 6, 64, 67, 12, 2, 6, 36, 2, 6, 61, 64, 64, 66, 65, 8, 2, 6, 32, 2, 6, 60, 2, 6, 63, 11, 2, 6, 63, 24, 2, 7, 19, 2, 6, 55, 2, 11, 2, 2, 2, 40, 2, 24, 2, 7, 47, 47, 44, 41, 49, 55, 53, 40, 44, 38, 16, 2, 22, 2, 30, 2, 6, 43, 25, 2, 7, 18, 2, 6, 51, 2, 7, 22, 2, 6, 37, 2, 34, 2, 7, 32, 2, 6, 12, 2, 7, 19, 2, 6, 53, 65, 65, 66, 64, 10, 2, 7, 13, 2, 6, 63, 41, 2, 7, 30, 2, 6, 62, 23, 2, 7, 20, 2, 6, 64, 66, 65, 28, 2, 7, 42, 2, 6, 29, 2, 22, 2, 7, 49, 41, 54, 50, 42, 45, 14, 2, 6, 14, 2, 7, 13, 2, 6, 7, 2, 7, 41, 2, 6, 59, 24, 2, 7, 28, 2, 6, 63, 51, 2, 9, 2, 7, 50, 45, 41, 54, 2, 40, 2, 51, 48, 43, 42, 47, 47, 38, 46, 43, 47, 44, 2, 9, 2, 2, 2, 31, 2, 42, 2, 6, 45, 43, 43, 44, 42, 39, 22, 2, 7, 23, 2, 6, 15, 2, 31, 2, 48, 2, 6, 35, 2, 7, 26, 2, 6, 32, 2, 7, 30, 2, 6, 25, 2, 7, 39, 2, 6, 42, 23, 2, 7, 39, 40, 41, 48, 41, 42, 2, 6, 44, 2, 7, 32, 2, 6, 47, 45, 50, 48, 45, 2, 7, 22, 2, 9, 2, 6, 32, 2, 6, 48, 2, 26, 2, 40, 42, 42, 45, 49, 39, 36, 42, 42, 43, 54, 45, 45, 54, 47, 45, 38, 44, 38, 36, 46, 44, 40, 40, 48, 46, 40, 46, 43, 40, 48, 43, 40, 46, 45, 2, 9, 2, 2, 2, 42, 2, 28, 2, 8, 28, 2, 7, 38, 32, 2, 8, 22, 2, 7, 47, 61, 53, 51, 38, 44, 51, 57, 53, 42, 53, 46, 2, 8, 18, 2, 17, 2, 43, 46, 39, 42, 2, 34, 2, 6, 44, 2, 8, 19, 2, 15, 37, 24, 33, 28, 2, 8, 43, 2, 6, 31, 10, 31, 27, 36, 28, 2, 8, 20, 2, 6, 17, 10, 43, 2, 15, 2, 8, 27, 2, 6, 10, 37, 37, 30, 2, 7, 26, 2, 6, 62, 67, 13, 2, 7, 26, 2, 6, 67, 25, 10, 39, 34, 33, 28, 2, 44, 35, 37, 27, 2, 7, 17, 2, 6, 53, 10, 33, 32, 43, 34, 2, 38, 30, 40, 40, 2, 7, 30, 2, 6, 59, 66, 63, 66, 33, 2, 9, 2, 7, 52, 2, 17, 2, 49, 52, 48, 45, 49, 45, 58, 56, 45, 45, 51, 44, 44, 47, 41, 48, 40, 42, 43, 43, 29, 2, 19, 2, 8, 28, 2, 7, 49, 2, 22, 2, 21, 2, 7, 25, 37, 46, 40, 51, 42, 37, 40, 46, 52, 40, 2, 8, 45, 44, 2, 19, 2, 7, 22, 2, 42, 2, 7, 51, 2, 8, 20, 2, 7, 28, 2, 8, 19, 2, 33, 2, 7, 49, 20, 2, 8, 23, 2, 7, 54, 47, 47, 20, 2, 7, 29, 43, 47, 42, 45, 45, 54, 13, 2, 7, 21, 2, 7, 7, 2, 8, 17, 2, 7, 26, 2, 7, 45, 51, 47, 45, 45, 44, 31, 2, 7, 21, 2, 7, 29, 46, 32, 2, 7, 15, 37, 56, 54, 19, 2, 7, 23, 2, 7, 26, 2, 7, 49, 44, 28, 2, 7, 20, 41, 45, 39, 43, 26, 2, 8, 27, 2, 7, 30, 2, 58, 11, 2, 51, 46, 49, 46, 42, 46, 43, 46, 43, 27, 2, 6, 10, 40, 35, 43, 2, 25, 2, 7, 50, 25, 2, 6, 59, 67, 20, 2, 7, 34, 2, 6, 55, 54, 2, 7, 58, 2, 6, 63, 58, 67, 67, 49, 10, 43, 2, 7, 47, 40, 2, 6, 10, 32, 32, 26, 27, 30, 2, 36, 29, 30, 29, 31, 2, 57, 2, 9, 2, 7, 25, 2, 7, 42, 37, 51, 50, 36, 49, 49, 37, 45, 44, 25, 2, 7, 17, 43, 49, 41, 50, 33, 2, 7, 15, 50, 24, 2, 11, 2, 2, 2, 39, 2, 32, 2, 6, 41, 2, 10, 51, 2, 6, 19, 2, 17, 2, 43, 47, 2, 18, 2, 11, 21, 2, 6, 25, 2, 9, 59, 67, 50, 2, 6, 52, 60, 63, 63, 66, 63, 67, 67, 66, 66, 66, 65, 65, 58, 44, 2, 51, 47, 36, 2, 11, 2, 2, 2, 40, 2, 27, 2, 7, 47, 47, 46, 44, 18, 2, 7, 31, 44, 39, 45, 29, 2, 7, 29, 49, 53, 46, 47, 43, 48, 43, 39, 48, 49, 52, 49, 43, 38, 33, 2, 7, 36, 41, 44, 42, 49, 2, 7, 53, 44, 49, 52, 43, 48, 2, 22, 2, 21, 2, 7, 32, 42, 2, 7, 32, 2, 7, 45, 50, 27, 2, 7, 31, 11, 2, 19, 2, 65, 63, 63, 64, 2, 52, 41, 2, 7, 20, 2, 7, 38, 44, 20, 2, 7, 45, 40, 46, 21, 2, 7, 25, 42, 26, 2, 7, 14, 41, 2, 7, 45, 46, 43, 36, 47, 42, 49, 23, 2, 7, 27, 38, 28, 2, 7, 17, 49, 45, 47, 43, 42, 27, 2, 7, 29, 2, 7, 36, 44, 45, 44, 52, 37, 51, 50, 45, 47, 43, 51, 42, 28, 2, 7, 17, 2, 7, 11, 2, 7, 23, 2, 7, 16, 2, 7, 42, 28, 2, 7, 28, 37, 39, 38, 46, 54, 47, 46, 37, 43, 44, 21, 2, 7, 28, 2, 7, 39, 43, 25, 2, 7, 19, 2, 7, 48, 40, 39, 42, 43, 45, 42, 37, 45, 55, 40, 49, 52, 56, 45, 44, 21, 2, 7, 34, 2, 7, 46, 51, 51, 47, 49, 38, 52, 44, 46, 47, 44, 46, 30, 2, 7, 14, 44, 38, 40, 44, 45, 47, 51, 52, 18, 2, 7, 30, 47, 47, 54, 51, 47, 49, 47, 9, 44, 48, 53, 47, 44, 29, 2, 16, 2, 23, 2, 8, 41, 55, 2, 7, 20, 2, 8, 41, 50, 44, 53, 45, 53, 48, 46, 42, 53, 45, 48, 39, 38, 45, 49, 47, 17, 2, 7, 28, 2, 8, 19, 2, 7, 44, 42, 43, 50, 41, 49, 31, 2, 9, 2, 7, 25, 40, 43, 25, 2, 11, 2, 2, 2, 8, 2, 24, 2, 38, 2, 10, 59, 26, 2, 10, 64, 57, 2, 10, 65, 2, 10, 21, 2, 10, 60, 66, 63, 39, 2, 10, 38, 2, 10, 59, 66, 66, 64, 56, 2, 10, 18, 2, 10, 39, 2, 10, 53, 67, 2, 10, 59, 67, 62, 67, 28, 2, 10, 21, 2, 10, 39, 2, 10, 19, 2, 10, 62, 65, 63, 29, 2, 10, 8, 2, 10, 60, 31, 2, 10, 64, 2, 10, 60, 63, 61, 67, 2, 10, 65, 2, 10, 31, 2, 10, 24, 2, 10, 7, 2, 10, 22, 2, 44, 2, 10, 60, 61, 62, 61, 9, 2, 22, 2, 19, 2, 40, 35, 49, 43, 2, 6, 62, 15, 2, 6, 52, 2, 6, 63, 8, 2, 10, 10, 38, 36, 39, 35, 2, 22, 2, 6, 61, 64, 63, 64, 15, 2, 6, 20, 2, 6, 61, 67, 57, 20, 2, 6, 14, 2, 6, 61, 65, 64, 62, 7, 2, 10, 10, 36, 33, 36, 32, 2, 28, 2, 6, 61, 66, 65, 65, 65, 64, 65, 65, 64, 65, 65, 66, 11, 2, 6, 26, 2, 6, 39, 2, 6, 37, 2, 6, 63, 54, 2, 10, 12, 10, 36, 32, 2, 6, 50, 2, 10, 67, 36, 2, 6, 62, 52, 2, 10, 59, 2, 6, 32, 2, 10, 18, 2, 6, 18, 2, 10, 19, 2, 6, 27, 2, 10, 60, 2, 6, 58, 62, 64, 66, 57, 2, 10, 60, 39, 2, 6, 25, 2, 10, 60, 64, 15, 2, 6, 42, 2, 10, 59, 47, 2, 6, 6, 2, 10, 66, 2, 6, 18, 2, 10, 27, 2, 6, 16, 2, 10, 35, 2, 6, 19, 2, 10, 61, 15, 2, 6, 50, 2, 10, 60, 66, 64, 16, 2, 6, 27, 2, 10, 61, 67, 67, 38, 2, 6, 15, 2, 10, 61, 2, 6, 18, 2, 10, 60, 61, 27, 2, 6, 7, 2, 10, 12, 2, 6, 64, 65, 67, 64, 65, 64, 65, 60, 61, 67, 20, 2, 6, 23, 2, 6, 64, 2, 6, 10, 2, 6, 20, 2, 26, 2, 6, 19, 2, 6, 55, 63, 23, 2, 6, 50, 2, 6, 62, 61, 66, 63, 50, 47, 45, 51, 52, 50, 2, 59, 66, 2, 52, 47, 47, 42, 27, 2, 26, 2, 7, 21, 2, 6, 18, 27, 2, 7, 21, 2, 11, 41, 48, 50, 47, 48, 54, 43, 46, 21, 2, 7, 29, 2, 11, 18, 43, 40, 27, 2, 7, 25, 40, 52, 40, 26, 2, 6, 25, 2, 8, 32, 23, 51, 53, 33, 2, 7, 15, 43, 44, 47, 48, 25, 45, 45, 42, 18, 2, 6, 14, 24, 48, 52, 41, 18, 25, 2, 7, 26, 23, 2, 6, 24, 46, 43, 39, 45, 2, 7, 21, 2, 8, 17, 2, 6, 14, 2, 6, 25, 2, 61, 2, 6, 44, 38, 2, 8, 23, 2, 6, 42, 45, 45, 2, 7, 24, 2, 8, 31, 2, 6, 36, 62, 41, 43, 42, 42, 49, 43, 45, 47, 28, 2, 8, 23, 44, 38, 46, 32, 2, 6, 16, 42, 40, 38, 46, 2, 9, 2, 7, 45, 2, 17, 14, 54, 45, 48, 42, 40, 42, 2, 11, 2, 2, 2, 33, 2, 29, 2, 6, 50, 39, 2, 6, 23, 2, 6, 47, 46, 49, 47, 43, 55, 42, 29, 2, 6, 23, 2, 6, 19, 43, 43, 47, 41, 40, 49, 38, 44, 48, 47, 43, 42, 31, 2, 6, 16, 2, 6, 49, 42, 2, 6, 16, 2, 6, 45, 42, 42, 42, 41, 45, 44, 44, 29, 2, 6, 19, 2, 6, 41, 40, 52, 48, 41, 44, 47, 43, 44, 28, 2, 6, 22, 2, 6, 40, 39, 42, 46, 57, 47, 49, 23, 2, 6, 42, 2, 6, 50, 47, 37, 44, 43, 22, 2, 6, 27, 2, 6, 50, 52, 46, 42, 53, 54, 39, 18, 2, 6, 46, 42, 2, 6, 40, 46, 36, 34, 36, 49, 48, 26, 2, 6, 24, 2, 16, 2, 6, 49, 2, 6, 52, 2, 6, 19, 2, 6, 65, 65, 67, 42, 2, 6, 56, 41, 2, 6, 58, 45, 2, 6, 39, 2, 6, 56, 2, 6, 42, 2, 6, 55, 2, 6, 63, 65, 58, 11, 2, 6, 28, 39, 2, 6, 61, 57, 61, 66, 66, 47, 2, 6, 61, 65, 64, 67, 67, 64, 45, 2, 6, 46, 2, 6, 64, 15, 2, 6, 6, 2, 6, 67, 14, 2, 6, 48, 2, 6, 13, 2, 6, 59, 2, 6, 14, 2, 6, 33, 2, 6, 63, 30, 2, 6, 55, 2, 6, 60, 58, 2, 6, 60, 43, 2, 6, 20, 2, 6, 20, 2, 6, 39, 2, 6, 58, 60, 67, 63, 63, 23, 2, 6, 30, 2, 6, 61, 2, 6, 38, 2, 6, 59, 67, 62, 67, 66, 2, 6, 58, 59, 63, 46, 2, 6, 21, 2, 6, 58, 2, 6, 62, 59, 64, 65, 25, 2, 6, 33, 2, 6, 60, 2, 6, 37, 2, 6, 15, 2, 15, 2, 63, 13, 2, 6, 52, 2, 6, 67, 67, 63, 60, 64, 43, 2, 17, 2, 7, 59, 66, 65, 24, 2, 6, 64, 67, 22, 2, 7, 45, 2, 6, 16, 2, 7, 59, 34, 2, 6, 24, 2, 14, 2, 6, 36, 2, 6, 61, 67, 63, 2, 6, 22, 2, 6, 60, 32, 2, 6, 64, 41, 2, 6, 61, 65, 66, 65, 29, 2, 64, 12, 2, 7, 49, 2, 46, 2, 6, 50, 39, 53, 42, 18, 47, 45, 45, 39, 47, 44, 45, 43, 37, 24, 41, 47, 42, 22, 2, 7, 27, 49, 42, 42, 44, 39, 45, 43, 24, 2, 6, 22, 47, 29, 2, 7, 19, 2, 6, 47, 53, 25, 2, 7, 19, 2, 6, 19, 2, 7, 50, 21, 2, 6, 21, 50, 2, 7, 41, 50, 2, 7, 40, 2, 6, 52, 2, 25, 2, 6, 19, 2, 7, 46, 41, 42, 46, 49, 41, 46, 49, 42, 39, 51, 50, 39, 2, 6, 15, 2, 7, 16, 2, 14, 2, 6, 6, 2, 7, 5, 2, 6, 11, 2, 6, 29, 2, 7, 15, 2, 7, 52, 25, 2, 47, 2, 19, 2, 6, 48, 35, 2, 14, 2, 7, 33, 2, 7, 20, 2, 8, 34, 46, 44, 2, 6, 13, 2, 7, 25, 2, 8, 40, 2, 7, 50, 2, 6, 41, 2, 8, 29, 2, 7, 28, 2, 7, 19, 2, 7, 53, 2, 6, 46, 42, 38, 2, 7, 22, 2, 14, 2, 6, 23, 2, 7, 18, 2, 50, 45, 2, 7, 31, 2, 6, 18, 2, 20, 2, 6, 30, 2, 6, 48, 2, 6, 20, 2, 7, 46, 45, 2, 6, 21, 2, 7, 31, 2, 8, 52, 39, 2, 9, 2, 6, 41, 25, 2, 18, 2, 7, 45, 44, 44, 44, 42, 43, 45, 48, 2, 6, 28, 27, 2, 19, 2, 18, 19, 2, 7, 43, 2, 6, 48, 44, 19, 2, 14, 2, 7, 22, 39, 45, 48, 18, 2, 9, 2, 6, 47, 47, 48, 45, 48, 50, 37, 44, 21, 2, 6, 19, 43, 30, 2, 6, 19, 52, 38, 53, 42, 35, 50, 21, 2, 36, 2, 29, 2, 6, 51, 37, 22, 2, 6, 20, 47, 46, 39, 39, 50, 45, 2, 9, 2, 6, 54, 46, 32, 2, 17, 2, 58, 2, 7, 22, 2, 6, 26, 47, 2, 7, 45, 45, 37, 26, 2, 15, 22, 45, 53, 42, 45, 34, 2, 6, 21, 42, 44, 47, 49, 48, 40, 45, 48, 39, 45, 47, 39, 48, 16, 2, 7, 26, 39, 43, 47, 48, 2, 6, 43, 51, 43, 54, 29, 2, 7, 19, 42, 40, 52, 42, 25, 43, 47, 29, 2, 17, 2, 65, 24]\n" + ] + } + ], + "source": [ + "linelengths=[len(line) for line in open(\"hamlet.txt\")]#poor code as we dont close the file\n", + "print linelengths" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "(180718, 26.69394387001477, 26.0, 21.029872021427462)" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "sum(linelengths), np.mean(linelengths), np.median(linelengths), np.std(linelengths)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "But perhaps we want to access Hamlet word by word and not line by line" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "31659" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "hamletfile=open(\"hamlet.txt\")\n", + "hamlettext=hamletfile.read()\n", + "hamletfile.close()\n", + "hamlettokens=hamlettext.split()#split with no arguments splits on whitespace\n", + "len(hamlettokens)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "One can use the `with` syntax which cretaes a context. The file closing is then done automatically for us." + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "31659\n" + ] + } + ], + "source": [ + "with open(\"hamlet.txt\") as hamletfile:\n", + " hamlettext=hamletfile.read()\n", + " hamlettokens=hamlettext.split()\n", + " print len(hamlettokens)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "There are roughly 32,000 words in Hamlet." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "###The indexing of lists" + ] + }, + { + "cell_type": "code", + "execution_count": 44, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "XXXX\r\n", + "HAMLET, PRINCE OF DENMARK\r\n", + "\r\n", + "by William Shakespeare\r\n", + "\r\n", + "\r\n", + "\r\n", + "\r\n", + "PERSONS REPRESENTED.\r\n", + "\r\n", + "Claudius, King of Denmark.\r\n", + "Hamlet, Son to the former, and Nephew to the present King.\r\n", + "Polonius, Lord Chamberlain.\r\n", + "Horatio, Friend to Hamlet.\r\n", + "Laertes, Son to Polonius.\r\n", + "Voltimand, Courtier.\r\n", + "Cornelius, Courtier.\r\n", + "Rosencrantz, Courtier.\r\n", + "Guildenstern, Courtier.\r\n", + "Osric, Courtier.\r\n", + "A Gentleman, Courtier.\r\n", + "A Priest.\r\n", + "Marcellus, Officer.\r\n", + "Bernardo, Officer.\r\n", + "Francisco, a Soldier\r\n", + "Reynaldo, Servant to Polonius.\r\n", + "Players.\r\n", + "Two Clowns, Grave-diggers.\r\n", + "Fortinbras, Prince of Norway.\r\n", + "A Captain.\r\n", + "English Ambassadors.\r\n", + "Ghost of Hamlet's Father.\r\n", + "\r\n", + "Gertrude, Queen of Denmark, and Mother of Hamlet.\r\n", + "Ophelia, Daughter to Polonius.\r\n", + "\r\n", + "Lords, Ladies, Officers, Soldiers, Sailors, Messengers, and other\r\n", + "Attendants.\r\n", + "\r\n", + "SCENE. Elsinore.\r\n", + "\r\n", + "\r\n", + "\r\n", + "ACT I.\r\n", + "\r\n", + "Scene I. Elsinore. A platform before the Castle.\r\n", + "\r\n", + "[Francisco at his post. Enter to him Bernardo.]\r\n", + "\r\n", + "Ber.\r\n", + "Who's there?\r\n", + "\r\n", + "Fran.\r\n", + "Nay, answer me: stand, and u\n" + ] + } + ], + "source": [ + "print hamlettext[:1000]#first 1000 characters from Hamlet." + ] + }, + { + "cell_type": "code", + "execution_count": 45, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "nd, in this upshot, purposes mistook\r\n", + "Fall'n on the inventors' heads: all this can I\r\n", + "Truly deliver.\r\n", + "\r\n", + "Fort.\r\n", + "Let us haste to hear it,\r\n", + "And call the noblest to the audience.\r\n", + "For me, with sorrow I embrace my fortune:\r\n", + "I have some rights of memory in this kingdom,\r\n", + "Which now, to claim my vantage doth invite me.\r\n", + "\r\n", + "Hor.\r\n", + "Of that I shall have also cause to speak,\r\n", + "And from his mouth whose voice will draw on more:\r\n", + "But let this same be presently perform'd,\r\n", + "Even while men's minds are wild: lest more mischance\r\n", + "On plots and errors happen.\r\n", + "\r\n", + "Fort.\r\n", + "Let four captains\r\n", + "Bear Hamlet like a soldier to the stage;\r\n", + "For he was likely, had he been put on,\r\n", + "To have prov'd most royally: and, for his passage,\r\n", + "The soldiers' music and the rites of war\r\n", + "Speak loudly for him.--\r\n", + "Take up the bodies.--Such a sight as this\r\n", + "Becomes the field, but here shows much amiss.\r\n", + "Go, bid the soldiers shoot.\r\n", + "\r\n", + "[A dead march.]\r\n", + "\r\n", + "[Exeunt, bearing off the dead bodies; after the which a peal of\r\n", + "ordnance is shot off.]\r\n", + "\n" + ] + } + ], + "source": [ + "print hamlettext[-1000:]#and last 1000 characters from Hamlet." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Lets split the word tokens. The first one below reads, give me the second, third, and fourth words (remember that python is 0 indexed). Try and figure what the others mean." + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "['HAMLET,', 'PRINCE', 'OF'] ['\\xef\\xbb\\xbfXXXX', 'HAMLET,', 'PRINCE', 'OF'] XXXX off.]\n" + ] + } + ], + "source": [ + "print hamlettokens[1:4], hamlettokens[:4], hamlettokens[0], hamlettokens[-1]" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "['HAMLET,', 'OF', 'by', 'Shakespeare']" + ] + }, + "execution_count": 17, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "hamlettokens[1:8:2]#get every 2nd world between the 2nd and the 9th: ie 2nd, 4th, 6th, and 8th" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "range and xrange get the list of integers upto N. But xrange behaves like an iterator. The reason for this is that there is no point generaing all os a million integers. We can just add 1 to the previous one and save memory. So we trade off storage for computation." + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]" + ] + }, + "execution_count": 18, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "mylist=[]\n", + "for i in xrange(10):\n", + " mylist.append(i)\n", + "mylist" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Dictionaries\n", + "\n", + "These are the bread and butter. You will use them a lot. They even duck like lists. But be careful how." + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "['three', 'two', 'one'] [('three', 3), ('two', 2), ('one', 1)] [3, 2, 1]\n" + ] + } + ], + "source": [ + "adict={'one':1, 'two': 2, 'three': 3}\n", + "print [i for i in adict], [(k,v) for k,v in adict.items()], adict.values()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The keys do not have to be strings. From python 2.7 you can use dictionary comprehensions as well" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{1: 1, 2: 4, 3: 9, 4: 16, 5: 25}" + ] + }, + "execution_count": 20, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "mydict ={k:v for (k,v) in zip(alist, asquaredlist)}\n", + "mydict" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "You can construct then nicely using the function `dict`." + ] + }, + { + "cell_type": "code", + "execution_count": 46, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{'a': 1, 'b': 2}" + ] + }, + "execution_count": 46, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "dict(a=1, b=2)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "###and conversion to json" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "import json" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{\"1\": 1, \"2\": 4, \"3\": 9, \"4\": 16, \"5\": 25}\n" + ] + } + ], + "source": [ + "s=json.dumps(mydict)\n", + "print s" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{u'1': 1, u'2': 4, u'3': 9, u'4': 16, u'5': 25}" + ] + }, + "execution_count": 23, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "json.loads(s)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Strings\n", + "\n", + "Basically they behave like immutable lists" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "off.]\n" + ] + } + ], + "source": [ + "lastword=hamlettokens[-1]\n", + "print(lastword)" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "ename": "TypeError", + "evalue": "'str' object does not support item assignment", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mlastword\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m-\u001b[0m\u001b[0;36m2\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m\"k\"\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;31mTypeError\u001b[0m: 'str' object does not support item assignment" + ] + } + ], + "source": [ + "lastword[-2]=\"k\"#cant change a part of a string" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "'.'" + ] + }, + "execution_count": 26, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "lastword[-2]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "You can join a list with a separator to make a string." + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "\"\\xef\\xbb\\xbfXXXX,HAMLET,,PRINCE,OF,DENMARK,by,William,Shakespeare,PERSONS,REPRESENTED.,Claudius,,King,of,Denmark.,Hamlet,,Son,to,the,former,,and,Nephew,to,the,present,King.,Polonius,,Lord,Chamberlain.,Horatio,,Friend,to,Hamlet.,Laertes,,Son,to,Polonius.,Voltimand,,Courtier.,Cornelius,,Courtier.,Rosencrantz,,Courtier.,Guildenstern,,Courtier.,Osric,,Courtier.,A,Gentleman,,Courtier.,A,Priest.,Marcellus,,Officer.,Bernardo,,Officer.,Francisco,,a,Soldier,Reynaldo,,Servant,to,Polonius.,Players.,Two,Clowns,,Grave-diggers.,Fortinbras,,Prince,of,Norway.,A,Captain.,English,Ambassadors.,Ghost,of,Hamlet's,Father.,Gertrude,,Queen,of,Denmark,,and,Mother,of,Hamlet.,Ophelia,,Daughter,to,Polonius.,Lords,,Ladies,,Officers,,Soldiers,,Sailors,,Messengers,,and,other,Attendants.,SCENE.,Elsinore.,ACT,I.,Scene,I.,Elsinore.,A,platform,before,the,Castle.,[Francisco,at,his,post.,Enter,to,him,Bernardo.],Ber.,Who's,there?,Fran.,Nay,,answer,me:,stand,,and,unfold,yourself.,Ber.,Long,live,the,king!,Fran.,Bernardo?,Ber.,He.,Fra\"" + ] + }, + "execution_count": 27, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "wierdstring=\",\".join(hamlettokens)\n", + "wierdstring[:1000]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Functions\n", + "\n", + "Functions are even more the bread and butter. You'll see them as methods on objects, or standing alone by themselves." + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "(25, 125)" + ] + }, + "execution_count": 28, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "def square(x):\n", + " return(x*x)\n", + "def cube(x):\n", + " return x*x*x\n", + "square(5),cube(5)" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " \n" + ] + } + ], + "source": [ + "print square, type(cube)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In Python, functions are \"first-class\". This is just a fancy way of saying, you can pass functions to other functions" + ] + }, + { + "cell_type": "code", + "execution_count": 47, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "3 4 \n" + ] + }, + { + "data": { + "text/plain": [ + "25" + ] + }, + "execution_count": 47, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "def sum_of_anything(x,y,f):\n", + " print x,y,f\n", + " return(f(x) + f(y))\n", + "sum_of_anything(3,4,square)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Python functions can have positional arguments and keyword arguments. Positional arguments are stored in a tuple, and keyword arguments in a dictionary. Note the \"starred\" syntax" + ] + }, + { + "cell_type": "code", + "execution_count": 50, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "got 1 3 () {}\n", + "1\n", + "got 1 3 (4,) {'c': 2, 'd': 1}\n", + "1\n" + ] + } + ], + "source": [ + "def f(a,b,*posargs,**dictargs):\n", + " print \"got\",a,b,posargs, dictargs\n", + " return a\n", + "print f(1,3)\n", + "print f(1,3,4,d=1,c=2)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + ">**YOUR TURN** create a dictionary with keys the integers upto and including 10, and values the cubes of these dictionaries" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "#your code here" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "##Booleans and Control-flow\n", + "\n", + "Lets test for belonging..." + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 32, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "a=[1,2,3,4,5]\n", + "1 in a" + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "False" + ] + }, + "execution_count": 33, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "6 in a" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Python supports if/elif/else clauses for multi-way conditionals" + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "One\n" + ] + } + ], + "source": [ + "def do_it(x):\n", + " if x==1:\n", + " print \"One\"\n", + " elif x==2:\n", + " print \"Two\"\n", + " else:\n", + " print x\n", + "do_it(1)" + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Two\n", + "3\n" + ] + }, + { + "data": { + "text/plain": [ + "(None, None)" + ] + }, + "execution_count": 35, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "do_it(2), do_it(3)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "You can `break` out of a loop based on a condition. The loop below is a for loop." + ] + }, + { + "cell_type": "code", + "execution_count": 36, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0\n", + "1\n", + "2\n", + "3\n", + "4\n", + "5\n", + "6\n" + ] + } + ], + "source": [ + "for i in range(10):\n", + " print i\n", + " if (i > 5):\n", + " break" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "While loops are also supported. `continue` continues to the next iteration of the loop skipping all the code below, while `break` breaks out of it." + ] + }, + { + "cell_type": "code", + "execution_count": 37, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0\n", + "1\n", + "2\n", + "3\n", + "4\n" + ] + } + ], + "source": [ + "i=0\n", + "while i < 10:\n", + " print i\n", + " i=i+1\n", + " if i < 5:\n", + " continue\n", + " else:\n", + " break\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Exceptions\n", + "\n", + "This is the way to catch errors." + ] + }, + { + "cell_type": "code", + "execution_count": 38, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(, TypeError('f() takes at least 2 arguments (1 given)',), )\n" + ] + } + ], + "source": [ + "try:\n", + " f(1)#takes atleast 2 arguments\n", + "except:\n", + " import sys\n", + " print sys.exc_info()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## All together now\n", + "\n", + "Lets see what hamlet gives us. We convert all words to lower-case" + ] + }, + { + "cell_type": "code", + "execution_count": 39, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "95" + ] + }, + "execution_count": 39, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "hamletlctokens=[word.lower() for word in hamlettokens]\n", + "hamletlctokens.count(\"thou\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We then find a unique set of words using python's `set` data structure. We count how often those words occured usinf the `count` method on lists." + ] + }, + { + "cell_type": "code", + "execution_count": 52, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "uniquelctokens=set(hamletlctokens)" + ] + }, + { + "cell_type": "code", + "execution_count": 41, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "tokendict={}\n", + "for ut in uniquelctokens:\n", + " tokendict[ut]=hamletlctokens.count(ut)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We find the 100 most used words..." + ] + }, + { + "cell_type": "code", + "execution_count": 42, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[('the', 1136),\n", + " ('and', 943),\n", + " ('to', 720),\n", + " ('of', 667),\n", + " ('a', 527),\n", + " ('my', 512),\n", + " ('i', 510),\n", + " ('in', 420),\n", + " ('you', 412),\n", + " ('ham.', 358),\n", + " ('that', 337),\n", + " ('it', 324),\n", + " ('is', 320),\n", + " ('his', 295),\n", + " ('not', 270),\n", + " ('with', 264),\n", + " ('this', 250),\n", + " ('your', 241),\n", + " ('for', 231),\n", + " ('but', 228),\n", + " ('as', 216),\n", + " ('he', 202),\n", + " ('be', 201),\n", + " ('what', 183),\n", + " ('have', 174),\n", + " ('will', 149),\n", + " ('so', 143),\n", + " ('me', 142),\n", + " ('we', 132),\n", + " ('do', 128),\n", + " ('are', 126),\n", + " ('him', 122),\n", + " ('our', 119),\n", + " ('king.', 113),\n", + " ('by', 111),\n", + " ('hor.', 110),\n", + " ('or', 109),\n", + " ('if', 109),\n", + " ('on', 109),\n", + " ('no', 107),\n", + " ('shall', 106),\n", + " ('thou', 95),\n", + " ('all', 95),\n", + " ('from', 95),\n", + " ('they', 93),\n", + " ('let', 92),\n", + " ('good', 88),\n", + " ('at', 86),\n", + " ('thy', 86),\n", + " ('pol.', 86),\n", + " ('how', 84),\n", + " ('most', 82),\n", + " ('lord,', 81),\n", + " ('her', 76),\n", + " ('more', 76),\n", + " ('queen.', 76),\n", + " ('like', 75),\n", + " ('would', 74),\n", + " ('was', 73),\n", + " (\"'tis\", 70),\n", + " ('you,', 66),\n", + " ('may', 65),\n", + " ('very', 64),\n", + " ('laer.', 62),\n", + " ('hath', 62),\n", + " ('[enter', 61),\n", + " ('lord.', 60),\n", + " ('did', 59),\n", + " ('give', 58),\n", + " ('must', 58),\n", + " ('oph.', 58),\n", + " ('their', 57),\n", + " ('o,', 57),\n", + " ('know', 57),\n", + " (\"i'll\", 56),\n", + " ('an', 55),\n", + " ('should', 55),\n", + " ('which', 55),\n", + " ('some', 54),\n", + " ('when', 54),\n", + " ('come', 54),\n", + " ('upon', 53),\n", + " ('make', 53),\n", + " ('am', 52),\n", + " ('such', 51),\n", + " ('ros.', 51),\n", + " ('than', 51),\n", + " ('there', 50),\n", + " ('where', 49),\n", + " ('now', 48),\n", + " ('go', 48),\n", + " ('o', 46),\n", + " ('us', 46),\n", + " ('clown.', 45),\n", + " ('much', 44),\n", + " ('had', 44),\n", + " ('these', 44),\n", + " ('them', 44),\n", + " ('she', 43),\n", + " ('out', 43)]" + ] + }, + "execution_count": 42, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "L=sorted(tokendict.iteritems(), key= lambda (k,v):v, reverse=True)[:100]\n", + "L" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Lets get the top 20 of this and plot a bar chart!" + ] + }, + { + "cell_type": "code", + "execution_count": 43, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[('the', 1136), ('and', 943), ('to', 720), ('of', 667), ('a', 527), ('my', 512), ('i', 510), ('in', 420), ('you', 412), ('ham.', 358), ('that', 337), ('it', 324), ('is', 320), ('his', 295), ('not', 270), ('with', 264), ('this', 250), ('your', 241), ('for', 231), ('but', 228)]\n" + ] + }, + { + "data": { + "image/png": "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\nfPCBxo0bp9raWuXk5CghIUF/+ctf1NDQIJvNpgULFuizzz7TE088oZiYGH3//fe67rrr9M477+jT\nTz9Vfn5+oz/Ppva7Z599Vv/617+0Z88ede7cWQsWLAg81//0pz/plltuCXqeH3roIdXV1amgoEAL\nFiwI6v6N5X7xxRf6/PPP5Xa7tWfPHt12221BHTUe6MB5v+6667R48WK99tprWr16tZYsWaKoqCh1\n7dpVxcXFzf7lXVpaqrfeekv19fXatm2bbrrpJvXt21dFRUWKjIxUTEyMioqKtHbtWu3YsaPJ+Rkz\nZoyWLFmi+Ph4nX/++Vq+fLn69eunAQMGqGfPnioqKtKaNWv0ySef6LTTTpPH49HUqVP13Xff6cQT\nT9Sjjz6qqKgj10FTz4sLL7xQ69at0/Lly/XCCy8oIiJCZ599tqZPn37U8bZk37jyyis1YcIEnXji\niRo2bJhuvPHGo26nsLBQlZWVuvfee1VTUyOXy3XQ7+LLLrtMvXv3VnR0tB555JFm/ewkae3atXrr\nrbdUV1enSZMmadasWXrttdcUExOjhx9+WKmpqaqurtbu3bt133336d5772129oGMLOiJEydq69at\nGjJkiKqrqzV79mxt3LhRS5YsUWZmphYsWKDS0lJ16NBBd9xxh9avX69BgwY1mrlt2zZdeuml+sUv\nfqGamhpdf/316tatmzIyMnT33XeruLhY//jHP3ThhRdqw4YNKi0tVX19vS677LKQx+9yuTR48GDl\n5eWpurpaubm5KisrC3VatGrVKp100kl6+OGH5Xa7NWbMGI0YMUKnn356i8tZOniOqqurm/yF3pi6\nujotXbpUr7zyipYtW6aSkhJt2LBBy5YtU2VlpX788UdVV1crMTGxReUshf/o0mazyWaz6auvvtLT\nTz+tjh076uKLL9bOnTvVpUuXZudcc801WrFihYYNG6bnnntOGRkZcjqdmjt3buDnN3DgwGY9Fr/f\nr+joaC1dulTffPONxo8fr8svv1xPPPGEOnbsqHvvvVdr165Vt27dVF1drRdeeEEff/yxpkyZojfe\neEPff/+9Jk2a1OjPs7H9bvjw4dq9e7eWLVsmm82mcePGadOmTYH7BFvO+x9rdna2Xn755aB+OTYn\nt6qqSj/88IOefPJJ1dbW6ssvvwwp69B5v+mmmwI/o5dfflk33nijRo4cqb///e9yuVxBHaW5XC4t\nXbpUlZWVuvnmmxUXF6f7779fZ5xxhsrKyjRnzhw9+uijevzxx5ucn5///Odas2aNunXrpl69emnd\nunWKiYnR4MGD9e233+qss87S0KFDdemll6p79+6qq6vT1KlT1aNHD+Xl5Wnz5s1KT08/YnZjz4sR\nI0YE5uP555/XzJkzdfbZZ2vFihXat2+fIiMjj5jZ0n1jx44dev7554/6R8V+M2fOVEFBgeLi4nTh\nhRce9ru4rq5Ov/3tb3XGGWc0mnMgv9+vxMREPfzww9q5c6eys7MPG6fNZtOECRP07LPPhlzOkqEF\nfeBnp5x55pmSpC5dumjPnj2qrKxUbW1t4K8mt9utqqqqJjO7dOmiZ555Rq+//rrsdnvgmk6/fv0k\nSd27d9eOHTv05Zdf6qyzzpIkdejQQeecc46C/SyX/et/8cUXGj16tCSpW7dustvtqq2tVWJiYlB5\n+33xxReBP0Ti4uLUp08fbdu2TWlpaSHlHerQOQr1OpvNZgvMq91uV2pqqiQpISFBXq9Xo0eP1ksv\nvaSvv/76sCe3SU499VTFxsZKkpKSklRfXx/U/QcMGKCioiLV1tZq/fr1Ou+88w76+aWmph723D3a\nqUybzRbYF0466aTAUeydd96p2NhYffnll/rZz34mSUpLS1NkZKTsdrt69eqlqKgoJSQkNDn+xvY7\nm82m6OhoFRQUKDY2VtXV1dq3b1/Q+8axcsopp2jEiBGaOnWqGhoalJeXF1LOofO+d+/eQFHcdddd\nWrx4sRwOh/r06RPUH8kH7iMnn3yyPB6P6urqAkXRv3//oF5zMHLkSD3++OPq0aOHbrvtNjkcDvl8\nPp111llHfA1Np06d1KNHD0k/Pbf37t171OzGnhcHmjNnjp566il9/fXXOvfccxt9brR030hOTm6y\nnA8c+5F+F+/cuVOSgv50S5vNpqysLEk/zYPdbj9orOHcJ4y8Br3/W6+kw48okpOT1b17dy1btkwO\nh0O5ubk699xzm8x8+umnde6552ru3Lm65JJLjrreaaedpo8++kg+n08ej0ebN28O+ght//j79Omj\n9957T9JP10J+/PFHnXjiiUFlHSg1NTWQ53K5tHXrViUnJ4ecd6jmzlFzNDZnV155pV577TX95z//\n0bBhw1q0HZPZbDaNHj1aRUVFGjx48GE/v88++0zJycnq0KFD4Nrg5s2bG83bz+l06rHHHtMf//hH\nFRUVqUOHDoFfDKGeUWhsv9uyZYvKyspUXFys6dOny+fzye/3KyIiosXXj8ORcSC/36/Kykq53W4t\nXrxYc+Yvn0PFAAADG0lEQVTM0ezZs0POO9p8rlq1SpMnT5bD4ZDf79cbb7zRotyuXbsGXsT17rvv\nBoqjOfOTlpamqqoqbdq0ScOGDZPb7da///3vg/Yvm82mffv2NfqYjqSx58WBSkpKNGvWLDkcDm3e\nvFkffPDBUddt6b5xtG9EPJoD86urq+V0OgO/i4PdX/x+f+CxVVdXq76+XieffLJqamrk9/v1ySef\nHLRuSxh5BN2lSxd5vV7V19cfNHk2m02JiYm64YYbNHbsWPl8PiUnJzfrNPSIESNUVFSkN954Q6ed\ndppiY2Pl9XoP++GcccYZuuiii3T11VerS5cu6ty5c8jjd7vdeuedd/TPf/5Te/fu1ezZs4N+Yh3o\nmmuu0YwZM5Sbm6u9e/dq0qRJ+vrrr8N2ivfQOYqLi5PX6w3pBTH7x3To2Gw2W+Av2MzMzBbNx5G2\nF07hyBwzZoyGDRuml156ScnJyYf9/BITE5WXl6dZs2ape/fu6tatW7PGEx8fr4yMDF177bVKTExU\n7969tX37diUnJx+2zxz672XLlumUU07RRRdddFB+Y/tdSkqKTjjhBI0dO1adO3fWmWeeqZqaGp17\n7rnyer2aN29eyK8B6N+/v2666SY5HI6Q7n+o/ePdsGGDXn31Vfl8Pk2ZMqVFeUeSnp4eODUdFxen\nESNGhJxrs9lUVFSk2bNny+/3KyoqSvfff7+kn+Zn/Pjx+vOf/9xo3vnnn69vvvlGNptNAwYMUEVF\nhU444YTAdjIyMvTII48c8Y/6xp7rjT0vDnT66acrNzdXcXFxOvnkk496yny/luwbweybNptNN998\ns+6+++7A7+L77rtPkZGRIe3jNptNu3fv1q9//Wvt2bNHRUVF2rZtm8aPH6+ePXsedBCWmpqqO+64\nQw899FDQ25H4LG4cJxMnTtTdd9+tXr16He+hWKqmpkZ33nmnnn766eM9FMAo7BtNM/IUN9quvXv3\nasyYMerTp0+bL+fXX39d48aN0+9+97vjPRTAKOwbzcMRNAAABuIIGgAAA1HQAAAYiIIGAMBAFDQA\nAAaioAEAMND/A8NudfT377dBAAAAAElFTkSuQmCC\n", + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "topfreq=L[:20]\n", + "print topfreq\n", + "pos = np.arange(len(topfreq))\n", + "plt.bar(pos, [e[1] for e in topfreq]);\n", + "plt.xticks(pos+0.4, [e[0] for e in topfreq]);" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 2", + "language": "python", + "name": "python2" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 2 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython2", + "version": "2.7.10" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} diff --git a/Lab1-git_original.ipynb b/Lab1-git_original.ipynb new file mode 100644 index 0000000..383225d --- /dev/null +++ b/Lab1-git_original.ipynb @@ -0,0 +1,2012 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Lab 1: Version Control with Git" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**This tutorial is largely based on the repository**:\n", + "\n", + "git@github.com:rdadolf/git-and-github.git\n", + "\n", + "**which was created for IACS's ac297r course, By Robert Adolf. Most of the credit goes to him**.\n", + "\n", + "Version control is a way of tracking the change history of a project. Even if you have never used a version control tool, you've probably already done it manually: copying and renaming project folders (\"paper-1.doc\", \"paper-2.doc\", etc.) is a form of version control.\n", + "\n", + "Git is a tool that automates and enhances a lot of the tasks that arise when dealing with larger, longer-living, and collaborative projects. It's also become the common underpinning to many popular online code repositories, [GitHub](https://github.com/) being the most popular.\n", + "\n", + "We'll go over the basics of git, but we should point out that a *lot* of talented people have given git tutorials, and we won't do any better than they have. In fact, if you're interested in learning git deeply and have some time on your hands, I suggest you stop reading this and instead read [the Git Book](http://git-scm.com/book/en/v2). Scott Chacon and Ben Straub have done a tremendous job, and if you want to understand both the interfaces and the mechanisms behind git, this is the place to start.\n", + "\n", + "In this document, we'll go over the concepts of git that are relevant to this course. You will be using git in a particular fashion, in this course, which is described in Homework 0. Homework 0 also contains details about how to install git; so if you havent done so, please do so and come back here." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#Table of Contents\n", + "* [Lab 1: Version Control with Git](#Lab-1:-Version-Control-with-Git)\n", + "\t* [Why should you use version control?](#Why-should-you-use-version-control?)\n", + "\t* [Git Basics](#Git-Basics)\n", + "\t* [Common Tasks in the version control of files.](#Common-Tasks-in-the-version-control-of-files.)\n", + "\t\t* [Forking a repository](#Forking-a-repository)\n", + "\t\t* [Cloning a repository](#Cloning-a-repository)\n", + "\t\t* [Poking around](#Poking-around)\n", + "\t\t* [Making changes](#Making-changes)\n", + "\t\t* [Remotes and `fetch`ing from them](#Remotes-and-fetching-from-them)\n", + "\t\t* [Branching.](#Branching.)\n", + "\t\t* [Recovering from a mistake](#Recovering-from-a-mistake)\n", + "\t\t* [Changing only one file](#Changing-only-one-file)\n", + "\t* [The Homework git flow](#The-Homework-git-flow)\n", + "\t* [The Lab git flow](#The-Lab-git-flow)\n", + "\t* [Creating a new repository](#Creating-a-new-repository)\n", + "\t* [Github Pages](#Github-Pages)\n", + "\t\t* [Automatically Generated Project Pages](#Automatically-Generated-Project-Pages)\n", + "\t\t* [Static Project Pages](#Static-Project-Pages)\n", + "\t* [Git habits](#Git-habits)\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**At this point, we assume you have installed git as described in HW0 and have followed the instructions there to create ssh keys for your machine**. This enables you to use git without a pesky username-password combination." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "----" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Why should you use version control?" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If you ask 10 people, you'll get 10 different answers, but one of the commonalities is that most people don't realize how integral it is to their development process until they've started using it. Still, for the sake of argument, here are some highlights:\n", + "\n", + "- ** You can undo anything: ** Git provides a *complete history* of every change that has ever been made to your project, timestamped, commented, and attributed. If something breaks, you always have the choice of going back to a previous state.\n", + "- ** You won't *need* to keep undo-ing things: ** One of the advantages of using git properly is that by keeping new changes separate from a stable base, you tend to avoid the massive rollbacks associated with constantly tinkering with a single code.\n", + "- ** You can identify exactly when and where changes were made: ** Git allows you to pinpoint when a particular piece of code was changed, so finding what other pieces of code a bug might affect or figuring out why a certain expression was added is easy.\n", + "- ** Git forces teams to face conflicts directly: ** On a team-based project, many people are often working with the same code. By having a tool which understands when and where files were changed, it's easy to see when changes might conflict with each other. While it might seem troublesome sometimes to have to deal with conflicts, the alternative—*not* knowing there's a conflict—is much more insidious." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "----" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Git Basics" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The first thing to understand about git is that the contents of your project are stored in several different states and forms at any given time. If you think about what version control is, this might not be surprising: in order to remember every change that's ever been made, you need to store a record of those changes *somewhere*, and to be able to handle multiple people changing the same code, you need to have different copies of the project and a way to combine them.\n", + "\n", + "You can think about git operating on four different areas:\n", + "\n", + "![Git Commands](git_layout.png)\n", + "\n", + " - The **working directory** is what you're currently looking at. When you use an editor to modify a file, the changes are made to the working directory.\n", + " - The **staging area** is a place to collect a set of changes made to your project. If you have changed three files to fix a bug, you will add all three to the staging area so that you can remember the changes as one historical entity. It is also called the **index**. You move files from the working directory to the index using the command `git add`.\n", + " - The **local repository** is the place where git stores everything you've ever done to your project. Even when you delete a file, a copy is stored in the repo (this is necessary for always being able to undo any change). It's important to note that a local repository doesn't look much at all like your project files or directories. Git has its own way of storing all the information, and if you're curious what it looks like, look in the `.git` directory in the working directory of your project. Files are moved from the index to the local repository via the command `git commit`.\n", + " - When working in a team, every member will be working on their own local repository. An **upstream repository** allows everyone to agree on a single version of history. If two people have made changes on their local repositories, they will combine those changes in the upstream repository. In our case this upstream repository is hosted by github. This need not be the case; SEAS provides git hosting, as do companies like Atlassian (bitbucket). This upstream repository is also called a **remote** in git parlance. The standard github remote is called the **origin**: it is the repository which is given a web page on github. One usually moves code from local to remote repositories using `git push`, and in the other direction using `git fetch`.\n", + "\n", + "You can think of most git operations as moving code or metadata from one of these areas to another." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "----" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Common Tasks in the version control of files." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Forking a repository" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Forking a repository done on github. On github, go to the url https://github.com/cs109/Testing. Click the \"Fork button on the upper right side. A screenshot is below. \n", + "\n", + "![forking](github-forking.png)\n", + "\n", + "Forking brings a repository into your own namespace. Its really a *cloning* process (see below), but its done between two \"remotes\" on the server. In other words it creates a second upstream repository on the server, called the **origin**.\n", + "\n", + "The forking process on github will ask you *where* you want to fork the repository. Choose your own github id.\n", + "\n", + "![forking](github-forking2.png)\n", + "\n", + "In my case I will choose `@rahuldave`, as in the screenshot above. In this tutorial, wherever you see `rahuldave`, substitute your own github id.\n", + "\n", + "This leaves me with my own repository, `rahuldave/Testing`, as seen in this image\n", + "\n", + "![forking](github-forking3.png)\n", + "\n", + "You will get a similar page." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Cloning a repository" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now that we have a **fork** of the `cs109/Testing` repository, lets **clone** it down to our local machines." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "----\n", + "`clone`\n", + "\n", + "![clone](git_clone.png)\n", + "\n", + "Cloning a repository does two things: it takes a repository from somewhere (usually an **upstream repository**) and makes a local copy (your new **local repository**), and it creates the most recent copy of all of the files in the project (your new **working directory**). This is generally how you will start working on a project for the first time." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Cloning a repository depends a lot on the type of repository you're using. If you're cloning out of a directory on the machine you're currently on, it's just the path to the `.git` file. For github, you can clone over ssh using the SSH clone url in the bottom right corner of the last screenshot. (This assumes you have set up your ssh keys. See HW0 for how to do this if you havent done it as yet)." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Cloning into 'Testing'...\n" + ] + } + ], + "source": [ + "%%bash\n", + "cd /tmp\n", + "rm -rf Testing #remove if it exists\n", + "git clone git@github.com:rahuldave/Testing.git" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "LICENSE\n", + "README.md\n", + "hello.md\n" + ] + } + ], + "source": [ + "%%bash\n", + "ls /tmp/Testing" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "###Poking around" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We have a nice smelling fresh repository. Lets look around it.\n", + "\n", + "`log`\n", + "\n", + "Log tells you all the changes that have occured in this project as of now..." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\u001b[33mcommit 3a2909aa790f041f1426e51565674165e52acdc8\u001b[m\r\n", + "Author: Rahul Dave \r\n", + "Date: Fri Aug 28 02:44:21 2015 -0400\r\n", + "\r\n", + " Added a test file to demonstrate git features\r\n", + "\r\n", + "\u001b[33mcommit 98bd53e8117d85cf0f7978f6aca22ce90ebc9709\u001b[m\r\n", + "Author: Rahul Dave \r\n", + "Date: Fri Aug 28 02:23:32 2015 -0400\r\n", + "\r\n", + " Attributed the test file to A.\r\n", + "\r\n", + "\u001b[33mcommit 5bd2f661fb25953b444bd5e8ba9557456406ece0\u001b[m\r\n", + "Author: Rahul Dave \r\n", + "Date: Fri Aug 28 02:21:57 2015 -0400\r\n", + "\r\n", + " Added a test file to demonstrate git features\r\n", + "\r\n", + "\u001b[33mcommit 45c25a4d944ad583a383fb7b35f185750e9b5b9c\u001b[m\r\n", + "Author: Rahul Dave \r\n", + "Date: Fri Aug 28 02:19:02 2015 -0400\r\n", + "\r\n", + " Added a test file to demonstrate git features\r\n", + "\r\n", + "\u001b[33mcommit 11961a3e0d50ea2ede1265da4bf586c001e63d7b\u001b[m\r\n", + "Author: Rahul Dave \r\n", + "Date: Fri Aug 28 01:55:49 2015 -0400\r\n", + "\r\n", + " Initial commit\r\n" + ] + } + ], + "source": [ + "!cd /tmp/Testing; git log" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Each one of these \"commits\" is a SHA hash. It uniquely identifies all actions that have happened to this repository previously. We shall soon see how to add our own actions in. In the meanwhile, lets see the \"status\"of our working directory." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If you ever need help on a command, you can find the git man pages by hyphenating `git` and the command name:" + ] + }, + { + "cell_type": "raw", + "metadata": {}, + "source": [ + "$man git-status" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "----\n", + "`status`\n", + "\n", + "![status](git_status.png)\n", + "\n", + "Status is your window into the current state of your project. It can tell you which files you have changed and which files you currently have in your staging area." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "On branch master\r\n", + "Your branch is up-to-date with 'origin/master'.\r\n", + "\r\n", + "nothing to commit, working directory clean\r\n" + ] + } + ], + "source": [ + "!cd /tmp/Testing; git status" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Pay close attention to the text above. It says we are on the master branch of our **local repository**, and that this branch is up-to-date with the master branch of the **upstream repository** or **remote** named **origin**. We know this as clone brings down a copy of the remote branch: \"`origin/master`\" represents the local copy of the branch that came from the upstream repository (nicknamed \"`origin`\" in this case). **Branches** are different, co-existing versions of your project. Here we have encountered two of them, but remember there is a third one in the repository we forked from, and perhaps many more, depending on who else made these forks (as well as my original clones of cs109/Testing).\n", + "\n", + "This sounds like a recipe for disaster, but in a sense, branches are just like commits. They represent a snapshot of the project, by someone, at some particular point in time. In general you will only care about your own branches, and those of the \"parent\" remotes you forked/cloned from.\n", + "\n", + "Configuration Information is stored in a special file `config`, in a hidden folder called `.git` in your working directory. (The index and the local repository are stored there as well...more on that in a bit)" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[core]\r\n", + "\trepositoryformatversion = 0\r\n", + "\tfilemode = true\r\n", + "\tbare = false\r\n", + "\tlogallrefupdates = true\r\n", + "\tignorecase = true\r\n", + "\tprecomposeunicode = true\r\n", + "[remote \"origin\"]\r\n", + "\turl = git@github.com:rahuldave/Testing.git\r\n", + "\tfetch = +refs/heads/*:refs/remotes/origin/*\r\n", + "[branch \"master\"]\r\n", + "\tremote = origin\r\n", + "\tmerge = refs/heads/master\r\n" + ] + } + ], + "source": [ + "!cd /tmp/Testing; cat .git/config" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Notice that this file tells us about a remote called \"origin\" which is simply the github repository we cloned from. So the process of cloning left us with a remote. The file also tells us about a branch called \"master\", which \"tracks\" a remote branch valled master at \"origin\". \n", + "\n", + "Finally I set us up with a `.gitignore` file, hidden in the repository folder. It tells us what files to ignore when adding files to the index, and then comitting them to the local repository. We use this file to ignore temporary data files and such when working in our repository. Folders are indicated with a `/` at the end, in which case, all files in that folder are ignored." + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "# Byte-compiled / optimized / DLL files\r\n", + "__pycache__/\r\n", + "*.py[cod]\r\n", + "\r\n", + "# C extensions\r\n", + "*.so\r\n", + "\r\n", + "# Distribution / packaging\r\n", + ".Python\r\n", + "env/\r\n", + "build/\r\n", + "develop-eggs/\r\n", + "dist/\r\n", + "downloads/\r\n", + "eggs/\r\n", + ".eggs/\r\n", + "lib/\r\n", + "lib64/\r\n", + "parts/\r\n", + "sdist/\r\n", + "var/\r\n", + "*.egg-info/\r\n", + ".installed.cfg\r\n", + "*.egg\r\n", + "\r\n", + "# PyInstaller\r\n", + "# Usually these files are written by a python script from a template\r\n", + "# before PyInstaller builds the exe, so as to inject date/other infos into it.\r\n", + "*.manifest\r\n", + "*.spec\r\n", + "\r\n", + "# Installer logs\r\n", + "pip-log.txt\r\n", + "pip-delete-this-directory.txt\r\n", + "\r\n", + "# Unit test / coverage reports\r\n", + "htmlcov/\r\n", + ".tox/\r\n", + ".coverage\r\n", + ".coverage.*\r\n", + ".cache\r\n", + "nosetests.xml\r\n", + "coverage.xml\r\n", + "*,cover\r\n", + "\r\n", + "# Translations\r\n", + "*.mo\r\n", + "*.pot\r\n", + "\r\n", + "# Django stuff:\r\n", + "*.log\r\n", + "\r\n", + "# Sphinx documentation\r\n", + "docs/_build/\r\n", + "\r\n", + "# PyBuilder\r\n", + "target/\r\n" + ] + } + ], + "source": [ + "!cd /tmp/Testing; cat .gitignore" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "You are always working on a given branch in a repository. Typically this is `master`. More on this later..You can know which branch you are on by typing `git branch`. The strred one is the one you are on." + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "* \u001b[32mmaster\u001b[m\r\n" + ] + } + ], + "source": [ + "!cd /tmp/Testing; git branch" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Making changes" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Ok! Enough poking around. Lets get down to business and add some files into our folder.\n", + "\n", + "Now let's say that we want to add a new file to the project. The canonical sequence is \"edit–add–commit–push\"." + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "On branch master\n", + "Your branch is up-to-date with 'origin/master'.\n", + "\n", + "Changes not staged for commit:\n", + " (use \"git add ...\" to update what will be committed)\n", + " (use \"git checkout -- ...\" to discard changes in working directory)\n", + "\n", + "\tmodified: hello.md\n", + "\n", + "no changes added to commit (use \"git add\" and/or \"git commit -a\")\n" + ] + } + ], + "source": [ + "%%bash\n", + "cd /tmp/Testing\n", + "echo '# Hello world rahuldave' > hello.md\n", + "git status" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We've added a file to the working directory, but it hasn't been staged yet." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "----\n", + "`add`\n", + "\n", + "![add](git_add.png)\n", + "\n", + "When you've made a change to a set of files and are ready to create a commit, the first step is to add all of the changed files to the staging area. Add does that. Remember that what you see in the filesystem is your working directory, so the way to see what's in the staging area is with the `status` command. This also means that **if you add something to the staging area and then edit it again, you'll also need to add the file to the staging area again if you want to remember the new changes**." + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "On branch master\n", + "Your branch is up-to-date with 'origin/master'.\n", + "\n", + "Changes to be committed:\n", + " (use \"git reset HEAD ...\" to unstage)\n", + "\n", + "\tmodified: hello.md\n", + "\n" + ] + } + ], + "source": [ + "%%bash\n", + "cd /tmp/Testing\n", + "git add hello.md\n", + "git status" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now our file is in the staging area (Index), waiting to be committed.\n", + "\n", + "I will sometimes simply use `git add .` in the top level of the repository. This adds all new files and changed files to the index, and is particularly useful if I have created multiple new files." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "----\n", + "`commit`\n", + "\n", + "![commit](git_commit.png)\n", + "\n", + "When you're satisfied with the changes you've added to your staging area, you can commit those changes to your local repository with the `commit` command. Those changes will have a permanent record in the repository from now on." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Every commit has two features you should be aware of. The first is a hash. This is a unique identifier for all of the information about that commit, including the code changes, the timestamp, and the author. The second is a commit message. This is text that you can (and should) add to a commit to describe what the changes were.\n", + "\n", + "**Good commit messages are important.**\n", + "\n", + "Commit messages are a way of quickly telling your future self (and your collaborators) what a commit was about. For even a moderately sized project, digging through tens or hundreds of commits to find the change you're looking for is a nightmare without friendly summaries.\n", + "\n", + "By convention, commit messages start with a single-line summary, then an empty line, then a more comprehensive description of the changes.\n", + "\n", + "[This](https://github.com/rdadolf/clangtool/commit/bdd8f1290146c28a4cb05b62ccb0ffbaaa314ff7) is an okay commit message. The changes are small, and the summary is sufficient to describe what happened.\n", + "\n", + "[This](https://github.com/rdadolf/protos/commit/9fcbe1084b17027e003c62043d764ed5551ddadc) is better. The summary captures the important information (major shift, direct vs. helper), and the full commit message describes what the high-level changes were.\n", + "\n", + "[This](https://github.com/rdadolf/autopaxos/commit/d43dd9b0a699c98bd142ba7cbc1836fbc4eba2ac). Don't do this." + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[master 2e12653] Said hello to myself\n", + " 1 file changed, 1 insertion(+), 1 deletion(-)\n", + "On branch master\n", + "Your branch is ahead of 'origin/master' by 1 commit.\n", + " (use \"git push\" to publish your local commits)\n", + "\n", + "nothing to commit, working directory clean\n" + ] + } + ], + "source": [ + "%%bash\n", + "cd /tmp/Testing\n", + "git commit -m \"Said hello to myself\"\n", + "git status" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The `git commit -m...` version is just a way to specify a commit message without opening a text editor (ipython notebook can't handle it). Otherwise you just say `git commit` or `git commit -a` (if you `add`ed a new file to the current branch on the repository)\n", + "\n", + "Now we see that our branch, \"`master`\", has one more commit than the \"`origin/master`\" branch, the local copy of the branch that came from the upstream repository (nicknamed \"`origin`\" in this case). Let's push the changes." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "`push`\n", + "\n", + "![push](git_push.png)\n", + "\n", + "The `push` command takes the changes you have made to your local repository and attempts to update a remote repository with them. If you're the only person working with both of these (which is how a solo GitHub project would work), then push should always succeed." + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Counting objects: 5, done.\n", + "Delta compression using up to 4 threads.\n", + "Compressing objects: 100% (2/2), done.\n", + "Writing objects: 100% (3/3), 286 bytes | 0 bytes/s, done.\n", + "Total 3 (delta 1), reused 0 (delta 0)\n", + "To git@github.com:rahuldave/Testing.git\n", + " 3a2909a..2e12653 master -> master\n", + "On branch master\n", + "Your branch is up-to-date with 'origin/master'.\n", + "\n", + "nothing to commit, working directory clean\n" + ] + } + ], + "source": [ + "!cd /tmp/Testing; git push\n", + "!cd /tmp/Testing; git status" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "###Remotes and `fetch`ing from them" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If you're working with other people, then it's possible that they have made changes to the remote repository between the time you first cloned it and now. `push` will fail. \n", + "\n", + "In our particular case of the `Testing` repository, this is not going to happen, since you just cloned it and presumably havent invited anyone to collaborate with you on it (you can do this from the settings link on the right side of the repository page). \n", + "\n", + "However you can imagine that the original repository `cs109/testing`, which you are now divorced from, has changed, and that you somehow want to pull those changes in.\n", + "\n", + "That's where the next two commands come in." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "---\n", + "\n", + "`remote`\n", + "\n", + "We have seen so far that our repository has one \"remote\", or upstream repository, which has been identified with the word `origin`, as seen in `.git/config`. We now wish to add another remote, which we shall call `course`, which points to the original repository we forked from. We want to do this to pull in changes, in-case something changed there." + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[core]\r\n", + "\trepositoryformatversion = 0\r\n", + "\tfilemode = true\r\n", + "\tbare = false\r\n", + "\tlogallrefupdates = true\r\n", + "\tignorecase = true\r\n", + "\tprecomposeunicode = true\r\n", + "[remote \"origin\"]\r\n", + "\turl = git@github.com:rahuldave/Testing.git\r\n", + "\tfetch = +refs/heads/*:refs/remotes/origin/*\r\n", + "[branch \"master\"]\r\n", + "\tremote = origin\r\n", + "\tmerge = refs/heads/master\r\n", + "[remote \"course\"]\r\n", + "\turl = git@github.com:cs109/Testing.git\r\n", + "\tfetch = +refs/heads/*:refs/remotes/course/*\r\n" + ] + } + ], + "source": [ + "!cd /tmp/Testing; git remote add course git@github.com:cs109/Testing.git\n", + "!cd /tmp/Testing; cat .git/config" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Notice that the `master` branch only tracks the same branch on the `origin` remote. We havent set up any connection with the `course` remote as yet.\n", + "\n", + "Now lets figure out how to get changes from an upstream repository, be it our `origin` upstream that a collaborator has `push`ed too, or another `course` remote to which your memory-added head TF has posted a change!" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "----\n", + "`fetch`\n", + "\n", + "![fetch](git_fetch.png)\n", + "\n", + "Let's say a collaborator has pushed changes to your shared upstream repository while you were editing. Their local repository and the upstream repository now both contain their changes, but your local repository does not. To update your local repository, you run `fetch`.\n", + "\n", + "But what if you've committed changes in the meantime? Does your local repository contain your changes or theirs? The answer is that it contains a *record* of both, but they are kept separate. Remember that git repositories are not copies of your project files. They store all the contents of your files, along with a bunch of metadata, but in its own internal format. This is one of the reasons.\n", + "\n", + "Let's say that you and your collaborator both edited the same line of the same file at the same time in different ways. On your respective machines, you both add and commit your different changes, and your collaborator pushes theirs to the upstream repository. When you run `fetch`, git adds a record of their changes to your local repository *alongside* your own. These are called *branches*, and they represent different, coexisting versions of your project. The `fetch` command adds your collaborator's branch to your local repository, but keeps yours as well." + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "remote: Counting objects: 3, done.\u001b[K\n", + "remote: Compressing objects: 100% (2/2), done.\u001b[K\n", + "remote: Total 3 (delta 1), reused 3 (delta 1), pack-reused 0\u001b[K\n", + "Unpacking objects: 100% (3/3), done.\n", + "From github.com:cs109/Testing\n", + " * [new branch] master -> course/master\n" + ] + } + ], + "source": [ + "!cd /tmp/Testing; git fetch course" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "You can see that a copy of a new remote branch has been made below, by providing the `-avv` argument to `git branch`." + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "* \u001b[32mmaster \u001b[m 2e12653 [\u001b[34morigin/master\u001b[m] Said hello to myself\r\n", + " \u001b[31mremotes/course/master\u001b[m 7ba94f7 added a line in readme\r\n", + " \u001b[31mremotes/origin/HEAD \u001b[m -> origin/master\r\n", + " \u001b[31mremotes/origin/master\u001b[m 2e12653 Said hello to myself\r\n" + ] + } + ], + "source": [ + "!cd /tmp/Testing; git branch -avv" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Indeed, the way git works is by creating copies of remote branches locally. Then it just compares to these \"copy\" branches to see what changes have been made.\n", + "\n", + "Sometimes we want to merge the changes in...precisely we want to merge the change from `remotes/course/master` in. In HW0 and later here, we'll show you a case where you want to simply create another branch." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "----\n", + "`merge`\n", + "\n", + "![merge](git_merge.png)\n", + "\n", + "Having multiple branches is fine, but at some point, you'll want to combine the changes that you've made with those made by others. This is called merging.\n", + "\n", + "There are two general cases when merging two branches: first, the two branches are different but the changes are in unrelated places; and second, the two branches are different and the changes are in the same locations in the same files.\n", + "\n", + "The first scenario is easy. Git will simply apply both sets of changes to the appropriate places and put the resulting files into the staging area for you. Then you can commit the changes and push them back to the upstream repository. Your collaborator does the same, and everyone sees everything.\n", + "\n", + "The second scenario is more complicated. Let's say the two changes set some variable to different values. Git can't know which is the correct value. One solution would be to simply use the more recent change, but this very easily leads to self-inconsistent programs. A more conservative solution, and the one git uses, is to simply leave the decision to the user. When git detects a conflict that it cannot resolve, `merge` fails, and git places a modified version of the offending file in your project directory. **This is important:** the file that git puts into your directory is not actually *either* of the originals. It is a new file that has special markings around the locations that conflicted. We shall not consider this case in this lab, deferring it to a time just before you work with other collaborators on your projects.\n", + "\n", + "Lets merge in the changes from `course/master`:" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Merge made by the 'recursive' strategy.\n", + " README.md | 2 ++\n", + " 1 file changed, 2 insertions(+)\n", + "On branch master\n", + "Your branch is ahead of 'origin/master' by 2 commits.\n", + " (use \"git push\" to publish your local commits)\n", + "\n", + "nothing to commit, working directory clean\n" + ] + } + ], + "source": [ + "%%bash\n", + "cd /tmp/Testing\n", + "git merge course/master\n", + "git status" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We seem to be ahead of our upstream-tracking repository by 2 commits..why?" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\u001b[33mcommit a59261af6004b6a3d967fba0fb7f799240366c51\u001b[m\r\n", + "Merge: 2e12653 7ba94f7\r\n", + "Author: Rahul Dave \r\n", + "Date: Tue Sep 1 23:37:27 2015 -0400\r\n", + "\r\n", + " Merge remote-tracking branch 'course/master'\r\n", + "\r\n", + "\u001b[33mcommit 7ba94f7e4ed9506b0b3eab02e03d516c2b38977e\u001b[m\r\n", + "Author: Rahul Dave \r\n", + "Date: Tue Sep 1 22:53:03 2015 -0400\r\n", + "\r\n", + " added a line in readme\r\n", + "\r\n", + "\u001b[33mcommit 2e1265352da452320b67c3e5496ee1367f68663d\u001b[m\r\n", + "Author: Rahul Dave \r\n", + "Date: Tue Sep 1 21:19:31 2015 -0400\r\n", + "\r\n", + " Said hello to myself\r\n" + ] + } + ], + "source": [ + "!cd /tmp/Testing; git log -3" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Aha: one commit came from the `course` upstream, and one was a merge commit. In the case you had edited the README.md at the same time and comitted locally, you would have been asked to resolve the conflict in the merge (the second case above).\n", + "\n", + "Lets push these changes to the origin now" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "On branch master\n", + "Your branch is up-to-date with 'origin/master'.\n", + "\n", + "nothing to commit, working directory clean\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "To git@github.com:rahuldave/Testing.git\n", + " 2e12653..a59261a master -> master\n" + ] + } + ], + "source": [ + "%%bash\n", + "cd /tmp/Testing\n", + "git push\n", + "git status" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "You can combine a fetch and a merge together by simply doing a git `pull`. This will fail if you and your collaborator have worked on the same file (since you will have to merge by hand), but is a great shortcut when the files worked on are different. I use it all the times on a personal level too, to shift work between two different machines, as long as I am not working on both at the same time. The usual use case is day work on a work computer, and then evening work at home on the laptop. Read the docs if you are interested." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "###Branching." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "As you might have seen by now, everything in git is a branch. We have branches on remote (upstream) repositories, copies of remote branches in our local repository, and branches on local repositories which (so far) track remote branches (or more precisely local copies of remote repositories)" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "* \u001b[32mmaster \u001b[m a59261a [\u001b[34morigin/master\u001b[m] Merge remote-tracking branch 'course/master'\r\n", + " \u001b[31mremotes/course/master\u001b[m 7ba94f7 added a line in readme\r\n", + " \u001b[31mremotes/origin/HEAD \u001b[m -> origin/master\r\n", + " \u001b[31mremotes/origin/master\u001b[m a59261a Merge remote-tracking branch 'course/master'\r\n" + ] + } + ], + "source": [ + "!cd /tmp/Testing; git branch -avv" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "And all of these branches are nothing but commit-streams in disguise, as can be seen above. Its a very simple model which leads to a lot of interesting version control patterns.\n", + "\n", + "Since branches are so light-weight, the recommended way of working on software using git is to create a new branch for each new feature you add, test it out, and if good, merge it into master. Then you deploy the software from master. But we have been using branches under the hood. Lets now lift the hood.\n", + "\n", + "----\n", + "`branch`\n", + "\n", + "![branch](git_branch.png)\n", + "\n", + "Branches can also be created manually, and they are a useful way of organizing unfinished changes.\n", + "\n", + "The `branch` command has two forms. The first:\n", + "\n", + "`git branch`" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "simply lists all of the branches in your local repository. If you run it without having created any branches, it will list only one, called `master`. This is the default branch. You have seen the use of `git branch -avv` to show all branches.\n", + "\n", + "The other form creates a branch with a given name:" + ] + }, + { + "cell_type": "raw", + "metadata": {}, + "source": [ + "$ git branch my-new-branch" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "It's important to note that the other branch is not *active*. If you make changes, they will still apply to the `master` branch, not `my-new-branch`. To change this, you need the next command." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "----\n", + "`checkout`\n", + "\n", + "![checkout](git_checkout.png)\n", + "\n", + "Checkout switches the active branch. Since branches can have different changes, `checkout` may make the working directory look very different. For instance, if you have added new files to one branch, and then check another branch out, those files will no longer show up in the directory. They are still stored in the `.git` folder, but since they only exist in the other branch, they cannot be accessed until you check out the original branch." + ] + }, + { + "cell_type": "raw", + "metadata": {}, + "source": [ + "# Example\n", + "$ git checkout my-new-branch" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "You can combine creating a new branch and checking it out with the shortcut:" + ] + }, + { + "cell_type": "raw", + "metadata": {}, + "source": [ + "# Example\n", + "$ git checkout -b my-new-branch" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Ok so lets try this out on our repository...." + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "!cd /tmp/Testing; git branch mybranch1" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "See what branches we have created..." + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "* \u001b[32mmaster\u001b[m\r\n", + " mybranch1\u001b[m\r\n" + ] + } + ], + "source": [ + "!cd /tmp/Testing; git branch " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Jump onto the `mybranch1` branch..." + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Switched to branch 'mybranch1'\r\n", + " master\u001b[m\r\n", + "* \u001b[32mmybranch1\u001b[m\r\n" + ] + } + ], + "source": [ + "!cd /tmp/Testing; git checkout mybranch1; git branch" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Notice that it is bootstrapped off the `master` branch and has the same files." + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "LICENSE README.md hello.md\r\n" + ] + } + ], + "source": [ + "!cd /tmp/Testing; ls" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Jump back to master...." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "You could have created this branch using `git checkout -b mybranch1`. Lets see the status here." + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "On branch mybranch1\r\n", + "nothing to commit, working directory clean\r\n" + ] + } + ], + "source": [ + "!cd /tmp/Testing; git status" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Lets add a new file...note that this file gets added on this branch only" + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "On branch mybranch1\r\n", + "Untracked files:\r\n", + " (use \"git add ...\" to include in what will be committed)\r\n", + "\r\n", + "\t\u001b[31mworld.md\u001b[m\r\n", + "\r\n", + "nothing added to commit but untracked files present (use \"git add\" to track)\r\n" + ] + } + ], + "source": [ + "!cd /tmp/Testing; echo '# Hello world' > world.md\n", + "!cd /tmp/Testing; git status" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We add the file to the index, and then commit the files to the local repository on the `mybranch` branch." + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "On branch mybranch1\r\n", + "Changes to be committed:\r\n", + " (use \"git reset HEAD ...\" to unstage)\r\n", + "\r\n", + "\t\u001b[32mnew file: world.md\u001b[m\r\n", + "\r\n" + ] + } + ], + "source": [ + "!cd /tmp/Testing; git add .\n", + "!cd /tmp/Testing; git status\n" + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[mybranch1 1ffe3d7] Added another test file to demonstrate git features\n", + " 1 file changed, 1 insertion(+)\n", + " create mode 100644 world.md\n", + "On branch mybranch1\n", + "nothing to commit, working directory clean\n" + ] + } + ], + "source": [ + "!cd /tmp/Testing; git commit -m \"Added another test file to demonstrate git features\" -a\n", + "!cd /tmp/Testing;git status" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Ok we have committed. Lets try to push!" + ] + }, + { + "cell_type": "code", + "execution_count": 36, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "fatal: The current branch mybranch1 has no upstream branch.\r\n", + "To push the current branch and set the remote as upstream, use\r\n", + "\r\n", + " git push --set-upstream origin mybranch1\r\n", + "\r\n" + ] + } + ], + "source": [ + "!cd /tmp/Testing; git push" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Oops that failed. Why? git didnt know what to push to on origin, and didnt want to assume we wanted to call the branch `mybranch1` on the remote. We need to tell that to git explicitly, as it tells us to." + ] + }, + { + "cell_type": "code", + "execution_count": 38, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Counting objects: 4, done.\n", + "Delta compression using up to 4 threads.\n", + "Compressing objects: 100% (2/2), done.\n", + "Writing objects: 100% (3/3), 308 bytes | 0 bytes/s, done.\n", + "Total 3 (delta 1), reused 1 (delta 0)\n", + "To git@github.com:rahuldave/Testing.git\n", + " * [new branch] mybranch1 -> mybranch1\n", + "Branch mybranch1 set up to track remote branch mybranch1 from origin.\n" + ] + } + ], + "source": [ + "!cd /tmp/Testing; git push --set-upstream origin mybranch1" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Aha, now we are set my with both a remote and a local for `mybranch1`" + ] + }, + { + "cell_type": "code", + "execution_count": 39, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " master \u001b[m a59261a [\u001b[34morigin/master\u001b[m] Merge remote-tracking branch 'course/master'\r\n", + "* \u001b[32mmybranch1 \u001b[m 1ffe3d7 [\u001b[34morigin/mybranch1\u001b[m] Added another test file to demonstrate git features\r\n", + " \u001b[31mremotes/course/master \u001b[m 7ba94f7 added a line in readme\r\n", + " \u001b[31mremotes/origin/HEAD \u001b[m -> origin/master\r\n", + " \u001b[31mremotes/origin/master \u001b[m a59261a Merge remote-tracking branch 'course/master'\r\n", + " \u001b[31mremotes/origin/mybranch1\u001b[m 1ffe3d7 Added another test file to demonstrate git features\r\n" + ] + } + ], + "source": [ + "!cd /tmp/Testing; git branch -avv" + ] + }, + { + "cell_type": "code", + "execution_count": 40, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Switched to branch 'master'\r\n", + "Your branch is up-to-date with 'origin/master'.\r\n" + ] + } + ], + "source": [ + "!cd /tmp/Testing; git checkout master" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "###Recovering from a mistake" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now suppose for a second that this `mybranch1` was created by someone else. We wanted to get it down using `fetch` and play. But we called `pull`, which did an automatic merge for us." + ] + }, + { + "cell_type": "code", + "execution_count": 41, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "From github.com:rahuldave/Testing\n", + " * branch mybranch1 -> FETCH_HEAD\n", + "Updating a59261a..1ffe3d7\n", + "Fast-forward\n", + " world.md | 1 \u001b[32m+\u001b[m\n", + " 1 file changed, 1 insertion(+)\n", + " create mode 100644 world.md\n" + ] + } + ], + "source": [ + "!cd /tmp/Testing; git pull origin mybranch1" + ] + }, + { + "cell_type": "code", + "execution_count": 42, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "On branch master\r\n", + "Your branch is ahead of 'origin/master' by 1 commit.\r\n", + " (use \"git push\" to publish your local commits)\r\n", + "\r\n", + "nothing to commit, working directory clean\r\n" + ] + } + ], + "source": [ + "!cd /tmp/Testing; git status" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "oops, that was not what we wanted. We undo it using `git reset`, to go back to the state at the last commit." + ] + }, + { + "cell_type": "code", + "execution_count": 43, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "HEAD is now at a59261a Merge remote-tracking branch 'course/master'\r\n" + ] + } + ], + "source": [ + "!cd /tmp/Testing; git reset --hard origin/master" + ] + }, + { + "cell_type": "code", + "execution_count": 44, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "On branch master\r\n", + "Your branch is up-to-date with 'origin/master'.\r\n", + "\r\n", + "nothing to commit, working directory clean\r\n" + ] + } + ], + "source": [ + "!cd /tmp/Testing; git status" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "###Changing only one file" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The last git command I want to talk about, since it might come handy in the course, is the situation in which you dont want to merge an entire branch from the upstream, but just one file from it. There is a direct use case for it. Indeed, suppose I've made an error in this lab and want to correct it. So i fix it in the upstream. In the meanwhile you have edited some other files. You dont care to manually ignore my older copies of those files. So you want to fix just one file from this new branch. This is how you do it.\n", + "\n", + "First you fetch from the remote (i ought to be doing this with the course remote but just want to illustrate it here)" + ] + }, + { + "cell_type": "code", + "execution_count": 45, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "!cd /tmp/Testing; git fetch origin" + ] + }, + { + "cell_type": "code", + "execution_count": 46, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "* \u001b[32mmaster \u001b[m a59261a [\u001b[34morigin/master\u001b[m] Merge remote-tracking branch 'course/master'\r\n", + " mybranch1 \u001b[m 1ffe3d7 [\u001b[34morigin/mybranch1\u001b[m] Added another test file to demonstrate git features\r\n", + " \u001b[31mremotes/course/master \u001b[m 7ba94f7 added a line in readme\r\n", + " \u001b[31mremotes/origin/HEAD \u001b[m -> origin/master\r\n", + " \u001b[31mremotes/origin/master \u001b[m a59261a Merge remote-tracking branch 'course/master'\r\n", + " \u001b[31mremotes/origin/mybranch1\u001b[m 1ffe3d7 Added another test file to demonstrate git features\r\n" + ] + } + ], + "source": [ + "!cd /tmp/Testing; git branch -avv" + ] + }, + { + "cell_type": "code", + "execution_count": 47, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "!cd /tmp/Testing; git checkout origin/mybranch1 -- world.md" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Why does the syntax have `origin/mybranch1`? Remember that multiple remotes may have the same branch...so you want to be specific. So we check out `origin`'s `mybranch1`, and only want `world.md`." + ] + }, + { + "cell_type": "code", + "execution_count": 48, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "On branch master\r\n", + "Your branch is up-to-date with 'origin/master'.\r\n", + "\r\n", + "Changes to be committed:\r\n", + " (use \"git reset HEAD ...\" to unstage)\r\n", + "\r\n", + "\t\u001b[32mnew file: world.md\u001b[m\r\n", + "\r\n" + ] + } + ], + "source": [ + "!cd /tmp/Testing; git status" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Note that the file as automatically added to the index. We'll commit and push." + ] + }, + { + "cell_type": "code", + "execution_count": 49, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[master 79f0dba] want world in master\r\n", + " 1 file changed, 1 insertion(+)\r\n", + " create mode 100644 world.md\r\n" + ] + } + ], + "source": [ + "!cd /tmp/Testing; git commit -m \"want world in master\" " + ] + }, + { + "cell_type": "code", + "execution_count": 50, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "On branch master\r\n", + "Your branch is ahead of 'origin/master' by 1 commit.\r\n", + " (use \"git push\" to publish your local commits)\r\n", + "\r\n", + "nothing to commit, working directory clean\r\n" + ] + } + ], + "source": [ + "!cd /tmp/Testing; git status" + ] + }, + { + "cell_type": "code", + "execution_count": 51, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Counting objects: 1, done.\n", + "Writing objects: 100% (1/1), 192 bytes | 0 bytes/s, done.\n", + "Total 1 (delta 0), reused 0 (delta 0)\n", + "To git@github.com:rahuldave/Testing.git\n", + " a59261a..79f0dba master -> master\n" + ] + } + ], + "source": [ + "!cd /tmp/Testing; git push" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Note that in git versions > 2.0, which you must use, `git push` will pugh the current branch to its appropriate remote, all of which can be seen through `git branch -avv` or by looking at the `config` file." + ] + }, + { + "cell_type": "code", + "execution_count": 52, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[core]\r\n", + "\trepositoryformatversion = 0\r\n", + "\tfilemode = true\r\n", + "\tbare = false\r\n", + "\tlogallrefupdates = true\r\n", + "\tignorecase = true\r\n", + "\tprecomposeunicode = true\r\n", + "[remote \"origin\"]\r\n", + "\turl = git@github.com:rahuldave/Testing.git\r\n", + "\tfetch = +refs/heads/*:refs/remotes/origin/*\r\n", + "[branch \"master\"]\r\n", + "\tremote = origin\r\n", + "\tmerge = refs/heads/master\r\n", + "[remote \"course\"]\r\n", + "\turl = git@github.com:cs109/Testing.git\r\n", + "\tfetch = +refs/heads/*:refs/remotes/course/*\r\n", + "[branch \"mybranch1\"]\r\n", + "\tremote = origin\r\n", + "\tmerge = refs/heads/mybranch1\r\n" + ] + } + ], + "source": [ + "!cd /tmp/Testing; cat .git/config" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "----" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "##The Homework git flow" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "![homework](cs109gitflow2.png)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The homeworks work by us creating repositories for each student of the signature `studentid-2015` on github. You will clone these. Initially you will find `master`, `hw0`, and `hw1` branches. You will checkout a homework branch and work on it, adding, comitting, pushing. Thats it. When its time for your next homework, we'll push, say, a `hw2` branch to your repositories `origin` remote on github. You will fetch this new branch, checkit out, and work on it. And rinse and repeat.\n", + "\n", + "DO NOT work on any files like `hw1_original.ipynb`. If there are any changes you will be able to incorporate them into the `hw1_original.ipynb` file from the `course` remote without clobbering your own work in `hw1.ipynb`.\n", + "\n", + "The `master` branch only contains instructions. You shouldnt be working on it.\n", + "\n", + "The homework repos are private, shared between you and the course staff. DO NOT share them or add any collaborators. That will violate the Honor Policy." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "##The Lab git flow" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Unlike homeworks, Labs are available publicly. \n", + "\n", + "![homework](cs109gitflow3.png)\n", + "\n", + "Here you will fork our repository, clone you fork, and work on your clone. Once again, DO NOT work on any files like `lab1_original.ipynb`. If there are any changes you will be able to incorporate them into the `lab1_original.ipynb` file from the `course` remote (the one you forked) without clobbering your own work in `lab1.ipynb`.\n", + "\n", + "Your fork will also be public." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Creating a new repository" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Creating a repository can be done with git command line tools, or it can be done on github. On your github home, click on the 'Repositories' tab, then click the green 'New' button. You'll be brought to a page that asks for some basic project information.\n", + "\n", + "![new repo](github_new.png)\n", + "\n", + " - The repository name needs to be unique, but only amongst *your* github repositories. Despite what github suggests, try to pick something at least a little representative of your project.\n", + " \n", + " - The description field is just a short text field that will accompany your repository's name on the github website.\n", + "\n", + " - If you're creating a new repository, check the \"Initialize this repository with a README\" box. This is a little bit of a misnomer. If you don't do this, you won't be able to clone your repository at all. Instead, you'll have to manually create a new repository on your computer and upload that to github. Suffice to say, unless you've got an existing git repository that was hosted somewhere besides github, *always check this box*.\n", + "\n", + " - You're free to click the `.gitignore` or `license` buttons, too, but there's no requirement to do so. You can easily create either later. For our class I use a python `.gitignore` from the dropdown menu" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "----" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Github Pages" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In addition to hosting git repositories, github also provides web hosting for each user and project. Github provides [some documentation](https://pages.github.com/), but it's easier to create one than it is to figure out what to do with it next." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Automatically Generated Project Pages" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The easiest (and most limited) mechanism for creating a project page is to use the automatic page generator. Github's documentation does a fantastic job of guiding you through this, so I won't spend time on it. It's a 30-second process.\n", + "\n", + "To edit the page, you can checkout the newly created `gh-pages` branch in your project and edit the index.html file. A much easier way to edit the page is simply to go through the automatic page generator tool again. It might seem counterintuitive, but github saves the content that you added the first time around, so you can make small changes without too much trouble.\n", + "\n", + "In the end, automatically generated pages are a great replacement for a README.md file, but not much beyond that. You are limited to a single `index.html` file, and the templates are fixed. If you want a larger site or more customization options, you're better off doing something else." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Static Project Pages" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The next natural step is to use plain old static HTML. Regardless of how you create your site, github uses the `gh-pages` branch of your project to find your website files. One way to create this branch is to click on the \"branch\" button on your repository page:\n", + "\n", + "\n", + "\n", + "Alternately, if you've already clone your repository somewhere, you can do it on the command line:" + ] + }, + { + "cell_type": "raw", + "metadata": {}, + "source": [ + "$ git branch gh-pages\n", + "$ git checkout gh-pages" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "When you push changes to this branch, they will immediately be reflected on the web at http://your-username.github.io/your-projectname.\n", + "\n", + "You can use any static HTML, handwritten or otherwise." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "----" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Git habits" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "** * Commit early, commit often. * **\n", + "\n", + "Git is more effective when used at a fine granularity. For starters, you can't undo what you haven't committed, so committing lots of small changes makes it easier to find the right rollback point. Also, merging becomes a lot easier when you only have to deal with a handful of conflicts.\n", + "\n", + "** * Commit unrelated changes separately. * **\n", + "\n", + "Identifying the source of a bug or understanding the reason why a particular piece of code exists is much easier when commits focus on related changes. Some of this has to do with simplifying commit messages and making it easier to look through logs, but it has other related benefits: commits are smaller and simpler, and merge conflicts are confined to only the commits which actually have conflicting code.\n", + "\n", + "** * Do not commit binaries and other temporary files. * **\n", + "\n", + "Git is meant for tracking changes. In nearly all cases, the only meaningful difference between the contents of two binaries is that they are different. If you change source files, compile, and commit the resulting binary, git sees an entirely different file. The end result is that the git repository (which contains a complete history, remember) begins to become bloated with the history of many dissimilar binaries. Worse, there's often little advantage to keeping those files in the history. An argument can be made for periodically snapshotting working binaries, but things like object files, compiled python files, and editor auto-saves are basically wasted space.\n", + "\n", + "** * Ignore files which should not be committed * **\n", + "\n", + "Git comes with a built-in mechanism for ignoring certain types of files. Placing filenames or wildcards in a `.gitignore` file placed in the top-level directory (where the `.git` directory is also located) will cause git to ignore those files when checking file status. This is a good way to ensure you don't commit the wrong files accidentally, and it also makes the output of `git status` somewhat cleaner.\n", + "\n", + "** * Always make a branch for new changes * **\n", + "\n", + "While it's tempting to work on new code directly in the `master` branch, it's usually a good idea to create a new one instead, especially for team-based projects. The major advantage to this practice is that it keeps logically disparate change sets separate. This means that if two people are working on improvements in two different branches, when they merge, the actual workflow is reflected in the git history. Plus, explicitly creating branches adds some semantic meaning to your branch structure. Moreover, there is very little difference in how you use git.\n", + "\n", + "** * Write good commit messages * **\n", + "\n", + "I cannot understate the importance of this.\n", + "\n", + "** Seriously. Write good commit messages. **" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 2", + "language": "python", + "name": "python2" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 2 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython2", + "version": "2.7.10" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} diff --git a/Lab1-pythonpandas_original.ipynb b/Lab1-pythonpandas_original.ipynb new file mode 100644 index 0000000..4d48574 --- /dev/null +++ b/Lab1-pythonpandas_original.ipynb @@ -0,0 +1,2946 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#Lab 1. An Introduction to Pandas and Python" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# The %... is an iPython thing, and is not part of the Python language.\n", + "# In this case we're just telling the plotting library to draw things on\n", + "# the notebook, instead of on a separate window.\n", + "%matplotlib inline \n", + "#this line above prepares IPython notebook for working with matplotlib\n", + "\n", + "# See all the \"as ...\" contructs? They're just aliasing the package names.\n", + "# That way we can call methods like plt.plot() instead of matplotlib.pyplot.plot().\n", + "\n", + "import numpy as np # imports a fast numerical programming library\n", + "import scipy as sp #imports stats functions, amongst other things\n", + "import matplotlib as mpl # this actually imports matplotlib\n", + "import matplotlib.cm as cm #allows us easy access to colormaps\n", + "import matplotlib.pyplot as plt #sets up plotting under plt\n", + "import pandas as pd #lets us handle data as dataframes\n", + "#sets up pandas table display\n", + "pd.set_option('display.width', 500)\n", + "pd.set_option('display.max_columns', 100)\n", + "pd.set_option('display.notebook_repr_html', True)\n", + "import seaborn as sns #sets up styles and gives us more plotting options" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Python depends on packages for most of its functionality; these can be either built-in (such as sys), or third-party (like all the packages below). Either way you need to import the packages you need before using them." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "##The Notebook\n", + "\n", + "Look up http:/www.google.com Lets eat a burrito. $\\alpha = \\frac{\\beta}{\\gamma}$\n", + "\n", + "Longer:\n", + "\n", + "$$\\alpha = \\frac{\\beta}{\\gamma}$$\n", + "\n", + "1. an item\n", + "2. another item\n", + "3. i like items" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "##Pandas" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Get Cheatsheet:\n", + "\n", + "from https://drive.google.com/folderview?id=0ByIrJAE4KMTtaGhRcXkxNHhmY2M&usp=sharing\n", + "\n", + "\n", + "We read in some data from a CSV file. CSV files can be output by any spreadsheet software, and are plain text, so make a great way to share data. This dataset is from Goodreads: i scraped the highest regarded (according to Goodread's proprietary algorithm) books on that site. Ypu'll see how to do such a scraping in the next lab." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
ratingreview_countisbnbooktypeauthor_urlyeargenre_urlsdirrating_countname
04.401364550439023483good_reads:bookhttps://www.goodreads.com/author/show/153394.S...2008/genres/young-adult|/genres/science-fiction|/g...dir01/2767052-the-hunger-games.html2958974The Hunger Games (The Hunger Games, #1)
14.41166480439358078good_reads:bookhttps://www.goodreads.com/author/show/1077326....2003/genres/fantasy|/genres/young-adult|/genres/fi...dir01/2.Harry_Potter_and_the_Order_of_the_Phoe...1284478Harry Potter and the Order of the Phoenix (Har...
23.56857460316015849good_reads:bookhttps://www.goodreads.com/author/show/941441.S...2005/genres/young-adult|/genres/fantasy|/genres/ro...dir01/41865.Twilight.html2579564Twilight (Twilight, #1)
34.23479060061120081good_reads:bookhttps://www.goodreads.com/author/show/1825.Har...1960/genres/classics|/genres/fiction|/genres/histo...dir01/2657.To_Kill_a_Mockingbird.html2078123To Kill a Mockingbird
44.23347720679783261good_reads:bookhttps://www.goodreads.com/author/show/1265.Jan...1813/genres/classics|/genres/fiction|/genres/roman...dir01/1885.Pride_and_Prejudice.html1388992Pride and Prejudice
\n", + "
" + ], + "text/plain": [ + " rating review_count isbn booktype author_url year genre_urls dir rating_count name\n", + "0 4.40 136455 0439023483 good_reads:book https://www.goodreads.com/author/show/153394.S... 2008 /genres/young-adult|/genres/science-fiction|/g... dir01/2767052-the-hunger-games.html 2958974 The Hunger Games (The Hunger Games, #1)\n", + "1 4.41 16648 0439358078 good_reads:book https://www.goodreads.com/author/show/1077326.... 2003 /genres/fantasy|/genres/young-adult|/genres/fi... dir01/2.Harry_Potter_and_the_Order_of_the_Phoe... 1284478 Harry Potter and the Order of the Phoenix (Har...\n", + "2 3.56 85746 0316015849 good_reads:book https://www.goodreads.com/author/show/941441.S... 2005 /genres/young-adult|/genres/fantasy|/genres/ro... dir01/41865.Twilight.html 2579564 Twilight (Twilight, #1)\n", + "3 4.23 47906 0061120081 good_reads:book https://www.goodreads.com/author/show/1825.Har... 1960 /genres/classics|/genres/fiction|/genres/histo... dir01/2657.To_Kill_a_Mockingbird.html 2078123 To Kill a Mockingbird\n", + "4 4.23 34772 0679783261 good_reads:book https://www.goodreads.com/author/show/1265.Jan... 1813 /genres/classics|/genres/fiction|/genres/roman... dir01/1885.Pride_and_Prejudice.html 1388992 Pride and Prejudice" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df=pd.read_csv(\"all.csv\", header=None,\n", + " names=[\"rating\", 'review_count', 'isbn', 'booktype','author_url', 'year', 'genre_urls', 'dir','rating_count', 'name'],\n", + ")\n", + "df.head()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Notice we have a table! A spreadsheet! And it indexed the rows. Pandas (borrowing from R) calls it a DataFrame. Lets see the types of the columns...\n", + "\n", + "`df`, in python parlance, is an **instance** of the `pd.DataFrame` class, created by calling the `pd.read_csv` function, which cllas the DataFrame constructor inside of it. If you dont understand this sentence, dont worry, it will become clearer later. What you need to take away is that `df` is a dataframe object, and it has **methods**, or functions belonging to it, which allow it to do things. For example `df.head()` is a method that shows the first 5 rows of the dataframe.\n", + "\n", + "![](files/pandastruct.png)\n", + "\n", + "###The basics" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "rating float64\n", + "review_count object\n", + "isbn object\n", + "booktype object\n", + "author_url object\n", + "year float64\n", + "genre_urls object\n", + "dir object\n", + "rating_count object\n", + "name object\n", + "dtype: object" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df.dtypes" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The shape of the object is:" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "(6000, 10)" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df.shape" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "6000 rows times 10 columns. A spredsheet is a table is a matrix. How can we access members of this **tuple** (brackets like so:() )" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "(6000, 10)" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df.shape[0], df.shape[1]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "These are the column names." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "Index([u'rating', u'review_count', u'isbn', u'booktype', u'author_url', u'year', u'genre_urls', u'dir', u'rating_count', u'name'], dtype='object')" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df.columns" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "As the diagram above shows, pandas considers a table (dataframe) as a pasting of many \"series\" together, horizontally." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "(pandas.core.series.Series, pandas.core.frame.DataFrame)" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "type(df.rating), type(df)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "###Querying\n", + "\n", + "A spreadsheet is useless if you cant dice/sort/etc it. Here we look for all books with a rating less than 3. " + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "0 False\n", + "1 False\n", + "2 False\n", + "3 False\n", + "4 False\n", + "5 False\n", + "6 False\n", + "7 False\n", + "8 False\n", + "9 False\n", + "10 False\n", + "11 False\n", + "12 False\n", + "13 False\n", + "14 False\n", + "15 False\n", + "16 False\n", + "17 False\n", + "18 False\n", + "19 False\n", + "20 False\n", + "21 False\n", + "22 False\n", + "23 False\n", + "24 False\n", + "25 False\n", + "26 False\n", + "27 False\n", + "28 False\n", + "29 False\n", + " ... \n", + "5970 False\n", + "5971 False\n", + "5972 False\n", + "5973 False\n", + "5974 False\n", + "5975 False\n", + "5976 False\n", + "5977 False\n", + "5978 False\n", + "5979 True\n", + "5980 False\n", + "5981 False\n", + "5982 False\n", + "5983 False\n", + "5984 False\n", + "5985 False\n", + "5986 False\n", + "5987 False\n", + "5988 False\n", + "5989 False\n", + "5990 False\n", + "5991 False\n", + "5992 False\n", + "5993 False\n", + "5994 False\n", + "5995 False\n", + "5996 False\n", + "5997 False\n", + "5998 False\n", + "5999 False\n", + "Name: rating, dtype: bool" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df.rating < 3" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This gives us `True`s and `False`s. Such a series is called a mask. If we count the number of `True`s, and divide by the total, we'll get the fraction of ratings $\\lt$ 3. To do this numerically see this:" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "4" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "np.sum(df.rating < 3)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Why did that work?" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1 0\n" + ] + } + ], + "source": [ + "print 1*True, 1*False" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "So we ought to be able to do this" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "0" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "np.sum(df.rating < 3)/df.shape[0]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "But we get a 0? Why? In Python 2.x division is **integer division** by default. So one can fix by converting the `df.shape[0]` to a float" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "0.00066666666666666664" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "np.sum(df.rating < 3)/float(df.shape[0])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Notice that you could just find the average since the `True`s map to 1s." + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "0.00066666666666666664" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "np.mean(df.rating < 3.0)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Or directly, in Pandas, which works since `df.rating < 3` is a pandas Series." + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "0.00066666666666666664" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "(df.rating < 3).mean()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "###Filtering\n", + "\n", + "Here are two ways to get a filtered dataframe" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
ratingreview_countisbnbooktypeauthor_urlyeargenre_urlsdirrating_countname
174.5813140345538374good_reads:bookhttps://www.goodreads.com/author/show/656983.J...1973/genres/fantasy|/genres/classics|/genres/scien...dir01/30.J_R_R_Tolkien_4_Book_Boxed_Set.html68495J.R.R. Tolkien 4-Book Boxed Set
1624.5515777075640407Xgood_reads:bookhttps://www.goodreads.com/author/show/108424.P...2007/genres/fantasy|/genres/fictiondir02/186074.The_Name_of_the_Wind.html210018The Name of the Wind (The Kingkiller Chronicle...
2224.5315256055357342Xgood_reads:bookhttps://www.goodreads.com/author/show/346732.G...2000/genres/fantasy|/genres/fiction|/genres/fantas...dir03/62291.A_Storm_of_Swords.html327992A Storm of Swords (A Song of Ice and Fire, #3)
2424.5354040545265355good_reads:bookhttps://www.goodreads.com/author/show/153394.S...2010/genres/young-adult|/genres/fiction|/genres/fa...dir03/7938275-the-hunger-games-trilogy-boxset....102330The Hunger Games Trilogy Boxset (The Hunger Ga...
2494.806440740748475good_reads:bookhttps://www.goodreads.com/author/show/13778.Bi...2005/genres/sequential-art|/genres/comics|/genres/...dir03/24812.The_Complete_Calvin_and_Hobbes.html22674The Complete Calvin and Hobbes
2844.58151951406321346good_reads:bookhttps://www.goodreads.com/author/show/150038.C...2013/genres/fantasy|/genres/young-adult|/genres/fa...dir03/18335634-clockwork-princess.html130161Clockwork Princess (The Infernal Devices, #3)
3044.545720140259449good_reads:bookhttps://www.goodreads.com/author/show/1265.Jan...1933/genres/classics|/genres/fiction|/genres/roman...dir04/14905.The_Complete_Novels.html17539The Complete Novels
3864.5588200756404738good_reads:bookhttps://www.goodreads.com/author/show/108424.P...2011/genres/fantasy|/genres/fantasy|/genres/epic-f...dir04/1215032.The_Wise_Man_s_Fear.html142499The Wise Man's Fear (The Kingkiller Chronicle,...
4004.5392921423140605good_reads:bookhttps://www.goodreads.com/author/show/15872.Ri...2012/genres/fantasy|/genres/young-adult|/genres/fa...dir05/12127750-the-mark-of-athena.html128412The Mark of Athena (The Heroes of Olympus, #3)
4754.578241416997857good_reads:bookhttps://www.goodreads.com/author/show/150038.C...2009/genres/fantasy|/genres/young-adult|/genres/fa...dir05/6485421-the-mortal-instruments-boxed-set...39720The Mortal Instruments Boxed Set (The Mortal I...
4834.5926220312362153good_reads:bookhttps://www.goodreads.com/author/show/4430.She...2008/genres/romance|/genres/paranormal-romance|/ge...dir05/2299110.Acheron.html35028Acheron (Dark-Hunter, #8)
5544.5448090385341679good_reads:bookhttps://www.goodreads.com/author/show/48206.Ka...2011/genres/fantasy|/genres/urban-fantasy|/genres/...dir06/7304203-shadowfever.html52812Shadowfever (Fever, #5)
5774.6057320765326353good_reads:bookhttps://www.goodreads.com/author/show/38550.Br...2010/genres/science-fiction-fantasy|/genres/fantas...dir06/7235533-the-way-of-kings.html76551The Way of Kings (The Stormlight Archive, #1)
6204.5477671423146727good_reads:bookhttps://www.goodreads.com/author/show/15872.Ri...2013/genres/fantasy|/genres/young-adult|/genres/fa...dir07/12127810-the-house-of-hades.html72082The House of Hades (The Heroes of Olympus, #4)
8404.574311423113497good_reads:bookhttps://www.goodreads.com/author/show/15872.Ri...2008/genres/fantasy|/genres/young-adult|/genres/fa...dir09/3165162-percy-jackson-and-the-olympians-...22937Percy Jackson and the Olympians Boxed Set (Per...
8834.585580140286802good_reads:bookhttps://www.goodreads.com/author/show/500.Jorg...1998/genres/short-stories|/genres/literature|/genr...dir09/17961.Collected_Fictions.html12596Collected Fictions
9114.85261491732954good_reads:bookhttps://www.goodreads.com/author/show/8189303....2014/genres/fictiondir10/22242097-honor-and-polygamy.html97Honor and Polygamy
9354.641481595142711good_reads:bookhttps://www.goodreads.com/author/show/137902.R...2009/genres/paranormal|/genres/vampires|/genres/yo...dir10/6339989-vampire-academy-collection.html21743Vampire Academy Collection (Vampire Academy, #...
9384.51110111481426303good_reads:bookhttps://www.goodreads.com/author/show/150038.C...2014/genres/fantasy|/genres/young-adult|/genres/fa...dir10/8755785-city-of-heavenly-fire.html69924City of Heavenly Fire (The Mortal Instruments,...
9534.56271477276068good_reads:bookhttps://www.goodreads.com/author/show/6621980....2012NaNdir10/16243767-crossing-the-seas.html90Crossing the Seas
9584.57381990545010225good_reads:bookhttps://www.goodreads.com/author/show/1077326....2007/genres/fantasy|/genres/young-adult|/genres/fa...dir10/136251.Harry_Potter_and_the_Deathly_Hall...1245866Harry Potter and the Deathly Hallows (Harry Po...
10334.5613040007119550good_reads:bookhttps://www.goodreads.com/author/show/346732.G...2000/genres/fiction|/genres/fantasy|/genres/epic-f...dir11/147915.A_Storm_of_Swords.html41161A Storm of Swords (A Song of Ice and Fire, #3-2)
11094.7023NaNgood_reads:bookhttps://www.goodreads.com/author/show/7488658....2013/genres/romancedir12/19181419-a-bird-without-wings.html56A Bird Without Wings
11274.526440141183047good_reads:bookhttps://www.goodreads.com/author/show/7816.Fer...1982/genres/poetry|/genres/fiction|/genres/philoso...dir12/45974.The_Book_of_Disquiet.html7463The Book of Disquiet
11514.64841491877928good_reads:bookhttps://www.goodreads.com/author/show/7271860....2013/genres/war|/genres/historical-fiction|/genres...dir12/18501652-the-guardian-of-secrets-and-her...167The Guardian of Secrets and Her Deathly Pact
11864.5148531619630621good_reads:bookhttps://www.goodreads.com/author/show/3433047....2013/genres/fantasy|/genres/young-adult|/genres/ro...dir12/17167166-crown-of-midnight.html34142Crown of Midnight (Throne of Glass, #2)
12024.5912600310902711good_reads:bookhttps://www.goodreads.com/author/show/5158478....1972/genres/religion|/genres/christian|/genres/non...dir13/280111.Holy_Bible.html25584Holy Bible
12604.6019430842377506good_reads:bookhttps://www.goodreads.com/author/show/6492.Fra...1993/genres/christian-fiction|/genres/historical-f...dir13/95617.A_Voice_in_the_Wind.html37923A Voice in the Wind (Mark of the Lion, #1)
12684.522151557091528good_reads:bookhttps://www.goodreads.com/author/show/63859.Ja...1787/genres/history|/genres/non-fiction|/genres/po...dir13/89959.The_Constitution_of_the_United_Sta...12894The Constitution of the United States of America
13004.61241499227299good_reads:bookhttps://www.goodreads.com/author/show/7414345....2014/genres/paranormal|/genres/vampires|/genres/pa...dir14/22090082-vampire-princess-rising.html128Vampire Princess Rising (The Winters Family Sa...
.................................
55324.8641477504540good_reads:bookhttps://www.goodreads.com/author/show/5989528....2013NaNdir56/17695243-call-of-the-lost-ages.html7Call Of The Lost Ages
55494.62130882408704good_reads:bookhttps://www.goodreads.com/author/show/947.Will...1899/genres/classics|/genres/fiction|/genres/poetr...dir56/17134346-the-complete-works-of-william-s...217The Complete Works of William Shakespeare
55574.6114NaNgood_reads:bookhttps://www.goodreads.com/author/show/32401.Al...2006/genres/fantasy|/genres/young-adultdir56/13488552-the-books-of-pellinor.html394The Books of Pellinor
55634.7030NaNgood_reads:bookhttps://www.goodreads.com/author/show/7153266....2014/genres/childrensdir56/20445451-children-s-book.html57Children's book
55645.009NaNgood_reads:bookhttps://www.goodreads.com/author/show/7738947....2014/genres/romance|/genres/new-adultdir56/21902777-untainted.html14Untainted (Photographer Trilogy, #3)
55844.7531481959824good_reads:bookhttps://www.goodreads.com/author/show/5100743....2013NaNdir56/17606460-why-not-world.html8Why Not-World
55884.66190NaNgood_reads:bookhttps://www.goodreads.com/author/show/4942228....2011/genres/romance|/genres/m-m-romance|/genres/sc...dir56/11737700-fade.html996Fade (In the company of shadows, #4)
55914.58311500118680good_reads:bookhttps://www.goodreads.com/author/show/7738947....2014/genres/romance|/genres/new-adultdir56/22023804-logan-s-story.html45Logan's Story (Sand & Clay, #0.5)
56014.663120842384898good_reads:bookhttps://www.goodreads.com/author/show/5158478....1902/genres/christian|/genres/religion|/genres/non...dir57/930470.Holy_Bible.html2666Holy Bible
56074.665130007444397good_reads:bookhttps://www.goodreads.com/author/show/4659154....2011/genres/non-fiction|/genres/biographydir57/11792612-dare-to-dream.html5572Dare to Dream (100% Official)
56194.524620991190920good_reads:bookhttps://www.goodreads.com/author/show/7092218....2014/genres/fantasy|/genres/paranormal|/genres/fai...dir57/18188649-escaping-destiny.html3795Escaping Destiny (The Fae Chronicles, #3)
56354.549580778315703good_reads:bookhttps://www.goodreads.com/author/show/4480131....2013/genres/erotica|/genres/bdsm|/genres/adult-fic...dir57/17251444-the-mistress.html4869The Mistress (The Original Sinners, #4)
56424.701581417642165good_reads:bookhttps://www.goodreads.com/author/show/13778.Bi...1992/genres/sequential-art|/genres/comics|/genres/...dir57/70487.Calvin_and_Hobbes.html9224Calvin and Hobbes
56574.8081469908530good_reads:bookhttps://www.goodreads.com/author/show/4695431....2012/genres/fantasydir57/15734769-myrtle-mae-and-the-mirror-in-th...10Myrtle Mae and the Mirror in the Attic (The Ma...
56654.5361NaNgood_reads:bookhttps://www.goodreads.com/author/show/7738947....2014/genres/romance|/genres/new-adult|/genres/myst...dir57/20975446-tainted-pictures.html103Tainted Pictures (Photographer Trilogy, #2)
56834.56204NaNgood_reads:bookhttps://www.goodreads.com/author/show/3097905....NaN/genres/fantasy|/genres/young-adult|/genres/ro...dir57/12474623-tiger-s-dream.html895Tiger's Dream (The Tiger Saga, #5)
56925.000NaNgood_reads:bookhttps://www.goodreads.com/author/show/5989528....2012NaNdir57/14288412-abstraction-in-theory---laws-of...6Abstraction In Theory - Laws Of Physical Trans...
57164.67340810117134good_reads:bookhttps://www.goodreads.com/author/show/205563.M...1970/genres/classics|/genres/fiction|/genres/histo...dir58/1679497.The_Fortress.html1335The Fortress
57174.714NaNgood_reads:bookhttps://www.goodreads.com/author/show/5838022....2012NaNdir58/13741511-american-amaranth.html14American Amaranth
57184.606561613725132good_reads:bookhttps://www.goodreads.com/author/show/1122775....2012/genres/romance|/genres/m-m-romance|/genres/ro...dir58/13246997-armed-dangerous.html5268Armed & Dangerous (Cut & Run, #5)
57264.551061594170347good_reads:bookhttps://www.goodreads.com/author/show/5158478....1952/genres/religion|/genres/reference|/genres/rel...dir58/147635.Holy_Bible.html1750Holy Bible
57294.8316NaNgood_reads:bookhttps://www.goodreads.com/author/show/7058502....2014NaNdir58/22312293-the-keeper.html29The Keeper (The Keeper, #5)
57534.618111937551865good_reads:bookhttps://www.goodreads.com/author/show/1122775....2013/genres/romance|/genres/m-m-romance|/genres/ro...dir58/16159276-touch-geaux.html4212Touch & Geaux (Cut & Run, #7)
57644.54228NaNgood_reads:bookhttps://www.goodreads.com/author/show/2112402....2013/genres/non-fiction|/genres/self-help|/genres/...dir58/18479831-staying-strong.html2343Staying Strong
57784.630NaNgood_reads:bookhttps://www.goodreads.com/author/show/4808225....2010NaNdir58/11187937-un-spoken.html19(Un) Spoken
58064.571210679777458good_reads:bookhttps://www.goodreads.com/author/show/8361.Dor...1966/genres/historical-fiction|/genres/fiction|/ge...dir59/351211.The_Disorderly_Knights.html2177The Disorderly Knights (The Lymond Chronicles,...
58734.55103144247372Xgood_reads:bookhttps://www.goodreads.com/author/show/2876763....2012/genres/fantasy|/genres/paranormal|/genres/ang...dir59/14367071-the-complete-hush-hush-saga.html2869The Complete Hush, Hush Saga
58744.78182851944371good_reads:bookhttps://www.goodreads.com/author/show/318835.O...1972/genres/poetry|/genres/fiction|/genres/nobel-p...dir59/2014000.Le_Monogramme.html565Le Monogramme
58804.61123NaNgood_reads:bookhttps://www.goodreads.com/author/show/4942228....2010/genres/romance|/genres/m-m-romance|/genres/sc...dir59/10506860-the-interludes.html1031The Interludes (In the company of shadows, #3)
59574.72104178048044Xgood_reads:bookhttps://www.goodreads.com/author/show/20248.J_...2010/genres/romance|/genres/paranormal|/genres/vam...dir60/10780042-j-r-ward-collection.html1788J. R. Ward Collection
\n", + "

224 rows × 10 columns

\n", + "
" + ], + "text/plain": [ + " rating review_count isbn booktype author_url year genre_urls dir rating_count name\n", + "17 4.58 1314 0345538374 good_reads:book https://www.goodreads.com/author/show/656983.J... 1973 /genres/fantasy|/genres/classics|/genres/scien... dir01/30.J_R_R_Tolkien_4_Book_Boxed_Set.html 68495 J.R.R. Tolkien 4-Book Boxed Set\n", + "162 4.55 15777 075640407X good_reads:book https://www.goodreads.com/author/show/108424.P... 2007 /genres/fantasy|/genres/fiction dir02/186074.The_Name_of_the_Wind.html 210018 The Name of the Wind (The Kingkiller Chronicle...\n", + "222 4.53 15256 055357342X good_reads:book https://www.goodreads.com/author/show/346732.G... 2000 /genres/fantasy|/genres/fiction|/genres/fantas... dir03/62291.A_Storm_of_Swords.html 327992 A Storm of Swords (A Song of Ice and Fire, #3)\n", + "242 4.53 5404 0545265355 good_reads:book https://www.goodreads.com/author/show/153394.S... 2010 /genres/young-adult|/genres/fiction|/genres/fa... dir03/7938275-the-hunger-games-trilogy-boxset.... 102330 The Hunger Games Trilogy Boxset (The Hunger Ga...\n", + "249 4.80 644 0740748475 good_reads:book https://www.goodreads.com/author/show/13778.Bi... 2005 /genres/sequential-art|/genres/comics|/genres/... dir03/24812.The_Complete_Calvin_and_Hobbes.html 22674 The Complete Calvin and Hobbes\n", + "284 4.58 15195 1406321346 good_reads:book https://www.goodreads.com/author/show/150038.C... 2013 /genres/fantasy|/genres/young-adult|/genres/fa... dir03/18335634-clockwork-princess.html 130161 Clockwork Princess (The Infernal Devices, #3)\n", + "304 4.54 572 0140259449 good_reads:book https://www.goodreads.com/author/show/1265.Jan... 1933 /genres/classics|/genres/fiction|/genres/roman... dir04/14905.The_Complete_Novels.html 17539 The Complete Novels\n", + "386 4.55 8820 0756404738 good_reads:book https://www.goodreads.com/author/show/108424.P... 2011 /genres/fantasy|/genres/fantasy|/genres/epic-f... dir04/1215032.The_Wise_Man_s_Fear.html 142499 The Wise Man's Fear (The Kingkiller Chronicle,...\n", + "400 4.53 9292 1423140605 good_reads:book https://www.goodreads.com/author/show/15872.Ri... 2012 /genres/fantasy|/genres/young-adult|/genres/fa... dir05/12127750-the-mark-of-athena.html 128412 The Mark of Athena (The Heroes of Olympus, #3)\n", + "475 4.57 824 1416997857 good_reads:book https://www.goodreads.com/author/show/150038.C... 2009 /genres/fantasy|/genres/young-adult|/genres/fa... dir05/6485421-the-mortal-instruments-boxed-set... 39720 The Mortal Instruments Boxed Set (The Mortal I...\n", + "483 4.59 2622 0312362153 good_reads:book https://www.goodreads.com/author/show/4430.She... 2008 /genres/romance|/genres/paranormal-romance|/ge... dir05/2299110.Acheron.html 35028 Acheron (Dark-Hunter, #8)\n", + "554 4.54 4809 0385341679 good_reads:book https://www.goodreads.com/author/show/48206.Ka... 2011 /genres/fantasy|/genres/urban-fantasy|/genres/... dir06/7304203-shadowfever.html 52812 Shadowfever (Fever, #5)\n", + "577 4.60 5732 0765326353 good_reads:book https://www.goodreads.com/author/show/38550.Br... 2010 /genres/science-fiction-fantasy|/genres/fantas... dir06/7235533-the-way-of-kings.html 76551 The Way of Kings (The Stormlight Archive, #1)\n", + "620 4.54 7767 1423146727 good_reads:book https://www.goodreads.com/author/show/15872.Ri... 2013 /genres/fantasy|/genres/young-adult|/genres/fa... dir07/12127810-the-house-of-hades.html 72082 The House of Hades (The Heroes of Olympus, #4)\n", + "840 4.57 431 1423113497 good_reads:book https://www.goodreads.com/author/show/15872.Ri... 2008 /genres/fantasy|/genres/young-adult|/genres/fa... dir09/3165162-percy-jackson-and-the-olympians-... 22937 Percy Jackson and the Olympians Boxed Set (Per...\n", + "883 4.58 558 0140286802 good_reads:book https://www.goodreads.com/author/show/500.Jorg... 1998 /genres/short-stories|/genres/literature|/genr... dir09/17961.Collected_Fictions.html 12596 Collected Fictions\n", + "911 4.85 26 1491732954 good_reads:book https://www.goodreads.com/author/show/8189303.... 2014 /genres/fiction dir10/22242097-honor-and-polygamy.html 97 Honor and Polygamy\n", + "935 4.64 148 1595142711 good_reads:book https://www.goodreads.com/author/show/137902.R... 2009 /genres/paranormal|/genres/vampires|/genres/yo... dir10/6339989-vampire-academy-collection.html 21743 Vampire Academy Collection (Vampire Academy, #...\n", + "938 4.51 11011 1481426303 good_reads:book https://www.goodreads.com/author/show/150038.C... 2014 /genres/fantasy|/genres/young-adult|/genres/fa... dir10/8755785-city-of-heavenly-fire.html 69924 City of Heavenly Fire (The Mortal Instruments,...\n", + "953 4.56 27 1477276068 good_reads:book https://www.goodreads.com/author/show/6621980.... 2012 NaN dir10/16243767-crossing-the-seas.html 90 Crossing the Seas\n", + "958 4.57 38199 0545010225 good_reads:book https://www.goodreads.com/author/show/1077326.... 2007 /genres/fantasy|/genres/young-adult|/genres/fa... dir10/136251.Harry_Potter_and_the_Deathly_Hall... 1245866 Harry Potter and the Deathly Hallows (Harry Po...\n", + "1033 4.56 1304 0007119550 good_reads:book https://www.goodreads.com/author/show/346732.G... 2000 /genres/fiction|/genres/fantasy|/genres/epic-f... dir11/147915.A_Storm_of_Swords.html 41161 A Storm of Swords (A Song of Ice and Fire, #3-2)\n", + "1109 4.70 23 NaN good_reads:book https://www.goodreads.com/author/show/7488658.... 2013 /genres/romance dir12/19181419-a-bird-without-wings.html 56 A Bird Without Wings\n", + "1127 4.52 644 0141183047 good_reads:book https://www.goodreads.com/author/show/7816.Fer... 1982 /genres/poetry|/genres/fiction|/genres/philoso... dir12/45974.The_Book_of_Disquiet.html 7463 The Book of Disquiet\n", + "1151 4.64 84 1491877928 good_reads:book https://www.goodreads.com/author/show/7271860.... 2013 /genres/war|/genres/historical-fiction|/genres... dir12/18501652-the-guardian-of-secrets-and-her... 167 The Guardian of Secrets and Her Deathly Pact\n", + "1186 4.51 4853 1619630621 good_reads:book https://www.goodreads.com/author/show/3433047.... 2013 /genres/fantasy|/genres/young-adult|/genres/ro... dir12/17167166-crown-of-midnight.html 34142 Crown of Midnight (Throne of Glass, #2)\n", + "1202 4.59 1260 0310902711 good_reads:book https://www.goodreads.com/author/show/5158478.... 1972 /genres/religion|/genres/christian|/genres/non... dir13/280111.Holy_Bible.html 25584 Holy Bible\n", + "1260 4.60 1943 0842377506 good_reads:book https://www.goodreads.com/author/show/6492.Fra... 1993 /genres/christian-fiction|/genres/historical-f... dir13/95617.A_Voice_in_the_Wind.html 37923 A Voice in the Wind (Mark of the Lion, #1)\n", + "1268 4.52 215 1557091528 good_reads:book https://www.goodreads.com/author/show/63859.Ja... 1787 /genres/history|/genres/non-fiction|/genres/po... dir13/89959.The_Constitution_of_the_United_Sta... 12894 The Constitution of the United States of America\n", + "1300 4.61 24 1499227299 good_reads:book https://www.goodreads.com/author/show/7414345.... 2014 /genres/paranormal|/genres/vampires|/genres/pa... dir14/22090082-vampire-princess-rising.html 128 Vampire Princess Rising (The Winters Family Sa...\n", + "... ... ... ... ... ... ... ... ... ... ...\n", + "5532 4.86 4 1477504540 good_reads:book https://www.goodreads.com/author/show/5989528.... 2013 NaN dir56/17695243-call-of-the-lost-ages.html 7 Call Of The Lost Ages\n", + "5549 4.62 13 0882408704 good_reads:book https://www.goodreads.com/author/show/947.Will... 1899 /genres/classics|/genres/fiction|/genres/poetr... dir56/17134346-the-complete-works-of-william-s... 217 The Complete Works of William Shakespeare\n", + "5557 4.61 14 NaN good_reads:book https://www.goodreads.com/author/show/32401.Al... 2006 /genres/fantasy|/genres/young-adult dir56/13488552-the-books-of-pellinor.html 394 The Books of Pellinor\n", + "5563 4.70 30 NaN good_reads:book https://www.goodreads.com/author/show/7153266.... 2014 /genres/childrens dir56/20445451-children-s-book.html 57 Children's book\n", + "5564 5.00 9 NaN good_reads:book https://www.goodreads.com/author/show/7738947.... 2014 /genres/romance|/genres/new-adult dir56/21902777-untainted.html 14 Untainted (Photographer Trilogy, #3)\n", + "5584 4.75 3 1481959824 good_reads:book https://www.goodreads.com/author/show/5100743.... 2013 NaN dir56/17606460-why-not-world.html 8 Why Not-World\n", + "5588 4.66 190 NaN good_reads:book https://www.goodreads.com/author/show/4942228.... 2011 /genres/romance|/genres/m-m-romance|/genres/sc... dir56/11737700-fade.html 996 Fade (In the company of shadows, #4)\n", + "5591 4.58 31 1500118680 good_reads:book https://www.goodreads.com/author/show/7738947.... 2014 /genres/romance|/genres/new-adult dir56/22023804-logan-s-story.html 45 Logan's Story (Sand & Clay, #0.5)\n", + "5601 4.66 312 0842384898 good_reads:book https://www.goodreads.com/author/show/5158478.... 1902 /genres/christian|/genres/religion|/genres/non... dir57/930470.Holy_Bible.html 2666 Holy Bible\n", + "5607 4.66 513 0007444397 good_reads:book https://www.goodreads.com/author/show/4659154.... 2011 /genres/non-fiction|/genres/biography dir57/11792612-dare-to-dream.html 5572 Dare to Dream (100% Official)\n", + "5619 4.52 462 0991190920 good_reads:book https://www.goodreads.com/author/show/7092218.... 2014 /genres/fantasy|/genres/paranormal|/genres/fai... dir57/18188649-escaping-destiny.html 3795 Escaping Destiny (The Fae Chronicles, #3)\n", + "5635 4.54 958 0778315703 good_reads:book https://www.goodreads.com/author/show/4480131.... 2013 /genres/erotica|/genres/bdsm|/genres/adult-fic... dir57/17251444-the-mistress.html 4869 The Mistress (The Original Sinners, #4)\n", + "5642 4.70 158 1417642165 good_reads:book https://www.goodreads.com/author/show/13778.Bi... 1992 /genres/sequential-art|/genres/comics|/genres/... dir57/70487.Calvin_and_Hobbes.html 9224 Calvin and Hobbes\n", + "5657 4.80 8 1469908530 good_reads:book https://www.goodreads.com/author/show/4695431.... 2012 /genres/fantasy dir57/15734769-myrtle-mae-and-the-mirror-in-th... 10 Myrtle Mae and the Mirror in the Attic (The Ma...\n", + "5665 4.53 61 NaN good_reads:book https://www.goodreads.com/author/show/7738947.... 2014 /genres/romance|/genres/new-adult|/genres/myst... dir57/20975446-tainted-pictures.html 103 Tainted Pictures (Photographer Trilogy, #2)\n", + "5683 4.56 204 NaN good_reads:book https://www.goodreads.com/author/show/3097905.... NaN /genres/fantasy|/genres/young-adult|/genres/ro... dir57/12474623-tiger-s-dream.html 895 Tiger's Dream (The Tiger Saga, #5)\n", + "5692 5.00 0 NaN good_reads:book https://www.goodreads.com/author/show/5989528.... 2012 NaN dir57/14288412-abstraction-in-theory---laws-of... 6 Abstraction In Theory - Laws Of Physical Trans...\n", + "5716 4.67 34 0810117134 good_reads:book https://www.goodreads.com/author/show/205563.M... 1970 /genres/classics|/genres/fiction|/genres/histo... dir58/1679497.The_Fortress.html 1335 The Fortress\n", + "5717 4.71 4 NaN good_reads:book https://www.goodreads.com/author/show/5838022.... 2012 NaN dir58/13741511-american-amaranth.html 14 American Amaranth\n", + "5718 4.60 656 1613725132 good_reads:book https://www.goodreads.com/author/show/1122775.... 2012 /genres/romance|/genres/m-m-romance|/genres/ro... dir58/13246997-armed-dangerous.html 5268 Armed & Dangerous (Cut & Run, #5)\n", + "5726 4.55 106 1594170347 good_reads:book https://www.goodreads.com/author/show/5158478.... 1952 /genres/religion|/genres/reference|/genres/rel... dir58/147635.Holy_Bible.html 1750 Holy Bible\n", + "5729 4.83 16 NaN good_reads:book https://www.goodreads.com/author/show/7058502.... 2014 NaN dir58/22312293-the-keeper.html 29 The Keeper (The Keeper, #5)\n", + "5753 4.61 811 1937551865 good_reads:book https://www.goodreads.com/author/show/1122775.... 2013 /genres/romance|/genres/m-m-romance|/genres/ro... dir58/16159276-touch-geaux.html 4212 Touch & Geaux (Cut & Run, #7)\n", + "5764 4.54 228 NaN good_reads:book https://www.goodreads.com/author/show/2112402.... 2013 /genres/non-fiction|/genres/self-help|/genres/... dir58/18479831-staying-strong.html 2343 Staying Strong\n", + "5778 4.63 0 NaN good_reads:book https://www.goodreads.com/author/show/4808225.... 2010 NaN dir58/11187937-un-spoken.html 19 (Un) Spoken\n", + "5806 4.57 121 0679777458 good_reads:book https://www.goodreads.com/author/show/8361.Dor... 1966 /genres/historical-fiction|/genres/fiction|/ge... dir59/351211.The_Disorderly_Knights.html 2177 The Disorderly Knights (The Lymond Chronicles,...\n", + "5873 4.55 103 144247372X good_reads:book https://www.goodreads.com/author/show/2876763.... 2012 /genres/fantasy|/genres/paranormal|/genres/ang... dir59/14367071-the-complete-hush-hush-saga.html 2869 The Complete Hush, Hush Saga\n", + "5874 4.78 18 2851944371 good_reads:book https://www.goodreads.com/author/show/318835.O... 1972 /genres/poetry|/genres/fiction|/genres/nobel-p... dir59/2014000.Le_Monogramme.html 565 Le Monogramme\n", + "5880 4.61 123 NaN good_reads:book https://www.goodreads.com/author/show/4942228.... 2010 /genres/romance|/genres/m-m-romance|/genres/sc... dir59/10506860-the-interludes.html 1031 The Interludes (In the company of shadows, #3)\n", + "5957 4.72 104 178048044X good_reads:book https://www.goodreads.com/author/show/20248.J_... 2010 /genres/romance|/genres/paranormal|/genres/vam... dir60/10780042-j-r-ward-collection.html 1788 J. R. Ward Collection\n", + "\n", + "[224 rows x 10 columns]" + ] + }, + "execution_count": 22, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df.query(\"rating > 4.5\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Here we create a mask and use it to \"index\" into the dataframe to get the rows we want." + ] + }, + { + "cell_type": "code", + "execution_count": 37, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
ratingreview_countisbnbooktypeauthor_urlyeargenre_urlsdirrating_countnameauthor
473.6857850143039954bookhttps://www.goodreads.com/author/show/903.Homer-800/genres/classics|/genres/fiction|/genres/poetr...dir01/1381.The_Odyssey.html560248The OdysseyHomer
2464.013650147712556bookhttps://www.goodreads.com/author/show/903.Homer-800/genres/classics|/genres/fantasy|/genres/mytho...dir03/1375.The_Iliad_The_Odyssey.html35123The Iliad/The OdysseyHomer
4553.8514990140449140bookhttps://www.goodreads.com/author/show/879.Plato-380/genres/philosophy|/genres/classics|/genres/no...dir05/30289.The_Republic.html82022The RepublicPlato
5963.7712400679729526bookhttps://www.goodreads.com/author/show/919.Virgil-29/genres/classics|/genres/poetry|/genres/fictio...dir06/12914.The_Aeneid.html60308The AeneidVirgil
6293.6412311580495931bookhttps://www.goodreads.com/author/show/1002.Sop...-429/genres/classics|/genres/plays|/genres/drama|/...dir07/1554.Oedipus_Rex.html93192Oedipus RexSophocles
6743.9235591590302257bookhttps://www.goodreads.com/author/show/1771.Sun...-512/genres/non-fiction|/genres/politics|/genres/c...dir07/10534.The_Art_of_War.html114619The Art of WarSun_Tzu
7464.0610870140449183bookhttps://www.goodreads.com/author/show/5158478....-500/genres/classics|/genres/spirituality|/genres/...dir08/99944.The_Bhagavad_Gita.html31634The Bhagavad GitaAnonymous
7773.5210381580493882bookhttps://www.goodreads.com/author/show/1002.Sop...-442/genres/drama|/genres/fiction|/genres/classics...dir08/7728.Antigone.html49084AntigoneSophocles
12333.94704015602764Xbookhttps://www.goodreads.com/author/show/1002.Sop...-400/genres/classics|/genres/plays|/genres/drama|/...dir13/1540.The_Oedipus_Cycle.html36008The Oedipus CycleSophocles
13974.038900192840509bookhttps://www.goodreads.com/author/show/12452.Aesop-560/genres/classics|/genres/childrens|/genres/lit...dir14/21348.Aesop_s_Fables.html71259Aesop's FablesAesop
13983.6016440141026286bookhttps://www.goodreads.com/author/show/5158478....-1500/genres/religion|/genres/literature|/genres/an...dir14/19351.The_Epic_of_Gilgamesh.html42026The Epic of GilgameshAnonymous
14283.805390486275485bookhttps://www.goodreads.com/author/show/973.Euri...-431/genres/classics|/genres/plays|/genres/drama|/...dir15/752900.Medea.html29858MedeaEuripides
18153.964930140443339bookhttps://www.goodreads.com/author/show/990.Aesc...-458/genres/classics|/genres/plays|/genres/drama|/...dir19/1519.The_Oresteia.html18729The OresteiaAeschylus
18824.023770872205541bookhttps://www.goodreads.com/author/show/879.Plato-400/genres/philosophy|/genres/classics|/genres/no...dir19/22632.The_Trial_and_Death_of_Socrates.html18712The Trial and Death of SocratesPlato
20783.843990140440399bookhttps://www.goodreads.com/author/show/957.Thuc...-411/genres/history|/genres/classics|/genres/non-f...dir21/261243.The_History_of_the_Peloponnesian_...17212The History of the Peloponnesian WarThucydides
25273.945060140449086bookhttps://www.goodreads.com/author/show/901.Hero...-440/genres/history|/genres/classics|/genres/non-f...dir26/1362.The_Histories.html20570The HistoriesHerodotus
31334.301310872203492bookhttps://www.goodreads.com/author/show/879.Plato-400/genres/philosophy|/genres/classics|/genres/no...dir32/9462.Complete_Works.html7454Complete WorksPlato
32743.884110140449493bookhttps://www.goodreads.com/author/show/2192.Ari...-350/genres/philosophy|/genres/classics|/genres/no...dir33/19068.The_Nicomachean_Ethics.html16534The Nicomachean EthicsAristotle
37573.823640872206033bookhttps://www.goodreads.com/author/show/1011.Ari...-411/genres/plays|/genres/classics|/genres/drama|/...dir38/1591.Lysistrata.html18070LysistrataAristophanes
44023.995160140449272bookhttps://www.goodreads.com/author/show/879.Plato-370/genres/non-fiction|/genres/classics|/genres/p...dir45/81779.The_Symposium.html18457The SymposiumPlato
44754.112810865163480bookhttps://www.goodreads.com/author/show/879.Plato-390/genres/philosophy|/genres/classics|/genres/no...dir45/73945.Apology.html11478ApologyPlato
53674.071330872206335bookhttps://www.goodreads.com/author/show/879.Plato-360/genres/philosophy|/genres/classics|/genres/no...dir54/30292.Five_Dialogues.html9964Five DialoguesPlato
\n", + "
" + ], + "text/plain": [ + " rating review_count isbn booktype author_url year genre_urls dir rating_count name author\n", + "47 3.68 5785 0143039954 book https://www.goodreads.com/author/show/903.Homer -800 /genres/classics|/genres/fiction|/genres/poetr... dir01/1381.The_Odyssey.html 560248 The Odyssey Homer\n", + "246 4.01 365 0147712556 book https://www.goodreads.com/author/show/903.Homer -800 /genres/classics|/genres/fantasy|/genres/mytho... dir03/1375.The_Iliad_The_Odyssey.html 35123 The Iliad/The Odyssey Homer\n", + "455 3.85 1499 0140449140 book https://www.goodreads.com/author/show/879.Plato -380 /genres/philosophy|/genres/classics|/genres/no... dir05/30289.The_Republic.html 82022 The Republic Plato\n", + "596 3.77 1240 0679729526 book https://www.goodreads.com/author/show/919.Virgil -29 /genres/classics|/genres/poetry|/genres/fictio... dir06/12914.The_Aeneid.html 60308 The Aeneid Virgil\n", + "629 3.64 1231 1580495931 book https://www.goodreads.com/author/show/1002.Sop... -429 /genres/classics|/genres/plays|/genres/drama|/... dir07/1554.Oedipus_Rex.html 93192 Oedipus Rex Sophocles\n", + "674 3.92 3559 1590302257 book https://www.goodreads.com/author/show/1771.Sun... -512 /genres/non-fiction|/genres/politics|/genres/c... dir07/10534.The_Art_of_War.html 114619 The Art of War Sun_Tzu\n", + "746 4.06 1087 0140449183 book https://www.goodreads.com/author/show/5158478.... -500 /genres/classics|/genres/spirituality|/genres/... dir08/99944.The_Bhagavad_Gita.html 31634 The Bhagavad Gita Anonymous\n", + "777 3.52 1038 1580493882 book https://www.goodreads.com/author/show/1002.Sop... -442 /genres/drama|/genres/fiction|/genres/classics... dir08/7728.Antigone.html 49084 Antigone Sophocles\n", + "1233 3.94 704 015602764X book https://www.goodreads.com/author/show/1002.Sop... -400 /genres/classics|/genres/plays|/genres/drama|/... dir13/1540.The_Oedipus_Cycle.html 36008 The Oedipus Cycle Sophocles\n", + "1397 4.03 890 0192840509 book https://www.goodreads.com/author/show/12452.Aesop -560 /genres/classics|/genres/childrens|/genres/lit... dir14/21348.Aesop_s_Fables.html 71259 Aesop's Fables Aesop\n", + "1398 3.60 1644 0141026286 book https://www.goodreads.com/author/show/5158478.... -1500 /genres/religion|/genres/literature|/genres/an... dir14/19351.The_Epic_of_Gilgamesh.html 42026 The Epic of Gilgamesh Anonymous\n", + "1428 3.80 539 0486275485 book https://www.goodreads.com/author/show/973.Euri... -431 /genres/classics|/genres/plays|/genres/drama|/... dir15/752900.Medea.html 29858 Medea Euripides\n", + "1815 3.96 493 0140443339 book https://www.goodreads.com/author/show/990.Aesc... -458 /genres/classics|/genres/plays|/genres/drama|/... dir19/1519.The_Oresteia.html 18729 The Oresteia Aeschylus\n", + "1882 4.02 377 0872205541 book https://www.goodreads.com/author/show/879.Plato -400 /genres/philosophy|/genres/classics|/genres/no... dir19/22632.The_Trial_and_Death_of_Socrates.html 18712 The Trial and Death of Socrates Plato\n", + "2078 3.84 399 0140440399 book https://www.goodreads.com/author/show/957.Thuc... -411 /genres/history|/genres/classics|/genres/non-f... dir21/261243.The_History_of_the_Peloponnesian_... 17212 The History of the Peloponnesian War Thucydides\n", + "2527 3.94 506 0140449086 book https://www.goodreads.com/author/show/901.Hero... -440 /genres/history|/genres/classics|/genres/non-f... dir26/1362.The_Histories.html 20570 The Histories Herodotus\n", + "3133 4.30 131 0872203492 book https://www.goodreads.com/author/show/879.Plato -400 /genres/philosophy|/genres/classics|/genres/no... dir32/9462.Complete_Works.html 7454 Complete Works Plato\n", + "3274 3.88 411 0140449493 book https://www.goodreads.com/author/show/2192.Ari... -350 /genres/philosophy|/genres/classics|/genres/no... dir33/19068.The_Nicomachean_Ethics.html 16534 The Nicomachean Ethics Aristotle\n", + "3757 3.82 364 0872206033 book https://www.goodreads.com/author/show/1011.Ari... -411 /genres/plays|/genres/classics|/genres/drama|/... dir38/1591.Lysistrata.html 18070 Lysistrata Aristophanes\n", + "4402 3.99 516 0140449272 book https://www.goodreads.com/author/show/879.Plato -370 /genres/non-fiction|/genres/classics|/genres/p... dir45/81779.The_Symposium.html 18457 The Symposium Plato\n", + "4475 4.11 281 0865163480 book https://www.goodreads.com/author/show/879.Plato -390 /genres/philosophy|/genres/classics|/genres/no... dir45/73945.Apology.html 11478 Apology Plato\n", + "5367 4.07 133 0872206335 book https://www.goodreads.com/author/show/879.Plato -360 /genres/philosophy|/genres/classics|/genres/no... dir54/30292.Five_Dialogues.html 9964 Five Dialogues Plato" + ] + }, + "execution_count": 37, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df[df.year < 0]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If you want to combine these conditions, use the second form and put '()' brackets around each condition. The query uses a boolean AND. Each condition ceates a mask of trues and falses." + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
ratingreview_countisbnbooktypeauthor_urlyeargenre_urlsdirrating_countname
2464.013650147712556good_reads:bookhttps://www.goodreads.com/author/show/903.Homer-800/genres/classics|/genres/fantasy|/genres/mytho...dir03/1375.The_Iliad_The_Odyssey.html35123The Iliad/The Odyssey
7464.0610870140449183good_reads:bookhttps://www.goodreads.com/author/show/5158478....-500/genres/classics|/genres/spirituality|/genres/...dir08/99944.The_Bhagavad_Gita.html31634The Bhagavad Gita
13974.038900192840509good_reads:bookhttps://www.goodreads.com/author/show/12452.Aesop-560/genres/classics|/genres/childrens|/genres/lit...dir14/21348.Aesop_s_Fables.html71259Aesop's Fables
18824.023770872205541good_reads:bookhttps://www.goodreads.com/author/show/879.Plato-400/genres/philosophy|/genres/classics|/genres/no...dir19/22632.The_Trial_and_Death_of_Socrates.html18712The Trial and Death of Socrates
31334.301310872203492good_reads:bookhttps://www.goodreads.com/author/show/879.Plato-400/genres/philosophy|/genres/classics|/genres/no...dir32/9462.Complete_Works.html7454Complete Works
44754.112810865163480good_reads:bookhttps://www.goodreads.com/author/show/879.Plato-390/genres/philosophy|/genres/classics|/genres/no...dir45/73945.Apology.html11478Apology
53674.071330872206335good_reads:bookhttps://www.goodreads.com/author/show/879.Plato-360/genres/philosophy|/genres/classics|/genres/no...dir54/30292.Five_Dialogues.html9964Five Dialogues
\n", + "
" + ], + "text/plain": [ + " rating review_count isbn booktype author_url year genre_urls dir rating_count name\n", + "246 4.01 365 0147712556 good_reads:book https://www.goodreads.com/author/show/903.Homer -800 /genres/classics|/genres/fantasy|/genres/mytho... dir03/1375.The_Iliad_The_Odyssey.html 35123 The Iliad/The Odyssey\n", + "746 4.06 1087 0140449183 good_reads:book https://www.goodreads.com/author/show/5158478.... -500 /genres/classics|/genres/spirituality|/genres/... dir08/99944.The_Bhagavad_Gita.html 31634 The Bhagavad Gita\n", + "1397 4.03 890 0192840509 good_reads:book https://www.goodreads.com/author/show/12452.Aesop -560 /genres/classics|/genres/childrens|/genres/lit... dir14/21348.Aesop_s_Fables.html 71259 Aesop's Fables\n", + "1882 4.02 377 0872205541 good_reads:book https://www.goodreads.com/author/show/879.Plato -400 /genres/philosophy|/genres/classics|/genres/no... dir19/22632.The_Trial_and_Death_of_Socrates.html 18712 The Trial and Death of Socrates\n", + "3133 4.30 131 0872203492 good_reads:book https://www.goodreads.com/author/show/879.Plato -400 /genres/philosophy|/genres/classics|/genres/no... dir32/9462.Complete_Works.html 7454 Complete Works\n", + "4475 4.11 281 0865163480 good_reads:book https://www.goodreads.com/author/show/879.Plato -390 /genres/philosophy|/genres/classics|/genres/no... dir45/73945.Apology.html 11478 Apology\n", + "5367 4.07 133 0872206335 good_reads:book https://www.goodreads.com/author/show/879.Plato -360 /genres/philosophy|/genres/classics|/genres/no... dir54/30292.Five_Dialogues.html 9964 Five Dialogues" + ] + }, + "execution_count": 19, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df[(df.year < 0) & (df.rating > 4)]#there were none greater than 4.5!" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "###Cleaning" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We first check the datatypes. Notice that `review_count`, `rating_count` are of type `object` (which means they are either strings or Pandas couldnt figure what they are), while `year` is a float." + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "rating float64\n", + "review_count object\n", + "isbn object\n", + "booktype object\n", + "author_url object\n", + "year float64\n", + "genre_urls object\n", + "dir object\n", + "rating_count object\n", + "name object\n", + "dtype: object" + ] + }, + "execution_count": 20, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df.dtypes" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Suppose we try and fix this" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "ename": "ValueError", + "evalue": "invalid literal for long() with base 10: 'None'", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mValueError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mdf\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m'rating_count'\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mdf\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mrating_count\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mastype\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mint\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 2\u001b[0m \u001b[0mdf\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m'review_count'\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mdf\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mreview_count\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mastype\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mint\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 3\u001b[0m \u001b[0mdf\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m'year'\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mdf\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0myear\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mastype\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mint\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m//anaconda/lib/python2.7/site-packages/pandas/core/generic.pyc\u001b[0m in \u001b[0;36mastype\u001b[0;34m(self, dtype, copy, raise_on_error, **kwargs)\u001b[0m\n\u001b[1;32m 2409\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2410\u001b[0m mgr = self._data.astype(\n\u001b[0;32m-> 2411\u001b[0;31m dtype=dtype, copy=copy, raise_on_error=raise_on_error, **kwargs)\n\u001b[0m\u001b[1;32m 2412\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_constructor\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mmgr\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m__finalize__\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2413\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m//anaconda/lib/python2.7/site-packages/pandas/core/internals.pyc\u001b[0m in \u001b[0;36mastype\u001b[0;34m(self, dtype, **kwargs)\u001b[0m\n\u001b[1;32m 2502\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2503\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mastype\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdtype\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 2504\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mapply\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'astype'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdtype\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mdtype\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 2505\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2506\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mconvert\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m//anaconda/lib/python2.7/site-packages/pandas/core/internals.pyc\u001b[0m in \u001b[0;36mapply\u001b[0;34m(self, f, axes, filter, do_integrity_check, **kwargs)\u001b[0m\n\u001b[1;32m 2457\u001b[0m copy=align_copy)\n\u001b[1;32m 2458\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 2459\u001b[0;31m \u001b[0mapplied\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mgetattr\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mb\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mf\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 2460\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2461\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0misinstance\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mapplied\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mlist\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m//anaconda/lib/python2.7/site-packages/pandas/core/internals.pyc\u001b[0m in \u001b[0;36mastype\u001b[0;34m(self, dtype, copy, raise_on_error, values, **kwargs)\u001b[0m\n\u001b[1;32m 371\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mastype\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdtype\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mcopy\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mFalse\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mraise_on_error\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mTrue\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mvalues\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mNone\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 372\u001b[0m return self._astype(dtype, copy=copy, raise_on_error=raise_on_error,\n\u001b[0;32m--> 373\u001b[0;31m values=values, **kwargs)\n\u001b[0m\u001b[1;32m 374\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 375\u001b[0m def _astype(self, dtype, copy=False, raise_on_error=True, values=None,\n", + "\u001b[0;32m//anaconda/lib/python2.7/site-packages/pandas/core/internals.pyc\u001b[0m in \u001b[0;36m_astype\u001b[0;34m(self, dtype, copy, raise_on_error, values, klass, **kwargs)\u001b[0m\n\u001b[1;32m 401\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mvalues\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0mNone\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 402\u001b[0m \u001b[0;31m# _astype_nansafe works fine with 1-d only\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 403\u001b[0;31m \u001b[0mvalues\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mcom\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_astype_nansafe\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mvalues\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mravel\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdtype\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mcopy\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mTrue\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 404\u001b[0m \u001b[0mvalues\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mvalues\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mreshape\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mvalues\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mshape\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 405\u001b[0m newb = make_block(values,\n", + "\u001b[0;32m//anaconda/lib/python2.7/site-packages/pandas/core/common.pyc\u001b[0m in \u001b[0;36m_astype_nansafe\u001b[0;34m(arr, dtype, copy)\u001b[0m\n\u001b[1;32m 2729\u001b[0m \u001b[0;32melif\u001b[0m \u001b[0marr\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdtype\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mobject_\u001b[0m \u001b[0;32mand\u001b[0m \u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0missubdtype\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mdtype\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtype\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0minteger\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2730\u001b[0m \u001b[0;31m# work around NumPy brokenness, #1987\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 2731\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mlib\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mastype_intsafe\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0marr\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mravel\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdtype\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mreshape\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0marr\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mshape\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 2732\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2733\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mcopy\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32mpandas/lib.pyx\u001b[0m in \u001b[0;36mpandas.lib.astype_intsafe (pandas/lib.c:14844)\u001b[0;34m()\u001b[0m\n", + "\u001b[0;32mpandas/src/util.pxd\u001b[0m in \u001b[0;36mutil.set_value_at (pandas/lib.c:63086)\u001b[0;34m()\u001b[0m\n", + "\u001b[0;31mValueError\u001b[0m: invalid literal for long() with base 10: 'None'" + ] + } + ], + "source": [ + "df['rating_count']=df.rating_count.astype(int)\n", + "df['review_count']=df.review_count.astype(int)\n", + "df['year']=df.year.astype(int)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Oppos we got an error. Something is not right. Its trying to convert some python datatype: `None` into an int. This usually means data was missing. Was it?" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
ratingreview_countisbnbooktypeauthor_urlyeargenre_urlsdirrating_countname
24424.23526good_reads:bookhttps://www.goodreads.com/author/show/623606.A...NaN/genres/religion|/genres/islam|/genres/non-fic...dir25/1301625.La_Tahzan.html4134La Tahzan
28694.612good_reads:bookhttps://www.goodreads.com/author/show/8182217....NaNdir29/22031070-my-death-experiences---a-preach...23My Death Experiences - A Preacher’s 18 Apoca...
3643NaNNoneNoneNoneNoneNaNdir37/9658936-harry-potter.htmlNoneNone
5282NaNNoneNoneNoneNoneNaNdir53/113138.The_Winner.htmlNoneNone
55723.71358423336603good_reads:bookhttps://www.goodreads.com/author/show/285658.E...NaN/genres/fictiondir56/890680._rase_una_vez_el_amor_pero_tuve_q...403Érase una vez el amor pero tuve que matarlo. ...
56584.3244good_reads:bookhttps://www.goodreads.com/author/show/25307.Ro...NaN/genres/fantasy|/genres/fantasy|/genres/epic-f...dir57/5533041-assassin-s-apprentice-royal-assa...3850Assassin's Apprentice / Royal Assassin (Farsee...
56834.56204good_reads:bookhttps://www.goodreads.com/author/show/3097905....NaN/genres/fantasy|/genres/young-adult|/genres/ro...dir57/12474623-tiger-s-dream.html895Tiger's Dream (The Tiger Saga, #5)
\n", + "
" + ], + "text/plain": [ + " rating review_count isbn booktype author_url year genre_urls dir rating_count name\n", + "2442 4.23 526 good_reads:book https://www.goodreads.com/author/show/623606.A... NaN /genres/religion|/genres/islam|/genres/non-fic... dir25/1301625.La_Tahzan.html 4134 La Tahzan\n", + "2869 4.61 2 good_reads:book https://www.goodreads.com/author/show/8182217.... NaN dir29/22031070-my-death-experiences---a-preach... 23 My Death Experiences - A Preacher’s 18 Apoca...\n", + "3643 NaN None None None None NaN dir37/9658936-harry-potter.html None None\n", + "5282 NaN None None None None NaN dir53/113138.The_Winner.html None None\n", + "5572 3.71 35 8423336603 good_reads:book https://www.goodreads.com/author/show/285658.E... NaN /genres/fiction dir56/890680._rase_una_vez_el_amor_pero_tuve_q... 403 Érase una vez el amor pero tuve que matarlo. ...\n", + "5658 4.32 44 good_reads:book https://www.goodreads.com/author/show/25307.Ro... NaN /genres/fantasy|/genres/fantasy|/genres/epic-f... dir57/5533041-assassin-s-apprentice-royal-assa... 3850 Assassin's Apprentice / Royal Assassin (Farsee...\n", + "5683 4.56 204 good_reads:book https://www.goodreads.com/author/show/3097905.... NaN /genres/fantasy|/genres/young-adult|/genres/ro... dir57/12474623-tiger-s-dream.html 895 Tiger's Dream (The Tiger Saga, #5)" + ] + }, + "execution_count": 22, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df[df.year.isnull()]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Aha, we had some incomplete data. Lets get rid of it" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "(5993, 10)" + ] + }, + "execution_count": 23, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df = df[df.year.notnull()]\n", + "df.shape" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We removed those 7 rows. Lets try the type conversion again" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "df['rating_count']=df.rating_count.astype(int)\n", + "df['review_count']=df.review_count.astype(int)\n", + "df['year']=df.year.astype(int)" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "rating float64\n", + "review_count int64\n", + "isbn object\n", + "booktype object\n", + "author_url object\n", + "year int64\n", + "genre_urls object\n", + "dir object\n", + "rating_count int64\n", + "name object\n", + "dtype: object" + ] + }, + "execution_count": 27, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df.dtypes" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Much cleaner now!" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "###Visualizing\n", + "\n", + "Pandas has handy built in visualization." + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAYAAAAECCAYAAAD3vwBsAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAEVZJREFUeJzt3X+QXXV5x/F3aMiv7mZLnI0oZmiH4jPpHyDgjxYcA5aW\nQlU6zqhTLANUiShFsFXHiaCjEwYthRmYUcZJRKBYdaAyxTJGLDImZKaCldKh2iekjEmcoRKyYbPL\nj/wg2z/uSb1uk727d3P33Hu/79c/ufd7zt3zPPPdOZ8953vvzbyJiQkkSeU5pu4CJEn1MAAkqVAG\ngCQVygCQpEIZAJJUKANAkgo1f6qNEXEscDtwIrAQWAv8AvhnYEu125cz856IuBxYDRwA1mbmAxGx\nGLgbGAbGgEsy87mOdCJJmpF5U30OICIuBU7JzL+OiOOAJ4DPAUOZeXPTfscDDwJnAIuBR4A3An8F\nDGTm5yPifcAfZOY1nWpGkjR9U14BAPcA91aPjwH20zjJR0RcCDwFXAO8GdicmfuB/RGxFTgFOAv4\nYvX6DcB1R7d8SVK7plwDyMwXMnM8IgZphMGngUeBj2fmKuBp4LPAIDDa9NIxYAhYCuyZNCZJ6gIt\nF4EjYgXwA+CuzPwmcF9mPl5tvg84jcZJfrDpZYPA85PGD41JkrpAq0XgV9O4t/+RzHy4Gt4QER/N\nzMeAc4Ef07gquD4iFgKLgJXAk8Bm4ALgMeB8YGOrgiYmJibmzZvXZjuSVKwZnzhbLQLfArwHyKbh\nTwE30VgPeAZYXd0m+iCNdwEdA1yfmfdV7wK6E3gNsBe4KDOfbVHTxM6dYzPto2cMDw/Sr/31c29g\nf72ugP6ObgDUxADoUf3cG3RHf/v27WPHjm0d+dnLlg0wMjI+rX1XrDiRBQsWdKSOTumG+eukdgKg\n1buAJHWRHTu2cfWN97NkaHltNbw4+iy3fOJdnHTSybXVoKPDAJB6zJKh5Qwcd0LdZagP+FUQklQo\nA0CSCmUASFKhDABJKpQBIEmFMgAkqVAGgCQVygCQpEIZAJJUKANAkgplAEhSoQwASSqUASBJhTIA\nJKlQBoAkFcoAkKRCGQCSVCgDQJIKZQBIUqEMAEkqlAEgSYUyACSpUAaAJBXKAJCkQhkAklQoA0CS\nCmUASFKhDABJKpQBIEmFml93AZJ6y8FXDrB9+7a6ywBgxYoTWbBgQd1l9CwDQNKMvDy+i5u+NcKS\noWdqrePF0We55RPv4qSTTq61jl5mAEiasSVDyxk47oS6y9AsuQYgSYUyACSpUAaAJBVqyjWAiDgW\nuB04EVgIrAV+BtwBHASeBK7MzImIuBxYDRwA1mbmAxGxGLgbGAbGgEsy87kO9SJJmoFWVwDvB3Zm\n5tuAPwG+BNwErKnG5gEXRsTxwFXAmcB5wA0RsQD4MPBEte9dwLWdaUOSNFOtAuAe4DNN++4HTs/M\njdXYd4FzgTcBmzNzf2buAbYCpwBnARuqfTdU+0qSusCUt4Ay8wWAiBikEQbXAn/XtMsYMAQsBUaP\nML5n0pgkqQu0/BxARKwAvg18KTO/ERF/27R5KfA8jZP8YNP44GHGD421NDw82HqnHtbP/fVzb1B/\nf7t3D9R6/G6zbNnAjOak7vnrNq0WgV8NPAh8JDMfroYfj4hVmflD4HzgIeBR4PqIWAgsAlbSWCDe\nDFwAPFbtu5Fp2LlzrI1WesPw8GDf9tfPvUF39DcyMl7r8bvNyMj4tOekG+avk9oJt1ZXAGto3Lb5\nTEQcWgu4Gri1WuT9KXBv9S6gW4FNNNYK1mTm3oi4DbgzIjYBe4GLZlyhJKkjWq0BXE3jhD/Z2YfZ\ndz2wftLYS8B7Z1GfJKlD/CCYJBXKAJCkQhkAklQoA0CSCmUASFKhDABJKpQBIEmFMgAkqVAGgCQV\nygCQpEIZAJJUKANAkgplAEhSoQwASSqUASBJhTIAJKlQBoAkFcoAkKRCGQCSVCgDQJIKZQBIUqEM\nAEkqlAEgSYUyACSpUAaAJBXKAJCkQhkAklQoA0CSCmUASFKhDABJKpQBIEmFMgAkqVAGgCQVygCQ\npEIZAJJUKANAkgo1fzo7RcRbgC9k5jkRcRrwHeCpavOXM/OeiLgcWA0cANZm5gMRsRi4GxgGxoBL\nMvO5o96FJGnGWgZARHwS+AtgvBo6A7g5M29u2ud44Kpq22LgkYj4PvBh4InM/HxEvA+4Frjm6LYg\nSWrHdK4AtgLvBv6+en4G8PqIuJDGVcA1wJuBzZm5H9gfEVuBU4CzgC9Wr9sAXHcUa5ckzULLNYDM\n/DaN2zqH/Aj4eGauAp4GPgsMAqNN+4wBQ8BSYM+kMUlSF2hnEfi+zHz80GPgNBon+cGmfQaB5yeN\nHxqTJHWBaS0CT7IhIj6amY8B5wI/Bh4Fro+IhcAiYCXwJLAZuAB4DDgf2DidAwwPD7beqYf1c3/9\n3BvU39/u3QO1Hr/bLFs2MKM5qXv+us1MAmCi+vcK4EsRsR94BlidmeMRcSuwicZVxZrM3BsRtwF3\nRsQmYC9w0XQOtHPn2AzK6i3Dw4N9218/9wbd0d/IyHjrnQoyMjI+7TnphvnrpHbCbVoBkJk/B86s\nHj8BvPUw+6wH1k8aewl474yrkiR1nB8Ek6RCGQCSVCgDQJIKZQBIUqEMAEkqlAEgSYUyACSpUAaA\nJBXKAJCkQhkAklQoA0CSCmUASFKhDABJKpQBIEmFMgAkqVAGgCQVygCQpEIZAJJUKANAkgplAEhS\noQwASSqUASBJhTIAJKlQBoAkFcoAkKRCGQCSVCgDQJIKZQBIUqEMAEkqlAEgSYUyACSpUAaAJBXK\nAJCkQhkAklQoA0CSCmUASFKhDABJKtT86ewUEW8BvpCZ50TE7wJ3AAeBJ4ErM3MiIi4HVgMHgLWZ\n+UBELAbuBoaBMeCSzHyuA31Ikmao5RVARHwSWAcsrIZuBtZk5tuAecCFEXE8cBVwJnAecENELAA+\nDDxR7XsXcO3Rb0GS1I7p3ALaCrybxske4PTM3Fg9/i5wLvAmYHNm7s/MPdVrTgHOAjZU+26o9pUk\ndYGWAZCZ36ZxW+eQeU2Px4AhYCkweoTxPZPGJEldoJ1F4INNj5cCz9M4yQ82jQ8eZvzQmCSpC0xr\nEXiSxyNiVWb+EDgfeAh4FLg+IhYCi4CVNBaINwMXAI9V+248/I/8dcPDg6136mH93F8/9wb197d7\n90Ctx+82y5YNzGhO6p6/bjOTAJio/v0bYF21yPtT4N7qXUC3AptoXFWsycy9EXEbcGdEbAL2AhdN\n50A7d47NoKzeMjw82Lf99XNv0B39jYyM13r8bjMyMj7tOemG+eukdsJtWgGQmT+n8Q4fMvMp4OzD\n7LMeWD9p7CXgvTOuSpLUcX4QTJIKZQBIUqEMAEkqlAEgSYUyACSpUAaAJBXKAJCkQhkAklSodr4K\nQirOvn372LJlS+2fxN2+fVutx1d/MQCkadixYxtX33g/S4aW11rHrl/8jFe9bmWtNah/GADSNC0Z\nWs7AcSfUWsOLo7+s9fjqL64BSFKhDABJKpQBIEmFMgAkqVAGgCQVygCQpEIZAJJUKANAkgplAEhS\noQwASSqUASBJhTIAJKlQBoAkFcoAkKRCGQCSVCgDQJIKZQBIUqEMAEkqlAEgSYUyACSpUAaAJBXK\nAJCkQhkAklQoA0CSCmUASFKhDABJKtT8dl8YET8BRqunTwM3AHcAB4EngSszcyIiLgdWAweAtZn5\nwKwqliQdFW0FQEQsAsjMc5rG7gfWZObGiLgNuDAi/hW4CjgDWAw8EhHfz8x9sy9dkjQb7V4BnAos\niYjvVT/j08Dpmbmx2v5d4I+BV4DNmbkf2B8RW4FTgB/PrmxJ0my1uwbwAnBjZp4HXAF8fdL2MWAI\nWMqvbhM1j0uSatbuFcAWYCtAZj4VEbuA05q2LwWeB/YAg03jg8DuVj98eHiw1S49rZ/769fedu8e\nqLsEHcayZQMz+p3r19/PdrUbAJfRuJVzZUS8lsaJ/cGIWJWZPwTOBx4CHgWuj4iFwCJgJY0F4int\n3DnWZlndb3h4sG/76+feRkbG6y5BhzEyMj7t37l+/v2E9sKt3QD4KvC1iDh0z/8yYBewLiIWAD8F\n7q3eBXQrsInG7aY1LgBLUndoKwAy8wBw8WE2nX2YfdcD69s5jiSpc/wgmCQVygCQpEIZAJJUKANA\nkgrV9ncBSVKdDr5ygO3bt017/927Bzrydt4VK05kwYIFR/3nzgUDQFJPenl8Fzd9a4QlQ8/UVsOL\no89yyyfexUknnVxbDbNhAEjqWUuGljNw3Al1l9GzXAOQpEIZAJJUKANAkgplAEhSoQwASSqUASBJ\nhTIAJKlQBoAkFcoAkKRCGQCSVCgDQJIKZQBIUqEMAEkqlAEgSYUyACSpUAaAJBXKAJCkQhkAklQo\nA0CSCmUASFKhDABJKpQBIEmFMgAkqVDz6y5AamXfvn3s2LGt1hq2b6/3+FInGADqejt2bOPqG+9n\nydDy2mrY9Yuf8arXrazt+FInGADqCUuGljNw3Am1Hf/F0V/WdmypU1wDkKRCGQCSVChvAUlSmw6+\ncqBr3iAwPHz6jF/T8QCIiGOALwOnAHuBD2bmf3f6uJLUaS+P7+Kmb42wZOiZWut4cfRZfvSPXRgA\nwJ8BCzLzzIh4C3BTNSZJPa/uNyjMxlysAZwFbADIzB8Bb5yDY0qSWpiLK4ClwJ6m569ExDGZeXAO\njq1ZmOkHsHbvHmBkZPyo19Et91ilfjMXAbAHGGx6PuXJ/9K//CAvv7y/81VN4exVZ/OGU0/tyM/u\n1EmyE7Zv38badd9n0cCyWusY/eXT/NZrXl9rDS+NjQDzaq2hW+rohhq6pY5uqAEaawDtmDcxMXGU\nS/l1EfFu4J2ZeVlE/D5wXWb+aUcPKklqaS6uAO4D/igiNlfPL5uDY0qSWuj4FYAkqTv5SWBJKpQB\nIEmFMgAkqVAGgCQVqpYvg4uIY4HbgROBhcDazPxO0/Z3AtcBB4DbM3N9HXW2axr9fQz4ALCzGvpQ\nZm6Z80LbFBG/AawDXg9MAFdk5n82be/1+WvVX0/PH0BELAf+DfjD5tp7fe4OmaK/fpi7nwCj1dOn\nM/MDTdtmNH91fRvo+4GdmXlxRBwH/DvwHfi/k+fNNL4y4kVgc0Tcn5ntfdKhHkfsr3I6cHFmPl5L\ndbP3DuBgZr41IlYB11N9v1OfzN8R+6v09PxVc/QV4IXDjPf63B2xv0qvz90igMw85zDbZjx/dd0C\nugf4TFMNB5q2rQS2ZuZoZu4HHgHeNsf1zdZU/QGcAayJiE0R8ak5rewoyMx/Aj5UPf1tYHfT5p6f\nvxb9QY/PH3AjcBsw+Ssse37uKkfqD3p/7k4FlkTE9yLioeoLNg+Z8fzVEgCZ+UJmjkfEII2T5aeb\nNi/lV5c3AGPA0FzWN1st+gP4Bo0TzNuBt0ZEz30yOjNfiYg7gFuBf2ja1PPzB1P2Bz08fxFxKY2r\n0weroebvMej5uWvRH/Tw3FVeAG7MzPOAK4CvV1+5D23MX22LwBGxAvgBcFdmfrNp0yi//t1Bg/z/\nv8C63hT9AdySmSNVSj8AnDbnBR4FmXkpjfvk6yJicTXcF/MHR+wPenv+LqPxyfyHgTcAd1b3y6E/\n5m6q/qC35w5gC/B1gMx8CtgFvKbaNuP5q2sR+NXAg8BHMvPhSZv/Czi5unf+Ao1LmBvnuMRZmaq/\niBgC/iMifo/Gfbq3A1+d+yrbFxEXA6/LzBuAl4CDNBZLoT/m74j99fr8ZeaqQ4+rk+SHmu4R9/zc\nTdVfr89d5TIa/7nWlRHxWhp/9f9PtW3G81fLV0FExC3Ae4BsGl4H/GZmrouId9C4h34M8NXMvG3O\ni5yFafT358DHaPwPaf+SmZ+rocy2VX8N3wEcDxwL3AAMAAN9Mn+t+uvp+TukOkFeQWNhtC/mrtkR\n+uvpuYuI+cDXaLzDEOCTwO/Q5vz5XUCSVCg/CCZJhTIAJKlQBoAkFcoAkKRCGQCSVCgDQJIKZQBI\nUqEMAEkq1P8CWOKSaEYjMvAAAAAASUVORK5CYII=\n", + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "df.rating.hist();" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We can do this in more detail, plotting against a mean, with cutom binsize or number of bins. Note how to label axes and create legends." + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "4.04220073358 4.04220073358 4.05\n" + ] + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAf4AAAFtCAYAAADmnQjIAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAIABJREFUeJzt3Xtc1HW+x/H3DOCFGdAot13LqMxbmSSKqXnfMkwlTbFA\n0ZNdjpZaeVnJG2qa17JMy9paS9RVS/J0cdOTmpaYGpWZpltWZIYkGuPMgAw4v/OHx9nIlEvMgPxe\nz7/gO7/v7/f5+vXBe353i2EYhgAAgClYK7sAAAAQOAQ/AAAmQvADAGAiBD8AACZC8AMAYCIEPwAA\nJkLwA5WsadOm6t27t/r06aO+ffsqNjZW/fv315dfflli39dff10rV66UJK1atUovvfSSv8tV06ZN\nlZubW6wtLS1Nw4YNkyQtXLhQ69atu+A6Fi1apE2bNvmtRgDnF1zZBQCQUlNTVbduXd/v//jHPzRj\nxgytWrXqgv0yMjLUuHFjSdI999zj1xovxGKx+H4eNWpUicvv3LlTjRo18mdJAM6D4AeqgF8/R6uo\nqEg//fST74tATk6OpkyZohMnTujYsWOqX7++nn32WWVkZGjLli1KT09XzZo1deLECeXm5mry5Mnq\n1q2b7rrrLu3YsUNZWVnq0aOHxo0bJ0l66aWXtHbtWtlsNrVq1UqbNm3S5s2b9cknn2jOnDk6ffq0\nLBaL/vu//1vdu3cvsd7f/p6cnKzGjRtr6NChWrhwod5//32FhISobt26mj17tjZu3Kgvv/xSc+fO\nVVBQkG6++WZNmzZNBw8elCR16tRJo0ePVlBQkLZu3ar58+crKChIzZo1U3p6ulauXKmdO3fqjTfe\n0KlTpxQWFqYlS5YoJSVFmZmZys3Nlc1m01NPPaVrrrlGSUlJat68uT7++GMdP35cgwcP1vHjx7Vr\n1y7l5+frmWee8X15AsyA4AeqgMGDB8tqterEiROqWbOmunbtqieffFKStH79ekVHR+v++++XJD34\n4IP6n//5H917773avHmzGjdurIEDB2rRokXF9rzz8vK0YsUKZWdnq3v37kpMTNS3336rN998U2vX\nrpXdbtfEiRN9fZ577jnde++9uuOOO3Tw4EGtWbPmvME/ePBgBQUF+X53OBxq0qSJpDN7/xaLRVlZ\nWVq2bJl27NihkJAQLV26VF988YUGDhyo9957T0lJSbr11ls1fvx4RURE6O2335bH49Hw4cP1yiuv\nKD4+Xn/729+0bNkyNWnSROvWrdObb77pq/fQoUPavHmzbDabNmzYoDp16mj16tWSpJSUFK1YsUKT\nJk2SJB05ckRvvvmmvvjiCw0YMEBLlizR+PHjNWvWLC1fvlzTp0+vyOkEqjSCH6gCzh7q/+qrr/TA\nAw+oZcuWioiIkHQmZD/55BMtXbpU33//vb7++mtFRUX5+p7d2/7tXvhf//pXSdLll1+uSy+9VLm5\nudq6dat69Oghu90uSRo4cKB27NghSbrjjjs0bdo0bd68We3bt9djjz1WYr1nvfnmm9qwYUOxZf78\n5z+radOm6tu3rzp27KhOnTqpXbt256zrww8/9J3SqFGjhhISEvTaa6/p2muv1XXXXef7QtGnTx/N\nmDHD169x48ay2WySpNtvv11XXnmlUlNTlZmZqV27dqlly5a+Zc9+gbnyyislSR07dpQkXXXVVdq5\nc+d5xwlUR1zcB1QhzZo10+OPP66JEyfqyJEjkqR58+Zp4cKFuvTSS3XPPffolltuKRbyv97L/7Va\ntWoV+90wDIWEhMjr9frarNb//Am4++679fbbb+uWW27RRx99pLi4OLlcrlLV/XuH/i0Wi5YvX67Z\ns2frkksu0axZszRz5sxz+nq93mL9T58+rcLCQgUFBZ2z3l/Xezb0JWnlypWaNGmSQkNDFRcXp549\nexbrW6NGjWLrOXu0gleVwIwIfqCK6dmzp1q2bOk71L99+3YNGTJEcXFxioiIUHp6ui+8g4KCVFhY\n6Ot7oSCzWCzq3LmzNm7c6Av0N954wxem99xzj7766iv17dtX06dP18mTJ3Xy5Mky13+2hgMHDqhX\nr1669tpr9eCDD2rIkCG+8/jBwcG+ujt06KAVK1ZIkjwej9asWaMOHTooOjpa33//va/Phg0bdPLk\nyd/9orN9+3b17dtX/fr109VXX63NmzcX+4JDwAP/waF+oJL9XpBNnjxZcXFx2r59ux5++GHNnTtX\nL774oiIiInT77bcrMzNT0pkL4c6enz57bv1C2rZtqwEDBujuu+9WrVq11KhRI9+RgXHjxmnmzJl6\n5plnZLFYNGLECNWvX79U9f667WwdTZs2VWxsrPr166fQ0FDVrl3bd869a9eumjNnjgoLCzVp0iQ9\n8cQT6t27tzwejzp16qRhw4YpODhYTz31lMaPHy+r1armzZsrODhYtWrVOqeGoUOHasqUKVq3bp0u\n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\n", + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "sns.set_context(\"notebook\")\n", + "meanrat=df.rating.mean()\n", + "#you can get means and medians in different ways\n", + "print meanrat, np.mean(df.rating), df.rating.median()\n", + "with sns.axes_style(\"whitegrid\"):\n", + " df.rating.hist(bins=30, alpha=0.4);\n", + " plt.axvline(meanrat, 0, 0.75, color='r', label='Mean')\n", + " plt.xlabel(\"average rating of book\")\n", + " plt.ylabel(\"Counts\")\n", + " plt.title(\"Ratings Histogram\")\n", + " plt.legend()\n", + " #sns.despine()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "One can see the sparseness of review counts. This will be important when we learn about recommendations: we'll have to *regularize* our models to deal with it." + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 34, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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\nY5QfQS3uAAAAAElFTkSuQmCC\n", + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "df.review_count.hist(bins=np.arange(0, 40000, 400))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The structure may be easier to see if we rescale the x-axis to be logarithmic." + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAfEAAAFaCAYAAAAO6WRQAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAFttJREFUeJzt3X+QnPVdwPH3VbiQmM1ZdIGxpjCD7WfQmaggVAltyhit\nYWxx6ggjWmlnmkhEhJkWRmPaDp0grRicpkOjQ6yh4q8hwlSbIZbpVBKutoDWOFj9lLTTUgTL0ZDL\nhYTjQs4/9rl6XO9uL3vP7d03937NdLj97nf3eTbz7b33eXZvt2d0dBRJklSe18z3DkiSpM4YcUmS\nCmXEJUkqlBGXJKlQRlySpEIZcUmSCnXaTCZFxFnAvwI/B5wAdlb/fQK4PjNHI2I9sAE4DmzJzN0R\nsRS4F2gCQ8C1mfl87Y9CkqRFqO2ReEScDvwZ8CLQA9wJbMrMt1SXr4yIc4AbgEuBtwG3R0QvsBHY\nX839FLB5Th6FJEmL0ExOp98BbAeerS5fmJl7q58fBNYCFwP9mTmSmYeBA8AqYDWwp5q7p5orSZJq\nMG3EI+LdwEBmfrYa6qn+N2YI6ANWAINTjB+eMCZJkmrQ7jXx9wCjEbEW+EngHlqvb49ZARyiFerG\nuPHGJONjY9MaHR0d7enpaTdNkqRTRcfRmzbimblm7OeI+DxwHXBHRKzJzIeBdcDngEeB2yJiCXAG\ncAGtN731A1cAj1Vz99JGT08PAwNDnT0aaRLNZsM1pVq5plSnZrPRftIUTvZPzEaB9wG3RsQXaD0J\n2JWZ3wa2AftoRX1TZg7Tei39xyNiH/Be4NaO91SSJL1KzwL8FrNRn+GqTh41qW6uKdWp2Wx0fDrd\nD3uRJKlQRlySpEIZcUmSCmXEJUkqlBGXJKlQRlySpEIZcUmSCmXEJUkqlBGXJKlQRlySpEIZcUmS\nCmXEJUkqlBGXJKlQRlySpEIZcUmSCmXEJUkqlBGXJKlQRlySpEIZcUmSCnXafO/ARLfesYNjx0Zq\nua/jx0e4+u2Xc95559Vyf5IkLSQLLuKP/2+ztvsaPjrI6meeMeKSpFOSp9MlSSqUEZckqVBGXJKk\nQhlxSZIKZcQlSSqUEZckqVBGXJKkQhlxSZIKZcQlSSqUEZckqVBtP3Y1Ir4PuBt4IzAKXAf0Ap8B\nvlpN+0Rm3hcR64ENwHFgS2bujoilwL1AExgCrs3M52t/JJIkLTIz+ez0XwJOZOZlEbEGuA34R2Br\nZt45NikizgFuAC4ClgKPRMRDwEZgf2Z+OCKuBjYDN9X8OCRJWnTaRjwzPx0Rn6kungccohXqiIgr\ngSdpRfkSoD8zR4CRiDgArAJWAx+tbr8H+ECtj0CSpEVqRt9ilpmvRMRO4JeBXwVeB9ydmV+OiE3A\nh4B/BwbH3WwI6ANWAIcnjHVNX98yms1GNzepBcg1oLq5prQQzPirSDPz3RFxNvAl4NLMfKa66gHg\n48BeYPyqbtA6aj88bnxsrGsGB48yMDDUzU1qgWk2G64B1co1pTrN5glh23enR8S7IuL3q4vHgBPA\n/RFxcTW2FngceBR4c0QsiYg+4ALgCaAfuKKau45W7CVJ0izN5Eh8F7AzIh4GTgduBJ4C7oqIEeBZ\nYENmHomIbcA+Wk8ONmXmcERsB+6JiH3AMHDNXDwQSZIWm5m8se0YcPUkV102ydwdwI5Jbn9Vpzso\nSZIm54e9SJJUKCMuSVKhjLgkSYUy4pIkFcqIS5JUKCMuSVKhjLgkSYUy4pIkFcqIS5JUKCMuSVKh\njLgkSYUy4pIkFcqIS5JUKCMuSVKhjLgkSYUy4pIkFcqIS5JUKCMuSVKhjLgkSYUy4pIkFcqIS5JU\nKCMuSVKhjLgkSYUy4pIkFcqIS5JUKCMuSVKhjLgkSYUy4pIkFcqIS5JUKCMuSVKhTms3ISK+D7gb\neCMwClwHDAM7gRPAE8D1mTkaEeuBDcBxYEtm7o6IpcC9QBMYAq7NzOfn4LFIkrSozORI/JeAE5l5\nGbAZ+ENgK7ApM98C9ABXRsQ5wA3ApcDbgNsjohfYCOyv5n6qug9JkjRLbSOemZ8Gfqu6eB7wAnBR\nZu6txh4E1gIXA/2ZOZKZh4EDwCpgNbCnmrunmitJkmZpRq+JZ+YrEbET+BjwV7SOvscMAX3ACmBw\nivHDE8YkSdIstX1NfExmvjsizgYeBc4Yd9UK4BCtUDfGjTcmGR8b65q+vmU0m432E3VKcw2obq4p\nLQQzeWPbu4AfyczbgWPAK8DjEbEmMx8G1gGfoxX32yJiCa3IX0DrTW/9wBXAY9Xcvd+7lbkzOHiU\ngYGhbm5SC0yz2XANqFauKdVpNk8IZ3IkvgvYGREPA6cDNwL/DdxdvXHtK8Cu6t3p24B9tE7Tb8rM\n4YjYDtwTEftovav9mo73VpIkfVfbiGfmMeDqSa566yRzdwA7Jrn9VR3unyRJmoIf9iJJUqGMuCRJ\nhTLikiQVyohLklQoIy5JUqGMuCRJhTLikiQVyohLklQoIy5JUqGMuCRJhTLikiQVyohLklQoIy5J\nUqGMuCRJhTLikiQVyohLklQoIy5JUqGMuCRJhTLikiQVyohLklQoIy5JUqGMuCRJhTLikiQVyohL\nklQoIy5JUqGMuCRJhTLikiQVyohLklQoIy5JUqGMuCRJhTptuisj4nTgk8C5wBJgC/A08Bngq9W0\nT2TmfRGxHtgAHAe2ZObuiFgK3As0gSHg2sx8fk4eiSRJi8y0EQd+HRjIzHdFxGuB/cCtwNbMvHNs\nUkScA9wAXAQsBR6JiIeAjcD+zPxwRFwNbAZumoPHIUnSotMu4vcBu6qfXwOM0Ap1RMSVwJO0onwJ\n0J+ZI8BIRBwAVgGrgY9Wt98DfKDe3ZckafGa9jXxzHwxM49ERINW0P8AeBR4f2auAb4OfAhoAIPj\nbjoE9AErgMMTxiRJUg3aHYkTESuB+4G7MvNvI6IvM8eC/QDwcWAvrZCPaQCHaAW8MWGsq/r6ltFs\nNtpP1CnNNaC6uaa0ELR7Y9vZwGeB387Mz1fDeyLidzPzMWAt8Dito/PbImIJcAZwAfAE0A9cATwG\nrKMV+64aHDzKwMBQtzerBaTZbLgGVCvXlOo0myeE7Y7EN9E6Bf7BiPhgNXYT8CcRMQI8C2yoTrlv\nA/bROkW/KTOHI2I7cE9E7AOGgWs63lNJkvQq00Y8M28EbpzkqssmmbsD2DFh7Bhw1Wx2UJIkTc4P\ne5EkqVBGXJKkQhlxSZIKZcQlSSqUEZckqVBGXJKkQhlxSZIKZcQlSSqUEZckqVBGXJKkQhlxSZIK\nZcQlSSqUEZckqVBGXJKkQhlxSZIKZcQlSSqUEZckqVBGXJKkQhlxSZIKZcQlSSqUEZckqVBGXJKk\nQhlxSZIKZcQlSSqUEZckqVBGXJKkQhlxSZIKZcQlSSqUEZckqVBGXJKkQhlxSZIKddp0V0bE6cAn\ngXOBJcAW4L+AncAJ4Ang+swcjYj1wAbgOLAlM3dHxFLgXqAJDAHXZubzc/RYJElaVNodif86MJCZ\nbwF+EbgL2ApsqsZ6gCsj4hzgBuBS4G3A7RHRC2wE9ldzPwVsnpuHIUnS4tMu4vcBHxw3dwS4MDP3\nVmMPAmuBi4H+zBzJzMPAAWAVsBrYU83dU82VJEk1mPZ0ema+CBARDVpB3wz88bgpQ0AfsAIYnGL8\n8ISxrurrW0az2ej2ZrXAuAZUN9eUFoJpIw4QESuB+4G7MvNvIuKPxl29AjhEK9TjV3RjkvGxsa4a\nHDzKwMBQtzerBaTZbLgGVCvXlOo0myeE055Oj4izgc8Ct2Tmzmr4yxGxpvp5HbAXeBR4c0QsiYg+\n4AJab3rrB66YMFeSJNWg3ZH4JlqnwD8YEWOvjd8IbKveuPYVYFf17vRtwD5aTww2ZeZwRGwH7omI\nfcAwcM2cPApJkhahdq+J30gr2hO9dZK5O4AdE8aOAVfNYv8kSdIU/LAXSZIKZcQlSSqUEZckqVBG\nXJKkQhlxSZIKZcQlSSqUEZckqVBGXJKkQhlxSZIKZcQlSSqUEZckqVBGXJKkQhlxSZIKZcQlSSqU\nEZckqVBGXJKkQhlxSZIKZcQlSSqUEZckqVBGXJKkQhlxSZIKZcQlSSqUEZckqVBGXJKkQhlxSZIK\nZcQlSSqUEZckqVBGXJKkQhlxSZIKZcQlSSrUaTOZFBFvAj6SmZdHxE8B/wg8WV39icy8LyLWAxuA\n48CWzNwdEUuBe4EmMARcm5nP1/4oJElahNpGPCJuAX4DOFINXQTcmZl3jptzDnBDdd1S4JGIeAjY\nCOzPzA9HxNXAZuCmeh+CJEmL00yOxA8A7wT+srp8EfDGiLiS1tH4TcAlQH9mjgAjEXEAWAWsBj5a\n3W4P8IEa912SpEWt7WvimXk/rVPkY74EvD8z1wBfBz4ENIDBcXOGgD5gBXB4wpgkSarBjF4Tn+CB\nzBwL9gPAx4G9tEI+pgEcohXwxoSxrurrW0az2Wg/Uac014Dq5prSQtBJxPdExO9m5mPAWuBx4FHg\ntohYApwBXAA8AfQDVwCPAetoxb6rBgePMjAw1O3NagFpNhuuAdXKNaU6zeYJ4clEfLT673XAXREx\nAjwLbMjMIxGxDdhH6xT9pswcjojtwD0RsQ8YBq7peE8lSdKr9IyOjraf1UVvf9+na9uh4aODbPzF\ns7ns0kvruksVyKMm1c01pTo1m42eTm/rh71IklQoIy5JUqGMuCRJhTLikiQVyohLklQoIy5JUqGM\nuCRJhTLikiQVyohLklQoIy5JUqGMuCRJhTLikiQVyohLklQoIy5JUqGMuCRJhTLikiQVyohLklQo\nIy5JUqGMuCRJhTLikiQVyohLklQoIy5JUqGMuCRJhTLikiQVyohLklQoIy5JUqGMuCRJhTLikiQV\nyohLklSo0+Z7B+bSiVeO88z/PM3XvvbkfO/KSVm58lx6e3vnezckSQvcjCIeEW8CPpKZl0fEjwI7\ngRPAE8D1mTkaEeuBDcBxYEtm7o6IpcC9QBMYAq7NzOfn4HFM6tjQ83zqc0fZ9fhwtzY5a0cHn+Nj\nN7+D889/w3zviiRpgWsb8Yi4BfgN4Eg1dCewKTP3RsR24MqI+CJwA3ARsBR4JCIeAjYC+zPzwxFx\nNbAZuGkOHseUlvWdxfLXvq6bm5QkqStm8pr4AeCdQE91+cLM3Fv9/CCwFrgY6M/Mkcw8XN1mFbAa\n2FPN3VPNlSRJNWgb8cy8n9Yp8jE9434eAvqAFcDgFOOHJ4xJkqQadPLGthPjfl4BHKIV6sa48cYk\n42NjauPMM5fTbDbaT9SM+e+purmmtBB0EvEvR8SazHwYWAd8DngUuC0ilgBnABfQetNbP3AF8Fg1\nd+/kd6nxDh48wsDA0Hzvximj2Wz476lauaZUp9k8ITyZvxMfrf77PuDWiPgCrScBuzLz28A2YB+t\nqG/KzGFgO/DjEbEPeC9wa8d7KkmSXmVGR+KZ+Q3g0urnJ4G3TjJnB7Bjwtgx4KrZ7qQkSfpefmKb\nJEmFMuKSJBXKiEuSVCgjLklSoYy4JEmFMuKSJBXKiEuSVCgjLklSoYy4JEmFMuKSJBXKiEuSVCgj\nLklSoYy4JEmFMuKSJBXKiEuSVCgjLklSoYy4JEmFMuKSJBXKiEuSVCgjLklSoYy4JEmFMuKSJBXK\niEuSVCgjLklSoYy4JEmFMuKSJBXKiEuSVCgjLklSoYy4JEmFMuKSJBXKiEuSVKjTOr1hRPwbMFhd\n/DpwO7ATOAE8AVyfmaMRsR7YABwHtmTm7lntsSRJAjqMeEScAZCZl48b+wdgU2bujYjtwJUR8UXg\nBuAiYCnwSEQ8lJkvz37XJUla3Do9Ev8JYFlE/FN1H38AXJiZe6vrHwR+AXgF6M/MEWAkIg4Aq4DH\nZ7fbkiSp04i/CNyRmX8eEW8A9ky4fgjoA1bw/6fcx49rGmeeuZxmszHfu3FK8d9TdXNNaSHoNOJf\nBQ4AZOaTEfEd4KfGXb8COAQcBsav9AbwQofbXDQOHjzCwMDQfO/GKaPZbPjvqVq5plSn2Twh7PTd\n6e8BtgJExA/TivNnI2JNdf06YC/wKPDmiFgSEX3ABbTe9CZJkmap0yPxPwf+IiLGXgN/D/Ad4O6I\n6AW+Auyq3p2+DdhH6wnDJt/UNr0Trxznqae+2ZVtrVx5Lr29vV3ZliSpfj2jo6PzvQ+v8vb3fbq2\nHTr4TNK7dDnLX/u6uu5yzj33jX8DeljWd9acbufo4HN87OZ3cP75b5jT7SwEnvpU3VxTqlOz2ejp\n9LYd/5245s6yvrOKeuIhSZoffmKbJEmFMuKSJBXKiEuSVCgjLklSoYy4JEmFMuKSJBXKiEuSVCgj\nLklSoYy4JEmFMuKSJBXKiEuSVCgjLklSoYy4JEmFMuKSJBXKryJdpE68cpynnvpmbfe3cuW59Pb2\n1nZ/kqT2jPgi9dKR77D17w6yrO/ZWd/X0cHn+NjN7+D8899Qw55JkmbKiC9iy/rOYvlrXzffuyFJ\n6pCviUuSVCgjLklSoYy4JEmFMuKSJBXKiEuSVCjfna5Zm83fnPv35ZLUOSOuWev0b879+3JJmh0j\nrlp08jfnnRzBe+QuSf/PiGvenOwRvEfukvRqRlzzyk+Nk6TOGXEV42ROv3vaXdJiYMRVjJmefj/y\nwrPc/GsX8vrXnwvACy8s5+DBI6+aY+QlnQrmPOIR8RrgE8AqYBh4b2Z+ba63q1PTTE6/Hx38Nlv/\nbv+UsZ8Y+YlGRkYAOP300ye93icAkhaKbhyJ/zLQm5mXRsSbgK3VmDRnpot9u8h/5+n/YmnjB1nW\nd9b3XDfVE4Dpwm/0Jc2VbkR8NbAHIDO/FBE/3YVtStNqF/mprp/qCcBU4Z8s+pMFf+LYbC5Pdv9j\nTyRefvllvvWtb045Pt39rFzZegxjt/fJiTT/uhHxFcDhcZdfiYjXZOaJySZ//0vJ8eOTXnXSlrz0\nNC++/EO13Fe3HBs6CPQUtZ1O7+tkbzfT+e3mzeb6Y0MHWdr4wbb7MGb4xUNsufshzlh+5nfHBr/9\ndZZ8/w9MOzabyxOve+nIQTav/3le//pzeeqpb353fyYbH37x0KT3MzYXYMvdDwF897aL0WTvs5gN\n/2xSneoZHR2d0w1ExFbgi5l5X3X5W5m5ck43KknSItCNL0DpB64AiIifAf6jC9uUJOmU143T6Q8A\nPx8R/dXl93Rhm5IknfLm/HS6JEmaG36fuCRJhTLikiQVyohLklQoIy5JUqEW/BegRMRFwO/Q+vSN\nWzLzuXneJRUuIs4GPpOZF8/3vqh8EfETwMeBrwH3ZOY/z+8eqXQR8WPAjUAv8MeZ+Z9TzS3hSHwJ\ncBOwG/jZed4XFS4ieoCbgW/M867o1HEJ8CxwHJjyl610Et4LPA28RJvfVQs+4pn5BeDHgPcD/z7P\nu6PyXQfcS+v/HFIdHqH1S/ePaP2ekmbrfFpnd3YBvzndxHk9nV59q9lHMvPyqb6yNCIuBh4H1gEf\nonWKQfoeM1lPwNpq7JKI+JXM/Pv522MtdDNcUz9J60j8EAW8RKn5NcM19RxwFHiBNgfb83YkHhG3\nAHfTOl0O476yFPg9Wl9ZCrAc+CRwB/BX3d5PlWGm6ykzfyUzNwJfMuCazkn8jvoGraOmjwLburyb\nKshJrKk/rebdBPz1dPc5n88aDwDvBP6yunwZk3xlaWZ+Hvj8vOyhSjKj9TQmM6c9RSUx899R/wL8\ny7zsoUoz0zX1r8C1M7nDeTsSz8z7ab0RZEyDSb6ytLt7pVK5nlQ315TqNhdraiEtwMO0HtCYKb9z\nXJoB15Pq5ppS3Wa9phZSxP3KUtXJ9aS6uaZUt1mvqYXwTsqxr1HzK0tVB9eT6uaaUt1qW1N+Fakk\nSYVaSKfTJUnSSTDikiQVyohLklQoIy5JUqGMuCRJhTLikiQVyohLklQoIy5JUqGMuCRJhfo/296B\nD18k4BsAAAAASUVORK5CYII=\n", + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "df.review_count.hist(bins=100)\n", + "plt.xscale(\"log\");" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Here we make a scatterplot in matplotlib of rating against year. By setting the alpha transparency low we can how the density of highly rated books on goodreads has changed." + ] + }, + { + "cell_type": "code", + "execution_count": 38, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 38, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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\nPxtVvum0I3bQAAAAAElFTkSuQmCC\n", + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "plt.scatter(df.year, df.rating, lw=0, alpha=.08)\n", + "plt.xlim([1900,2010])\n", + "plt.xlabel(\"Year\")\n", + "plt.ylabel(\"Rating\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "###Pythons and ducks\n", + "\n", + "Notice that we used the series in the x-list and y-list slots in the `scatter` function in the `plt` module.\n", + "\n", + "In working with python I always remember: a python is a duck.\n", + "\n", + "What I mean is, python has a certain way of doing things. For example lets call one of these ways listiness. Listiness works on lists, dictionaries, files, and a general notion of something called an iterator.\n", + "\n", + "A Pandas series plays like a python list:" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "alist=[1,2,3,4,5]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We can construct another list by using the syntax below, also called a list comprehension." + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[1, 4, 9, 16, 25]" + ] + }, + "execution_count": 29, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "asquaredlist=[i*i for i in alist]\n", + "asquaredlist" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "And then we can again make a scatterplot" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/png": "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\n4IEHsn379nz/+9/339876O/vzx133JHjjz++9Cij1muvvZYk2bhxY+FJRr/f/e53+eMf/5iurq78\n61//yr333vuO9x2xI+Ann3wyF154YZLk3HPPzdNPPz1STzUmTJs2LWvXro3fCntnra2tueGGG5L8\n+wzLhAkTCk80es2aNSsrV65Mkrz44os58cQTC080en33u9/NvHnz0tTUVHqUUWvXrl159dVXs3jx\n4lx11VXZsWNH6ZFGrSeeeCJnnHFGvv71r+drX/vakAcJI3YEvH///kyZMuWtrydMmJCBgYHU17vs\n/HYuvvjivPDCC6XHGNUmTZqU5N9/t2688cbcdNNNhSca3SZMmJCOjo786le/yg9/+MPS44xKmzdv\nztSpU3PBBRdkw4YNXgC/g+OPPz6LFy/O3Llz89xzz+Waa67Jo48+6uf523jllVeye/fubNiwIX//\n+99z3XXX5ZFHHnnb+47Y9qZMmZIDBw689bX4ciTs3r07V111VS677LLMnj279Dij3urVq/Poo4/m\n9ttvT19fX+lxRp3Nmzdn27ZtaW9vz65du9LR0ZG9e/eWHmvUOfXUU/OFL3zhrX9+73vfmz179hSe\nanQ66aSTcsEFF6ShoSGnnXZajjvuuLzyyitve98RK+J555331v+k4amnnsoZZ5wxUk/FOLF3794s\nWrQoS5cuzRe/+MXS44xqDz30UDZs2JAkqdVqqaur8wL4bdx///3ZuHFjNm7cmDPPPDPf+c538r73\nva/0WKPO5s2bs3r16iTJyy+/nP379ztl/w4+/vGP57e//W2Sf+/q1VdfzUknnfS29x2xU9AXXXRR\nnnjiibS1tSVJVq1aNVJPNabU1dWVHmHUWr9+fXp7e7Nu3bqsW7cuSXLvvffmuOOOKzzZ6NPa2pqO\njo5ceeWVef3117N8+fK85z3vKT0Wx6jLL788t956a+bPn5/k3z/PvaB7e5/61Kfy+9//PpdffnkG\nBgbS2dn5jj/XfRY0ABTgJQwAFCDAAFCAAANAAQIMAAUIMAAUIMAAUIAAA0AB/w974zB2h57R5wAA\nAABJRU5ErkJggg==\n", + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "plt.scatter(alist, asquaredlist);" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n" + ] + } + ], + "source": [ + "print type(alist)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In other words, something is a duck if it quacks like a duck. A Pandas series quacks like a python list. They both support something called the iterator protocol, an notion of behaving in a \"listy\" way. And Python functions like `plt.scatter` will accept anything that behaves listy. Indeed here's one more example:" + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/png": "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\nlZWVpRkzZmjDhg3y+XxqaWnRzp075ff7VVVVpQULFqi3t1dr1qxRT0+PLMtSQ0OD8vLyxmJuAADg\nv0Ys/DfeeENZWVlqbm5We3u7fv3rX0uSqqurVVJSog0bNmj37t2aPXu2mpqa1NraqmQyqYqKCs2d\nO1fNzc0qKirSqlWrtGvXLu3YsUN1dXWjPjEAAPClEQv/6quv1lVXXSVJ+uijj3TRRRepra1NJSUl\nkqSysjK99dZbysrKUjQaVU5OjnJyclRQUKDOzk51dHTonnvukSSVlpbqySefHMXpAACAoXj6HX52\ndrZqa2u1ZcsWXX/99XJdN3OfZVlKJBKybVuhUGjAuG3bsm1blmUNWBcAAIytEd/hn9HQ0KDjx4/r\ntttuUyqVyozbtq1wOKxgMCjHcTLjjuMoFAoNGHccR+FweMTXsqwLMrfDuZOUnx8aZm1zkYt3ZOUN\nOXlHVt6Q08QxYuG//PLL+uSTT7RixQrl5uYqKytLs2bNUnt7u6644grF43HNmTNHkUhE27ZtUyqV\nUjKZVFdXlwoLCxWNRhWPxxWJRBSPx1VcXDziRjlOMnM7kDyl7m7OCgyWnx8iF4/Iyhty8o6svCEn\nb8bqoGjEwi8vL1dtba2WLFmi06dPq66uTpdddpnWr1+vvr4+TZ8+XeXl5fL5fKqsrFQsFlM6nVZ1\ndbUCgYAqKipUU1OjWCymQCCgxsbGsZgXAAA4i889+xfyE8AzL70tZeVmli/2n9T8OT8dxy2amDhy\n9o6svCEn78jKG3LyZqze4XPhHQAADEDhAwBgAAofAAADUPgAABiAwgcAwAAUPgAABqDwAQAwAIUP\nAIABKHwAAAxA4QMAYAAKHwAAA1D4AAAYgMIHAMAAFD4AAAag8AEAMACFDwCAASh8AAAMQOEDAGAA\nCh8AAANQ+AAAGIDCBwDAABQ+AAAGoPABADAAhQ8AgAEofAAADEDhAwBgAAofAAADUPgAABiAwgcA\nwAAUPgAABvAPd2dfX5/Wrl2rY8eOKZVKqaqqSpdeeqlWrFihadOmSZJisZiuvfZatbS0aOfOnfL7\n/aqqqtKCBQvU29urNWvWqKenR5ZlqaGhQXl5eWMxLwAAcJZhC/+VV15RXl6eHn/8cZ08eVI33nij\nfvGLX2jZsmW66667Mut1d3erqalJra2tSiaTqqio0Ny5c9Xc3KyioiKtWrVKu3bt0o4dO1RXVzfq\n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\nGIDCBwDAAP8fTbhp017bPN4AAAAASUVORK5CYII=\n", + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "plt.hist(df.rating_count.values, bins=100, alpha=0.5);" + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " \n" + ] + } + ], + "source": [ + "print type(df.rating_count), type(df.rating_count.values)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Series and numpy lists behave similarly as well.\n", + "\n", + "\n", + "### Vectorization\n", + "\n", + "Numpy arrays are a bit different from regular python lists, and are the bread and butter of data science. Pandas Series are built atop them. " + ] + }, + { + "cell_type": "code", + "execution_count": 36, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[1, 2, 3, 4, 5, 1, 2, 3, 4, 5]" + ] + }, + "execution_count": 36, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "alist + alist" + ] + }, + { + "cell_type": "code", + "execution_count": 37, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([1, 2, 3, 4, 5])" + ] + }, + "execution_count": 37, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "np.array(alist)" + ] + }, + { + "cell_type": "code", + "execution_count": 38, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([ 2, 4, 6, 8, 10])" + ] + }, + "execution_count": 38, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "np.array(alist)+np.array(alist)" + ] + }, + { + "cell_type": "code", + "execution_count": 39, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([ 1, 4, 9, 16, 25])" + ] + }, + "execution_count": 39, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "np.array(alist)**2" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In other words, operations on numpy arrays, and by extension, Pandas Series, are **vectorized**. You can add two numpy lists by just using `+` whereas the result isnt what you might expect for regular python lists. To add regular python lists elementwise, you will need to use a loop:" + ] + }, + { + "cell_type": "code", + "execution_count": 40, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[2, 4, 6, 8, 10]" + ] + }, + "execution_count": 40, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "newlist=[]\n", + "for item in alist:\n", + " newlist.append(item+item)\n", + "newlist" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Vectorization** is a powerful idiom, and we will use it a lot in this class. And, for almost all data intensive computing, we will use numpy arrays rather than python lists, as the python numerical stack is based on it. \n", + "\n", + "You have seen this in idea in spreadsheets where you add an entire column to another one.\n", + "\n", + "Two final examples" + ] + }, + { + "cell_type": "code", + "execution_count": 41, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "[ 1 4 9 16 25]\n" + ] + } + ], + "source": [ + "a=np.array([1,2,3,4,5])\n", + "print type(a)\n", + "b=np.array([1,2,3,4,5])\n", + "\n", + "print a*b" + ] + }, + { + "cell_type": "code", + "execution_count": 42, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([2, 3, 4, 5, 6])" + ] + }, + "execution_count": 42, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "a+1" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 2", + "language": "python", + "name": "python2" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 2 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython2", + "version": "2.7.10" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +}