146 |
147 | The code format can be generated from jupyter by clicking the download-as -> markdown button. Each block of input and output has to be enclosed in a separate div tag.
148 |
149 | For a more complete list of languages see [highlight.js](http://softwaremaniacs.org/media/soft/highlight/test.html)
150 |
--------------------------------------------------------------------------------
/_config.yml:
--------------------------------------------------------------------------------
1 | permalinks: title
2 | markdown: kramdown
3 | baseurl: /python-data-intro
4 | title: Introduction to Data Processing with Python
5 | map:
6 | - title: Home
7 | path: /
8 | caption: Introduction to Data Processing with Python
9 | - title: Core
10 | caption: The 'mandatory' workshop content
11 | subpages:
12 | - title: Python and Jupyter-Notebook (Recap)
13 | path: /core/recap.html
14 | caption: A quick recap of some of the Introduction to Programming essentials
15 | - title: Data Structures in Python
16 | path: /core/data.html
17 | caption: An introduction to the list and dictionary data structures.
18 | - title: Introducing IPython Notebook
19 | path: /core/notebook.html
20 | caption: A whole new way to work with Python!
21 | - title: Analyzing a survey
22 | path: /core/survey.html
23 | caption: Once we have our text in Python, what can we do with it?
24 | - title: Creating Charts
25 | path: /core/charts.html
26 | caption: Using IPython Notebook with matplotlib to create charts.
27 | - title: CSV Files
28 | path: /core/csv.html
29 | caption: Reading comma-separated data.
30 | - title: Extras
31 | caption: Additional workshop content
32 | subpages:
33 | - title: Alternative Approaches
34 | path: /extras/alternatives.html
35 | caption: Some other ways to store and process data.
36 | - title: Open Data
37 | path: /extras/opendata.html
38 | caption: Some places to find open data sets.
39 | kramdown:
40 | parse_block_html: true
41 |
--------------------------------------------------------------------------------
/_layouts/default.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Social Coding with OpenTechSchool
7 |
8 |
9 |
10 |
11 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
',minLength:1},e.fn.typeahead.Constructor=t,e.fn.typeahead.noConflict=function(){return e.fn.typeahead=n,this},e(document).on("focus.typeahead.data-api",'[data-provide="typeahead"]',function(t){var n=e(this);if(n.data("typeahead"))return;n.typeahead(n.data())})}(window.jQuery),!function(e){"use strict";var t=function(t,n){this.options=e.extend({},e.fn.affix.defaults,n),this.$window=e(window).on("scroll.affix.data-api",e.proxy(this.checkPosition,this)).on("click.affix.data-api",e.proxy(function(){setTimeout(e.proxy(this.checkPosition,this),1)},this)),this.$element=e(t),this.checkPosition()};t.prototype.checkPosition=function(){if(!this.$element.is(":visible"))return;var t=e(document).height(),n=this.$window.scrollTop(),r=this.$element.offset(),i=this.options.offset,s=i.bottom,o=i.top,u="affix affix-top affix-bottom",a;typeof i!="object"&&(s=o=i),typeof o=="function"&&(o=i.top()),typeof s=="function"&&(s=i.bottom()),a=this.unpin!=null&&n+this.unpin<=r.top?!1:s!=null&&r.top+this.$element.height()>=t-s?"bottom":o!=null&&n<=o?"top":!1;if(this.affixed===a)return;this.affixed=a,this.unpin=a=="bottom"?r.top-n:null,this.$element.removeClass(u).addClass("affix"+(a?"-"+a:""))};var n=e.fn.affix;e.fn.affix=function(n){return this.each(function(){var r=e(this),i=r.data("affix"),s=typeof n=="object"&&n;i||r.data("affix",i=new t(this,s)),typeof n=="string"&&i[n]()})},e.fn.affix.Constructor=t,e.fn.affix.defaults={offset:0},e.fn.affix.noConflict=function(){return e.fn.affix=n,this},e(window).on("load",function(){e('[data-spy="affix"]').each(function(){var t=e(this),n=t.data();n.offset=n.offset||{},n.offsetBottom&&(n.offset.bottom=n.offsetBottom),n.offsetTop&&(n.offset.top=n.offsetTop),t.affix(n)})})}(window.jQuery);
--------------------------------------------------------------------------------
/core/charts.md:
--------------------------------------------------------------------------------
1 | ---
2 |
3 | layout: ots
4 | title: Creating Charts
5 |
6 | ---
7 |
8 | So far we haven't done anything to really explore IPython Notebook's features, but now we're going to use the library *matplotlib* to create some graphical charts based on our data.
9 |
10 | ## Inline Charts
11 |
12 | If you're using Windows to run IPython Notebook or IPython QtConsole, you'll need to run the following special IPython command (in Notebook, type it into an IPython Notebook cell and then run it):
13 |
14 | %matplotlib inline
15 |
16 | ... this tells IPython:
17 |
18 | * `inline` means that you want charts to be shown "inline style" inside your notebook, not in a separate window.
19 |
20 | ## Simple Example
21 |
22 | Here's an example of a simple chart:
23 |
24 | import matplotlib.pyplot as plt
25 | vals = [3,2,5,0,1]
26 | plt.plot(vals)
27 |
28 | Try this in Notebook and you'll see the line chart is plotted in the notebook, under the cell.
29 |
30 | matplotlib can also output charts in other formats like image files, but being able to edit the code and regenerate the chart inline is one of the nice features of IPython Notebook!
31 |
32 | ## Using Matplotlib without IPython Notebook
33 |
34 | If you want to use matplotlib directly from Python instead of via IPython Notebook, you just need to add one final line to each of your programs:
35 |
36 | plt.show()
37 |
38 | This will display a window with the chart you created, and pause the script until you close it.
39 |
40 | All the examples in this workshop assume you're using matplotlib with Notebook, so remember this additional line as you work through it (or your program will run, but nothing will happen!)
41 |
42 | ## Radish Votes
43 |
44 | Let's start by using matplotlib to generate a bar graph to display the vote counts from the radish variety program we just wrote.
45 |
46 | If you already have the radish program loaded in IPython Notebook, then you should have generated the variable named "counts" which holds a dictionary mapping each radish name to the vote count. Let's use that to plot the vote counts.
47 |
48 | You can add this as a new cell in your notebook:
49 |
50 | import matplotlib.pyplot as plt
51 | import numpy as np
52 |
53 | names = []
54 | votes = []
55 | # Split the dictionary of name:votes into two lists, one for names and one for vote count
56 | for radish in counts:
57 | names.append(radish)
58 | votes.append(counts[radish])
59 |
60 | # The X axis can just be numbered 0,1,2,3...
61 | x = np.arange(len(counts))
62 |
63 | plt.bar(x, votes)
64 | plt.xticks(x + 0.5, names, rotation=90)
65 |
66 |
67 |
68 |
69 | There's a lot going on here so we'll go through it line by line. Don't be afraid to add `print()` statements, or tweak some of the values, or comment out certain lines (like the xticks line) and rerun the code in order to figure out what's going on here.
70 |
71 | import matplotlib.pyplot as plt
72 | import numpy as np
73 |
74 | We're importing two modules - pyplot is one way to plot graph data with Matplotlib. It's modelled on the way charting works in another popular commercial program, MATLab.
75 |
76 | NumPy is a module providing lots of numeric functions for Python.
77 |
78 | names = []
79 | votes = []
80 | # Split the dictionary of names->votes into two lists, one holding names and the other holding vote counts
81 | for radish in counts:
82 | names.append(radish)
83 | votes.append(counts[radish])
84 |
85 | This loop processes the dictionary into a format that's easy to send to matplotlib - a list of radish names (for the labels on the bars) and a list of vote counts (for the actual graph.)
86 |
87 | # The X axis can just be numbered 0,1,2,3...
88 | x = np.arange(len(counts))
89 |
90 | We create a range of indexes for the X values in the graph, one entry for each entry in the "counts" dictionary (ie `len(counts)`), numbered 0,1,2,3,etc. This will spread out the graph bars evenly across the X axis on the plot.
91 |
92 | `np.arange` is a NumPy function like the `range()` function in Python, only the result it produces is a "NumPy array". We'll see why this is useful in a second.
93 |
94 | plt.bar(x, votes)
95 |
96 |
97 |
98 |
99 | `plt.bar()` creates a bar graph, using the "x" values as the X axis positions and the values in the votes array (ie the vote counts) as the height of each bar.
100 |
101 | plt.xticks(x + 0.5, names, rotation=90)
102 |
103 |
104 |
105 |
106 | `plt.xticks()` specifies a range of values to use as labels ("ticks") for the X axis.
107 |
108 | `x + 0.5` is a special expression because x is a NumPy array. NumPy arrays have some special capabilities that normal lists or `range()` objects don't have.
109 |
110 | Doing this with a normal range is an error (try it and see):
111 |
112 | x = range(5)
113 | print(x)
114 | print(x + 0.5)
115 |
116 | However, for [NumPy arrays this means](http://docs.scipy.org/doc/numpy/reference/arrays.ndarray.html#arithmetic-and-comparison-operations) "add 0.5 to all of the numbers in the array."
117 |
118 | x = np.arange(5)
119 | print(x)
120 | print(x + 0.5)
121 |
122 | Run the above code in IPython Notebook and see what it prints out.
123 |
124 | This is what positions the X axis labels in the middle of each bar (0.5 across from the left hand side.) If you remove the `+ 0.5` from the bar graph example then the labels move across to the left hand side of each bar. Try it and see!
125 |
126 | Finally, `rotation=90` ensures that the labels are drawn sideways (90 degree angle) not straight. You can experiment with different rotations to create different effects.
127 |
128 | ## Challenge
129 |
130 | There's no label on the Y axis showing that it represents the vote count.
131 |
132 | Can you update your bar graph code so it does this? Take a look at the [ylabel() function in the pyplot documentation](http://matplotlib.org/api/pyplot_api.html#matplotlib.pyplot.ylabel).
133 |
134 |
135 | ## Advanced Charting
136 |
137 | *matplotlib* and *pyplot* are both extremely powerful charting frameworks.
138 |
139 | To take a look at some of what they can do (and the sample Python code that does it), take a moment to browse through the [Matplotlib thumbnail gallery](http://matplotlib.org/gallery.html#pylab_examples) and the [Pyplot tutorial](http://matplotlib.org/users/pyplot_tutorial.html).
140 |
141 | Because these tools are fairly complex it can also be helpful to copy and tweak an existing example from the gallery, if you're looking to create a new chart.
142 |
143 | (You'll notice the term "pylab" used on some of those pages. Pylab just means Pyplot combined with Numpy.)
144 |
145 | ## Next Chapter
146 |
147 | Time to get into some real world data! The next chapter is [CSV Files](csv.html)
148 |
--------------------------------------------------------------------------------
/core/csv.md:
--------------------------------------------------------------------------------
1 | ---
2 |
3 | layout: ots
4 | title: Reading and writing comma-separated data
5 |
6 | ---
7 |
8 | Comma-separated values (CSV) is a way of expressing structured data in flat text files:
9 |
10 | "Coffee","Water","Milk","Icecream"
11 | "Espresso","No","No","No"
12 | "Long Black","Yes","No","No"
13 | "Flat White","No","Yes","No"
14 | "Cappuccino","No","Yes - Frothy","No"
15 | "Affogato","No","No","Yes"
16 |
17 | It's a commonly used format to get data in and out of programs like Spreadsheet software, where the data is tabular.
18 |
19 | Python comes with a [CSV module](http://docs.python.org/3/library/csv.html) which provides one way to easily work with CSV-delimited data:
20 |
21 | Try downloading the [coffee.csv](../files/coffee.csv) file, which contains the rows shown above, and then run this program in IPython Notebook:
22 |
23 | import csv
24 | f=open("coffee.csv")
25 | for row in csv.reader(f):
26 | print(row)
27 |
28 | Each row is read as a list of strings representing the fields in the row.
29 |
30 | ## Why not use .split()/.strip()?
31 |
32 | We already a learned another way to do this, we've learned `split(",")` to split each row of text into comma-delimited fields, and then `strip()` to take off the quote marks.
33 |
34 | There are a few good reasons to use the CSV module here:
35 |
36 | * The csv module makes it clear what you're doing to anyone reading your code.
37 | * The csv module is less likely to contain an error that splits some lines the wrong way.
38 | * The csv module [has a lot of other features, documented here](http://docs.python.org/3/library/csv.html). These allow it to process differently formatted files, so you can easily update your program if the file format changes.
39 |
40 |
41 | ## Reading Airport data
42 |
43 | We're going to do some processing of real-world data now, using freely available airline data sets from the [OpenFlights project](http://www.openflights.org/).
44 |
45 | **TIP:** As we're moving on from radishes to aircraft, now is a good time to start a new notebook in IPython Notebook (under File->New) to keep everything organised. Don't forget to save your old notebook!
46 |
47 | Visit the [OpenFlights data page](http://openflights.org/data.html) and download their airports data file - "airports.dat". This is a file in CSV format, open it in a text editor if you want to have a look at it.
48 |
49 | ## Challenge
50 |
51 | Can you use this file to print all of the airport names for a particular country (say, Australia or Russia)?
52 |
53 | To get you started, on the OpenFlights web page it shows that "Name" is the second field in each row of data. This means in the list of fields it will have index 1 (index 0 is the first field.)
54 |
55 | Here's some code that prints the name of every airport:
56 |
57 | import csv
58 | f = open("airports.dat")
59 | for row in csv.reader(f):
60 | print(row[1])
61 |
62 | Can you expand on that to only print airports for a certain country?
63 |
64 | ## Solution
65 |
66 | import csv
67 | f = open("airports.dat")
68 | for row in csv.reader(f):
69 | if row[3] == "Australia" or row[3] == "Russia":
70 | print(row[1])
71 |
72 | ## Bonus Challenge
73 |
74 | How about writing a program that counts the number of airports in each country? This would be quite similar to the radishes problem we looked at back in the [Working with Strings](strings.md) chapter.
75 |
76 | Suggestion: Use Edit->Copy to copy the radish counting program in IPython Notebook, and then modify it to work with the airport data.
77 |
78 | # Airline Route Histogram
79 |
80 | For our final piece of code, we're going to combine everything we've learned into a more complex problem to solve.
81 |
82 | OpenFlights distribute databases for both airline locations and airline route details. You can download the routes database "routes.dat" from the [OpenFlights data page](http://www.openflights.org/data.html). This database stores every unique flight route that OpenFlights knows about. Take a moment to look at the fields available in the routes data (listed on the OpenFlights page.)
83 |
84 | By using both data sources, we can calculate how far each route travels and then plot a [histogram](https://en.wikipedia.org/wiki/Histogram) showing the distribution of distances flown.
85 |
86 | This a multiple stage problem:
87 |
88 | * Read the airports file (airports.dat) and build a dictionary mapping the unique airport ID to the geographical coordinates (latitude & longitude.) This allows you to look up the location of each airport by its ID.
89 |
90 | * Read the routes file (routes.dat) and get the IDs of the source and destination airports. Look up the latitude and longitude based on the ID. Using those coordinates, calculate the length of the route and append it to a list of all route lengths.
91 |
92 | * Plot a histogram based on the route lengths, to show the distribution of different flight distances.
93 |
94 | ## Reading the airport database
95 |
96 | Can you write code to read through "airports.dat" and create a dictionary mapping from an airport ID key (use the numeric ID in the first field) to the geographic coordinates? You may want to create two dictionaries, one holding latitudes and one holding longitudes.
97 |
98 | Look back at the [OpenFlights data page](http://www.openflights.org/data.html) to see the fields available in the airports.dat file.
99 |
100 | ### Solution
101 |
102 | latitudes = {}
103 | longitudes = {}
104 | f = open("airports.dat")
105 | for row in csv.reader(f):
106 | airport_id = row[0]
107 | latitudes[airport_id] = float(row[6])
108 | longitudes[airport_id] = float(row[7])
109 |
110 | In IPython Notebook, to see the contents of the latitudes or longitudes dictionaries, just type the variable name ("latitudes" or "longitudes") into a cell and run it.
111 |
112 |
113 |
114 |
115 | If you're not using IPython Notebook, running this program won't print any output. Add a line `print(latitudes)` or `print(longitudes)` to the end of the program to print out the variable contents. It won't be as pretty as IPython Notebook, though!
116 |
117 | There's one new thing in this example solution: `float(row[6])`. `float()` means to convert the string value to a floating point (ie fractional) number:
118 |
119 | * The CSV module returns the latitude as a string like "-6.081689"
120 | * You can convert this to an *integer number* (ie whole number) with `int(row[6])` but this would just be -6
121 | * Floating point numbers can store fractions, so we convert it to a floating point number with `float(row[6])` and get the full number -6.081689
122 |
123 | Storing the values as numbers rather than strings means you can use them for calculations later on.
124 |
125 | ## Route distances
126 |
127 | Now we have the latitude & longitude of each airport we can calculate the distance of each airline route.
128 |
129 | Calculating geographic distances is a bit tricky because the earth is a sphere. The distance we measure is the "[great circle distance](http://people.hofstra.edu/geotrans/eng/ch1en/conc1en/greatcircle.html)". We're not going to implement our own great circle distance function in Python here, instead you can [download a Python file with a geo_distance() function from here](../files/geo_distance.py). Feel free to read over it if you like, but don't worry about understanding it.
130 |
131 | There are two ways you can use this function:
132 |
133 | * Place the file in the Notebook working directory and then import it as a Python module to use it.
134 |
135 | Here's an example to test everything is working:
136 |
137 | import geo_distance
138 | geo_distance.distance(-37.814,144.963,52.519,13.406) # Melbourne to Berlin in km!
139 |
140 | In IPython Notebook, you can paste this code into a cell and Run it to see the distance.
141 |
142 | If you're not using IPython Notebook, this code snippet doesn't display anything. You'll need to store the result of the `distance` function to a variable, then add a line with a `print()` statement to display the contents of the variable.
143 |
144 | * As an laternative to the `import` statement, you can also copy and paste the contents of the geo_distance.py file into an IPython Notebook cell. Run the cell to define the `distance` function, and then use it in subsequent cells!
145 |
146 | ## Next Challenge
147 |
148 | Once you have the `distance()` function working, can you write a program that reads all the airline routes from "routes.dat", looks up the latitude and longitude of the source and destination airports, and builds a list of route distances?
149 |
150 | When looking at the list of fields in the OpenFlights data documentation, remember that we used the "Unique OpenFlights identifier" fields for each airport when we made the dictionaries of latitudes and longitudes, not the multi-letter airport codes.
151 |
152 | **TIP:** You might come across an error like "KeyError: \\N" when you first run your program. This is another problem of 'dirty data', the "routes.dat" file contains some airports that aren't listed in "airports.dat". You can skip these routes by adding a test of the type `if airport in latitudes`. If you don't quite get what I mean, sneak a peek at the solution to see one way this could work.
153 |
154 | ## Solution
155 |
156 | distances = []
157 | f = open("routes.dat")
158 | for row in csv.reader(f):
159 | source_airport = row[3]
160 | dest_airport = row[5]
161 | if source_airport in latitudes and dest_airport in latitudes:
162 | source_lat = latitudes[source_airport]
163 | source_long = longitudes[source_airport]
164 | dest_lat = latitudes[dest_airport]
165 | dest_long = longitudes[dest_airport]
166 | distances.append(geo_distance.distance(source_lat,source_long,dest_lat,dest_long))
167 |
168 | Once again, you can test the results of your program by typing the name of the output list (`distances` in this case) into an IPython Notebook cell and running it:
169 |
170 |
171 |
172 |
173 | (If you're not using IPython Notebook, this is yet another program that doesn't display anything when it runs. Add `print()` statements to the end of the program to display the variable values.)
174 |
175 | ## Histogram
176 |
177 | Now we're ready to create a histogram displaying the frequency of flights by distance.
178 |
179 | import numpy as np
180 | import matplotlib.pyplot as plt
181 |
182 | plt.hist(distances, 100, facecolor='r')
183 | plt.xlabel("Distance (km)")
184 | plt.ylabel("Number of flights")
185 |
186 |
187 |
188 |
189 |
190 | `plt.hist()` does most of the work here. The first argument we supply is the dataset (list of distances.)
191 |
192 | The second argument (100) is the number of bins to divide the histogram up into. You can increase this number to see more distinct bars and a more detailed picture, or reduce it to see a coarser picture. Try setting it to some other values and see what happens to the histogram plot.
193 |
194 | The third argument, `facecolor`, sets the colour of the graph, "r" for red. There are a lot of ways to specify colours in matplotlib, [the documentation explains them all](http://matplotlib.org/api/colors_api.html).
195 |
196 | The [full arguments available for hist() can be viewed in the matplotlib documentation](http://matplotlib.org/api/pyplot_api.html#matplotlib.pyplot.hist).
197 |
198 | # Done
199 |
200 | You've taken some real world data and graphed it in an informative way!
201 |
202 | Granted, the results aren't earth shattering but you're well on your way to understanding the techniques to perform other data analysis, and chart other data. Congratulations!
203 |
204 | If you're wondering what to look at next then there is some additional material on the [index page](../index.html) - both Extras chapters and some additional reference links.
205 |
--------------------------------------------------------------------------------
/core/data.md:
--------------------------------------------------------------------------------
1 | ---
2 |
3 | layout: ots
4 | title: Data Structures in Python
5 |
6 | ---
7 |
8 | When working with data, we need ways to store it in variables so we can manipulate it. We will use two new data structures that we didn't cover in Introduction to Programming. These are **lists** and **dictionaries**.
9 |
10 | (This chapter contains the same content as the "Data Structures in Python" chapter of the "Websites with Python Flask" workshop.)
11 |
12 | If you are already comfortable with lists and dictionaries then you can skip this and move on to the next chapter.
13 |
14 | ## Understanding data structures
15 |
16 | Back in the first session we introduced three of the most common data types used in programming: numbers, strings and booleans. We assigned those data types to variables one-by-one, like so:
17 |
18 | x = 3 # numbers
19 | a = "gorillas" # strings
20 | t = True # booleans
21 |
22 | But what if we need something more complicated, like a shopping list? Assigning a variable for every item in the list would makes things very complicated:
23 |
24 | item_1 = "milk"
25 | item_2 = "cheese"
26 | item_3 = "bread"
27 |
28 | ### Lists
29 |
30 | Fortunately we don't have to do this. Instead, we have the ``list`` data type. An empty list is simply ``[]``
31 |
32 | shopping_list = []
33 |
34 | When you are in the Python interpreter you can see what is inside a list by just typing the name of the list. For example:
35 |
36 | >>> shopping_list
37 | []
38 |
39 | The interpreter shows us that the list is empty.
40 |
41 | Now we can add items to ``shopping_list``. Try typing the following commands into the Python interpreter.
42 |
43 | shopping_list.append("milk")
44 | shopping_list.append("cheese")
45 | shopping_list.append("bread")
46 |
47 | What is in the shopping list? What happens when you append numbers or booleans to the list?
48 |
49 | You can also assign a list with some items in it all in a single line, like this:
50 |
51 | shopping_list = [ "milk", "cheese", "bread" ]
52 |
53 | To remove an item from the list we use ``remove()``:
54 |
55 | shopping_list.remove("milk")
56 |
57 | Lists can easily be processed in a ``for`` loop. Have a look at this example which prints each item of the list in a new row:
58 |
59 | for item in shopping_list:
60 | print(item)
61 |
62 | And that's it! Python also makes it really easy to check if something is in a list or not:
63 |
64 | if "milk" in shopping_list:
65 | print("Delicious!")
66 |
67 | if "eggs" not in shopping_list:
68 | print("Well we can't have that!")
69 | shopping_list.append("eggs")
70 |
71 | Lists are the most common data structure in programming. There are lots of other things you can do with lists, and all languages have their own subtly different interpretation. But fundamentally they are all very similar.
72 |
73 | In summary:
74 |
75 | shopping_list = []
76 | shopping_list.append("cookies")
77 | shopping_list.remove("cookies")
78 |
79 | ### Dictionaries
80 |
81 | The other main data type is the dictionary. The dictionary allows you to associate one piece of data (a "key") with another (a "value"). The analogy comes from real-life dictionaries, where we associate a word (the "key") with its meaning. It's a little harder to understand than a list, but Python makes them very easy to deal with.
82 |
83 | You can create a dictionary with ``{}``
84 |
85 | foods = {}
86 |
87 | And you can add items to the dictionary like this:
88 |
89 | foods["banana"] = "A delicious and tasty treat!"
90 | foods["dirt"] = "Not delicious. Not tasty. DO NOT EAT!"
91 |
92 | The keys in this example are "banana" and "dirt", and the values are the things that we assign to them. You can use any data type that won't change as a dictionary key. Check it out by using a number, a boolean value, and a list as keys in a dictionary. What does this say about strings?
93 |
94 | As with lists, you can always see what is inside a dictionary:
95 |
96 | >>> foods
97 | {'banana': 'A delicious and tasty treat!', 'dirt': 'Not delicious. Not tasty. DO NOT EAT!'}
98 |
99 | You can look up any entry in the dictionary by its key:
100 |
101 | >>> foods["banana"]
102 | 'A delicious and tasty treat!'
103 |
104 | If the key isn't found in the dictionary, a `KeyError` occurs:
105 |
106 | >>> foods["cheese"]
107 | Traceback (most recent call last):
108 | File "", line 1, in
109 | KeyError: 'cheese'
110 |
111 | For this reason, you can test whether a key is in the dictionary or not, by using the keyword `in`:
112 |
113 | if "cheese" in foods:
114 | print("Cheese is one of the known foods!")
115 | print(foods["cheese"])
116 |
117 | `not in` works as well, just like with lists.
118 |
119 | You can delete from a dictionary as well. We don't really need to include an entry for dirt:
120 |
121 | del foods["dirt"]
122 |
123 | What makes dictionaries so useful is that we can give meaning to the items within them. A list is just a bag of things, but a dictionary is a specific mapping of something to something else. By combining lists and dictionaries you can describe basically any data structure used in computing.
124 |
125 | For example, you can easily add a list to a dictionary:
126 |
127 | ingredients = {}
128 | ingredients["blt sandwich"] = ["bread", "lettuce", "tomato", "bacon"]
129 |
130 | Or add dictionaries to lists:
131 |
132 | europe = []
133 | germany = {"name": "Germany", "population": 81000000}
134 | europe.append(germany)
135 | luxembourg = {"name": "Luxembourg", "population": 512000}
136 | europe.append(luxembourg)
137 |
138 | Outside of Python, dictionaries are often called ``hash tables``, ``hash maps`` or just ``maps``.
139 |
140 | ## Next Chapter
141 |
142 | Once you're comfortable with lists and dictionaries it's time for the next chapter, [Introducing IPython Notebook](notebook.html)
143 |
--------------------------------------------------------------------------------
/core/notebook.md:
--------------------------------------------------------------------------------
1 | ---
2 |
3 | layout: ots
4 | title: Introducing Jupyter Notebook
5 |
6 | ---
7 |
8 | # Jupyter Notebook
9 |
10 | Until now we've worked with Python either directly via the interactive Python console, or by writing Python programs using a text
11 | editor.
12 |
13 | However, there are other ways to work with Python. [Jupyter](http://jupyter.org/) is a set of tools originally developed to make it easier for scientists to work with Python and data. It allows you to combine interactive Python exploration with prewritten programs and even text and equations for documentation.
14 |
15 | *Jupyter isn't a different programming language, it's just a set of computer programs for working with the Python language.*
16 |
17 | ## Sneak Preview of Jupyter
18 |
19 | ![A sample from the Jupyter Notebook introduction examples][ipn-example]
20 |
21 | (This is just an example of what Jupyter Notebook can do, don't feel like you need to understand it just yet! If you want to type it into Jupyter Notebook later on, type the special command `%matplotlib inline` before you start - there's an explanation coming up in the Charts chapter.)
22 |
23 | # Installing Jupyter Notebook
24 |
25 | There are a number of ways to install Jupyter Notebook.
26 |
27 | If you're using OS X or Windows, we recommend you download and install [Anaconda](http://continuum.io/downloads.html), which is a free bundled installer of Python together with many other useful tools (including Jupyter Notebook.)
28 |
29 | **Anaconda is a fairly large (around 300Mb) download so if you're at a workshop event we'll have some USB keys with the predownloaded installers to save on bandwidth**
30 |
31 | Anaconda comes with its own version of Python 2.7, Jupyter Notebook, plus other libraries like matplotlib and a package manager ("conda") that you can use to install other packages or other Python versions.
32 |
33 | If you're using Linux, Anaconda is available as an option but we recommend you try to install the programs using your Linux distribution instead (see under "Alternative Options", below.)
34 |
35 | ## Alternative Options
36 |
37 | **This section is only if you don't want to or can't use Anaconda**
38 |
39 | Anaconda (described above) is the easiest option for this workshop. There are some other installer options that you can test out if you'd like to try something different:
40 |
41 | * If you're on Linux, most package managers include Jupyter Notebook. For instance on Ubuntu or Debian:
42 |
43 | sudo apt-get install jupyter-notebook python-matplotlib
44 |
45 | * If you have 'pip' installed (maybe from another OTS workshop) then you may be able to install Jupyter by itself (plus matplotlib) via 'pip', as follows:
46 |
47 | pip install jupyter
48 |
49 | (If you're on OS X you may need Xcode to compile dependencies.)
50 |
51 | * If you can't get Jupyter Notebook to work on your computer at all, there's a hosted service called [Wakari](https://www.wakari.io/) that you can use for free. In this case your programs won't be running on your own computer, they'll be running "in the cloud" (i.e. on Wakari's servers somewhere else) and you'll just see the results in your web browser.
52 |
53 | ## Note about Python 3
54 |
55 | Anaconda and some of the other installers come with Python version 2. You may have been using Python version 3 up until now, this is the version that the Introduction to Programming workshop encourages you to use.
56 |
57 | The Python world is slowly migrating towards using Python 3 for everything. Jupyter is available for both 2 & 3, but Anaconda comes with Python 2 as it includes some components which are still Python 2 only.
58 |
59 | Python 2 and Python 3 have some minor incompatible differences in language syntax. The programs shown in this workshop are designed to work with both, but if you find some code that doesn't work (but perhaps works on your neighbour's computer) then this may be why.
60 |
61 |
62 | ## Starting Jupyter Notebook
63 |
64 | You interact with Jupyter Notebook using your web browser. The Notebook program creates a "web server" locally on your computer that you then connect to.
65 |
66 | On Windows, you can find a launcher for Jupyter Notebook under Anaconda in the Start menu.
67 |
68 | On Linux or OS X, you can start Jupyter Notebook from the command line. First open a terminal window, use 'cd' to navigate to the directory where you want to store your Python files and notebook document files. Then run this command:
69 |
70 | jupyter notebook
71 |
72 | You should see some output like this:
73 |
74 | [NotebookApp] Using existing profile dir: u'/home/gus/.ipython/profile_default'
75 | [NotebookApp] Serving notebooks from /home/gus/workshops
76 | [NotebookApp] The Jupyter Notebook is running at: http://127.0.0.1:8888/
77 | [NotebookApp] Use Control-C to stop this server and shut down all kernels.
78 |
79 | A browser window may automatically open showing the Jupyter Notebook interface. If it doesn't open, you can copy-paste the "http" address from the output and paste it into your browser.
80 |
81 | Even though you're interacting with Jupyter Notebook using your browser, Notebook is running right there on your computer in that window. Only you have access to it.
82 |
83 |
84 | ## First Steps with Notebook
85 |
86 | In your browser, click the "New Notebook" button and a new notebook will open up.
87 |
88 | ![Jupyter Notebook empty][ipn-empty]
89 |
90 | The empty box at the top is the first "cell" for entering Python code.
91 |
92 | Try typing something like `print("Hello World")` into the cell. To run the code in the cell and see the output, click the Run button (play icon) on the toolbar, or type Shift-Enter:
93 |
94 | ![Jupyter Notebook Hello World][ipn-hello]
95 |
96 | You'll see that whenever you run a cell, a new empty cell appears where you can enter another set of Python statements. Try assigning a variable. Let's make another shopping list:
97 |
98 | ![Jupyter Notebook Assign Variable][ipn-variable]
99 |
100 | When you Run this cell you won't see any output, but behind the scenes the variable "shopping list" has been assigned.
101 |
102 | We can see this by making a third cell to print the contents:
103 |
104 | ![Jupyter Notebook Print Shopping List][ipn-list]
105 |
106 | You can do anything with Jupyter Notebook cells that you'd do with normal Python code. As you build up the notebook full of cells you create a history of the things you've done and the results that were printed.
107 |
108 | ## Jupyter Notebook Directory
109 |
110 | When Jupyter Notebook starts up it prints a line like this:
111 |
112 | [NotebookApp] Serving notebooks from /home/gus/workshops
113 |
114 | This is the directory that it was started from, and it's the working directory for loading Python files, text files, etc.
115 |
116 | It can be helpful to make sure this directory is the directory where you plan to keep files related to your work.
117 |
118 | On Windows with Anaconda this directory is called "Jupyter Notebooks" inside "My Documents", and is created when you install Anaconda. On OS X, Linux or other Windows installations it's up to you which directory you use.
119 |
120 | If you're launching from the command line, you can 'cd' to this directory before you launch Notebook.
121 |
122 | If you're using the command line on Windows, you can use Explorer to find your directory, then hold shift+right click. The context menu that comes up should have an option to "Start a command prompt here".
123 |
124 |
125 | ## Loading Notebook Files
126 |
127 | You can also load Jupyter Notebooks that other people have created, saved as Jupyter Notebook files (File extension .ipynb.) Try [downloading and opening this Notebook file with the shopping list example](../files/shopping_list.ipynb).
128 |
129 | After you download the Notebook file, move it into your Jupyter Notebook working directory and then choose File -> Open in Notebook to open it.
130 |
131 | That Notebook contains some additional code, and some suggestions for changes you can make by going back and editing the existing files. Take a few moments to play with the Notebook - rerun the cells, edit the cells to change them, don't be afraid to break things!
132 |
133 | ## Loading Python Files
134 |
135 | You can also load a pre-existing Python file into an Jupyter Notebook cell by typing
136 |
137 | %load "myprogram.py"
138 |
139 | Into a cell and running it. This loads up a new cell containing the contents of *myprogram.py*.
140 |
141 | Test this feature out by loading one of the scripts you wrote during the recap session. You may have to specify the full path to the script file, depending on the directory Jupyter Notebook started up from.
142 |
143 | There is one other useful built-in tool for working with Python files:
144 |
145 | %run "myprogram.py"
146 |
147 | This will run *myprogram.py* and load the output into a Notebook cell.
148 |
149 | ## Other Jupyter tips
150 |
151 | * As well as Shift-Enter there are other keyboard shortcuts in Notebook. Look under the Help menu -> Keyboard Shortcuts to see them all.
152 |
153 | * In previous workshops we used `help()` to view help information in the Python interpreter. Jupyter Notebook makes this even simpler, you can just type the name of a Python function or module and end it with a `?`. Try it now, type `range?` into a cell and run it.
154 |
155 | * Using a nifty tool called NBViewer you can easily share Jupyter Notebooks on the internet, rendered as web pages (but still downloadable to play with in Jupyter.) Check out the [NBViewer home page](http://nbviewer.jupyter.org/) or the [Jupyter Notebook gallery](https://github.com/jupyter/jupyter/wiki/A-gallery-of-interesting-Jupyter-Notebooks) for some interesting ones.
156 |
157 | ## Other Ways to Run Jupyter
158 |
159 | Other options if you feel like exploring:
160 |
161 | * There is a command line "ipython" program (just run `ipython` without the --notebook argument) that behaves similarly to the "python" interactive shell, but with some of the nice features of Jupyter Notebook (although none of the graphical features.)
162 |
163 | * There is a graphical Jupyter program (ie not web browser based) called "Jupyter QtConsole". It's like the command line Jupyter but with some graphical features. Launch this one by running `jupyter qtconsole`.
164 |
165 |
166 | ## Doing the workshop without Jupyter
167 |
168 | Tried out Jupyter Notebook but don't really like it? No problem! The rest of the workshop can be completed without using Jupyter Notebook at all, feel free to go back to the Python coding tools you were using already.
169 |
170 | ## Next Chapter
171 |
172 | Time to give Notebook a real workout! The next chapter is [Working With Text Files](text-files.html)
173 |
174 | [ipn-example]: ../images/ipython_example.png
175 | [ipn-empty]: ../images/ipython_notebook.png
176 | [ipn-hello]: ../images/notebook_hello_world.png
177 | [ipn-variable]: ../images/assign_shopping_list.png
178 | [ipn-list]: ../images/print_shopping_list.png
179 |
--------------------------------------------------------------------------------
/core/recap.md:
--------------------------------------------------------------------------------
1 | ---
2 |
3 | layout: ots-jupyter
4 | title: Python and Jupyter-Notebook (Recap)
5 |
6 | ---
7 |
8 | This chapter is a recap of some of the important points of the Introduction to Programming with Python course. Feel free to skip ahead if this course is still fresh in your memory. In addition, we will introduce jupyter-notebooks, an interactive way to execute python scripts.
9 |
10 | # Installing Python and Jupyter
11 |
12 | The easiest way to install python on your computer is to use *anaconda*. There are many other ways to get python and jupyter but this one is most suitable for beginners. Follow the instructions for your operating system on [https://www.anaconda.com/download/].
13 |
14 | With the anaconda package, you get the anaconda navigator, an interactive program that lets you install addons and run programs.
15 |
16 | Use the anaconda navigator to install jupyter notebook. Alternatively, you can use the command line and type
17 | ```
18 | conda install jupyter notebook
19 | ```
20 |
21 |
22 |
23 | # Running Python and Jupyter
24 |
25 | After installing Python on your system successfully, you can start the
26 | interactive Python prompt by typing `python` in the command line and
27 | pressing ``. It will show you some context information about
28 | Python similar to this::
29 |
30 | Python 3.6.5 (default, Apr 1 2018, 05:46:30)
31 | [GCC 7.3.0] on linux
32 | Type "help", "copyright", "credits" or "license" for more information.
33 | >>>
34 |
35 | On Windows you can open Python through the Start Menu.
36 |
37 | To exit the Python interpreter, press `Ctrl-D`.
38 |
39 | To run a program saved in a Python file, you can run it from the command line like so:
40 |
41 | python program.py
42 |
43 | On Windows you can run a Python file by double-clicking it.
44 |
45 | But there is a much more interactive and fast way to start using python. Launch jupyter notebook from the anaconda navigator or by typing on the command line
46 |
47 | ```
48 | jupyter notebook
49 | ```
50 |
51 | It will start the python interpreter in the background and show a browser page that is connected to python. The browser will let you interactively edit and run your python code on your local machine. In this tutorial, we will encourage you to use jupyter-notebooks as it is a tool often used in data science. The python code is the same whether you run it interactively in jupyter or not.
52 |
53 | In the jupyter browser window, navigate to a directory where you want to start you python project and press the *new* button on the top right of the web page.
54 |
55 | 
56 |
57 |
58 | With jupyter and python running, lets recap some of the basic features of the python language. Type the code into a *cell* in jupyter and execute the cell by pressing the *Run* button or *Shift+Return* on your keyboard.
59 |
60 | # Python language basics
61 |
62 | ## Loops
63 |
64 | What does this code do?
65 |
66 |
77 |
78 | This code prints the even numbers 2 through 8, one per line.
79 |
80 | ### Bonus Challenge
81 |
82 | Python has a built-in function called `range` that can automatically generate a range of numbers like \[2, 4, 6, 8\]. For example, `range(1,10)` is a sequence of the numbers 1 through 9 (a common but sometimes confusing thing in programming is for the "end" number not to be included in a sequence.)
83 |
84 |
85 | ```python
86 | for i in range(1,10):
87 | print(i)
88 | ```
89 |
90 |
91 | Can you make a `range` equivalent to \[2, 4, 6, 8\]? To get some clues, type `help(range)`. The useful details are near the top. The help utility is available for most python functions and once you know how to read them, they are very useful.
92 |
93 |
94 | ## Variables
95 |
96 | You can use variables to manipulate values inside code. What does this code do?
97 |
98 |
99 | ```python
100 | total = 0
101 | for i in 1, 3, 7:
102 | total = total + i
103 | print(total)
104 | ```
105 |
106 | 11
107 |
108 |
109 | This code prints the sum of the numbers 1, 3 and 7.
110 |
111 | ### Bonus Challenge
112 |
113 | If you don't want to use a `for` loop for some reason, Python actually has a built-in function called `sum` that lets you bypass it completely. You can get the same result with this:
114 |
115 |
120 |
121 | Can you make a one line Python statement that uses both `sum` and `range` to print the sum of the numbers 1 through 10?
122 |
123 |
124 | ## Functions
125 |
126 | You can define your own functions with parameters in order to reuse some code again with slight differences. What does this code print?
127 |
128 |
140 |
141 | ## Conditionals
142 |
143 | You can use the 'if' statement to execute some statements only if a condition is true. What does this code print?
144 |
145 |
160 |
161 |
162 | ## Next Chapter
163 |
164 | All set with Python? On to the next chapter, [Data Structures in Python](data.html)
165 |
--------------------------------------------------------------------------------
/core/survey.md:
--------------------------------------------------------------------------------
1 | ---
2 |
3 | layout: ots
4 | title: Analyzing a survey
5 |
6 | ---
7 |
8 | # Our very, very important problem
9 |
10 | Suppose you're a greengrocer, and you run a survey to see what radish varieties your customers prefer the most. You have your assistant type up the survey results into a text file on your computer, so you have 300 lines of survey data in the file [radishsurvey.txt](../files/radishsurvey.txt). Each line consists of a name, a hyphen, then a radish variety:
11 |
12 | Angelina Belmore - Plum Purple
13 | Fred Smith - Red king
14 | Matthew Wroe - White Icicle
15 | Keira Cani - Sicily Giant
16 | Isaac Hallstrom - Red King
17 | Jin Li - White Icicle
18 | Georgia McKellar - Bunny Tail
19 | Maximilian Avdeev - Cherry Belle
20 | Lorna Beneventi - White Icicle
21 | Lara Tunnecliffe - Plum Purple
22 | Hugo Sodersten - Daikon
23 | ... and so on
24 |
25 |
26 |
27 | (You may have noticed that this is a very simple file: Unlike on a document or web page, there is no formatting whatsoever. It doesn't look pretty, but it has one big advantage: This is the simplest type of text format to work with on a computer, so it is also the most easy to process and analyze.)
28 |
29 | You want to know:
30 |
31 | * What's the most popular radish variety?
32 | * What are the least popular?
33 | * Did anyone vote twice?
34 |
35 | # Useful?
36 |
37 | ... as _ridiculously contrived_ as this example is, I'm sure lots of you have come across situations where you have some data and you want to extract some relevant information from it.
38 |
39 |
40 | # Reading The Survey
41 |
42 | Save the file [radishsurvey.txt](../files/radishsurvey.txt) to your computer. How do we write a program to find out which person voted for each radish preference?
43 |
44 | We can easily open the file with Python and go through the file line by line. Each line will have a value like `"Jin Li - White Icicle\n"`. Then we can strip off the trailing newline with the `strip()` method. (If you are curious, you can look at the documentation for [open](https://docs.python.org/3/tutorial/inputoutput.html#reading-and-writing-files) and [split](https://docs.python.org/3/library/stdtypes.html?highlight=strip#str.strip) )
45 |
46 | whith open("radishsurvey.txt") as file:
47 | for line in file:
48 | line = line.strip()
49 | # Do something with each line
50 |
51 | We need a way to split each line into the name and the vote. Thankfully, Python comes with dozens of string methods including one called `split()`. [Have a look at the documentation for split()](http://docs.python.org/3.3/library/stdtypes.html#str.split) and see if you can figure out how to split each line into the name and the vote.
52 |
53 | (Don't worry if you can't write a program that does this just yet, but at least have a think about it before you skip to the solution.)
54 |
55 | ### Solution
56 |
57 | whith open("radishsurvey.txt") as file:
58 | for line in file:
59 | line = line.strip()
60 | parts = line.split(" - ")
61 | name = parts[0]
62 | vote = parts[1]
63 | print(name + " voted for " + vote)
64 |
65 | There's a few things going on here, so let's go through it line by line. *Walking through a program in your head and thinking about what each line does by itself is a good way to start to understand it*
66 |
67 | line = line.strip()
68 |
69 | If `line` was `"Jin Li - White Icicle\n"`, this code strips the newline from the end so the value of `line` becomes `"Jin Li - White Icicle"`
70 |
71 | parts = line.split(" - ")
72 |
73 | This code looks for the substring `" - "` anywhere inside `line`, and uses that as a *delimiter* to split the string up into a list of strings on either side.
74 |
75 | After this line runs, `parts` has the value `['Jin Li', 'White Icicle']`.
76 |
77 | `split()` is a very versatile function. Try typing in a few split experiments yourself in Notebook.
78 |
79 | See if you can guess what each of these does before you run them:
80 |
81 | "1,2,3,4,5".split(",")
82 |
83 | "cheese".split(",")
84 |
85 | "Jin Li - White - Icicle".split(" - ")
86 |
87 | "Jin Li - White Icicle".split("-")
88 |
89 |
90 | Once we've split the string into `parts`, we can use indexes in the `parts` list to get at the name (the first element in the list) and the vote (the second element in the list.)
91 |
92 | name = parts[0]
93 | vote = parts[1]
94 |
95 | These two lines of code just make this clear to the reader by storing each field in a named variable. You could use `parts[0]` anywhere you used `name` and `parts[1]` anywhere that you used `vote`, but then your code would be harder for someone else to understand.
96 |
97 | print(name + " voted for " + vote)
98 |
99 | This last line *concatenates* (joins) the two variable values together with the string `" voted for "`, to make a message which is printed out.
100 |
101 |
102 | # Inspecting Votes
103 |
104 | Can you write a program which only prints out the names of people who voted for *White Icicle* radishes?
105 |
106 | Use the previous example as a base. You'll need to compare the vote with the string `"White Icicle"`, for each line in the file.
107 |
108 | ### Solution
109 |
110 | with open("radishsurvey.txt") as file:
111 | for line in file:
112 | line = line.strip()
113 | parts = line.split(" - ")
114 | name, vote = parts
115 | if vote == "White Icicle":
116 | print(name + " likes White Icicle!")
117 |
118 | You might notice that the code splitting the line has become even shorter here. Instead of assigning each element of parts separately, we can assign them together using a technique called "multiple assignment". The line `name, vote = parts` means to assign each variable to the corresponding item in the list.
119 |
120 | ### More about multiple assignment
121 |
122 | Take a moment to play with multiple assignment in IPython Notebook (see the previous solution for an example of this.) Try some lines like these:
123 |
124 | a, b, c = [1, 2, 3]
125 | print(b)
126 | print(a)
127 |
128 | Or this:
129 |
130 | name, cheese, cracker = "Fred,Jarlsberg,Rye".split(",")
131 | print(cheese)
132 |
133 | You'll notice that multiple assignment only works when the number of elements being assigned on the left hand side of the " = " matches the number on the right.
134 |
135 | For instance, this doesn't work:
136 |
137 | x, y, z = [1, 2]
138 |
139 | Neither does this:
140 |
141 | name, cheese, cracker = "Fred,Jarlsberg,Rye,Buckwheat".split(",")
142 |
143 | You may have noticed in the [documentation for split()](http://docs.python.org/3/library/stdtypes.html#str.split) that you can attach an optional second argument which is the maximum number of times to split the string. You can use this to prevent errors by creating too many elements, like this:
144 |
145 | name, cheese, cracker = "Fred,Jarlsberg,Rye,Buckwheat".split(",",2)
146 | print(name)
147 | print(cracker)
148 |
149 | Confusion warning: The optional argument to split is the *number of times to split the string*, not the number of parts to split it into. So splitting it one time creates two strings, splitting it two times creates three strings, etc. A little "got you" moment for the unwary Python programmer!
150 |
151 | # Tip
152 |
153 | Multiple assignment actually makes use of a Python type called a 'tuple' and a notion called 'sequence unpacking'. Tuples and sequence unpacking aren't required knowledge to complete this workshop. However if you're feeling curious you can have a peek at the [Python tutorial](http://docs.python.org/3/tutorial/datastructures.html#tuples-and-sequences) where the concept of a tuple is explained.
154 |
155 | # Counting Votes
156 |
157 | Can you write a program which counts the total number of votes for *White Icicle* radishes?
158 |
159 | Use your previous solution as a base. You'll need a variable to hold the number of votes recorded for *White Icicle*, which you increment (i.e add one to) as part of the loop.
160 |
161 | ### Solution
162 |
163 | print("Counting votes for White Icicle...")
164 | count = 0
165 | whith open("radishsurvey.txt") as file:
166 | for line in file:
167 | line = line.strip()
168 | name, vote = line.split(" - ")
169 | if vote == "White Icicle":
170 | count = count + 1
171 | print(count)
172 |
173 |
174 | ## Making a generic function
175 |
176 | Can you rewrite this code as a *function definition* where you specify an argument with the name of the radish you want to count votes for, and the function returns the number of votes for that radish variety?
177 |
178 | Using your function, can you write a program which counts votes for White Icicle, Daikon and Sicily Giant radishes, and prints out all three counts?
179 |
180 | ### Solution
181 |
182 | def count_votes(radish):
183 | print("Counting votes for " + radish + "...")
184 | count = 0
185 | whith open("radishsurvey.txt") as file:
186 | for line in file:
187 | line = line.strip()
188 | name, vote = line.split(" - ")
189 | if vote == radish:
190 | count = count + 1
191 | return count
192 |
193 | print(count_votes("White Icicle"))
194 |
195 | print(count_votes("Daikon"))
196 |
197 | print(count_votes("Sicily Giant"))
198 |
199 |
200 | # Counting All The Votes
201 |
202 | Counting votes for each radish variety is a bit time consuming, you have to know all the names in advance and you have to loop through the file multiple times. How about if you could automatically find all the varieties that were voted for, and count them all in one pass?
203 |
204 | You'll need a data structure where you can associate a radish variety with the number of votes counted for it. A dictionary would be perfect!
205 |
206 | Imagine a program that can count votes to create a dictionary with contents like this:
207 |
208 | {
209 | 'White Icicle': 65,
210 | 'Snow Belle': 63,
211 | 'Champion': 76,
212 | 'Cherry Belle': 58,
213 | 'Daikon': 63,
214 | 'French Breakfast': 72,
215 | 'Bunny Tail': 72,
216 | 'Sicily Giant': 57,
217 | 'Red King': 56,
218 | 'Plum Purple': 56,
219 | 'April Cross': 72
220 | }
221 |
222 | Meaning the key 'White Icicle' is associated with the value of 65 votes, the key 'Snow Belle' is associated with the value of 63 votes, 'Champion' has 76 votes, etc, etc.
223 |
224 | Can you create such a program? Start with one of your previous vote-counting programs and try to modify it to count all varieties.
225 |
226 | Here are two snippets of code you might find useful:
227 |
228 | # Create an empty dictionary for associating radish names
229 | # with vote counts
230 | counts = {}
231 |
232 | also
233 |
234 | if vote not in counts:
235 | # First vote for this variety
236 | counts[vote] = 1
237 | else:
238 | # Increment the vote count
239 | counts[vote] = counts[vote] + 1
240 |
241 | Remember that for dictionaries `counts[vote]` means "the value in `counts` which is associated with the key `vote`". In this case, the key is a string (radish name) and the value is a number (vote count.)
242 |
243 | ### Solution
244 |
245 | # Create an empty dictionary for associating radish names
246 | # with vote counts
247 | counts = {}
248 |
249 | whith open("radishsurvey.txt") as file:
250 | for line in file:
251 | line = line.strip()
252 | name, vote = line.split(" - ")
253 | if vote not in counts:
254 | # First vote for this variety
255 | counts[vote] = 1
256 | else:
257 | # Increment the vote count
258 | counts[vote] = counts[vote] + 1
259 | print(counts)
260 |
261 | ### Pretty printing
262 |
263 | When you run this program the output is pretty hard for a person to read, even though it's all there. What we want is to print the data in a way which is easy for people to read. Programmers call this "pretty printing"
264 |
265 | Instead of
266 |
267 | print(counts)
268 |
269 | A pretty printing option could be:
270 |
271 | for name in counts:
272 | count = counts[name]
273 | print(name + ": " + str(count))
274 |
275 | * This option prints each vote on its own line.
276 |
277 | * Iterating through a dictionary (ie `for name in counts`) means iterating through the *keys* (radish variety names), so we still need to look up each *value* (the vote count) with `count = counts[name]`.
278 |
279 | * Why do we use `str(count)` here? Try removing the `str()` call and see what python tells you! `str()` returns the string equivalent of the number, ie `str(12)` returns `"12"`.
280 |
281 | Python needs to distinguish between strings and numbers for lots of reasons. For example, using numbers `12+1` is 13. Using strings, `"12" + "1"` *concatenates* the strings to give you `"121"`.
282 |
283 | ### Tip
284 |
285 | Python actually has a built-in module called [pprint](http://docs.python.org/3/library/pprint.html) to make it easy to pretty-print things. You can use it like:
286 |
287 | from pprint import pprint
288 | pprint(some_dictionary)
289 |
290 | Try it out with your program if you like!
291 |
292 | ### Sneakier Tip
293 |
294 | IPython Notebook can automatically pretty-print things, you just need to make them the last thing in the cell.
295 |
296 | So if you replace `print(counts)` with simply `counts` on the last line, this becomes the last thing in the cell and gets formatted nicely in the output.
297 |
298 | The reason is that `print` is a built-in Python function and formats the dictionary the only way it knows - the simple ugly way. By the time IPython Notebook sees the dictionary contents it's already formatted as a string. Whereas `count` is still a dictionary, so IPython Notebook can apply smarts to format it in a better way.
299 |
300 | # Cleaning ("Munging") data
301 |
302 | There's some weird stuff in our vote count:
303 |
304 | Red King: 1
305 | red king: 3
306 | White Icicle: 1
307 | Cherry Belle: 2
308 | daikon: 4
309 | Cherry Belle: 1
310 |
311 | *Vote rigging!* Probably not, it's just unclean data. To a computer, "Red King" and "red King" look different because of the different capitalisation. So do "Cherry Belle" and " Cherry Belle" because of the leading space.
312 |
313 | We need to clean up (sometimes called "munge") the data so it all looks the same.
314 |
315 | We already know one munging function, `strip()`. Try applying `strip()` to each voting choice, to remove distinctions like " Cherry Belle" and "Cherry Belle".
316 |
317 | How about "Red King" and "red king"? Take a look at the [Python string functions reference](http://docs.python.org/3/library/stdtypes.html#string-methods) and see if you can find a function that could transform these two so they look the same to the computer.
318 |
319 | ### Solution
320 |
321 | There are lots of functions which could remove the case distinction. `str.lower()` would convert all the names to all lower case, `str.upper()` would CONVERT THEM ALL TO UPPER CASE, or `str.capitalize()` would Capitalise the first letter only. Here's one way:
322 |
323 |
324 | # Create an empty dictionary for associating radish names
325 | # with vote counts
326 | counts = {}
327 |
328 | whith open("radishsurvey.txt") as file:
329 | for line in file:
330 | line = line.strip()
331 | name, vote = line.split(" - ")
332 | # munge the vote string to clean it up
333 | vote = vote.strip().capitalize()
334 | if not vote in counts:
335 | # First vote for this variety
336 | counts[vote] = 1
337 | else:
338 | # Increment the vote count
339 | counts[vote] = counts[vote] + 1
340 | print(counts)
341 |
342 | If you're having trouble spotting the difference here, it's
343 |
344 | vote = vote.strip().capitalize()
345 |
346 | Which means "take the variable called `vote`, and call the `strip()` function on it, and then call the `capitalize()` function on the result, and then assign that result back to the variable `vote`.
347 |
348 | This could be written in two lines like this, if you prefer:
349 |
350 | vote = vote.strip()
351 | vote = vote.capitalize()
352 |
353 | This would do the *same thing* when you run it. It's up to you which you use, a good practice is to use the version which is the most readable to a human being, without being unnecessarily verbose.
354 |
355 | ## Not quite there
356 |
357 | There are still some funny votes counted in the output of this program:
358 |
359 | Sicily giant: 1
360 | Plum purple: 1
361 | Cherry belle: 1
362 |
363 | They all have something in common, a double space " " between the first and second words. Damn typos!
364 |
365 | strip() only cleaned up additional whitespace at the start and end of the string.
366 |
367 | The `replace` function can be used to replace all double spaces with a single space:
368 |
369 | vote = vote.replace(" ", " ")
370 |
371 | Try putting that into your program so those last few votes get counted correctly.
372 |
373 | # Checking if anyone voted twice
374 |
375 | So far we've counted votes without paying attention to the name of the person who voted.
376 |
377 | Can you modify your program so it also prints out a warning if anyone voted twice?
378 |
379 | ## Hint
380 |
381 | You will need to start making a list of the names of everyone who has voted so far. Each time you see a new name, check if it is already in the list of names. Starting with an empty list of names, you can use `voterlist.append(newentry)` to append a new entry to the end.
382 |
383 | You'll need to apply the same data munging techniques to clean up people's names, so that "Joanne Smith" and "joanne smith" are counted as the same person.
384 |
385 | ### Solution
386 |
387 | This is just one of many ways to do this:
388 |
389 | # Create an empty dictionary for associating radish names
390 | # with vote counts
391 | counts = {}
392 |
393 | # Create an empty list with the names of everyone who voted
394 | voted = []
395 |
396 | whith open("radishsurvey.txt") as file:
397 | for line in file:
398 | line = line.strip()
399 | name, vote = line.split(" - ")
400 | # clean up the person's name
401 | name = name.strip().capitalize().replace(" "," ")
402 | # check if this person already voted
403 | if name in voted:
404 | print(name + " has already voted! Fraud!")
405 | continue
406 | voted.append(name)
407 | # munge the vote string to clean it up
408 | vote = vote.strip().capitalize().replace(" "," ")
409 | if not vote in counts:
410 | # First vote for this variety
411 | counts[vote] = 1
412 | else:
413 | # Increment the vote count
414 | counts[vote] += 1
415 |
416 | print("Results:")
417 | print()
418 | for name in counts:
419 | print(name + ": " + str(counts[name]))
420 |
421 |
422 | There's two new concepts in the code above:
423 |
424 | `continue` means "stop whatever you were doing and go to the next iteration of the loop". In this case, if the person has already voted then we don't want to count their invalid vote - instead we `continue` and start the next iteration, with the next vote on the next line of the file.
425 |
426 | `counts[vote] += 1` is a shorthand for `counts[vote] = counts[vote] + 1`. This shortcut can be used any time you are performing operations like arithmetic, for example these are equivalent:
427 |
428 | x = x + 1
429 | x += 1
430 |
431 | And so are these:
432 |
433 | lemons = lemons * 3
434 | lemons *= 3
435 |
436 | You can also use `-=` and `/=` in the same way.
437 |
438 | # Factoring our code
439 |
440 | Our program here is now getting a little bit long, and a little bit complex. There are lots of comments pointing out what specific sections do.
441 |
442 | Perhaps we can split it into functions to make it easier to read:
443 |
444 | * A function to clean up (munge) a string to make it easy to match against (because we do the exact same thing to clean up names as we do to clean up the vote choice.)
445 | * A function to check if someone has voted before
446 | * A function to count a vote
447 |
448 | Have a try at breaking out some of the parts into functions, one function at a time, without breaking the program.
449 |
450 | IPython Notebook makes this easy because you can run the cell (with Shift-Enter if you like) after each change, to check the program still works.
451 |
452 | ### Solution
453 |
454 | This is just one possible way to break it down:
455 |
456 | # Create an empty dictionary for associating radish names
457 | # with vote counts
458 | counts = {}
459 |
460 | # Create an empty list with the names of everyone who voted
461 | voted = []
462 |
463 | # Clean up (munge) a string so it's easy to match against other strings
464 | def clean_string(s):
465 | return s.strip().capitalize().replace(" "," ")
466 |
467 | # Check if someone has voted already and return True or False
468 | def has_already_voted(name):
469 | if name in voted:
470 | print(name + " has already voted! Fraud!")
471 | return True
472 | return False
473 |
474 | # Count a vote for the radish variety named 'radish'
475 | def count_vote(radish):
476 | if not radish in counts:
477 | # First vote for this variety
478 | counts[radish] = 1
479 | else:
480 | # Increment the radish count
481 | counts[radish] = counts[radish] + 1
482 |
483 |
484 | whith open("radishsurvey.txt") as file:
485 | for line in file:
486 | line = line.strip()
487 | name, vote = line.split(" - ")
488 | name = clean_string(name)
489 | vote = clean_string(vote)
490 |
491 | if not has_already_voted(name):
492 | count_vote(vote)
493 | voted.append(name)
494 |
495 | print("Results:")
496 | print()
497 | for name in counts:
498 | print(name + ": " + str(counts[name]))
499 |
500 |
501 | What do you think? Is that easier to read and understand?
502 |
503 | For small programs it's not as important as big programs, but with big programs it becomes very important to factor things out so you can understand them - as well as so parts can be reused.
504 |
505 |
506 |
507 | # Finding the winner
508 |
509 | Our program prints the number of votes cast for each radish variety, but it doesn't declare a winner. Can you update the program so it goes through the votes counted and finds the one with the most votes?
510 |
511 | (You may want to add this as a totally separate cell, after the previous cells, rather than modifying your existing loops.)
512 |
513 | ## Hint
514 |
515 | You can make a for loop which iterates over all of the keys in a dictionary by using the syntax `for key in dictionary:`. In this case it might be `for name in counts:`.
516 |
517 | ### Solution
518 |
519 | You can do something like this:
520 |
521 | # Record the winning name and the votes cast for it
522 | winner_name = "No winner"
523 | winner_votes = 0
524 |
525 | for name in counts:
526 | if counts[name] > winner_votes:
527 | winner_votes = counts[name]
528 | winner_name = name
529 |
530 | print("The winner is: " + winner_name)
531 |
532 | The loop shown above keeps track of one name, `winner_name`, and the number of votes cast for it. Each iteration through the loop it checks if there is a name with more votes than the current winner, and updates it if so.
533 |
534 | ## Challenge
535 |
536 | Can you extract the part of the program that finds the winner into a function?
537 |
538 | ## Bigger Challenge
539 |
540 | The solution shown above can't deal with ties. It only updates `winner_name` if it finds another name with more votes than it, a second name with an equal number of votes will be ignored.
541 |
542 | Can you write a winner function that could deal with a tie?
543 |
544 | ## Next Chapter
545 |
546 | That became complicated pretty quickly, didn't it? In the next chapter, we will try an easier way to [analyze the survey using pandas](pandas.html), a Python library designed for data analysis.
547 |
--------------------------------------------------------------------------------
/css/pygments-default.css:
--------------------------------------------------------------------------------
1 | /* https://raw.githubusercontent.com/jwarby/jekyll-pygments-themes/master/default.css */
2 | .highlight .hll { background-color: #ffffcc }
3 | .highlight .c { color: #408080; font-style: italic } /* Comment */
4 | .highlight .err { border: 1px solid #FF0000 } /* Error */
5 | .highlight .k { color: #008000; font-weight: bold } /* Keyword */
6 | .highlight .o { color: #666666 } /* Operator */
7 | .highlight .cm { color: #408080; font-style: italic } /* Comment.Multiline */
8 | .highlight .cp { color: #BC7A00 } /* Comment.Preproc */
9 | .highlight .c1 { color: #408080; font-style: italic } /* Comment.Single */
10 | .highlight .cs { color: #408080; font-style: italic } /* Comment.Special */
11 | .highlight .gd { color: #A00000 } /* Generic.Deleted */
12 | .highlight .ge { font-style: italic } /* Generic.Emph */
13 | .highlight .gr { color: #FF0000 } /* Generic.Error */
14 | .highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */
15 | .highlight .gi { color: #00A000 } /* Generic.Inserted */
16 | .highlight .go { color: #808080 } /* Generic.Output */
17 | .highlight .gp { color: #000080; font-weight: bold } /* Generic.Prompt */
18 | .highlight .gs { font-weight: bold } /* Generic.Strong */
19 | .highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
20 | .highlight .gt { color: #0040D0 } /* Generic.Traceback */
21 | .highlight .kc { color: #008000; font-weight: bold } /* Keyword.Constant */
22 | .highlight .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */
23 | .highlight .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */
24 | .highlight .kp { color: #008000 } /* Keyword.Pseudo */
25 | .highlight .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */
26 | .highlight .kt { color: #B00040 } /* Keyword.Type */
27 | .highlight .m { color: #666666 } /* Literal.Number */
28 | .highlight .s { color: #BA2121 } /* Literal.String */
29 | .highlight .na { color: #7D9029 } /* Name.Attribute */
30 | .highlight .nb { color: #008000 } /* Name.Builtin */
31 | .highlight .nc { color: #0000FF; font-weight: bold } /* Name.Class */
32 | .highlight .no { color: #880000 } /* Name.Constant */
33 | .highlight .nd { color: #AA22FF } /* Name.Decorator */
34 | .highlight .ni { color: #999999; font-weight: bold } /* Name.Entity */
35 | .highlight .ne { color: #D2413A; font-weight: bold } /* Name.Exception */
36 | .highlight .nf { color: #0000FF } /* Name.Function */
37 | .highlight .nl { color: #A0A000 } /* Name.Label */
38 | .highlight .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */
39 | .highlight .nt { color: #008000; font-weight: bold } /* Name.Tag */
40 | .highlight .nv { color: #19177C } /* Name.Variable */
41 | .highlight .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */
42 | .highlight .w { color: #bbbbbb } /* Text.Whitespace */
43 | .highlight .mf { color: #666666 } /* Literal.Number.Float */
44 | .highlight .mh { color: #666666 } /* Literal.Number.Hex */
45 | .highlight .mi { color: #666666 } /* Literal.Number.Integer */
46 | .highlight .mo { color: #666666 } /* Literal.Number.Oct */
47 | .highlight .sb { color: #BA2121 } /* Literal.String.Backtick */
48 | .highlight .sc { color: #BA2121 } /* Literal.String.Char */
49 | .highlight .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */
50 | .highlight .s2 { color: #BA2121 } /* Literal.String.Double */
51 | .highlight .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */
52 | .highlight .sh { color: #BA2121 } /* Literal.String.Heredoc */
53 | .highlight .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */
54 | .highlight .sx { color: #008000 } /* Literal.String.Other */
55 | .highlight .sr { color: #BB6688 } /* Literal.String.Regex */
56 | .highlight .s1 { color: #BA2121 } /* Literal.String.Single */
57 | .highlight .ss { color: #19177C } /* Literal.String.Symbol */
58 | .highlight .bp { color: #008000 } /* Name.Builtin.Pseudo */
59 | .highlight .vc { color: #19177C } /* Name.Variable.Class */
60 | .highlight .vg { color: #19177C } /* Name.Variable.Global */
61 | .highlight .vi { color: #19177C } /* Name.Variable.Instance */
62 | .highlight .il { color: #666666 } /* Literal.Number.Integer.Long */
63 |
64 |
--------------------------------------------------------------------------------
/css/styles.scss:
--------------------------------------------------------------------------------
1 | ---
2 | ---
3 |
4 | /* keep the above dashes for jekyll to preprocess this file */
5 | body {
6 | background: url("{{site.baseurl}}/images/background.png") #FFF repeat fixed;
7 | font-family: "Open Sans", Helvetica, sans-serif;
8 | line-height: 1.6;
9 | }
10 |
11 | h1, h2, h3, h4, h5, h6 {
12 | font-family: "Montserrat", "Helvetica Neue", Arial, Helvetica, sans-serif;
13 | margin: 1em 0 .5em 0;
14 | }
15 |
16 | .sidebar-nav {
17 | margin-top: 2.25em;
18 | }
19 |
20 | code {
21 | font-family: Monaco, Menlo, Consolas, "DejaVu Sans Mono", Inconsolata,
22 | "Courier New", monospace;
23 | }
24 |
25 | pre {
26 | border: none;
27 | background: none;
28 | }
29 |
30 | pre code {
31 | font-size: 15px;
32 | }
33 |
34 | .navbar h1 a, .navbar h1 {
35 | color: #f5f5f5;
36 | font-size: 18px;
37 | line-height: 20px;
38 | text-align: center;
39 | text-decoration: none;
40 | }
41 |
42 | .navbar h1 a:hover {
43 | color: #fff;
44 | }
45 |
46 | .navbar-static-top {
47 | z-index: 1000;
48 | position: relative;
49 | }
50 |
51 | .navbar-inner {
52 | background: #085987 !important;
53 | border-color: #085987 !important;
54 | }
55 |
56 | .title {
57 | text-align: center;
58 | margin-bottom: 30px;
59 | margin-top: 30px;
60 | }
61 |
62 | .container-fluid {
63 | max-width: 1200px;
64 | margin: auto;
65 | }
66 |
67 | #main-content {
68 | background: rgb(255, 255, 255);
69 | background: rgba(255, 255, 255, 0.5);
70 | -webkit-box-shadow: 0px 0px 50px 20px rgba(255, 255, 255, 0.5);
71 | -moz-box-shadow: 0px 0px 50px 20px rgba(255, 255, 255, 0.5);
72 | box-shadow: 0px 0px 50px 20px rgba(255, 255, 255, 0.5);
73 | }
74 |
75 | #main-content p, #main-content li {
76 | font-size: 15px;
77 | }
78 |
79 | #footer {
80 | text-align: center;
81 | background-color: #085987;
82 | clear: both;
83 | margin-top: 6em;
84 | padding: 1em 0;
85 | width: 100%;
86 | color: #FFF;
87 | }
88 |
89 | #footer a {
90 | color: #c1d5e1;
91 | }
92 |
93 | #footer a:hover {
94 | color: #FFF;
95 | }
96 |
97 | pre.highlight {
98 | color: #F9FBFB;
99 | background-color: #3F3F3F;
100 | }
101 |
102 |
103 | /* jupyter highlight style */
104 | $indent: 120px;
105 |
106 | div.jupyter {
107 | border: 1px black solid;
108 | border-color: #ababab;
109 | border-left: 5px #42A5F5 solid;
110 | margin-bottom: 20px;
111 |
112 | pre.highlight {
113 | position: relative;
114 | margin: 10px;
115 | margin-left: $indent;
116 | border: 1px solid #CFCFCF;
117 | border-radius: 2px;
118 | color: black;
119 | background-color: #F7F7F7;
120 | }
121 | pre.highlight::before {
122 | display: block;
123 | box-sizing: border-box;
124 | position: absolute;
125 | left: - $indent;
126 | content: "In [ ]:";
127 | width: $indent;
128 | text-align: right;
129 | padding-right: 12px;
130 | }
131 |
132 | /* reset for following output fields */
133 | div.highlighter-rouge + div.highlighter-rouge {
134 |
135 | pre.highlight {
136 | background-color: white;
137 | border: none;
138 | // filter: blur(2px);
139 |
140 | }
141 |
142 | pre.highlight::before {
143 | content: "";
144 | }
145 | }
146 |
147 | code {
148 | display: block;
149 | //height: auto;
150 | overflow: hidden;
151 | transition: height 250ms ease-in-out;
152 | }
153 | }
154 |
155 | .button-hide {
156 | font-size: 80%;
157 | position: absolute;
158 | top: -5px;
159 | left: - $indent + 15;
160 |
161 | }
162 | .output-hidden {
163 | code {
164 | height: 0 !important;
165 | }
166 | }
167 |
168 |
169 |
--------------------------------------------------------------------------------
/css/zenburn.min.css:
--------------------------------------------------------------------------------
1 | pre code{display:block;padding:.5em;background:#3f3f3f;color:#dcdcdc}pre .keyword,pre .tag,pre .css .class,pre .css .id,pre .lisp .title,pre .nginx .title,pre .request,pre .status,pre .clojure .attribute{color:#e3ceab}pre .django .template_tag,pre .django .variable,pre .django .filter .argument{color:#dcdcdc}pre .number,pre .date{color:#8cd0d3}pre .dos .envvar,pre .dos .stream,pre .variable,pre .apache .sqbracket{color:#efdcbc}pre .dos .flow,pre .diff .change,pre .python .exception,pre .python .built_in,pre .literal,pre .tex .special{color:#efefaf}pre .diff .chunk,pre .subst{color:#8f8f8f}pre .dos .keyword,pre .python .decorator,pre .title,pre .haskell .type,pre .diff .header,pre .ruby .class .parent,pre .apache .tag,pre .nginx .built_in,pre .tex .command,pre .prompt{color:#efef8f}pre .dos .winutils,pre .ruby .symbol,pre .ruby .symbol .string,pre .ruby .string{color:#dca3a3}pre .diff .deletion,pre .string,pre .tag .value,pre .preprocessor,pre .built_in,pre .sql .aggregate,pre .javadoc,pre .smalltalk .class,pre .smalltalk .localvars,pre .smalltalk .array,pre .css .rules .value,pre .attr_selector,pre .pseudo,pre .apache .cbracket,pre .tex .formula{color:#cc9393}pre .shebang,pre .diff .addition,pre .comment,pre .java .annotation,pre .template_comment,pre .pi,pre .doctype{color:#7f9f7f}pre .coffeescript .javascript,pre .javascript .xml,pre .tex .formula,pre .xml .javascript,pre .xml .vbscript,pre .xml .css,pre .xml .cdata{opacity:.5}
--------------------------------------------------------------------------------
/extras/alternatives.md:
--------------------------------------------------------------------------------
1 | ---
2 |
3 | layout: ots
4 | title: Alternative Approaches
5 |
6 | ---
7 |
8 | In this workshop we've mostly looked at processing unstructured data
9 | from plain text files. This is a very common and simple way to come
10 | across data, but it's not the only way and it's not always the easiest
11 | way to work with data.
12 |
13 | # Relational Databases
14 |
15 | Relational databases provide a way of storing data in tables with
16 | relationships between them. Many large organisations and websites
17 | store their data in some kind of relational database.
18 |
19 | For instance, the OpenFlights data we worked with in the
20 | [CSV](../core/csv.html) chapter is almost certainly exported from a
21 | relational database of some kind. The relational database holds all of
22 | its data in tables, for instance the "airports" table hold all the
23 | airports and the "routes" table would hold all the airline routes.
24 |
25 | However the relational database also holds *relations* between
26 | different kinds of data - for example it can know that all airline
27 | routes in the routes table contain references to a source and a
28 | destination airport, and that these airports should exist in the
29 | airports table.
30 |
31 | We often use a query language called SQL to retrieve information from
32 | a relational database. For example, here is a made-up SQL query to
33 | count the number of airports in Russia:
34 |
35 | SELECT COUNT(*) FROM airports WHERE country = 'Russia';
36 |
37 | You can integrate SQL queries into other general purpose programming
38 | languages like Python.
39 |
40 | OpenTechSchool doesn't have specific workshops about SQL yet, although
41 | "Django 101" uses SQL for its databases. In the meantime you might
42 | want to check out Zed Shaw's book
43 | [Learn SQL The Hard Way](http://sql.learncodethehardway.org/) (free to
44 | read online.)
45 |
46 |
47 | # Pandas
48 |
49 | [Pandas](http://pandas.pydata.org/) is a suite of data analysis tools
50 | for Python, and it allows you to do more complex data modelling and
51 | analysis with Python.
52 |
53 | For this workshop we haven't needed Pandas, but if you're looking to
54 | use Python for a lot of numerical data analysis then you should look
55 | into it - there are tutorials linked from the homepage. Pandas can
56 | make complex tasks much easier to work with.
57 |
58 | Pandas also makes it easy to integrate with more complex data sources
59 | than simple text files. For example, here's [an IPython Notebook that
60 | uses Pandas to import data the Guardian published regarding the Gaza-Israel 2012 crisis](https://gistpynb.herokuapp.com/4121857).
61 | The Guardian publishes this data in the format of "Google Fusion
62 | Tables", and Pandas can read this format directly from the web.
63 |
64 |
65 |
--------------------------------------------------------------------------------
/extras/opendata.md:
--------------------------------------------------------------------------------
1 | ---
2 |
3 | layout: ots
4 | title: Open Data Sources
5 |
6 | ---
7 |
8 | In this workshop we a small dataset published by the
9 | [OpenFlights](http://openflights.org/) project. This data is published
10 | under the Open Database License, one of several open data licenses
11 | that grants rights to anyone who wants to use or redistribute the
12 | data.
13 |
14 | In recent years there has been a strong movement encouraging
15 | organisations to publish data openly on the web. As a result there are
16 | many public data repositories, both government and non-government,
17 | that you can source data from:
18 |
19 |
20 | * The
21 | [Google Public Data Explorer](http://www.google.com/publicdata/directory)
22 | indexes many public datasets and features an in-browser data explorer.
23 | You can also download the data to perform more in-depth analysis.
24 |
25 | * UK's Guardian Newspaper [Data Store](http://www.guardian.co.uk/data)
26 | provides a wide range of data and data-based analysis.
27 | ([Here's a giant list of just their data sets and the articles that mention them](https://views.scraperwiki.com/run/guardian_datablog_spreadsheets/).)
28 |
29 | * The [World Bank](http://data.worldbank.org/) publishes its data
30 | catalog online.
31 |
32 | * Numerous governments, including [Australia](http://data.gov.au/),
33 | the [European Union](http://ec.europa.eu/atoz_en.htm) and the
34 | [United States](http://www.data.gov/) have open dataset repositories.
35 |
36 | * Some countries are sponsoring open data "hackathons" to raise
37 | awareness and find new uses for their data, for instance
38 | [GovHack](http://www.govhack.org/) in Australia.
39 |
--------------------------------------------------------------------------------
/files/coffee.csv:
--------------------------------------------------------------------------------
1 | "Coffee","Water","Milk","Icecream"
2 | "Espresso","No","No","No"
3 | "Long Black","Yes","No","No"
4 | "Flat White","No","Yes","No"
5 | "Cappuccino","No","Yes - Frothy","No"
6 | "Affogato","No","No","Yes"
7 |
--------------------------------------------------------------------------------
/files/geo_distance.py:
--------------------------------------------------------------------------------
1 | # Using the Haversine formula for geographic Great Circle Distance
2 | #
3 | # As per https://en.wikipedia.org/wiki/Haversine_formula
4 |
5 | from math import cos,radians,sin,pow,asin,sqrt
6 |
7 | def distance(lat1, long1, lat2, long2):
8 | radius = 6371 # radius of the earth in km, roughly https://en.wikipedia.org/wiki/Earth_radius
9 |
10 | # Lat,long are in degrees but we need radians
11 | lat1 = radians(lat1)
12 | lat2 = radians(lat2)
13 | long1 = radians(long1)
14 | long2 = radians(long2)
15 |
16 | dlat = lat2-lat1
17 | dlon = long2-long1
18 |
19 | a = pow(sin(dlat/2),2) + cos(lat1)*cos(lat2)*pow(sin(dlon/2),2)
20 | distance = 2 * radius * asin(sqrt(a))
21 |
22 | return distance
23 |
24 |
25 |
--------------------------------------------------------------------------------
/files/names.txt:
--------------------------------------------------------------------------------
1 | Emily Kumm
2 | Layla Hitchcock
3 | James Larra
4 | Angus De Mestre
5 | Christopher Walton
6 | Lincoln Hoare
7 | Ethan Dickson
8 | Jake Murdoch
9 | Piper Wheelwright
10 | Lola Catchpole
11 | Chloe MacLaurin
12 | Sara Coffill
13 | Archer Dodds
14 | Amelie Torpy
15 | Hamish Helena
16 | Lara Cawker
17 | Fang Ch'eng
18 | Toby Spring
19 | Ava Sorell
20 | William Doyle
21 | Lucy Somers
22 | Eliza O'Haran
23 | Cooper Menkens
24 | Jin Huang
25 | Quinzia Costa
26 | Sean Glew
27 | Ava McNaughtan
28 | Victoria Hardie
29 | Galeazzo Milanesi
30 | Brock Brunker
31 | Anthony Hugo
32 | Jaxon Keen
33 | Nathan Aird
34 | Sarah Paten
35 | Tyler Makutz
36 | Jordan Catani
37 | Sophie Browning
38 | Joel Bruce
39 | David Morgans
40 | Oliviero Lucchesi
41 | Ella Weston
42 | Alfonso Costa
43 | Bethany Layh
44 | Sarah Joris
45 | Jake Hambly
46 | Gemma Norton
47 | Harry Wormald
48 | Matthew Knibbs
49 | Mafalda Marchesi
50 | Blake Sodersten
51 | Madeleine Hartung
52 | Angelina Dangar
53 | Abbey Dunkley
54 | Lok Fan
55 | Isla Mehaffey
56 | Lola Atkinson
57 | Noah Doyne
58 | Isabelle Camden
59 | Eufrosina Ferri
60 | Cody Glauert
61 | Hugo Stretch
62 | Anthony Wand
63 | Sarah Milford
64 | Grace Frayne
65 | Taj Bjelke-Petersen
66 | Makayla McMinn
67 | Hui Hsiung
68 | Grace Wentworth
69 | Ling Tuan
70 | Beau Hauslaib
71 | Natalie Schlapp
72 | Aidan Santo
73 | Sebastian Langford
74 | Caleb Clancy
75 | Indiana Angwin
76 | Jasper Harford
77 | Jonathan Parsons
78 | Lilian Pike
79 | Giusy Lombardi
80 | Riley Leakey
81 | Cai Pan
82 | Lauren Rosevear
83 | Connor Fairbridge
84 | Scarlett Hughes
85 | Skye Garvin
86 | Lilly Tait
87 | Li Ming Niu
88 | Jamie Faithful
89 | Lelia Toscani
90 | Nate Shelley
91 | Michael Hargrave
92 | Caitlin Houlding
93 | Christian Morris
94 | Darcy Kayser
95 | Archer Frederick
96 | Bella Lyttle
97 | Callimaco Lombardi
98 | Leda Romani
99 | Sebastian Helmore
100 | Lincoln Gatehouse
101 | Ludovica Siciliano
102 | Ben Vosper
103 | Ubaldo Trevisani
104 | Xavier Sligo
105 | Jake Sterne
106 | Patrick Porteus
107 | Claire Boelke
108 | Andrew Quick
109 | Brianna Pye
110 | Laura Samuels
111 | Alana Sturdee
112 | Harrison Barlee
113 | Claire Bisdee
114 | Brayden Stretch
115 | Georgia Bruny
116 | Lincoln Hirschfeld
117 | Samantha Mansell
118 | Anna Howarde
119 | David Moynihan
120 | Taj Shackell
121 | Blake Ricardo
122 | Lilian Burne
123 | Koby Ledger
124 | Emily Plante
125 | Isabella Pardey
126 | Alyssa Loewe
127 | Makayla Fairbairn
128 | Timothy Baldwinson
129 | Lucinda Emanuel
130 | Lisandro Monaldo
131 | Andrew Schwarz
132 | Noah Berrick
133 | Luke Gye
134 | Ashley Brigstocke
135 | Qiang Tsui
136 | Durante Ferri
137 | Makayla Sutton
138 | Flynn Weingarth
139 | Toby Queale
140 | Imogen Gaunson
141 | Stephanie Synan
142 | Raffaella Trevisan
143 | Alyssa Batman
144 | Isaac Banks
145 | Audrey Bock
146 | Jonathan Rolph
147 | Sofia Donnithorne
148 | Lei Tai
149 | Summer Stenhouse
150 | Amy Goulburn
151 | Samuel Ansell
152 | Oscar Saltau
153 | Aiden Tasman
154 | Mackenzie Geach
155 | Salvatore Sagese
156 | Tristan Gwynn
157 | Kaitlyn Carnegie
158 | Sheng Shen
159 | Logan Truchanas
160 | Stephanie Schnaars
161 | Antonietta Baresi
162 | Bethany Bardolph
163 | Feng Li
164 | Mariam Langridge
165 | Benito Cocci
166 | Georgia Jessop
167 | Sarah Kashiwagi
168 | Jessica Rapke
169 | Connor Morphett
170 | Egidio Mancini
171 | Jian Ts'ao
172 | Sophie Eipper
173 | Mia Alngindabu
174 | Sarah Ahuia Ova
175 | Ali Dedman
176 | Wang Tien
177 | Edoardo Sal
178 | Rory Springthorpe
179 | Aidan Dore
180 | Sienna Bonnor
181 | Kaitlyn Mullen
182 | Hamish Kevin
183 | Finn Dunstan
184 | Henry Birdseye
185 | Jaxon Cowles
186 | Alexis Cowlishaw
187 | Cody Laffer
188 | Timothy Beeton
189 | Summer Withers
190 | Beata Endrizzi
191 | Rachel Luke
192 | Levi Ferry
193 | Mikayla Biddell
194 | Alannah Housley
195 | Jacob Spowers
196 | Alex Wemyss
197 | Ben Denovan
198 | Luke Leeper
199 | Skye Reynolds
200 | Ryan Langley
201 | Harrison Rose
202 | Phoebe Barwell
203 | Baldo Palerma
204 | Logan Lackey
205 | Nicodemo Udinese
206 | Kayla Kinsella
207 | Mary Cardell
208 | Bailey Derrington
209 | Isabelle Finney
210 | Oliver Potts
211 | John Bale
212 | Guang Lo
213 | Shu Fang Tsou
214 | Blake Hurst
215 | Alicia Farmer
216 | Sophie Keynes
217 | Joel Cassell
218 | Abbey Rivett
219 | Quintilia Trentini
220 | Laura Macdowell
221 | Andrew Coventry
222 | Victoria Brereton
223 | James Poupinel
224 | Eugenio Pagnotto
225 | Laura Wawn
226 | Thomas Darcy
227 | Bailey Mussen
228 | Dewei Niu
229 | Mikayla Hebblethwaite
230 | Henry Wright
231 | Zane Pavy
232 | Luce De Luca
233 | Oliver Thirkell
234 | Scarlett Price
235 | Claudia Westgarth
236 | Nilde Beneventi
237 | Ella Irving
238 | Hannah Gabriel
239 | Tristan Turley
240 | Taylah Shore
241 | Madeline Corbin
242 | Imogen Raws
243 | Zoe Jasprizza
244 | Sebastian George
245 | Elizabeth McNab
246 | Gianfranco Cremonesi
247 | Jackson Longman
248 | Blake Dakin
249 | On Hê
250 | Corinna Lucchese
251 | Eliana Baresi
252 | Cataldo Trevisan
253 | Beau McLarty
254 | Scarlett Sullivan
255 | Bailey Randell
256 | Declan Winston
257 | Amy Harriman
258 | Jack Finlay
259 | Rossana Cattaneo
260 | Abbey Tyas
261 | Chi Hsiung
262 | Zachary Bass
263 | Claudia Boxall
264 | Daniel Krimper
265 | Bruna Rizzo
266 | Jesse Fairley
267 | Kayla Sievier
268 | Evie Pulsford
269 | Jayden Josephson
270 | Cameron Landseer
271 | Hannah Dibbs
272 | Samuel Henschke
273 | Olivia Warnes
274 | Ella McLellan
275 | Andrew Bower
276 | Kate Buchanan
277 | Anna Septimus
278 | Matthew Birch
279 | Lara Macarthur
280 | Abbey Garvin
281 | Jamie Ham
282 | Archie Michelides
283 | Oliver Aspinall
284 | Shaiming Fu
285 | Nate Lodewyckx
286 | Maya Shackleton
287 | Madeleine Abrahams
288 | Alana Meares
289 | Lola Lea
290 | Rose Leahy
291 | Keira Strzelecki
292 | Annabelle Scarfe
293 | Lauren Nisbet
294 | Agostino Milanesi
295 | Gang Chia
296 | Olimpia Udinesi
297 | Lola Mashman
298 | Daniel Hogben
299 | Park Ch'en
300 | David Rees
301 | Sabrina Li Fonti
302 | Toby Lundie
303 | Dylan Synnot
304 | Tyler Hansen
305 | Mackenzie Knatchbull
306 | Norma Fiorentino
307 | Erin Binnie
308 | Alexander McKean
309 | Kuan-Yin Sun
310 | Finn Whitworth
311 | Skye Atkins
312 | Tyson Kaberry
313 | Daniel Appleton
314 | Kaitlyn Collings
315 | David Tomlinson
316 | Guan-yin Hsiao
317 | Anthony Stuart
318 | Matilda Gullett
319 | Tristan Monson
320 | Stella Inwood
321 | Kate Cyril
322 | Alexis Le Hunte
323 | Jake Hervey
324 | Eva Geiger
325 | Dominic Nangle
326 | Abbey Strzelecki
327 | Isabelle Mathew
328 | Sean Tait
329 | Jasper Gibney
330 | Mia Legg
331 | Connor Letters
332 | Ruby Wakefield
333 | Yue Wan Yeh
334 | David Read
335 | Lee T'an
336 | Caitlyn Mullah
337 | Amy Clunie
338 | Guido Beneventi
339 | Chelsea Warby
340 | Charlie McCabe
341 | Marcus South
342 | Erin Stephen
343 | Alyssa McInnes
344 | Eden Petchy
345 | Fabio Pugliesi
346 | Lilian Woodriff
347 | Christopher Gillan
348 | Cooper Lasseter
349 | Li Qin Ch'ien
350 | Park Wu
351 | Abbey Dawson
352 | Brock Fiaschi
353 | Emma Slater
354 | Matilda Condon
355 | Thomas Oom
356 | Sam Scarfe
357 | Beato Mazzanti
358 | Koby Gabriel
359 | Abigail Wiltshire
360 | Andrew Howitt
361 | Ruby Elias
362 | Hannah Collie
363 | Poppy Duggan
364 | Owen Montgomery
365 | Mason Dymock
366 | Ashton Pearce
367 | George Carandini
368 | Adelmo De Luca
369 | Cody Leakey
370 | Prospero Milano
371 | Sean Maclurcan
372 | Amelia Ellwood
373 | Brodie De Lissa
374 | Patrick Camidge
375 | Azeglio Napolitano
376 | Li Wei Chien
377 | Laura Callinan
378 | Blake D'Alton
379 | Aidan Clutterbuck
380 | Abbey Aronson
381 | Harrison Moowattin
382 | Isabella Van De Velde
383 | Kayla Sandover
384 | Abbey Cousens
385 | Hugo Coppleson
386 | Marcus Brown
387 | Qiao Tien
388 | Imogen Gertrude
389 | Shi She
390 | Zane Weindorfer
391 | Keira Horner
392 | Sienna Dann
393 | Tyson Platt
394 | Isabelle Llewelyn
395 | Sabrina Beneventi
396 | Zhen Juan Tsai
397 | Ciriaca Genovesi
398 | Ivo Lucchesi
399 | Henry McCorkindale
400 | Ebony Agnes
401 | Xavier Howchin
402 | George Schlunke
403 | Chan Yen
404 | Carolina Cattaneo
405 | Charles Card
406 | Alfonsina Marchesi
407 | Carla De Luca
408 | Ryan Skeats
409 | Jake Champ
410 | Milla Winn
411 | Chan Chao
412 | Caitlyn Ridgeway
413 | Jordan Manning
414 | Alexis Nesbitt
415 | Jett Faucett
416 | Emma Slattery
417 | Indiana Cory
418 | Abby Metters
419 | Eve Gargett
420 | Ryan Aird
421 | Jonathan Walton
422 | Ava Musgrave
423 | Lee Chen
424 | Dean Mattner
425 | Ebony Anton
426 | Indiana Cowper
427 | Taylah Reynolds
428 | Gabrielle Porteus
429 | Hamish Yarnold
430 | Ruby Fox
431 | Kuan-Yin Tao
432 | Silvia Rossi
433 | Liam Copeland
434 | Brayden Massina
435 | Rory Evenden
436 | Tao Hsiao
437 | Ivo Sagese
438 | Hudson Devine
439 | Giosuè Romano
440 | Joel Brownell
441 | Fai Teng
442 | Sarah Bindi
443 | Lucinda Howarde
444 | Kiara Maxwell-Mahon
445 | Amelia Blue
446 | Lilly Wunderlich
447 | Alicia Muscio
448 | Kai Emmett
449 | Maya Woolcock
450 | Brodie Agnew
451 | Angus Christie
452 | Lilian Andrade
453 | Annabelle Armytage
454 | Edward Greener
455 | Nicholas Kirby
456 | Rose Stacy
457 | Hudson Crane
458 | Laura Uhr
459 | Nate Brooker
460 | Matthew John
461 | Dominic Gale
462 | William Fenner
463 | Riley Stewart
464 | Mikayla Brodney
465 | Ethan Macdougall
466 | Matilda Macarthur-Onslow
467 | Scarlett Bruny
468 | Jai Keith
469 | Annabelle Colechin
470 | Layla Fossey
471 | Alicia Forrest
472 | Yi Min Chu
473 | Hunter McEachern
474 | Leah Ross-Watt
475 | Zac Cowles
476 | Yong Hsiao
477 | Brayden Brill
478 | Nate Higgs
479 | Eliza Fink
480 | Jai Burgoyne
481 | Milla Garling
482 | Eden Sheehan
483 | Ella Boucaut
484 | Alex Falk
485 | Chan Juan Hsü
486 | Tristan Glynde
487 | Lara Salting
488 | Rachele Russo
489 | Ramiro Esposito
490 | Andrew Martens
491 | Kaitlyn Kay
492 | Mikayla Fullagar
493 | Eve Peacock
494 | Jesse Abercrombie
495 | Antonia Buccho
496 | Kang Yu
497 | Hsin Tan
498 | Da-Xia Liang
499 | Mikayla Kennerley
500 | Ethan Collings
501 | Emily Walters
502 | Hunter Connely
503 | Scarlett Macdougall
504 | Indiana Scott
505 | Xiang Hsü
506 | Iacopo Baresi
507 | Victoria Shipp
508 | Brooke Kisch
509 | Dylan Barney
510 | Jonathan Paten
511 | Mikayla Minogue
512 | Edward Edmond
513 | Jesse Jury
514 | Raul Pinto
515 | Christopher Moss
516 | Hong Tsui
517 | Luke Komine
518 | Alexandra Shoebridge
519 | Giselda Napolitano
520 | Abbey Bouton
521 | Caitlyn Hotchin
522 | Tristan Lack
523 | Anthony Collits
524 | Bianca Knopwood
525 | Piera Trevisan
526 | Emma Sodersten
527 | Natasha Prout
528 | Anna Deniehy
529 | Madeleine Behan
530 | Brock Eames
531 | Lauren Pennefather
532 | Cody Le Rennetel
533 | Sienna Hovell
534 | Gabriella Titheradge
535 | Mary Randall
536 | Giuseppe Manna
537 | Yi Tseng
538 | Keira Wrenfordsley
539 | Victoria Humffray
540 | Isaac Tennyson
541 | Amelie Farber
542 | Marcus Derbyshire
543 | Jade Grimmett
544 | Evie Langwell
545 | Lucas Tomkinson
546 | Bethany Calwell
547 | Blanda Panicucci
548 | Julian O'Leary
549 | Aaron Addison
550 | Meng Ni
551 | Mikayla Woollacott
552 | Gabriella Beale
553 | Sarah Band
554 | Jasmine Fetherstonhaugh
555 | Erin Stretton
556 | Elijah Kingsbury
557 | Archie Mathy
558 | Nathan Trott
559 | Beau Gosling
560 | Oliver Beit
561 | Callum Prentice
562 | Procopio Zito
563 | Isabella Hoffnung
564 | Tyler Lister
565 | Benjamin Rankin
566 | Victoria Edinburgh
567 | Kiara Maxted
568 | Liam Burn
569 | Victoria Witt
570 | Patrick Tilly
571 | Kuan-Yin Mao
572 | Archer Larra
573 | Victoria Birch
574 | Da-Xia Hsiao
575 | Oscar Cocci
576 | Flynn Poninski
577 | Grace Parkinson
578 | Elizabeth Minifie
579 | William De Satg
580 | Sebastian Ball
581 | Zachary Burford
582 | Adele Buccho
583 | Alma Longo
584 | Napoleone Marcelo
585 | Fabiana Milanesi
586 | Eliza Naylor
587 | Bartolomeo Mancini
588 | Aiden Reginald
589 | Wei Hsiao
590 | Wan Tsai
591 | Maya Huish
592 | Savannah Sheehan
593 | Tyler Forbes
594 | Olindo De Luca
595 | Jett Glynde
596 | Thomas Muecke
597 | Brooke Huffer
598 | Archie Gilfillan
599 | Charles Tearle
600 | Cameron Embley
601 | Finn Leverrier
602 | Yue Yan Hu
603 | Edgardo Mazzanti
604 | Abigail Clark
605 | Bethany Macfarlan
606 | Hu K'ung
607 | Brayden Dixon
608 | Rebecca Godfrey
609 | Sebastian Davitt
610 | Harrison Macgeorge
611 | Joseph Hill
612 | Brooke Mahomet
613 | Brianna Eltham
614 | Michael Elliot
615 | Sean Hogben
616 | Ellie Eaton
617 | Ettore Marcelo
618 | Mulan Kung
619 | Isabelle Coombes
620 | Hudson Dodgshun
621 | Alvisio Mazzi
622 | Kaitlyn Rudduck
623 | Hudson Greene
624 | Christopher Clunies
625 | Molly Piguenit
626 | Angus Langley
627 | Hayley Kernot
628 | Seth Bramston
629 | Imogen Macaulay
630 | Owen Lea
631 | Taj Moonlight
632 | Xin Qian Shih
633 | Dominic Tregurtha
634 | Evie Carey
635 | Xue Fang Fu
636 | Jasper Alfred
637 | Pia Folliero
638 | Lucas Schuler
639 | Ebony Lawlor
640 | Zoe Canning
641 | Xiao Chen Chiang
642 | Keira Toutcher
643 | Jasmine Baughan
644 | Zane Wreford
645 | Zhi Chin
646 | Rong Kuo
647 | Matilda Wardlaw
648 | Anna Denning
649 | Alannah Bleakley
650 | Taj Maria
651 | Kuan-Yin Kuo
652 | Lucy Ley
653 | Archer Cathcart
654 | Gabriella Bruton
655 | Clorinda Pugliesi
656 | Koby Mary
657 | Xavier Truman
658 | Cameron Pearce
659 | Kai MacMahon
660 | Skye Thynne
661 | Tayla English
662 | Lilian Macquarie
663 | Charli Birkbeck
664 | Toby Docker
665 | Matilda Madden
666 | Margherita Milani
667 | Thomas Catt
668 | Gang Hsu
669 | Georgia Gillen
670 | Ebony Florence
671 | Brodie Fraser
672 | Laura Bath
673 | Cristian Pisano
674 | Hayley Coverdale
675 | Eva Ruth
676 | Jasmine Brake
677 | Abbey Cochran
678 | Rose Peeler
679 | Cooper Monk
680 | Ennio DeRose
681 | Seth Reginald
682 | Leo Sheil
683 | Alexis Kelynack
684 | Tristan Charteris
685 | Joseph Gresswell
686 | Archer Kirwan
687 | Yue Yan T'ang
688 | Hayden O'Connell
689 | Jasper Harper
690 | Indiana Keast
691 | Charlotte Slattery
692 | Jun Hsiung
693 | Shi Shen
694 | Scarlett Schonell
695 | Aaron Yarnold
696 | Cody Vale
697 | Na T'ao
698 | Jorja Franklyn
699 | Geronima Trevisani
700 | Hayley Hinchcliffe
701 | Anthony Gairdner
702 | Charles Mockridge
703 | Blake MacFarland
704 | Eleuterio Lombardo
705 | Raffaello Schiavone
706 | Mackenzie Andrade
707 | Eve Everingham
708 | Rebecca Petrie
709 | James Luke
710 | Caleb Ride
711 |
--------------------------------------------------------------------------------
/files/radishes.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 |
3 | # take a list of names from names.txt, read in a list of radish breeds in radishes.txt,
4 | # output radishsurvey.txt with each name choosing a random radish breed
5 |
6 | import random
7 |
8 | output = open("radishsurvey.txt", "w")
9 |
10 | # Radish names are cribbed from https://en.wikipedia.org/wiki/Radish
11 | radishes = [
12 | "April Cross",
13 | "Bunny Tail",
14 | "Cherry Belle",
15 | "Champion",
16 | "Red King",
17 | "Sicily Giant",
18 | "Snow Belle",
19 | "White Icicle",
20 | "French Breakfast",
21 | "Plum Purple",
22 | "Daikon",
23 | ]
24 |
25 | for line in open("names.txt"):
26 | radish = random.choice(radishes)
27 | output.write(line.strip() + " - " + radish + "\n")
28 |
--------------------------------------------------------------------------------
/files/radishsurvey.txt:
--------------------------------------------------------------------------------
1 | Evie Pulsford - April Cross
2 | Matilda Condon - April Cross
3 | Samantha Mansell - Champion
4 | geronima trevisani - cherry belle
5 | Alexandra Shoebridge - Snow Belle
6 | Sarah Ahuia Ova - Snow Belle
7 | Emma Slattery - Bunny Tail
8 | Fabiana Milanesi - Champion
9 | Makayla McMinn - Snow Belle
10 | Julian O'Leary - Sicily Giant
11 | Hannah Collie - Bunny Tail
12 | Toby Lundie - Plum Purple
13 | Baldo Palerma - Champion
14 | Phoebe Barwell - Plum Purple
15 | Sheng Shen - Champion
16 | Jonathan Rolph - Snow Belle
17 | Aaron Yarnold - Red King
18 | Indiana angwin - Daikon
19 | Luke Komine - White Icicle
20 | Blake Ricardo - Daikon
21 | Mikayla Biddell - Daikon
22 | Piper Wheelwright - Bunny Tail
23 | Bailey Derrington - White Icicle
24 | Eufrosina Ferri - Daikon
25 | Madeleine Abrahams - Daikon
26 | Indiana Cowper - Sicily Giant
27 | Procopio Zito - Red King
28 | Ryan Langley - French Breakfast
29 | anthony Gairdner - French Breakfast
30 | Darcy Kayser - Champion
31 | Adelmo De Luca - Plum Purple
32 | Sienna Hovell - Champion
33 | Mary Cardell - April Cross
34 | Ebony Agnes - Daikon
35 | Lola Atkinson - Plum Purple
36 | Jonathan Walton - Champion
37 | Tristan Gwynn - Red King
38 | Jackson Longman - Red King
39 | Archer Dodds - April Cross
40 | Lilian Burne - French Breakfast
41 | Ava McNaughtan - April Cross
42 | Nate Shelley - Daikon
43 | Antonia Buccho - Champion
44 | Kaitlyn Rudduck - Cherry Belle
45 | Skye Thynne - Champion
46 | Ethan Collings - Plum Purple
47 | Finn Leverrier - Plum Purple
48 | Lee T'an - Plum Purple
49 | Tyler Forbes - White Icicle
50 | abbey dunkley - plum purple
51 | rose stacy - french breakfast
52 | Gianfranco Cremonesi - White Icicle
53 | Grace Wentworth - French Breakfast
54 | Cooper Menkens - Snow Belle
55 | Scarlett Macdougall - French Breakfast
56 | Fabio Pugliesi - Bunny Tail
57 | Keira Wrenfordsley - Red King
58 | Daniel Krimper - Plum Purple
59 | Anna Deniehy - April Cross
60 | Sabrina Beneventi - Cherry Belle
61 | Oliver Potts - Snow Belle
62 | Milla Winn - Plum Purple
63 | Finn Whitworth - Sicily Giant
64 | Sophie Keynes - Plum Purple
65 | Joel Brownell - Plum Purple
66 | Jonathan Parsons - French Breakfast
67 | Amelia Ellwood - Snow Belle
68 | Lincoln Gatehouse - Bunny Tail
69 | Jin Huang - Daikon
70 | Kuan-Yin Sun - Champion
71 | Tao Hsiao - White Icicle
72 | Emily Walters - White Icicle
73 | nicholas kirby - french breakfast
74 | Hong Tsui - April Cross
75 | Mikayla Fullagar - Cherry Belle
76 | Lola Catchpole - April Cross
77 | Lelia Toscani - Bunny Tail
78 | Natasha Prout - Cherry Belle
79 | Raffaello Schiavone - Red King
80 | Erin Stephen - Plum Purple
81 | Eve Peacock - Daikon
82 | Jordan Manning - Sicily Giant
83 | Tyler Lister - April Cross
84 | brodie agnew - daikon
85 | Lincoln Hirschfeld - Champion
86 | Ciriaca Genovesi - Bunny Tail
87 | Dewei Niu - Snow Belle
88 | Fai Teng - Bunny Tail
89 | Rossana Cattaneo - Snow Belle
90 | Isabelle Coombes - Daikon
91 | Layla Hitchcock - Red King
92 | Ashley Brigstocke - Red King
93 | Lei Tai - Daikon
94 | Victoria Humffray - Sicily Giant
95 | Jake Champ - Daikon
96 | Ben Vosper - Cherry Belle
97 | Harrison Rose - Red King
98 | Thomas Oom - White Icicle
99 | Sophie Browning - Red King
100 | Scarlett Hughes - Bunny Tail
101 | Anthony Collits - Champion
102 | Alicia Forrest - Sicily Giant
103 | Riley Leakey - April Cross
104 | Bethany Calwell - French Breakfast
105 | Leo Sheil - April Cross
106 | Kai MacMahon - April Cross
107 | Rong Kuo - Champion
108 | Stephanie Schnaars - White Icicle
109 | Bethany Bardolph - French Breakfast
110 | Guido Beneventi - French Breakfast
111 | Victoria Witt - Daikon
112 | Jun Hsiung - Bunny Tail
113 | Noah Berrick - Daikon
114 | Beato Mazzanti - Sicily Giant
115 | Anna Denning - White Icicle
116 | Sebastian George - Cherry Belle
117 | Mackenzie Andrade - Champion
118 | Sarah Joris - Champion
119 | Joel Cassell - Plum Purple
120 | Harrison Moowattin - Champion
121 | william fenner - plum purple
122 | Madeline Corbin - Bunny Tail
123 | Sebastian Davitt - Champion
124 | Li Qin Ch'ien - Sicily Giant
125 | Owen Lea - Champion
126 | Liam Copeland - Champion
127 | Brianna Eltham - Sicily Giant
128 | Joseph Gresswell - Sicily Giant
129 | Alfonsina Marchesi - April Cross
130 | Caitlin Houlding - Snow Belle
131 | Natalie Schlapp - April Cross
132 | Shaiming Fu - Champion
133 | Lisandro Monaldo - Champion
134 | Ruby Fox - White Icicle
135 | Benjamin Rankin - Snow Belle
136 | Connor Letters - April Cross
137 | Laura Macdowell - Daikon
138 | Jake Hervey - April Cross
139 | Alyssa Batman - Snow Belle
140 | Archer Larra - French Breakfast
141 | Brayden Dixon - Bunny Tail
142 | Kuan-Yin Kuo - Cherry Belle
143 | Lucy Ley - Red King
144 | Rachele Russo - Cherry Belle
145 | Lucy Somers - Daikon
146 | Ella Boucaut - Champion
147 | Iacopo Baresi - Bunny Tail
148 | Ali Dedman - White Icicle
149 | Victoria Edinburgh - French Breakfast
150 | Brianna Pye - Red King
151 | Joel Bruce - Snow Belle
152 | Lola Lea - Bunny Tail
153 | Zachary Burford - Champion
154 | Gabriella Bruton - April Cross
155 | Finn Dunstan - Cherry Belle
156 | Logan Truchanas - Red King
157 | beau mclarty - white icicle
158 | Carla De Luca - Daikon
159 | Taylah Reynolds - Champion
160 | Ava Musgrave - Bunny Tail
161 | Jade Grimmett - Bunny Tail
162 | Eliza Fink - April Cross
163 | Charles Tearle - April Cross
164 | Victoria Birch - Snow Belle
165 | Mackenzie Geach - Plum Purple
166 | Charles Card - Cherry Belle
167 | Olivia Warnes - Sicily Giant
168 | Jake Murdoch - Cherry Belle
169 | Brayden Massina - April Cross
170 | Sarah Milford - White Icicle
171 | Lilian Pike - French Breakfast
172 | Blake Dakin - Champion
173 | Chi Hsiung - April Cross
174 | Ludovica Siciliano - Sicily Giant
175 | Rose Leahy - French Breakfast
176 | Nicodemo Udinese - Bunny Tail
177 | Amy Harriman - Sicily Giant
178 | Harrison Macgeorge - Red King
179 | Charles Mockridge - Cherry Belle
180 | Victoria Hardie - Sicily Giant
181 | Jake Hambly - Sicily Giant
182 | Bartolomeo Mancini - French Breakfast
183 | Maya Shackleton - Snow Belle
184 | Hudson Dodgshun - White Icicle
185 | Scarlett Sullivan - Snow Belle
186 | Noah Doyne - April cross
187 | Aidan Santo - Bunny Tail
188 | kai emmett - bunny tail
189 | Christopher Gillan - Daikon
190 | Lara Salting - White Icicle
191 | Alfonso Costa - Daikon
192 | Mackenzie Knatchbull - Red King
193 | Oliver Beit - Plum Purple
194 | Thomas Muecke - French Breakfast
195 | Sabrina Li Fonti - Bunny Tail
196 | Jasmine Brake - Snow Belle
197 | Sienna Bonnor - Daikon
198 | Isabelle Llewelyn - Daikon
199 | Amelie Farber - White Icicle
200 | Keira Horner - Red King
201 | Annabelle Colechin - French Breakfast
202 | George Schlunke - Daikon
203 | Hugo Stretch - French Breakfast
204 | Isabella Pardey - White Icicle
205 | Toby Docker - Red King
206 | Caitlyn Hotchin - French Breakfast
207 | Samuel Ansell - Sicily Giant
208 | Prospero Milano - Champion
209 | Zhi Chin - White Icicle
210 | nate brooker - daikon
211 | Elizabeth McNab - April Cross
212 | Amelie Torpy - Champion
213 | Audrey Bock - Bunny Tail
214 | Abbey Dawson - Plum Purple
215 | Hugo Coppleson - Daikon
216 | Lilly Tait - Red King
217 | Archer Frederick - April Cross
218 | Alvisio Mazzi - April Cross
219 | Chloe MacLaurin - Champion
220 | Georgia Bruny - April Cross
221 | Caitlyn Mullah - White Icicle
222 | Gang Chia - Red King
223 | Lauren Pennefather - French Breakfast
224 | Fang Ch'eng - Cherry Belle
225 | Summer Withers - Snow Belle
226 | Kayla Sievier - Snow Belle
227 | Edoardo Sal - Champion
228 | Layla Fossey - April Cross
229 | Ella Weston - Champion
230 | Patrick Camidge - French Breakfast
231 | Erin Stretton - French Breakfast
232 | Poppy Duggan - Champion
233 | Daniel Hogben - Daikon
234 | Wan Tsai - Snow Belle
235 | Olimpia Udinesi - April Cross
236 | Xue Fang Fu - Daikon
237 | Alyssa McInnes - Daikon
238 | Connor Morphett - Plum Purple
239 | Nathan Trott - French Breakfast
240 | Brock Brunker - Bunny Tail
241 | Hayden O'Connell - French Breakfast
242 | James Larra - April Cross
243 | Eva Geiger - Plum Purple
244 | Taj Shackell - White Icicle
245 | Eliza O'Haran - Champion
246 | Aidan Dore - April Cross
247 | Aiden Reginald - Plum Purple
248 | Bruna Rizzo - Snow Belle
249 | Alex Wemyss - April Cross
250 | claudia westgarth - daikon
251 | Jett Glynde - Plum Purple
252 | Brooke Huffer - Daikon
253 | Stephanie Synan - Sicily Giant
254 | Salvatore Sagese - French Breakfast
255 | Edgardo Mazzanti - Daikon
256 | Brodie De Lissa - Cherry Belle
257 | Cai Pan - Sicily Giant
258 | Caitlyn Ridgeway - Sicily Giant
259 | Mason Dymock - Plum Purple
260 | Oliviero Lucchesi - Bunny Tail
261 | Antonietta Baresi - Cherry Belle
262 | Abbey Cousens - Daikon
263 | Hui Hsiung - Cherry Belle
264 | Marcus Brown - Sicily Giant
265 | James Poupinel - Daikon
266 | Lucas Tomkinson - Champion
267 | Xin Qian Shih - White Icicle
268 | Abigail Clark - White Icicle
269 | Archie Gilfillan - French Breakfast
270 | maya woolcock - april cross
271 | Wei Hsiao - Daikon
272 | Lauren Rosevear - Red King
273 | Eve Gargett - Snow Belle
274 | Cristian Pisano - Champion
275 | Bianca Knopwood - White Icicle
276 | Alyssa Loewe - Daikon
277 | Feng Li - French Breakfast
278 | Yi Min Chu - Plum Purple
279 | Aiden Tasman - Red King
280 | corinna lucchese - champion
281 | Taylah Shore - Cherry Belle
282 | nilde beneventi - french breakfast
283 | edward greener - bunny tail
284 | Nate Lodewyckx - Sicily Giant
285 | Mariam Langridge - Red King
286 | Indiana Cory - Champion
287 | David Rees - April Cross
288 | Daniel Appleton - Red King
289 | Luke Leeper - Red King
290 | Toby Spring - French Breakfast
291 | Cody Laffer - Red King
292 | Lilian Woodriff - Plum Purple
293 | hudson crane - sicily giant
294 | Anthony Wand - Bunny Tail
295 | Dean Mattner - Red King
296 | Lucinda Howarde - Sicily Giant
297 | Caleb Clancy - Red King
298 | Mia Legg - White Icicle
299 | Isla Mehaffey - Sicily Giant
300 | Cooper Lasseter - April Cross
301 | Indiana Scott - Cherry Belle
302 | Kaitlyn Kay - French Breakfast
303 | Abbey Aronson - April Cross
304 | Madeleine Hartung - Snow Belle
305 | Abbey Tyas - Red King
306 | Jacob Spowers - Snow Belle
307 | Brodie Fraser - French Breakfast
308 | Ivo Lucchesi - Champion
309 | Harry Wormald - French Breakfast
310 | Lilian Macquarie - White Icicle
311 | Chelsea Warby - Bunny Tail
312 | Eugenio Pagnotto - Sicily Giant
313 | Michael Hargrave - Cherry Belle
314 | Leda Romani - April Cross
315 | Christopher Walton - Champion
316 | Zachary Bass - White Icicle
317 | jorja franklyn - white icicle
318 | Makayla Sutton - Plum Purple
319 | Shu Fang Tsou - French Breakfast
320 | Evie Carey - Bunny Tail
321 | Alannah Bleakley - Bunny Tail
322 | Alma Longo - Cherry Belle
323 | Abbey Garvin - Snow Belle
324 | Isabella Van De Velde - Plum Purple
325 | scarlett price - april cross
326 | Beau Hauslaib - Champion
327 | Isabelle Mathew - Sicily Giant
328 | Laura Callinan - Cherry Belle
329 | Cody Le Rennetel - French Breakfast
330 | Rachel Luke - Snow Belle
331 | Tristan Glynde - Snow Belle
332 | Qiao Tien - Bunny Tail
333 | Alana Meares - Red King
334 | Xiao Chen Chiang - Sicily Giant
335 | Jack Finlay - Cherry Belle
336 | Jaxon Keen - Plum Purple
337 | Jordan Catani - Plum Purple
338 | Piera Trevisan - Red King
339 | Bailey Mussen - Bunny Tail
340 | Hayley Coverdale - White Icicle
341 | Sophie Eipper - Snow Belle
342 | Beata Endrizzi - Daikon
343 | David Moynihan - White Icicle
344 | Andrew Martens - French Breakfast
345 | Nate Higgs - Red King
346 | Isaac Banks - Snow Belle
347 | Xavier Sligo - Champion
348 | Nathan Aird - Plum Purple
349 | Cooper Monk - Bunny Tail
350 | Kayla Kinsella - Champion
351 | Sean Maclurcan - Sicily Giant
352 | Jett Faucett - April Cross
353 | Koby Mary - Red King
354 | Lok Fan - Champion
355 | Liam Burn - French Breakfast
356 | Ryan Skeats - Snow Belle
357 | Harrison Barlee - Cherry Belle
358 | Marcus South - Champion
359 | Emily Kumm - White Icicle
360 | Tristan Lack - Cherry Belle
361 | Rebecca Godfrey - Red King
362 | Bailey Randell - Red King
363 | Emma Slater - Bunny Tail
364 | Ellie Eaton - Sicily Giant
365 | Hamish Kevin - Sicily Giant
366 | Bella Lyttle - Bunny Tail
367 | Guang Lo - April Cross
368 | Jai Keith - Daikon
369 | Lucinda Emanuel - Plum Purple
370 | Tayla English - Plum Purple
371 | Eden Petchy - Daikon
372 | Lee Chen - April Cross
373 | Angus De Mestre - White Icicle
374 | Maya Huish - Snow Belle
375 | Emily Plante - White Icicle
376 | Connor Fairbridge - Bunny Tail
377 | Lara Cawker - Champion
378 | Blanda Panicucci - Bunny Tail
379 | Napoleone Marcelo - Champion
380 | Georgia Gillen - Snow Belle
381 | Giselda Napolitano - French Breakfast
382 | Anthony Hugo - Red King
383 | Oscar Saltau - April Cross
384 | Ashton Pearce - Daikon
385 | Kiara Maxwell-Mahon - White Icicle
386 | Sebastian Ball - French Breakfast
387 | Anna Howarde - Bunny Tail
388 | Lauren Nisbet - Plum Purple
389 | Patrick Porteus - Bunny Tail
390 | ling tuan - Red King
391 | Park Ch'en - Sicily Giant
392 | Yi Tseng - French Breakfast
393 | Angelina Dangar - Snow Belle
394 | Carolina Cattaneo - Snow Belle
395 | Sean Tait - Snow Belle
396 | Alex Falk - White Icicle
397 | oliver thirkell - french breakfast
398 | Jesse Fairley - Champion
399 | Benito Cocci - Snow Belle
400 | Laura Samuels - Champion
401 | Kuan-Yin Tao - Cherry Belle
402 | Shi She - Champion
403 | Isabella Hoffnung - April Cross
404 | George Carandini - White Icicle
405 | Sarah Bindi - French Breakfast
406 | Andrew Quick - April Cross
407 | Giosuè Romano - Champion
408 | Eva Ruth - Plum Purple
409 | Koby Gabriel - Champion
410 | Jayden Josephson - April Cross
411 | Mafalda Marchesi - Snow Belle
412 | Gabrielle Porteus - Daikon
413 | Dylan Synnot - Red King
414 | Brooke Kisch - Bunny Tail
415 | Quintilia Trentini - Bunny Tail
416 | Taj Moonlight - Plum Purple
417 | Ava Sorell - Bunny Tail
418 | Kate Buchanan - Sicily Giant
419 | Stella Inwood - Cherry Belle
420 | Cody Glauert - Snow Belle
421 | Callimaco Lombardi - Champion
422 | ella irving - cherry belle
423 | Guan-yin Hsiao - Red King
424 | alicia muscio - april cross
425 | Alana Sturdee - Champion
426 | Makayla Fairbairn - White Icicle
427 | Kaitlyn Collings - Bunny Tail
428 | Alexis Le Hunte - Champion
429 | lilian andrade - bunny tail
430 | Alannah Housley - Bunny Tail
431 | Rose Peeler - Champion
432 | Yue Wan Yeh - White Icicle
433 | Evie Langwell - Snow Belle
434 | Zoe Jasprizza - Red King
435 | Ivo Sagese - April Cross
436 | Rory Springthorpe - Snow Belle
437 | hannah gabriel - red king
438 | Jonathan Paten - Bunny Tail
439 | Jessica Rapke - Sicily Giant
440 | Jake Sterne - Daikon
441 | Lola Mashman - Bunny Tail
442 | Chan Yen - Cherry Belle
443 | Timothy Beeton - White Icicle
444 | Joseph Hill - Daikon
445 | Luke Gye - Plum Purple
446 | Giuseppe Manna - Sicily Giant
447 | Matilda Wardlaw - Red King
448 | Hannah Dibbs - Plum Purple
449 | Xavier Truman - French Breakfast
450 | Emma Sodersten - April Cross
451 | Blake Sodersten - French Breakfast
452 | Andrew Schwarz - Cherry Belle
453 | Owen Montgomery - Snow Belle
454 | Blake Hurst - White Icicle
455 | Brayden Brill - Cherry Belle
456 | Keira Strzelecki - Champion
457 | Zhen Juan Tsai - White Icicle
458 | Mulan Kung - Red King
459 | Clorinda Pugliesi - Champion
460 | Abbey Strzelecki - French Breakfast
461 | Andrew Howitt - April Cross
462 | Sebastian Langford - Cherry Belle
463 | hayley Hinchcliffe - Cherry Belle
464 | Ebony Anton - Sicily Giant
465 | Seth Reginald - April Cross
466 | Beau Gosling - Plum Purple
467 | Christopher Moss - White Icicle
468 | laura uhr - red king
469 | Jamie Faithful - Red King
470 | Isaac Tennyson - Daikon
471 | Gemma Norton - Sicily Giant
472 | Matilda Madden - Red King
473 | Azeglio Napolitano - Red King
474 | David Tomlinson - Bunny Tail
475 | Christian Morris - Champion
476 | Amy Goulburn - April Cross
477 | Christopher Clunies - April Cross
478 | annabelle armytage - daikon
479 | Hunter Connely - Snow Belle
480 | Summer Stenhouse - April Cross
481 | Alicia Farmer - White Icicle
482 | Charlotte Slattery - Red King
483 | Georgia Jessop - Cherry Belle
484 | Abby Metters - Champion
485 | Madeleine Behan - Snow Belle
486 | Hayley Kernot - Plum Purple
487 | Ubaldo Trevisani - Champion
488 | Annabelle Scarfe - Cherry Belle
489 | Flynn Weingarth - Sicily Giant
490 | Indiana Keast - April Cross
491 | Wang Tien - French Breakfast
492 | Elijah Kingsbury - Plum Purple
493 | henry wright - sicily giant
494 | Meng Ni - Snow Belle
495 | Sara Coffill - Sicily Giant
496 | Giusy Lombardi - Plum Purple
497 | Egidio Mancini - Sicily Giant
498 | Bethany Macfarlan - Bunny Tail
499 | Alexis Cowlishaw - Bunny Tail
500 | Skye Garvin - April Cross
501 | Abbey Rivett - Snow Belle
502 | Mikayla Woollacott - Sicily Giant
503 | Abbey Cochran - Daikon
504 | Jasmine Baughan - White Icicle
505 | Da-Xia Liang - April Cross
506 | Dominic Nangle - White Icicle
507 | Jesse Jury - Sicily Giant
508 | Ruby Elias - Daikon
509 | David Read - Bunny Tail
510 | Yue Yan T'ang - April Cross
511 | Qiang Tsui - Cherry Belle
512 | Grace Parkinson - Snow Belle
513 | Yue Yan Hu - White Icicle
514 | Adele Buccho - White Icicle
515 | Imogen Gertrude - Bunny Tail
516 | Kate Cyril - April Cross
517 | Zoe Canning - Plum Purple
518 | Imogen Gaunson - Bunny Tail
519 | Brayden Stretch - April Cross
520 | Jian Ts'ao - Plum Purple
521 | Gabriella Titheradge - Red King
522 | Alexis Nesbitt - Daikon
523 | Galeazzo Milanesi - Champion
524 | Eve Everingham - Daikon
525 | on hê - snow belle
526 | Archie Mathy - White Icicle
527 | Skye Reynolds - French Breakfast
528 | Ben Denovan - April Cross
529 | Pia Folliero - White Icicle
530 | Archie Michelides - Cherry Belle
531 | zane pavy - bunny tail
532 | Ramiro Esposito - Daikon
533 | Brock Eames - Daikon
534 | Savannah Sheehan - French Breakfast
535 | angus christie - french breakfast
536 | Dominic Tregurtha - Cherry Belle
537 | Molly Piguenit - Plum Purple
538 | matthew john - snow belle
539 | Koby Ledger - White Icicle
540 | Jasper Harper - White Icicle
541 | William Doyle - French Breakfast
542 | Taj Maria - Sicily Giant
543 | Michael Elliot - April Cross
544 | Matthew Knibbs - Sicily Giant
545 | Patrick Tilly - White Icicle
546 | Sarah Kashiwagi - Bunny Tail
547 | Abbey Bouton - Champion
548 | Kayla Sandover - Bunny Tail
549 | Anna Septimus - French Breakfast
550 | Matthew Birch - Champion
551 | Mikayla Kennerley - French Breakfast
552 | Charli Birkbeck - Daikon
553 | Matilda Gullett - Champion
554 | Ella McLellan - April Cross
555 | Silvia Rossi - Plum Purple
556 | Chan Juan Hsü - French Breakfast
557 | Oliver Aspinall - Cherry Belle
558 | Timothy Baldwinson - Bunny Tail
559 | Li Wei Chien - Snow Belle
560 | Bethany Layh - French Breakfast
561 | Gang Hsu - April Cross
562 | Mikayla Brodney - Champion
563 | Kuan-Yin Mao - Daikon
564 | Elizabeth Minifie - Champion
565 | Sarah Band - Sicily Giant
566 | Tyson Kaberry - French Breakfast
567 | Victoria Shipp - Cherry Belle
568 | Henry McCorkindale - French Breakfast
569 | William De Satg - Snow Belle
570 | Skye Atkins - Cherry Belle
571 | Sean Hogben - Champion
572 | Claire Boelke - Cherry Belle
573 | Tristan Turley - Snow Belle
574 | Tyler Hansen - Champion
575 | Caleb Ride - Bunny Tail
576 | Archer Cathcart - April Cross
577 | Hamish Helena - French Breakfast
578 | Agostino Milanesi - April Cross
579 | lilly wunderlich - french breakfast
580 | Brooke Mahomet - Sicily Giant
581 | Seth Bramston - Daikon
582 | Archer Kirwan - Cherry Belle
583 | Ettore Marcelo - Champion
584 | Blake D'Alton - Sicily Giant
585 | Jai Burgoyne - Bunny Tail
586 | Mikayla Minogue - April Cross
587 | Thomas Catt - April Cross
588 | Oscar Cocci - Daikon
589 | Claudia Boxall - Plum Purple
590 | Imogen Macaulay - Snow Belle
591 | Tyson Platt - Bunny Tail
592 | Isabelle Camden - White Icicle
593 | Kiara Maxted - Daikon
594 | Raffaella Trevisan - Daikon
595 | Xiang Hsü - Plum Purple
596 | Hudson Greene - Bunny Tail
597 | Ruby Wakefield - Cherry Belle
598 | Matilda Macarthur-Onslow - Plum Purple
599 | Jasmine Fetherstonhaugh - Snow Belle
600 | Andrew Bower - Bunny Tail
601 | Olindo De Luca - Cherry Belle
602 | Alexis Kelynack - French Breakfast
603 | Amy Clunie - White Icicle
604 | Kang Yu - Cherry Belle
605 | Henry Birdseye - Snow Belle
606 | dominic gale - april cross
607 | Edward Edmond - Snow Belle
608 | Raul Pinto - Cherry Belle
609 | Laura Bath - Red King
610 | John Bale - Cherry Belle
611 | Margherita Milani - Red King
612 | Hudson Devine - Champion
613 | Jaxon Cowles - Sicily Giant
614 | Cameron Embley - Sicily Giant
615 | Laura Wawn - Cherry Belle
616 | Li Ming Niu - Cherry Belle
617 | Eden Sheehan - Cherry Belle
618 | Taj Bjelke-Petersen - French Breakfast
619 | Declan Winston - White Icicle
620 | Chan Chao - Red King
621 | mikayla hebblethwaite - sicily giant
622 | Tristan Monson - Cherry Belle
623 | Leah Ross-Watt - Plum Purple
624 | Hu K'ung - Daikon
625 | Kaitlyn Carnegie - Champion
626 | Victoria Brereton - Plum Purple
627 | Keira Toutcher - Cherry Belle
628 | David Morgans - Daikon
629 | Norma Fiorentino - Red King
630 | Sarah Paten - Sicily Giant
631 | Zac Cowles - Sicily Giant
632 | Brock Fiaschi - French Breakfast
633 | Eliza Naylor - French Breakfast
634 | Imogen Raws - Red King
635 | Jesse Abercrombie - Snow Belle
636 | James Luke - White Icicle
637 | Riley Stewart - White Icicle
638 | amelia blue - white icicle
639 | Cameron Pearce - Red King
640 | Ennio DeRose - French Breakfast
641 | Samuel Henschke - Sicily Giant
642 | Blake MacFarland - Cherry Belle
643 | Mary Randall - Cherry Belle
644 | luce de luca - snow belle
645 | Marcus Derbyshire - Bunny Tail
646 | Hunter McEachern - Bunny Tail
647 | Jasper Gibney - French Breakfast
648 | Lincoln Hoare - French Breakfast
649 | Sofia Donnithorne - Snow Belle
650 | Anthony Stuart - Snow Belle
651 | Hamish Yarnold - April Cross
652 | Lucas Schuler - Plum Purple
653 | Milla Garling - French Breakfast
654 | Abigail Wiltshire - Bunny Tail
655 | Zane Wreford - Snow Belle
656 | Sean Glew - Daikon
657 | Ryan Aird - Red King
658 | Jasper Harford - Champion
659 | Charlie McCabe - Bunny Tail
660 | Rory Evenden - White Icicle
661 | Ebony Florence - Snow Belle
662 | Flynn Poninski - Daikon
663 | Ebony Lawlor - Bunny Tail
664 | Ethan Dickson - Bunny Tail
665 | Xavier Howchin - Bunny Tail
666 | Zane Weindorfer - Cherry Belle
667 | Sienna Dann - Snow Belle
668 | Eleuterio Lombardo - White Icicle
669 | Tyler Makutz - Champion
670 | Yong Hsiao - White Icicle
671 | Erin Binnie - Bunny Tail
672 | Phoebe Barwell - Plum Purple
673 | Dylan Barney - French Breakfast
674 | Tristan Charteris - April Cross
675 | Sebastian Helmore - Bunny Tail
676 | Thomas Darcy - Bunny Tail
677 | Quinzia Costa - Daikon
678 | Da-Xia Hsiao - French Breakfast
679 | Grace Frayne - Sicily Giant
680 | Toby Queale - White Icicle
681 | Logan Lackey - Plum Purple
682 | na t'ao - french breakfast
683 | Callum Prentice - Plum Purple
684 | Levi Ferry - Sicily Giant
685 | Hsin Tan - April Cross
686 | Lara Macarthur - French Breakfast
687 | Scarlett Bruny - Champion
688 | Procopio Zito - white icicle
689 | Jamie Ham - Bunny Tail
690 | Kaitlyn Mullen - Daikon
691 | Cameron Landseer - April Cross
692 | Jasper Alfred - White Icicle
693 | Andrew Coventry - Cherry Belle
694 | Scarlett Schonell - Plum Purple
695 | Mia Alngindabu - Champion
696 | Claire Bisdee - Daikon
697 | Gabriella Beale - Cherry Belle
698 | Rebecca Petrie - Snow Belle
699 | Alexander McKean - Bunny Tail
700 | Cody Leakey - Plum Purple
701 | Sam Scarfe - Sicily Giant
702 | Angus Langley - French Breakfast
703 | Shi Shen - Sicily Giant
704 | Park Wu - Champion
705 | Isabelle Finney - April Cross
706 | Aaron Addison - Plum Purple
707 | Ethan Macdougall - Champion
708 | cody vale - red king
709 | Aidan Clutterbuck - French Breakfast
710 | Durante Ferri - White Icicle
711 | eliana baresi - white icicle
712 |
--------------------------------------------------------------------------------
/files/shopping_list.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "metadata": {
3 | "name": "shopping_list"
4 | },
5 | "nbformat": 3,
6 | "nbformat_minor": 0,
7 | "worksheets": [
8 | {
9 | "cells": [
10 | {
11 | "cell_type": "code",
12 | "collapsed": false,
13 | "input": "shopping_list = [ \"bananas\", \"carrots\", \"tea\" ]",
14 | "language": "python",
15 | "metadata": {},
16 | "outputs": [],
17 | "prompt_number": 6
18 | },
19 | {
20 | "cell_type": "code",
21 | "collapsed": false,
22 | "input": "print(shopping_list)",
23 | "language": "python",
24 | "metadata": {},
25 | "outputs": [
26 | {
27 | "output_type": "stream",
28 | "stream": "stdout",
29 | "text": "['bananas', 'carrots', 'tea']\n"
30 | }
31 | ],
32 | "prompt_number": 7
33 | },
34 | {
35 | "cell_type": "code",
36 | "collapsed": false,
37 | "input": "if \"bananas\" in shopping_list:\n print(\"Don't forget to get the bananas!\")",
38 | "language": "python",
39 | "metadata": {},
40 | "outputs": [
41 | {
42 | "output_type": "stream",
43 | "stream": "stdout",
44 | "text": "Don't forget to get the bananas!\n"
45 | }
46 | ],
47 | "prompt_number": 8
48 | },
49 | {
50 | "cell_type": "markdown",
51 | "metadata": {},
52 | "source": "## Things to try\n\n* Change the first cell to add different items to the shopping_list. Rerun the second and third cells to see the differences in out.\n\n* "
53 | }
54 | ],
55 | "metadata": {}
56 | }
57 | ]
58 | }
--------------------------------------------------------------------------------
/images/assign_shopping_list.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenTechSchool/python-data-intro/71cc56017dbbfc1cf1e8bccd00b9773c4509707e/images/assign_shopping_list.png
--------------------------------------------------------------------------------
/images/background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenTechSchool/python-data-intro/71cc56017dbbfc1cf1e8bccd00b9773c4509707e/images/background.png
--------------------------------------------------------------------------------
/images/histogram.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenTechSchool/python-data-intro/71cc56017dbbfc1cf1e8bccd00b9773c4509707e/images/histogram.png
--------------------------------------------------------------------------------
/images/ipython_example.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenTechSchool/python-data-intro/71cc56017dbbfc1cf1e8bccd00b9773c4509707e/images/ipython_example.png
--------------------------------------------------------------------------------
/images/ipython_notebook.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenTechSchool/python-data-intro/71cc56017dbbfc1cf1e8bccd00b9773c4509707e/images/ipython_notebook.png
--------------------------------------------------------------------------------
/images/jupyter_new.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenTechSchool/python-data-intro/71cc56017dbbfc1cf1e8bccd00b9773c4509707e/images/jupyter_new.png
--------------------------------------------------------------------------------
/images/notebook_hello_world.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenTechSchool/python-data-intro/71cc56017dbbfc1cf1e8bccd00b9773c4509707e/images/notebook_hello_world.png
--------------------------------------------------------------------------------
/images/print_shopping_list.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenTechSchool/python-data-intro/71cc56017dbbfc1cf1e8bccd00b9773c4509707e/images/print_shopping_list.png
--------------------------------------------------------------------------------
/images/radish_bargraph.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenTechSchool/python-data-intro/71cc56017dbbfc1cf1e8bccd00b9773c4509707e/images/radish_bargraph.png
--------------------------------------------------------------------------------
/images/radish_barsection.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenTechSchool/python-data-intro/71cc56017dbbfc1cf1e8bccd00b9773c4509707e/images/radish_barsection.png
--------------------------------------------------------------------------------
/images/radish_ticks.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenTechSchool/python-data-intro/71cc56017dbbfc1cf1e8bccd00b9773c4509707e/images/radish_ticks.png
--------------------------------------------------------------------------------
/images/viewing_distances.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenTechSchool/python-data-intro/71cc56017dbbfc1cf1e8bccd00b9773c4509707e/images/viewing_distances.png
--------------------------------------------------------------------------------
/images/viewing_latitudes.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenTechSchool/python-data-intro/71cc56017dbbfc1cf1e8bccd00b9773c4509707e/images/viewing_latitudes.png
--------------------------------------------------------------------------------
/images/windows_fixing_startdir.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenTechSchool/python-data-intro/71cc56017dbbfc1cf1e8bccd00b9773c4509707e/images/windows_fixing_startdir.png
--------------------------------------------------------------------------------
/index.md:
--------------------------------------------------------------------------------
1 | ---
2 |
3 | layout: ots
4 | title: Introduction to Data Processing with Python
5 |
6 | ---
7 |
8 | This is the course content for Introduction to Data Processing with
9 | Python, which has been developed and maintained by
10 | [OpenTechSchool](http://www.opentechschool.org).
11 |
12 | # Welcome
13 |
14 | Welcome to Introduction to Data Processing with Python. In this workshop we will take you through the fundamentals of working with text and other types of data with Python. We'll learn how to read data from files into data structures in our program, to extract the information we want. We'll display that data in graphs and charts, and get a glimpse of the world of Open Data that's available online. You'll never want to wrangle a spreadsheet again!
15 |
16 | We only expect you to know a little Python, not a lot. If you've done our
17 | [Introduction to Programming](http://opentechschool.github.com/python-beginners/en/index.html)
18 | workshop then that will be perfect.
19 |
20 | # Core workshop material
21 |
22 | * [Recap of Python essentials](core/recap.html) - A quick recap of some of the Introduction to Programming essentials.
23 | * [Data Structures in Python](core/data.html) - An introduction to the list and dictionary data structures.
24 | * [Introducing IPython Notebook](core/notebook.html) - A whole new way to work with Python!
25 | * [Analyzing a survey](core/survey.html) - Once we have our text in Python, what can we do with it?
26 | * [Creating Charts](core/charts.html) - Using IPython Notebook with matplotlib to create charts.
27 | * [CSV Files](core/csv.html) - Reading comma-separated data.
28 |
29 | # Extra fun stuff
30 |
31 | * [Alternative Approaches](extras/alternatives.html) - Other ways to store and process data (Pandas, SQL databases.)
32 |
33 | * [Open Data Sources](extras/opendata.html) Data.
34 |
35 | # Reference material
36 |
37 | * [Jupyter NBViewer home page](https://nbviewer.jupyter.org/)
38 |
39 | * [Jupyter Notebook gallery](https://github.com/jupyter/jupyter/wiki/A-gallery-of-interesting-Jupyter-Notebooks)
40 |
41 | * [matplotlib gallery](http://matplotlib.org/gallery.html)
42 |
43 | ## More Advanced Follow Up Material
44 |
45 | If you're wondering how to "level up" to more advanced data analysis after mastering the material here, you could try these;
46 |
47 | * A tutorial series by Hernan Rojas showing the basics of [using the Python library "pandas" for data analysis](https://bitbucket.org/hrojas/learn-pandas). You can click on the lessons directly to view them in your browser, or click the "(download)" link on the right of the page to download a ZIP file containing them as IPython Notebook files.
48 |
49 | * If you have statistical modelling experience then [this video tutorial by Skipper Seabold from SciPy 2012](http://pyvideo.org/video/1200/statsmodels) ([accompanying material as IPython Notebook files](https://github.com/jseabold/tutorial)) comes highly recommended.
50 |
51 | * [SciPy tutorial notes](http://scipy-lectures.github.io/), that can be used for a full course of scientific computing with Python.
52 |
--------------------------------------------------------------------------------
/js/highlight.min.js:
--------------------------------------------------------------------------------
1 | var hljs=new function(){function l(o){return o.replace(/&/gm,"&").replace(//gm,">")}function b(p){for(var o=p.firstChild;o;o=o.nextSibling){if(o.nodeName=="CODE"){return o}if(!(o.nodeType==3&&o.nodeValue.match(/\s+/))){break}}}function h(p,o){return Array.prototype.map.call(p.childNodes,function(q){if(q.nodeType==3){return o?q.nodeValue.replace(/\n/g,""):q.nodeValue}if(q.nodeName=="BR"){return"\n"}return h(q,o)}).join("")}function a(q){var p=(q.className+" "+q.parentNode.className).split(/\s+/);p=p.map(function(r){return r.replace(/^language-/,"")});for(var o=0;o"}while(x.length||v.length){var u=t().splice(0,1)[0];y+=l(w.substr(p,u.offset-p));p=u.offset;if(u.event=="start"){y+=s(u.node);r.push(u.node)}else{if(u.event=="stop"){var o,q=r.length;do{q--;o=r[q];y+=(""+o.nodeName.toLowerCase()+">")}while(o!=u.node);r.splice(q,1);while(q'+L[0]+""}else{r+=L[0]}N=A.lR.lastIndex;L=A.lR.exec(K)}return r+K.substr(N)}function z(){if(A.sL&&!e[A.sL]){return l(w)}var r=A.sL?d(A.sL,w):g(w);if(A.r>0){v+=r.keyword_count;B+=r.r}return''+r.value+""}function J(){return A.sL!==undefined?z():G()}function I(L,r){var K=L.cN?'':"";if(L.rB){x+=K;w=""}else{if(L.eB){x+=l(r)+K;w=""}else{x+=K;w=r}}A=Object.create(L,{parent:{value:A}});B+=L.r}function C(K,r){w+=K;if(r===undefined){x+=J();return 0}var L=o(r,A);if(L){x+=J();I(L,r);return L.rB?0:r.length}var M=s(A,r);if(M){if(!(M.rE||M.eE)){w+=r}x+=J();do{if(A.cN){x+=""}A=A.parent}while(A!=M.parent);if(M.eE){x+=l(r)}w="";if(M.starts){I(M.starts,"")}return M.rE?0:r.length}if(t(r,A)){throw"Illegal"}w+=r;return r.length||1}var F=e[D];f(F);var A=F;var w="";var B=0;var v=0;var x="";try{var u,q,p=0;while(true){A.t.lastIndex=p;u=A.t.exec(E);if(!u){break}q=C(E.substr(p,u.index-p),u[0]);p=u.index+q}C(E.substr(p));return{r:B,keyword_count:v,value:x,language:D}}catch(H){if(H=="Illegal"){return{r:0,keyword_count:0,value:l(E)}}else{throw H}}}function g(s){var o={keyword_count:0,r:0,value:l(s)};var q=o;for(var p in e){if(!e.hasOwnProperty(p)){continue}var r=d(p,s);r.language=p;if(r.keyword_count+r.r>q.keyword_count+q.r){q=r}if(r.keyword_count+r.r>o.keyword_count+o.r){q=o;o=r}}if(q.language){o.second_best=q}return o}function i(q,p,o){if(p){q=q.replace(/^((<[^>]+>|\t)+)/gm,function(r,v,u,t){return v.replace(/\t/g,p)})}if(o){q=q.replace(/\n/g," ")}return q}function m(r,u,p){var v=h(r,p);var t=a(r);if(t=="no-highlight"){return}var w=t?d(t,v):g(v);t=w.language;var o=c(r);if(o.length){var q=document.createElement("pre");q.innerHTML=w.value;w.value=j(o,c(q),v)}w.value=i(w.value,u,p);var s=r.className;if(!s.match("(\\s|^)(language-)?"+t+"(\\s|$)")){s=s?(s+" "+t):t}r.innerHTML=w.value;r.className=s;r.result={language:t,kw:w.keyword_count,re:w.r};if(w.second_best){r.second_best={language:w.second_best.language,kw:w.second_best.keyword_count,re:w.second_best.r}}}function n(){if(n.called){return}n.called=true;Array.prototype.map.call(document.getElementsByTagName("pre"),b).filter(Boolean).forEach(function(o){m(o,hljs.tabReplace)})}function k(){window.addEventListener("DOMContentLoaded",n,false);window.addEventListener("load",n,false)}var e={};this.LANGUAGES=e;this.highlight=d;this.highlightAuto=g;this.fixMarkup=i;this.highlightBlock=m;this.initHighlighting=n;this.initHighlightingOnLoad=k;this.IR="[a-zA-Z][a-zA-Z0-9_]*";this.UIR="[a-zA-Z_][a-zA-Z0-9_]*";this.NR="\\b\\d+(\\.\\d+)?";this.CNR="(\\b0[xX][a-fA-F0-9]+|(\\b\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)";this.BNR="\\b(0b[01]+)";this.RSR="!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|\\.|-|-=|/|/=|:|;|<|<<|<<=|<=|=|==|===|>|>=|>>|>>=|>>>|>>>=|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~";this.BE={b:"\\\\[\\s\\S]",r:0};this.ASM={cN:"string",b:"'",e:"'",i:"\\n",c:[this.BE],r:0};this.QSM={cN:"string",b:'"',e:'"',i:"\\n",c:[this.BE],r:0};this.CLCM={cN:"comment",b:"//",e:"$"};this.CBLCLM={cN:"comment",b:"/\\*",e:"\\*/"};this.HCM={cN:"comment",b:"#",e:"$"};this.NM={cN:"number",b:this.NR,r:0};this.CNM={cN:"number",b:this.CNR,r:0};this.BNM={cN:"number",b:this.BNR,r:0};this.inherit=function(q,r){var o={};for(var p in q){o[p]=q[p]}if(r){for(var p in r){o[p]=r[p]}}return o}}();hljs.LANGUAGES.bash=function(a){var g="true false";var e="if then else elif fi for break continue while in do done echo exit return set declare";var c={cN:"variable",b:"\\$[a-zA-Z0-9_#]+"};var b={cN:"variable",b:"\\${([^}]|\\\\})+}"};var h={cN:"string",b:'"',e:'"',i:"\\n",c:[a.BE,c,b],r:0};var d={cN:"string",b:"'",e:"'",c:[{b:"''"}],r:0};var f={cN:"test_condition",b:"",e:"",c:[h,d,c,b],k:{literal:g},r:0};return{k:{keyword:e,literal:g},c:[{cN:"shebang",b:"(#!\\/bin\\/bash)|(#!\\/bin\\/sh)",r:10},c,b,a.HCM,h,d,a.inherit(f,{b:"\\[ ",e:" \\]",r:0}),a.inherit(f,{b:"\\[\\[ ",e:" \\]\\]"})]}}(hljs);hljs.LANGUAGES.cs=function(a){return{k:"abstract as base bool break byte case catch char checked class const continue decimal default delegate do double else enum event explicit extern false finally fixed float for foreach goto if implicit in int interface internal is lock long namespace new null object operator out override params private protected public readonly ref return sbyte sealed short sizeof stackalloc static string struct switch this throw true try typeof uint ulong unchecked unsafe ushort using virtual volatile void while ascending descending from get group into join let orderby partial select set value var where yield",c:[{cN:"comment",b:"///",e:"$",rB:true,c:[{cN:"xmlDocTag",b:"///|"},{cN:"xmlDocTag",b:"?",e:">"}]},a.CLCM,a.CBLCLM,{cN:"preprocessor",b:"#",e:"$",k:"if else elif endif define undef warning error line region endregion pragma checksum"},{cN:"string",b:'@"',e:'"',c:[{b:'""'}]},a.ASM,a.QSM,a.CNM]}}(hljs);hljs.LANGUAGES.ruby=function(e){var a="[a-zA-Z_][a-zA-Z0-9_]*(\\!|\\?)?";var j="[a-zA-Z_]\\w*[!?=]?|[-+~]\\@|<<|>>|=~|===?|<=>|[<>]=?|\\*\\*|[-/+%^&*~`|]|\\[\\]=?";var g={keyword:"and false then defined module in return redo if BEGIN retry end for true self when next until do begin unless END rescue nil else break undef not super class case require yield alias while ensure elsif or include"};var c={cN:"yardoctag",b:"@[A-Za-z]+"};var k=[{cN:"comment",b:"#",e:"$",c:[c]},{cN:"comment",b:"^\\=begin",e:"^\\=end",c:[c],r:10},{cN:"comment",b:"^__END__",e:"\\n$"}];var d={cN:"subst",b:"#\\{",e:"}",l:a,k:g};var i=[e.BE,d];var b=[{cN:"string",b:"'",e:"'",c:i,r:0},{cN:"string",b:'"',e:'"',c:i,r:0},{cN:"string",b:"%[qw]?\\(",e:"\\)",c:i},{cN:"string",b:"%[qw]?\\[",e:"\\]",c:i},{cN:"string",b:"%[qw]?{",e:"}",c:i},{cN:"string",b:"%[qw]?<",e:">",c:i,r:10},{cN:"string",b:"%[qw]?/",e:"/",c:i,r:10},{cN:"string",b:"%[qw]?%",e:"%",c:i,r:10},{cN:"string",b:"%[qw]?-",e:"-",c:i,r:10},{cN:"string",b:"%[qw]?\\|",e:"\\|",c:i,r:10}];var h={cN:"function",bWK:true,e:" |$|;",k:"def",c:[{cN:"title",b:j,l:a,k:g},{cN:"params",b:"\\(",e:"\\)",l:a,k:g}].concat(k)};var f=k.concat(b.concat([{cN:"class",bWK:true,e:"$|;",k:"class module",c:[{cN:"title",b:"[A-Za-z_]\\w*(::\\w+)*(\\?|\\!)?",r:0},{cN:"inheritance",b:"<\\s*",c:[{cN:"parent",b:"("+e.IR+"::)?"+e.IR}]}].concat(k)},h,{cN:"constant",b:"(::)?(\\b[A-Z]\\w*(::)?)+",r:0},{cN:"symbol",b:":",c:b.concat([{b:j}]),r:0},{cN:"symbol",b:a+":",r:0},{cN:"number",b:"(\\b0[0-7_]+)|(\\b0x[0-9a-fA-F_]+)|(\\b[1-9][0-9_]*(\\.[0-9_]+)?)|[0_]\\b",r:0},{cN:"number",b:"\\?\\w"},{cN:"variable",b:"(\\$\\W)|((\\$|\\@\\@?)(\\w+))"},{b:"("+e.RSR+")\\s*",c:k.concat([{cN:"regexp",b:"/",e:"/[a-z]*",i:"\\n",c:[e.BE,d]}]),r:0}]));d.c=f;h.c[1].c=f;return{l:a,k:g,c:f}}(hljs);hljs.LANGUAGES.diff=function(a){return{c:[{cN:"chunk",b:"^\\@\\@ +\\-\\d+,\\d+ +\\+\\d+,\\d+ +\\@\\@$",r:10},{cN:"chunk",b:"^\\*\\*\\* +\\d+,\\d+ +\\*\\*\\*\\*$",r:10},{cN:"chunk",b:"^\\-\\-\\- +\\d+,\\d+ +\\-\\-\\-\\-$",r:10},{cN:"header",b:"Index: ",e:"$"},{cN:"header",b:"=====",e:"=====$"},{cN:"header",b:"^\\-\\-\\-",e:"$"},{cN:"header",b:"^\\*{3} ",e:"$"},{cN:"header",b:"^\\+\\+\\+",e:"$"},{cN:"header",b:"\\*{5}",e:"\\*{5}$"},{cN:"addition",b:"^\\+",e:"$"},{cN:"deletion",b:"^\\-",e:"$"},{cN:"change",b:"^\\!",e:"$"}]}}(hljs);hljs.LANGUAGES.javascript=function(a){return{k:{keyword:"in if for while finally var new function do return void else break catch instanceof with throw case default try this switch continue typeof delete let yield const",literal:"true false null undefined NaN Infinity"},c:[a.ASM,a.QSM,a.CLCM,a.CBLCLM,a.CNM,{b:"("+a.RSR+"|\\b(case|return|throw)\\b)\\s*",k:"return throw case",c:[a.CLCM,a.CBLCLM,{cN:"regexp",b:"/",e:"/[gim]*",i:"\\n",c:[{b:"\\\\/"}]},{b:"<",e:">;",sL:"xml"}],r:0},{cN:"function",bWK:true,e:"{",k:"function",c:[{cN:"title",b:"[A-Za-z$_][0-9A-Za-z$_]*"},{cN:"params",b:"\\(",e:"\\)",c:[a.CLCM,a.CBLCLM],i:"[\"'\\(]"}],i:"\\[|%"}]}}(hljs);hljs.LANGUAGES.css=function(a){var b={cN:"function",b:a.IR+"\\(",e:"\\)",c:[a.NM,a.ASM,a.QSM]};return{cI:true,i:"[=/|']",c:[a.CBLCLM,{cN:"id",b:"\\#[A-Za-z0-9_-]+"},{cN:"class",b:"\\.[A-Za-z0-9_-]+",r:0},{cN:"attr_selector",b:"\\[",e:"\\]",i:"$"},{cN:"pseudo",b:":(:)?[a-zA-Z0-9\\_\\-\\+\\(\\)\\\"\\']+"},{cN:"at_rule",b:"@(font-face|page)",l:"[a-z-]+",k:"font-face page"},{cN:"at_rule",b:"@",e:"[{;]",eE:true,k:"import page media charset",c:[b,a.ASM,a.QSM,a.NM]},{cN:"tag",b:a.IR,r:0},{cN:"rules",b:"{",e:"}",i:"[^\\s]",r:0,c:[a.CBLCLM,{cN:"rule",b:"[^\\s]",rB:true,e:";",eW:true,c:[{cN:"attribute",b:"[A-Z\\_\\.\\-]+",e:":",eE:true,i:"[^\\s]",starts:{cN:"value",eW:true,eE:true,c:[b,a.NM,a.QSM,a.ASM,a.CBLCLM,{cN:"hexcolor",b:"\\#[0-9A-F]+"},{cN:"important",b:"!important"}]}}]}]}]}}(hljs);hljs.LANGUAGES.xml=function(a){var c="[A-Za-z0-9\\._:-]+";var b={eW:true,c:[{cN:"attribute",b:c,r:0},{b:'="',rB:true,e:'"',c:[{cN:"value",b:'"',eW:true}]},{b:"='",rB:true,e:"'",c:[{cN:"value",b:"'",eW:true}]},{b:"=",c:[{cN:"value",b:"[^\\s/>]+"}]}]};return{cI:true,c:[{cN:"pi",b:"<\\?",e:"\\?>",r:10},{cN:"doctype",b:"",r:10,c:[{b:"\\[",e:"\\]"}]},{cN:"comment",b:"",r:10},{cN:"cdata",b:"<\\!\\[CDATA\\[",e:"\\]\\]>",r:10},{cN:"tag",b:"",rE:true,sL:"css"}},{cN:"tag",b:"