{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "###### The cell above loads the visual style of the notebook when run." ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", "\n", "\n", "" ], "text/plain": [ "" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from IPython.core.display import HTML\n", "css_file = '../styles.css'\n", "HTML(open(css_file, \"r\").read())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Making Choices" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
\n", "
\n", "

Learning Objectives

\n", "
\n", "
\n", "\n", "> * Explain the similarities and differences between tuples and lists.\n", "* Write conditional statements including `if`, `elif`, and `else` branches.\n", "* Correctly evaluate expressions containing `and` and `or`." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In our last lesson we saw how we could find datasets containing variable stars by drawing plots. How can we use Python to recognise the features we saw, and take a different action when it finds them? In this lesson, we’ll learn how to write code that runs only when certain conditions are true.\n", "\n", "## Conditionals\n", "\n", "We can ask Python to take different actions, depending on a condition, with an if statement:" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "not greater\n", "done\n" ] } ], "source": [ "num = 37\n", "if num > 100:\n", " print('greater')\n", "else:\n", " print('not greater')\n", "print('done')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The second line of this code uses the keyword `if` to tell Python that we want to make a choice. If the test that follows the `if` statement is true, the body of the `if` (i.e., the lines indented underneath it) are executed. If the test is false, the body of the `else` is executed instead. Only one or the other is ever executed:\n", "\n", "\n", "
Figure: Executing a conditional
\n", "\n", "Conditional statements don't have to include an `else`. If there isn't one, Python simply does nothing if the test is false:" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "before conditional...\n", "...after conditional\n" ] } ], "source": [ "num = 53\n", "print('before conditional...')\n", "if num > 100:\n", " print('53 is greater than 100')\n", "print('...after conditional')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can also chain several tests together using `elif`, which is short for \"else if\". The following Python code uses `elif` to print the sign of a number." ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "-3 is negative\n" ] } ], "source": [ "num = -3\n", "if num > 0:\n", " print(num,'is positive')\n", "elif num == 0:\n", " print(num,'is zero')\n", "else:\n", " print(num,'is negative')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "One important thing to notice in the code above is that we use a double equals sign `==` to test for equality\n", "rather than a single equals sign\n", "because the latter is used to mean assignment.\n", "\n", "We can also combine tests using `and` and `or`.\n", "`and` is only true if both tests are true:" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "one test is not true\n" ] } ], "source": [ "if (1 > 0) and (-1 > 0):\n", " print('both tests are true')\n", "else:\n", " print('one test is not true')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "while `or` is true if at least one test is true:" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "at least one test is true\n" ] } ], "source": [ "if (1 > 0) or (-1 > 0):\n", " print('at least one test is true')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Checking our Data\n", "\n", "Now we've seen how conditionals work, we can use them to look for variable stars in our star data. \n", "\n", "When there was no variable star present in our dataset, the \"processed data\" for each showed nothing but random noise, and the scatter of each star looked to be similar. The exception was the fourth dataset, where one star seemed to vary more than the others. \n", "\n", "How might we test for this? As a reminder, \n", "\n", "```python\n", "processed_data.std(axis=1)\n", "```\n", "\n", "will calculate a numpy array of standard deviations, one for each star. If a star is variable, it will have a higher standard deviation than the other stars." ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[ 0.07354632 0.0783064 0.06865498 0.07188308 0.07207184 0.07693856\n", " 0.07701755 0.07000342 0.07514565 0.07822513 1.22748527 0.07364551\n", " 0.07889032 0.07324603 0.07469193 0.07667576 0.07701152 0.06589979\n", " 0.06935011 0.06868695]\n" ] } ], "source": [ "import numpy\n", "\n", "#load data\n", "data = numpy.loadtxt(fname='data/star_data_04.csv', delimiter=',')\n", "\n", "# calculate the average brightness at each time, over all stars (rows)\n", "ave_brightness = data.mean(axis=0)\n", "\n", "# divide by the average brightness\n", "processed_data = data/ave_brightness\n", "\n", "# find the standard deviation of each star\n", "deviations = processed_data.std(axis=1)\n", "print(deviations)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can see that one star has a much higher standard deviation than the others. How might we use Python to find such an outlier?\n", "\n", "Once we have an array of standard deviations for each star, we can look for ones much greater than the mean:" ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "variable star in this data\n" ] } ], "source": [ "mean_deviation = deviations.mean()\n", "std_deviations = deviations.std()\n", "for star_deviation in deviations:\n", " if (star_deviation - mean_deviation > 3.0*std_deviations):\n", " print('variable star in this data')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Putting this together with the `for` loop from the last session we have:" ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "data/star_data_01.csv\n", "data/star_data_02.csv\n", "data/star_data_03.csv\n", "data/star_data_04.csv\n", "variable star in this data\n", "data/star_data_05.csv\n", "data/star_data_06.csv\n", "data/star_data_07.csv\n", "data/star_data_08.csv\n", "data/star_data_09.csv\n", "data/star_data_10.csv\n", "data/star_data_11.csv\n", "data/star_data_12.csv\n" ] } ], "source": [ "import glob\n", "\n", "filenames = glob.glob('data/*.csv')\n", "for f in filenames:\n", " print (f)\n", " \n", " data = numpy.loadtxt(fname=f, delimiter=',') # load in the data\n", "\n", " # calculate the average brightness over all stars (rows)\n", " ave_brightness = data.mean(axis=0) \n", "\n", " # divide by the average brightness\n", " processed_data = data/ave_brightness\n", "\n", " # standard deviation of each star\n", " deviations = processed_data.std(axis=1)\n", " \n", " mean_deviation = deviations.mean()\n", " std_deviations = deviations.std()\n", " for star_deviation in deviations:\n", " if (star_deviation - mean_deviation > 3.0*std_deviations):\n", " print('variable star in this data')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
\n", "
\n", "

How many paths?

\n", "
\n", "
\n", "\n", "> Which of the following would be printed if you were to run this code? Why did you pick this answer?\n", ">\n", "> 1. A\n", "> 2. B\n", "> 3. C\n", "> 4. B and C\n", ">\n", "> ```python\n", "> if 4 > 5:\n", "> print 'A'\n", "> elif 4 == 5:\n", "> print 'B'\n", "> elif 4 < 5:\n", "> print 'C'\n", "> ```" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "> ##### Write your answer here" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
\n", "
\n", "

What is truth?

\n", "
\n", "
\n", "\n", "> `True` and `False` are special words in Python called `booleans` which represent true\n", "and false statements. However, they aren't the only values in Python that are true and false.\n", "> In fact, *any* value can be used in an `if` or `elif`.\n", "> After reading and running the code below,\n", "> explain what the rule is for which values are considered true and which are considered false.\n", "> (Note that if the body of a conditional is a single statement, we can write it on the same line as the `if`.)\n", ">" ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "word is true\n", "non-empty list is true\n", "one is true\n" ] } ], "source": [ "if '': print ('empty string is true')\n", "if 'word': print ('word is true')\n", "if []: print ('empty list is true')\n", "if [1, 2, 3]: print ('non-empty list is true')\n", "if 0: print ('zero is true')\n", "if 1: print ('one is true')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "> ##### Write your answer here" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
\n", "
\n", "

Close enough

\n", "
\n", "
\n", "\n", "> Write some conditions that print `True` if the variable `a` is within 10% of the variable `b`\n", "> and `False` otherwise.\n", "> Compare your implementation with your partner's:\n", "> do you get the same answer for all possible pairs of numbers?" ] }, { "cell_type": "code", "execution_count": 12, "metadata": { "collapsed": true }, "outputs": [], "source": [ "# Write your code here" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Miscellany\n", "---" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
\n", "
\n", "

In place operators

\n", "
\n", "
\n", "\n", "> Python (and most other languages in the C family) provides [in-place operators](reference.html#in-place-operator)\n", "> that work like this:\n", ">\n", "> ```python\n", "> x = 1 # original value\n", "> x += 1 # add one to x, assigning result back to x\n", "> x *= 3 # multiply x by 3\n", "> print x\n", "> ```\n", "> ```\n", "> 6\n", "> ```\n", ">\n", "> Write some code that sums the positive and negative numbers in a list separately,\n", "> using in-place operators.\n", "> Do you think the result is more or less readable than writing the same without in-place operators?" ] }, { "cell_type": "code", "execution_count": 14, "metadata": { "collapsed": true }, "outputs": [], "source": [ "# WRITE YOUR CODE HERE" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
\n", "
\n", "

Exchanges

\n", "
\n", "
\n", "\n", ">What is the overall effect of the code below?\n", ">\n", "> ```python\n", "> left = 'L'\n", "> right = 'R'\n", ">\n", "> temp = left\n", "> left = right\n", "> right = temp\n", "> ```\n", ">\n", "> Compare it to\n", ">\n", "> ```python\n", "> left, right = right, left \n", "> ```\n", "\n", "> Do they do the same thing? Which do you find easier to read? " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "> ##### Write your answer here" ] } ], "metadata": { "kernelspec": { "display_name": "IPython (Python 3)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.4.3" } }, "nbformat": 4, "nbformat_minor": 0 }