{ "cells": [ { "cell_type": "markdown", "metadata": { "ein.tags": [ "worksheet-0" ], "slideshow": { "slide_type": "-" } }, "source": [ "# Loops\n", "\n", "## The `for` statement\n", "\n", "Consider the scenario where we are examining wind observations related to a site being considered for wind energy production. The wind data consist of a time series of [tuples](http://nbviewer.jupyter.org/github/Unidata/online-python-training/blob/master/notebooks/Basic%2520Data%2520Structures.ipynb#Tuples) containing the time of the observation and the wind gusts in meters per second. [Wind turbines can handle winds up to 40-72 meters per second](https://en.wikipedia.org/wiki/Wind_turbine_design) before measures have to be taken to limit their rotation. The goal here is to find the times at which the observations exceeded 35 meters per second.\n", "\n", "Consider the following wind gust data. Values of -1 are missing observations. UTC times are represented as strings." ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "autoscroll": "json-false", "collapsed": false, "ein.tags": [ "worksheet-0" ], "slideshow": { "slide_type": "-" } }, "outputs": [], "source": [ "data = [('2016-12-27T19:02:00Z', 19.03), ('2016-12-27T19:22:00Z', -1),\n", " ('2016-12-27T19:42:00Z', -1), ('2016-12-27T20:02:00Z', -1),\n", " ('2016-12-27T20:22:00Z', -1), ('2016-12-27T21:02:00Z', 19.03),\n", " ('2016-12-27T21:22:00Z', -1), ('2016-12-27T22:02:00Z', 28.29),\n", " ('2016-12-27T22:22:00Z', -1), ('2016-12-27T23:02:00Z', 34.98),\n", " ('2016-12-27T23:22:00Z', 35.5), ('2016-12-28T00:01:00Z', -1),\n", " ('2016-12-28T00:21:00Z', 33.44), ('2016-12-28T01:02:00Z', -1),\n", " ('2016-12-28T01:22:00Z', 36.01), ('2016-12-28T02:01:00Z', 37.55),\n", " ('2016-12-28T02:22:00Z', 44.76), ('2016-12-28T03:02:00Z', 38.58),\n", " ('2016-12-28T03:22:00Z', 36.53), ('2016-12-28T04:02:00Z', 26.75),\n", " ('2016-12-28T04:22:00Z', 23.15), ('2016-12-28T05:02:00Z', 24.18),\n", " ('2016-12-28T05:22:00Z', 22.12), ('2016-12-28T06:02:00Z', 27.78),\n", " ('2016-12-28T06:22:00Z', 27.27), ('2016-12-28T07:02:00Z', 28.29)]" ] }, { "cell_type": "markdown", "metadata": { "ein.tags": [ "worksheet-0" ], "slideshow": { "slide_type": "-" } }, "source": [ "We will find observations greater than 35 meters per second and append them to a `gusts` list. There are a few ways we could achieve this objective with Python. We could employ a `while` statement or the `range` function to enumerate incrementally through the list index to retrieve the value at a particular list index. This style of programming is familiar to Fortran or C family languages with the inevitable `for` loops (e.g., `for(int i = 0; i < n; i++)`). But often, keeping track of the list index is completely unnecessary. We are simply proceeding through a list, grabbing values of interest. In Python, when trying to process a list, instinctively gravitate towards using a `for` loop statement:\n", "\n", "```ipython\n", "for iterating_var in sequence:\n", " statements(s) # usually involving the iterating_var variable\n", "```\n", "Let's make use of the Python `for` statement for our wind gusts:\n" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "autoscroll": "json-false", "collapsed": false, "ein.tags": [ "worksheet-0" ], "slideshow": { "slide_type": "slide" } }, "outputs": [ { "data": { "text/plain": [ "[('2016-12-27T23:22:00Z', 35.5),\n", " ('2016-12-28T01:22:00Z', 36.01),\n", " ('2016-12-28T02:01:00Z', 37.55),\n", " ('2016-12-28T02:22:00Z', 44.76),\n", " ('2016-12-28T03:02:00Z', 38.58),\n", " ('2016-12-28T03:22:00Z', 36.53)]" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "gusts = []\n", "for time, obs in data:\n", " if obs > 35:\n", " gusts.append((time, obs))\n", "gusts" ] }, { "cell_type": "markdown", "metadata": { "ein.tags": [ "worksheet-0" ], "slideshow": { "slide_type": "-" } }, "source": [ "\n", "Take a closer look at the `for time, obs in data` statement. We could have written a statement such as `for observation in data` to retrieve each `observation` tuple in the series and subsequently pull apart the `time` and `obs` using tuple operations. Python, however, allows us to pull the tuple apart right in the `for` statement, yielding a concise way to obtain the observation. After that, we test the wind gust speed and append it to the `gusts` list if the wind speed exceeds the threshold.\n", "\n", "Another even more concise approach we could take is **list comprehension** which we cover in the [Functions notebook](http://nbviewer.jupyter.org/github/Unidata/online-python-training/blob/master/notebooks/Functions.ipynb) and in an example in the [Basic Input and Output notebook](http://nbviewer.jupyter.org/github/Unidata/online-python-training/blob/master/notebooks/Basic%2520Input%2520and%2520Output.ipynb#List-Comprehension-Explanation). Indeed [Guido](https://en.wikipedia.org/wiki/Guido_van_Rossum) would have preferred:" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "[('2016-12-27T23:22:00Z', 35.5),\n", " ('2016-12-28T01:22:00Z', 36.01),\n", " ('2016-12-28T02:01:00Z', 37.55),\n", " ('2016-12-28T02:22:00Z', 44.76),\n", " ('2016-12-28T03:02:00Z', 38.58),\n", " ('2016-12-28T03:22:00Z', 36.53)]" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "[(time, obs) for time, obs in data if obs > 35]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In sum, you will be employing loops extensively and you will benefit by making use of Python `for` loops to process sequences." ] } ], "metadata": { "kernelspec": { "display_name": "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.5.1" } }, "nbformat": 4, "nbformat_minor": 2 }