diff --git a/00_python_in_a_nutshell.ipynb b/00_python_in_a_nutshell.ipynb deleted file mode 100644 index e2172dd..0000000 --- a/00_python_in_a_nutshell.ipynb +++ /dev/null @@ -1,1965 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Chapter 0: Python in a Nutshell" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Python itself is a so-called **general purpose** programming language. That means it does *not* know about any **scientific algorithms** \"out of the box.\"\n", - "\n", - "The purpose of this notebook is to summarize anything that is worthwhile knowing about Python and programming on a \"high level\" and lay the foundation for working with so-called **third-party libraries**, some of which we see in subsequent chapters." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Using Python as a Calculator" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Any computer can always be viewed as some sort of a \"fancy calculator\" and Python is no exception from that. The following code snippet, for example, does exactly what we expect it would, namely *addition*." - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "3" - ] - }, - "execution_count": 1, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "1 + 2" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "In terms of **syntax** (i.e., \"grammatical rules\"), digits are interpreted as plain numbers (i.e., a so-called **numerical literal**) and the `+` symbol consitutes a so-called **operator** that is built into Python.\n", - "\n", - "Other common operators are `-` for *subtraction*, `*` for *multiplication*, and `**` for *exponentiation*. In terms of arithmetic, Python allows the **chaining** of operations and adheres to conventions from math, namely the [PEMDAS rule ](https://en.wikipedia.org/wiki/Order_of_operations#Mnemonics)." - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "45" - ] - }, - "execution_count": 2, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "87 - 42" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "15" - ] - }, - "execution_count": 3, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "3 * 5" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "8" - ] - }, - "execution_count": 4, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "2 ** 3" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "16" - ] - }, - "execution_count": 5, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "2 * 2 ** 3" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To change the **order of precedence**, parentheses may be used for grouping. Syntactically, they are so-called **delimiters** that mark the beginning and the end of a **(sub-)expression** (i.e., a group of symbols that are **evaluated** together)." - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "64" - ] - }, - "execution_count": 6, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "(2 * 2) ** 3" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We must beware that some operators do *not* do what we expect. So, the following code snippet is *not* an example of exponentiation." - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "1" - ] - }, - "execution_count": 7, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "2 ^ 3" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "*Division* is also not as straighforward as we may think!\n", - "\n", - "While the `/` operator does *ordinary division*, we must note the subtlety of the `.0` in the result." - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "4.0" - ] - }, - "execution_count": 8, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "8 / 2" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Whereas both `4` and `4.0` have the *same* **semantic meaning** to us humans, they are two *different* \"things\" for a computer!\n", - "\n", - "Instead of using a single `/`, we may divide with a double `//` just as well." - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "4" - ] - }, - "execution_count": 9, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "8 // 2" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "However, then we must be certain that the result is not a number with decimals other than `.0`. As we can guess from the result below, the `//` operator does *integer division* (i.e., \"whole number\" division)." - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "3" - ] - }, - "execution_count": 10, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "7 // 2" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "On the contrary, the `%` operator implements the so-called *modulo division* (i.e., \"rest\" division). Here, a result of `0` indicates that a number is divisible by another one whereas any result other than `0` shows the opposite." - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "1" - ] - }, - "execution_count": 11, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "7 % 2" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "0" - ] - }, - "execution_count": 12, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "8 % 2" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "What makes Python such an intuitive and thus beginner-friendly language, is the fact that it is a so-called **[interpreted language ](https://en.wikipedia.org/wiki/Interpreter_%28computing%29)**. In layman's terms, this means that we can go back up and *re-execute* any of the code cells in *any order*: That allows us to built up code *incrementally*. So-called **[compiled languages ](https://en.wikipedia.org/wiki/Compiler)**, on the other hand, would require us to run a program in its entirety even if only one small part has been changed.\n", - "\n", - "Instead of running individual code cells \"by hand\" and taking the result as it is, Python offers us the usage of **variables** to store \"values.\" A variable is created with the single `=` symbol, the so-called **assignment statement**." - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": {}, - "outputs": [], - "source": [ - "a = 1" - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "metadata": {}, - "outputs": [], - "source": [ - "b = 2" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "After assignment, we can simply ask Python about the values of `a` and `b`." - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "1" - ] - }, - "execution_count": 15, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "a" - ] - }, - { - "cell_type": "code", - "execution_count": 16, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "2" - ] - }, - "execution_count": 16, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "b" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Similarly, we can use a variable in place of, for example, a numerical literal within an expression." - ] - }, - { - "cell_type": "code", - "execution_count": 17, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "3" - ] - }, - "execution_count": 17, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "a + b" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Also, we may combine several lines of code into a single code cell, adding as many empty lines as we wish to group the code. Then, all of the lines are executed from top to bottom in linear order whenever we execute the cell as a whole." - ] - }, - { - "cell_type": "code", - "execution_count": 18, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "3" - ] - }, - "execution_count": 18, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "a = 1\n", - "b = 2\n", - "\n", - "a + b" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Something that fools many beginners is the fact that the `=` statement is *not* to be confused with the concept of an *equation* from math! An `=` statement is *always* to be interpreted from right to left.\n", - "\n", - "The following code snippet, for example, takes the \"old\" value of `a`, adds the value of `b` to it, and then stores the resulting `3` as the \"new\" value of `a`. After all, a variable is called a variable as its value is indeed variable!" - ] - }, - { - "cell_type": "code", - "execution_count": 19, - "metadata": {}, - "outputs": [], - "source": [ - "a = a + b" - ] - }, - { - "cell_type": "code", - "execution_count": 20, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "3" - ] - }, - "execution_count": 20, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "a" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "In general, the result of some expression involving variables is often stored in yet another variable for further processing. This is how more realistic programs are built up." - ] - }, - { - "cell_type": "code", - "execution_count": 21, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "3" - ] - }, - "execution_count": 21, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "a = 1\n", - "b = 2\n", - "\n", - "c = a + b\n", - "\n", - "c" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "As most real-life projects involve *non-scalar* data, we take a pre-liminary look at how Python models `list`-like data next. Intuitively, a `list` can be thought of as a **container** holding many \"things.\"\n", - "\n", - "The syntax to create a `list` are brackets, `[` and `]`, another example of delimiters, listing the individual **elements** of the `list` in between them, separated by commas.\n", - "\n", - "For example, the next code snippet creates a `list` named `numbers` with the numbers `1`, `2`, `3`, and `4` in it." - ] - }, - { - "cell_type": "code", - "execution_count": 22, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[1, 2, 3, 4]" - ] - }, - "execution_count": 22, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "numbers = [a, b, c, 4]\n", - "\n", - "numbers" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Whenever we use any kind of delimiter, we may break the lines in between them as we wish and add other so-called **whitespace** characters like spaces to format the way the code looks like. So, the following two code cells do *exactly* the same as the previous one, even the `,` after the `4` in the second cell is ignored." - ] - }, - { - "cell_type": "code", - "execution_count": 23, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[1, 2, 3, 4]" - ] - }, - "execution_count": 23, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "numbers = [\n", - " a, b, c, 4\n", - "]\n", - "\n", - "numbers" - ] - }, - { - "cell_type": "code", - "execution_count": 24, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[1, 2, 3, 4]" - ] - }, - "execution_count": 24, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "numbers = [\n", - " a,\n", - " b,\n", - " c,\n", - " 4,\n", - "]\n", - "\n", - "numbers" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "A nice thing to know is that JupyterLab comes with **tab completion** built in. That means we do not have to type out the name `numbers` as a whole. Try it out by simply typing `num` and then hit the tab key on your keyboard. JupyterLab should complete the variable into `numbers`." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "num" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "A natural operation to do with `list`s is to **access** its elements. That is achieved with another operator that also uses a bracket notation. Each element is associated with an **index**, which is why we say that we \"index into a `list`.\" As with many other programming languages, Python is 0-based, which simply means that whenever we count something, we start to count at `0`.\n", - "\n", - "For example, to obtain the first element in `numbers`, we write the following." - ] - }, - { - "cell_type": "code", - "execution_count": 25, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "1" - ] - }, - "execution_count": 25, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "numbers[0]" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Note that the indexing operation implicitly assumes an **order** among the elements, which is quite intuitive as we specified the numbers in order above.\n", - "\n", - "Another implicit assumption behind `list`s is that the number of elements is *finite*. Because of that, we may use negative indices starting at `-1` to obtain an element in right-to-left order.\n", - "\n", - "So, to obtain the last element in `numbers`, we write the following." - ] - }, - { - "cell_type": "code", - "execution_count": 26, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "4" - ] - }, - "execution_count": 26, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "numbers[-1]" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Expressing Logic" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The main point of using `list`s in Python is to write code that does something repeatedly, once for each element in the `list`.\n", - "\n", - "The syntactical construct to achieve that is the `for`-loop, which consists of two parts:\n", - "- a **header** line specifying what is looped over, and\n", - "- a **body** consisting of the block of code that is repeated for each element.\n", - "\n", - "In the example below, `for number in numbers:` constitutes the header. The expression after the `in` references the \"thing\" that is looped over (here: a `list` of `numbers`) and the name between `for` and `in` becomes a variable that is assigned a new value in each **iteration** over of the loop. A best practice is to use a meaingful name, which is why we choose the singular `number`. The `:` at the end is the charactistic symbol of a header line in general and requires the next line (and possibly many more lines) to be **indented**.\n", - "\n", - "The indented line constitues the `for`-loop's body. In the example, we simply take each of the numbers in `numbers`, one at a time, and add it to a `total` that is initialized at `0`. In other words, we calculate the sum of all the elements in `numbers`.\n", - "\n", - "Many beginners struggle with the term \"loop.\" To visualize the looping behavior of this code, we use the online tool [PythonTutor ](http://pythontutor.com/visualize.html#code=numbers%20%3D%20%5B1,%202,%203,%204%5D%0A%0Atotal%20%3D%200%0A%0Afor%20number%20in%20numbers%3A%0A%20%20%20%20total%20%3D%20total%20%2B%20number%0A%0Atotal&cumulative=false&curInstr=0&heapPrimitives=nevernest&mode=display&origin=opt-frontend.js&py=3&rawInputLstJSON=%5B%5D&textReferences=false). That tool is helpful for two reasons:\n", - "1. It allows us to execute code in \"slow motion\" (i.e., by clicking the \"next\" button on the left side, only the next atomic step of the code snippet is executed).\n", - "2. It shows what happens inside the computer's memory on the right-hand side (cf., the \"*Thinking like a Computer*\" section further below)." - ] - }, - { - "cell_type": "code", - "execution_count": 27, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "10" - ] - }, - "execution_count": 27, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "total = 0\n", - "\n", - "for number in numbers:\n", - " total = total + number\n", - "\n", - "total" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Python is pretty agnostic about how far the `for`-loop's body is indented. So, both of the next code cells are equivalent to the one above. Yet, a popular convention in the Python world is to always indent code with 4 spaces per indentation level." - ] - }, - { - "cell_type": "code", - "execution_count": 28, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "10" - ] - }, - "execution_count": 28, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "total = 0\n", - "\n", - "for number in numbers:\n", - " total = total + number\n", - "\n", - "total" - ] - }, - { - "cell_type": "code", - "execution_count": 29, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "10" - ] - }, - "execution_count": 29, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "total = 0\n", - "\n", - "for number in numbers:\n", - " total = total + number\n", - "\n", - "total" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Conditional Execution" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "As a variation, let's add up only the even numbers. To achieve that, we exploit the fact that even numbers are all numbers that are divisible by `2` and use the `%` operator from above and a new one, namely the `==` operator for *equality comparison*, to express that idea." - ] - }, - { - "cell_type": "code", - "execution_count": 30, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "1" - ] - }, - "execution_count": 30, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "7 % 2" - ] - }, - { - "cell_type": "code", - "execution_count": 31, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "0" - ] - }, - "execution_count": 31, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "8 % 2" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Whenever *arithmetic* operators like `%` are combined in an expression with *relational* operators like `==`, the arithmetic is done first and the comparison last. So, the next two cells first obtain the rest after dividing `7` and `8` by `2` and then compare that to `0`. The result is a so-called **boolean**, either `True` or `False`, which is a computer's way of saying \"yes\" or \"no.\"" - ] - }, - { - "cell_type": "code", - "execution_count": 32, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "False" - ] - }, - "execution_count": 32, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "7 % 2 == 0" - ] - }, - { - "cell_type": "code", - "execution_count": 33, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "True" - ] - }, - "execution_count": 33, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "8 % 2 == 0" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We use such kind of expressions as the **condition** in an `if` statement that constitutes a second layer within our `for`-loop implementation. An `if` statement itself consists of yet another header line with a body. That body's code is only executed if the condition is `True`.\n", - "\n", - "As an example, the next code snippet loops over all the elements in `numbers` and, for each individual `number`, checks if it is even. Only if that is the case, the `number` is added to the `total`. Otherwise, nothing is done with the `number`. The example also shows how we can add so-called **comments** at the end of a line: Anything that comes after the `#` symbol is disregarded by Python. We use such comments to put little notes to ourselves within the code." - ] - }, - { - "cell_type": "code", - "execution_count": 34, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "6" - ] - }, - "execution_count": 34, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "total = 0\n", - "\n", - "for number in numbers:\n", - " if number % 2 == 0: # if the number is even\n", - " total = total + number\n", - "\n", - "total" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "`if` statements may have more than one header line: For example, the code in the `else`-clause's body is only executed if the condition in the `if`-clause is `False`. In the code cell below, we calculate the sum of all even numbers and subtract the sum of all odd numbers. The result is `(2 + 4) - (1 + 3)` or `-1 + 2 - 3 + 4` resembling the order of the numbers in the `for`-loop." - ] - }, - { - "cell_type": "code", - "execution_count": 35, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "2" - ] - }, - "execution_count": 35, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "total = 0\n", - "\n", - "for number in numbers:\n", - " if number % 2 == 0: # if the number is even\n", - " total = total + number\n", - " else: # if the number is odd\n", - " total = total - number\n", - "\n", - "total" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Modularizing Code" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "One big idea in software engineering is to **modularize** code. The purpose of that is manyfold. Two very important motivations are to\n", - "- make a code segment **re-usable**, and to\n", - "- give a meaningful name to that code segment.\n", - "\n", - "The latter gets more important as the codebase in a project grows so big that we can only look at a tiny fraction of it at one point in time.\n", - "\n", - "The syntactical construct that enables us to achieve that is that of a **function definition**. Just like in math, we can \"define\" a function to be some set of parametrized instructions that provide some (deterministic) **output** given some *concrete* **input**.\n", - "\n", - "A function is defined with the `def` statement: After the `def` part comes the name of the function followed by the **parameter list** within parentheses. The first couple of lines in the function's body should be a so-called **docstring** that describes what the function does in plain English. Then, comes the code that is to be made repeatable. In the example below, we simply copy & pasted the code to calculate the sum of all even numbers in a `list` into the example function `sum_evens()`. Note that we exchanged the variable name `total` with `result` here to illustrate a point further below. In order for the function to provide back the output to \"the outside world,\" we use the `return` statement (Hint: to see its effect simply re-run the couple of code cells below with and without the `return result` line)." - ] - }, - { - "cell_type": "code", - "execution_count": 36, - "metadata": {}, - "outputs": [], - "source": [ - "def sum_evens(numbers):\n", - " \"\"\"Sum up all the even numbers in a list.\n", - "\n", - " Args:\n", - " numbers (list of int's): numbers to be summed up\n", - "\n", - " Returns:\n", - " total (int)\n", - " \"\"\"\n", - " result = 0\n", - "\n", - " for number in numbers:\n", - " if number % 2 == 0: # if the number is even\n", - " result = result + number\n", - "\n", - " return result" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "After defining a function, we can **call** (i.e., \"execute\") it with the `()` operator. So, just as with the `[]` above, the `()` may have a different meaning in a given context.\n", - "\n", - "Let's execute the function with `numbers` as the input. We see the same `6` below the cell as we do above where we run the code without a function. Without the `return` statement in the function's body, we would not see any output here.\n", - "\n", - "To see what happens in detail, take a look at [PythonTutor ](http://pythontutor.com/visualize.html#code=numbers%20%3D%20%5B1,%202,%203,%204%5D%0A%0Adef%20sum_evens%28numbers%29%3A%0A%20%20%20%20%22%22%22Sum%20up%20all%20the%20even%20numbers%20in%20a%20list.%22%22%22%0A%20%20%20%20result%20%3D%200%0A%0A%20%20%20%20for%20number%20in%20numbers%3A%0A%20%20%20%20%20%20%20%20if%20number%20%25%202%20%3D%3D%200%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20result%20%3D%20result%20%2B%20number%0A%0A%20%20%20%20return%20result%0A%0Atotal%20%3D%20sum_evens%28numbers%29&cumulative=false&curInstr=0&heapPrimitives=nevernest&mode=display&origin=opt-frontend.js&py=3&rawInputLstJSON=%5B%5D&textReferences=false) again. You should notice how there are two variables by the name `numbers` in memory. Python manages the memory with a concept called **namespaces** or **scopes**, which are just fancy terms for saying that Python can tell variables from different contexts apart." - ] - }, - { - "cell_type": "code", - "execution_count": 37, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "6" - ] - }, - "execution_count": 37, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "sum_evens(numbers)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To re-use the *same* instructions with *different* input, we call the function a second time and give it a brand-new `list` of numbers as its input." - ] - }, - { - "cell_type": "code", - "execution_count": 38, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "30" - ] - }, - "execution_count": 38, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "sum_evens([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Note how the variable `result` only exists \"inside\" the `sum_evens()` function. Hence, we see the `NameError` here." - ] - }, - { - "cell_type": "code", - "execution_count": 39, - "metadata": {}, - "outputs": [ - { - "ename": "NameError", - "evalue": "name 'result' is not defined", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", - "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mresult\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", - "\u001b[0;31mNameError\u001b[0m: name 'result' is not defined" - ] - } - ], - "source": [ - "result" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The concept of re-usable functions is so important in programming that Python comes with many [built-in functions ](https://docs.python.org/3/library/functions.html). Two popular examples are the [sum() ](https://docs.python.org/3/library/functions.html#sum) and [len() ](https://docs.python.org/3/library/functions.html#len) functions that calculate the sum or the number of elements in a `list` input." - ] - }, - { - "cell_type": "code", - "execution_count": 40, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "10" - ] - }, - "execution_count": 40, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "sum(numbers)" - ] - }, - { - "cell_type": "code", - "execution_count": 41, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "4" - ] - }, - "execution_count": 41, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "len(numbers)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Another function that comes in handy at times, is the [print() ](https://docs.python.org/3/library/functions.html#print) function that simply \"prints\" out its input to the screen. Below is the popular \"Hello World\" example that is shown in almost any introduction text on any programming language. The double quotes `\"` are yet another delimiter that specifies anything in between them as textual data (cf., the docstring above is just a special case thereof)." - ] - }, - { - "cell_type": "code", - "execution_count": 42, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Hello World\n" - ] - } - ], - "source": [ - "print(\"Hello World\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Single quotes `'` are basically just synonyms for double quotes `\"`." - ] - }, - { - "cell_type": "code", - "execution_count": 43, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Hello World\n" - ] - } - ], - "source": [ - "print('Hello World')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The [print() ](https://docs.python.org/3/library/functions.html#print) function is often helpful to **debug** a code snippet (i.e., trying to figure out what it does, step by step)." - ] - }, - { - "cell_type": "code", - "execution_count": 44, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "The square of 1 is 1\n", - "The square of 2 is 4\n", - "The square of 3 is 9\n", - "The square of 4 is 16\n" - ] - } - ], - "source": [ - "for number in numbers:\n", - " square = number ** 2\n", - " print(\"The square of\", number, \"is\", square)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Extending Core Python" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "In the Python community, we even say that \"Python comes with batteries included,\" meaning that a plain Python installation (like the one you are probably using to execute this notebook) offers all kinds of functionalities for a multitude of application domains. Thus, the name **general purpose** language.\n", - "\n", - "To \"enable\" most of these, however, we need to first **import** them from the so-called [standard library ](https://docs.python.org/3/library/index.html). Let's do a quick example here and look at the [random ](https://docs.python.org/3/library/random.html) module that provides functionalities to simulate and work with random numbers." - ] - }, - { - "cell_type": "code", - "execution_count": 45, - "metadata": {}, - "outputs": [], - "source": [ - "import random" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To access a function inside the [random ](https://docs.python.org/3/library/random.html) module, for example, the [random() ](https://docs.python.org/3/library/random.html#random.random) function, we use the `.` operator, formally called the attribute access operator. The [random() ](https://docs.python.org/3/library/random.html#random.random) function simply returns a random decimal number between `0` and `1`." - ] - }, - { - "cell_type": "code", - "execution_count": 46, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "0.38523914298287465" - ] - }, - "execution_count": 46, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "random.random()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "It could be used, for example, to model a fair coin toss by comparing the number it returns to `0.5` with the `<` operator: In 50% of the cases we see `True` and in the other 50% `False`." - ] - }, - { - "cell_type": "code", - "execution_count": 47, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "False" - ] - }, - "execution_count": 47, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "random.random() < 0.5" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "A second example would be the [choice() ](https://docs.python.org/3/library/random.html#random.choice) function, which draws a random element from a `list` with replacement. We could use it to model a fair die." - ] - }, - { - "cell_type": "code", - "execution_count": 48, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "2" - ] - }, - "execution_count": 48, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "random.choice([1, 2, 3, 4, 5, 6])" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "In the next chapter, we see how we can extend Python even further by installing and importing **third-party packages**." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Thinking like a Computer" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "An important skill for any data scientist is to learn to \"think\" like a computer does. So far, we have seen that Python is a pretty \"intuitive\" language: Many concepts can already be understood after seeing them once or just a couple of times. Many of the aspects that make other languages harder to learn, are somehow \"magically\" automated by Python in the background, most notably the management of the memory.\n", - "\n", - "This section introduces a couple of more \"advanced\" concepts that presumably are *not* so intuitive to beginners." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### \"Simple\" Data Types" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "At first, let's review the concept of **object-orientation**, which is the paradigm by which Python manages the memory.\n", - "\n", - "Take the following three examples. Whereas `a` and `b` have the same **value** (i.e., **semantic meaning**) to us humans, we see in this section that there are a couple of caveats to look out for." - ] - }, - { - "cell_type": "code", - "execution_count": 49, - "metadata": {}, - "outputs": [], - "source": [ - "a = 42\n", - "b = 42.0\n", - "c = 42.87" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "An important idea to understand is that each of the right-hand sides lead to a *new* **object** being created in the computer's memory *first*. An object can be thought of as a \"box\" in memory holding $1$s and $0$s (i.e., physical energy flows inside the computer).\n", - "\n", - "Objects can and do exist without being **referenced** by a variable. Also, an object may even have several variables referencing them, just as a human may have different names in different contexts (e.g., a formal name in the password, a name by which one is known to friends, and maybe a different name by which one is called by one's spouse).\n", - "\n", - "In the example, while both `a` and `b` have the *same* value, they are two *distinct* objects. The `is` operator checks if the objects referenced by two variables are indeed the *same* one, or, in other words, have the same **identity**." - ] - }, - { - "cell_type": "code", - "execution_count": 50, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "True" - ] - }, - "execution_count": 50, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "a == b" - ] - }, - { - "cell_type": "code", - "execution_count": 51, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "False" - ] - }, - "execution_count": 51, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "a is b" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Every object always has some **data type**, which determines how the object behaves and what we can do with it. The types of `a` and `b` are `int` and `float`, respectively." - ] - }, - { - "cell_type": "code", - "execution_count": 52, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "int" - ] - }, - "execution_count": 52, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "type(a)" - ] - }, - { - "cell_type": "code", - "execution_count": 53, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "float" - ] - }, - "execution_count": 53, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "type(b)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "While it seems cumbersome to analyze numbers at this level of detail, the following code cell shows how `float`ing-point numbers, one gold standard of numbers in all of computer science and engineering, behave couter-intutive. Yet, *nothing* is wrong here." - ] - }, - { - "cell_type": "code", - "execution_count": 54, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "False" - ] - }, - "execution_count": 54, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "0.1 + 0.2 == 0.3" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The data type of an object also determines which **methods** we can invoke on it. A method is just a function that is \"attached\" to an object and can be accessed with the `.` operator seen above. A method necessarily needs the objects it is attached to as in input, which is why it is attached to an object to begin with.\n", - "\n", - "For example, `float` objects come with an `.is_integer()` method that tells us if the number has non-`0` decimals." - ] - }, - { - "cell_type": "code", - "execution_count": 55, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "True" - ] - }, - "execution_count": 55, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "b.is_integer()" - ] - }, - { - "cell_type": "code", - "execution_count": 56, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "False" - ] - }, - "execution_count": 56, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "c.is_integer()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "`int` objects on the contrary have no notion of the concept of decimals, which is why they do *not* have an `.is_integer()` method. That is what the `AttributeError` tells us." - ] - }, - { - "cell_type": "code", - "execution_count": 57, - "metadata": {}, - "outputs": [ - { - "ename": "AttributeError", - "evalue": "'int' object has no attribute 'is_integer'", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mAttributeError\u001b[0m Traceback (most recent call last)", - "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0ma\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mis_integer\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", - "\u001b[0;31mAttributeError\u001b[0m: 'int' object has no attribute 'is_integer'" - ] - } - ], - "source": [ - "a.is_integer()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "What we could do here, is to take `a` and pass it to the [float() ](https://docs.python.org/3/library/functions.html#float) built-in, a so-called **constructor**, which takes the value of its input and creates a *new* object of the desired `float` type. Yet, we know the answer to `aa.is_integer()` already, even without executing the code cell as `a` has no non-`0` decimals to begin with." - ] - }, - { - "cell_type": "code", - "execution_count": 58, - "metadata": {}, - "outputs": [], - "source": [ - "aa = float(a)" - ] - }, - { - "cell_type": "code", - "execution_count": 59, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "True" - ] - }, - "execution_count": 59, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "aa.is_integer()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let's create another example `d` to see further examples of methods." - ] - }, - { - "cell_type": "code", - "execution_count": 60, - "metadata": {}, - "outputs": [], - "source": [ - "d = \"Python rocks\"" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The type of `d` is `str`, which is short for \"**string**\" and is defined in computer science as a sequence of characters." - ] - }, - { - "cell_type": "code", - "execution_count": 61, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "str" - ] - }, - "execution_count": 61, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "type(d)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "`str` objects support various methods that \"make sense\" in the context of textual data, for example, the `.lower()` and `.upper()` methods." - ] - }, - { - "cell_type": "code", - "execution_count": 62, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "'python rocks'" - ] - }, - "execution_count": 62, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "d.lower()" - ] - }, - { - "cell_type": "code", - "execution_count": 63, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "'PYTHON ROCKS'" - ] - }, - "execution_count": 63, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "d.upper()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### \"Complex\" Data Types" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The examples in the previous section are considered \"simple\" as they only model *scalar* values (i.e., an individual object per example). However, we have already seen an example of a more \"complex\" object, namely the `list` called `numbers` above." - ] - }, - { - "cell_type": "code", - "execution_count": 64, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "list" - ] - }, - "execution_count": 64, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "type(numbers)" - ] - }, - { - "cell_type": "code", - "execution_count": 65, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[1, 2, 3, 4]" - ] - }, - "execution_count": 65, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "numbers" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "`list` objects also come with specific methods on them, for example, the `.append()` method that adds another element at the end of a `list`." - ] - }, - { - "cell_type": "code", - "execution_count": 66, - "metadata": {}, - "outputs": [], - "source": [ - "numbers.append(5)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Note how the `.append()` method does not lead to any output below the code cell. That is an indication that `numbers` is \"changed in place.\" The formal term for this property is **mutability**. A good working definition is: Any object whose value can be changed *after* its creation, is a **mutable** objects. Objects *without* this property are called **immutable**.\n", - "\n", - "An example for the latter, is the `tuple` data type. `tuple`s are simply `list`s with the additional property that they cannot be changed. Everything is else is the same as for `list`s. `tuple`s are created with parentheses replacing the brackets." - ] - }, - { - "cell_type": "code", - "execution_count": 67, - "metadata": {}, - "outputs": [], - "source": [ - "more_numbers = (7, 8, 9)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "`more_numbers` does not know about the `.append()` method." - ] - }, - { - "cell_type": "code", - "execution_count": 68, - "metadata": {}, - "outputs": [ - { - "ename": "AttributeError", - "evalue": "'tuple' object has no attribute 'append'", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mAttributeError\u001b[0m Traceback (most recent call last)", - "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mmore_numbers\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mappend\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m10\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", - "\u001b[0;31mAttributeError\u001b[0m: 'tuple' object has no attribute 'append'" - ] - } - ], - "source": [ - "more_numbers.append(10)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Whereas both `list` and `tuple` objects perserve the **order** of their elements, the `set` data type does not. Additionally, any object may only be an element of a `set` at most once. The syntax to create `set`s are curly braces, `{` and `}`. By giving up order, `set` objects offer significantly increased processing speed in various situations." - ] - }, - { - "cell_type": "code", - "execution_count": 69, - "metadata": {}, - "outputs": [], - "source": [ - "other_numbers = {3, 3, 3, 2, 2, 1}" - ] - }, - { - "cell_type": "code", - "execution_count": 70, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "{1, 2, 3}" - ] - }, - "execution_count": 70, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "other_numbers" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "One last example of a \"complex\" data type is the `dict`ionary type, which models a mapping relationship among the objects it contains. The syntax to create `dict`s also involves curly braces with the additon of using a `:` to specify the mapping relationships.\n", - "\n", - "For example, to map `int`egers to `str`ings modeling the English words corresponding to the numbers, we could write the following. The objects to the left of the `:` take the role of the **keys** while the ones to the right take the role of the **values**." - ] - }, - { - "cell_type": "code", - "execution_count": 71, - "metadata": {}, - "outputs": [], - "source": [ - "to_words = {\n", - " 0: \"zero\",\n", - " 1: \"one\",\n", - " 2: \"two\",\n", - "}" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The main purpose of `dict`s is to look up the value mapped to by some key. We can use the indexing notion to achieve that." - ] - }, - { - "cell_type": "code", - "execution_count": 72, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "'zero'" - ] - }, - "execution_count": 72, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "to_words[0]" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "`dict`s are among the most optimized data type in the Python world and a major building block in codebases solving real-life problems." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "A big factor in getting good at any programming language is to learn what data types to use in which situations. There is no \"best\" data type; choosing among a couple of data types always comes down to trade-offs." - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.8.9" - }, - "toc": { - "base_numbering": 1, - "nav_menu": {}, - "number_sections": false, - "sideBar": true, - "skip_h1_title": false, - "title_cell": "Table of Contents", - "title_sidebar": "Contents", - "toc_cell": false, - "toc_position": {}, - "toc_section_display": true, - "toc_window_display": false - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} diff --git a/00_python_in_a_nutshell/00_content_arithmetic.ipynb b/00_python_in_a_nutshell/00_content_arithmetic.ipynb new file mode 100644 index 0000000..3a27936 --- /dev/null +++ b/00_python_in_a_nutshell/00_content_arithmetic.ipynb @@ -0,0 +1,571 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Note**: Click on \"*Kernel*\" > \"*Restart Kernel and Clear All Outputs*\" in [JupyterLab](https://jupyterlab.readthedocs.io/en/stable/) *before* reading this notebook to reset its output. If you cannot run this file on your machine, you may want to open it [in the cloud ](https://mybinder.org/v2/gh/webartifex/intro-to-data-science/main?urlpath=lab/tree/00_python_in_a_nutshell/00_content_arithmetic.ipynb)." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Chapter 0: Python in a Nutshell (Part 1)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Python itself is a so-called **general purpose** programming language. That means it does *not* know about any **scientific algorithms** \"out of the box.\"\n", + "\n", + "The purpose of this notebook is to summarize anything that is worthwhile knowing about Python and programming on a \"high level\" and lay the foundation for working with so-called **third-party libraries**, some of which we see in subsequent chapters." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Basic Arithmetic" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Any computer can always be viewed as some sort of a \"fancy calculator\" and Python is no exception from that. The following code snippet, for example, does exactly what we expect it would, namely *addition*." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "3" + ] + }, + "execution_count": 1, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "1 + 2" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In terms of **syntax** (i.e., \"grammatical rules\"), digits are interpreted as plain numbers (i.e., a so-called **numerical literal**) and the `+` symbol consitutes a so-called **operator** that is built into Python.\n", + "\n", + "Other common operators are `-` for *subtraction*, `*` for *multiplication*, and `**` for *exponentiation*. In terms of arithmetic, Python allows the **chaining** of operations and adheres to conventions from math, namely the [PEMDAS rule ](https://en.wikipedia.org/wiki/Order_of_operations#Mnemonics)." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "45" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "87 - 42" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "15" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "3 * 5" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "8" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "2 ** 3" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "16" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "2 * 2 ** 3" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To change the **order of precedence**, parentheses may be used for grouping. Syntactically, they are so-called **delimiters** that mark the beginning and the end of a **(sub-)expression** (i.e., a group of symbols that are **evaluated** together)." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "64" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "(2 * 2) ** 3" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We must beware that some operators do *not* do what we expect. So, the following code snippet is *not* an example of exponentiation." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "1" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "2 ^ 3" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "*Division* is also not as straighforward as we may think!\n", + "\n", + "While the `/` operator does *ordinary division*, we must note the subtlety of the `.0` in the result." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "4.0" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "8 / 2" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Whereas both `4` and `4.0` have the *same* **semantic meaning** to us humans, they are two *different* \"things\" for a computer!\n", + "\n", + "Instead of using a single `/`, we may divide with a double `//` just as well." + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "4" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "8 // 2" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "However, then we must be certain that the result is not a number with decimals other than `.0`. As we can guess from the result below, the `//` operator does *integer division* (i.e., \"whole number\" division)." + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "3" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "7 // 2" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "On the contrary, the `%` operator implements the so-called *modulo division* (i.e., \"rest\" division). Here, a result of `0` indicates that a number is divisible by another one whereas any result other than `0` shows the opposite." + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "1" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "7 % 2" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "0" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "8 % 2" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "What makes Python such an intuitive and thus beginner-friendly language, is the fact that it is a so-called **[interpreted language ](https://en.wikipedia.org/wiki/Interpreter_%28computing%29)**. In layman's terms, this means that we can go back up and *re-execute* any of the code cells in *any order*: That allows us to built up code *incrementally*. So-called **[compiled languages ](https://en.wikipedia.org/wiki/Compiler)**, on the other hand, would require us to run a program in its entirety even if only one small part has been changed.\n", + "\n", + "Instead of running individual code cells \"by hand\" and taking the result as it is, Python offers us the usage of **variables** to store \"values.\" A variable is created with the single `=` symbol, the so-called **assignment statement**." + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [], + "source": [ + "a = 1" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [], + "source": [ + "b = 2" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "After assignment, we can simply ask Python about the values of `a` and `b`." + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "1" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "a" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "2" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "b" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Similarly, we can use a variable in place of, for example, a numerical literal within an expression." + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "3" + ] + }, + "execution_count": 17, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "a + b" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Also, we may combine several lines of code into a single code cell, adding as many empty lines as we wish to group the code. Then, all of the lines are executed from top to bottom in linear order whenever we execute the cell as a whole." + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "3" + ] + }, + "execution_count": 18, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "a = 1\n", + "b = 2\n", + "\n", + "a + b" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Something that fools many beginners is the fact that the `=` statement is *not* to be confused with the concept of an *equation* from math! An `=` statement is *always* to be interpreted from right to left.\n", + "\n", + "The following code snippet, for example, takes the \"old\" value of `a`, adds the value of `b` to it, and then stores the resulting `3` as the \"new\" value of `a`. After all, a variable is called a variable as its value is indeed variable!" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": {}, + "outputs": [], + "source": [ + "a = a + b" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "3" + ] + }, + "execution_count": 20, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "a" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In general, the result of some expression involving variables is often stored in yet another variable for further processing. This is how more realistic programs are built up." + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "3" + ] + }, + "execution_count": 21, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "a = 1\n", + "b = 2\n", + "\n", + "c = a + b\n", + "\n", + "c" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.12" + }, + "toc": { + "base_numbering": 1, + "nav_menu": {}, + "number_sections": false, + "sideBar": true, + "skip_h1_title": false, + "title_cell": "Table of Contents", + "title_sidebar": "Contents", + "toc_cell": false, + "toc_position": {}, + "toc_section_display": true, + "toc_window_display": false + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/00_python_in_a_nutshell/01_exercises_calculator.ipynb b/00_python_in_a_nutshell/01_exercises_calculator.ipynb new file mode 100644 index 0000000..758aa47 --- /dev/null +++ b/00_python_in_a_nutshell/01_exercises_calculator.ipynb @@ -0,0 +1,184 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Note**: Click on \"*Kernel*\" > \"*Restart Kernel and Run All*\" in [JupyterLab](https://jupyterlab.readthedocs.io/en/stable/) *after* finishing the exercises to ensure that your solution runs top to bottom *without* any errors. If you cannot run this file on your machine, you may want to open it [in the cloud ](https://mybinder.org/v2/gh/webartifex/intro-to-data-science/main?urlpath=lab/tree/00_python_in_a_nutshell/01_exercises_calculator.ipynb)." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Chapter 0: Python in a Nutshell (Coding Exercises)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The exercises below assume that you have read the preceeding content sections.\n", + "\n", + "The `...`'s in the code cells indicate where you need to fill in code snippets. The number of `...`'s within a code cell give you a rough idea of how many lines of code are needed to solve the task. You should not need to create any additional code cells for your final solution. However, you may want to use temporary code cells to try out some ideas." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Python as a Calculator" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The [volume of a sphere ](https://en.wikipedia.org/wiki/Sphere) is defined as $\\frac{4}{3} * \\pi * r^3$.\n", + "\n", + "**Q1**: Calculate it for `r = 2.88` and approximate $\\pi$ with `pi = 3.14`!" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "pi = 3.14\n", + "r = 2.88" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "..." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "While Python may be used as a calculator, it behaves a bit differently compared to calculator apps that phones or computers come with and that we are accustomed to.\n", + "\n", + "A major difference is that Python \"forgets\" intermediate results that are not assigned to variables. On the contrary, the calculators we work with outside of programming always keep the last result and allow us to use it as the first input for the next calculation.\n", + "\n", + "One way to keep on working with intermediate results in Python is to write the entire calculation as just *one* big expression that is composed of many sub-expressions representing the individual steps in our overall calculation.\n", + "\n", + "**Q2.1**: Given `a` and `b` like below, subtract the smaller `a` from the larger `b`, divide the difference by `9`, and raise the result to the power of `2`! Use operators that preserve the `int` type of the final result! The entire calculations *must* be placed within *one* code cell.\n", + "\n", + "Hint: You may need to group sub-expressions with parentheses `(` and `)`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "a = 42\n", + "b = 87" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "..." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The code cell below contains nothing but a single underscore `_`. In both, a Python command-line prompt and Jupyter notebooks, the variable `_` is automatically updated and always references the object to which the *last* expression executed evaluated to.\n", + "\n", + "**Q2.2**: Execute the code cell below! It should evaluate to the *same* result as the previous code cell (i.e., your answer to **Q2.1** assuming you go through this notebook in order)." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "_" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q2.3**: Implement the same overall calculation as in your answer to **Q2.1** in several independent steps (i.e., code cells)! Use only *one* operator per code cell!\n", + "\n", + "Hint: You should need *two* more code cells after the `b - a` one immediately below. If you *need* to use parentheses, you must be doing something wrong." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "b - a" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "_ ..." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "_ ..." + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.12" + }, + "toc": { + "base_numbering": 1, + "nav_menu": {}, + "number_sections": false, + "sideBar": true, + "skip_h1_title": true, + "title_cell": "Table of Contents", + "title_sidebar": "Contents", + "toc_cell": false, + "toc_position": {}, + "toc_section_display": false, + "toc_window_display": false + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/00_python_in_a_nutshell/02_content_logic.ipynb b/00_python_in_a_nutshell/02_content_logic.ipynb new file mode 100644 index 0000000..c40c754 --- /dev/null +++ b/00_python_in_a_nutshell/02_content_logic.ipynb @@ -0,0 +1,1034 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Note**: Click on \"*Kernel*\" > \"*Restart Kernel and Clear All Outputs*\" in [JupyterLab](https://jupyterlab.readthedocs.io/en/stable/) *before* reading this notebook to reset its output. If you cannot run this file on your machine, you may want to open it [in the cloud ](https://mybinder.org/v2/gh/webartifex/intro-to-data-science/main?urlpath=lab/tree/00_python_in_a_nutshell/02_content_logic.ipynb)." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Chapter 0: Python in a Nutshell (Part 2)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In the previous section, we only looked at **scalars** (i.e., a variable referencing one number at a time). However, that is not the only kind of data a computer can hold in its memory. In the section below, we look at how computers process many numbers in a generic fashion." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Non-Scalar Data" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "As most real-life projects involve *non-scalar* data, we take a pre-liminary look at how Python models `list`-like data next. Intuitively, a `list` can be thought of as a **container** holding many \"things.\"\n", + "\n", + "The syntax to create a `list` are brackets, `[` and `]`, another example of delimiters, listing the individual **elements** of the `list` in between them, separated by commas.\n", + "\n", + "For example, the next code snippet creates a `list` named `numbers` with the numbers `1`, `2`, `3`, `4`, and `5` in it." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[1, 2, 3, 4, 5]" + ] + }, + "execution_count": 1, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "numbers = [1, 2, 3, 4, 5]\n", + "\n", + "numbers" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Whenever we use any kind of delimiter, we may break the lines in between them as we wish and add other so-called **whitespace** characters like spaces to format the way the code looks like. So, the following two code cells do *exactly* the same as the previous one, even the `,` after the `5` in the second cell is ignored." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[1, 2, 3, 4, 5]" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "numbers = [\n", + " 1, 2, 3, 4, 5\n", + "]\n", + "\n", + "numbers" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[1, 2, 3, 4, 5]" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "numbers = [\n", + " 1,\n", + " 2,\n", + " 3,\n", + " 4,\n", + " 5,\n", + "]\n", + "\n", + "numbers" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "A nice thing to know is that JupyterLab comes with **tab completion** built in. That means we do not have to type out the name `numbers` as a whole. Try it out by simply typing `num` and then hit the tab key on your keyboard. JupyterLab should complete the variable into `numbers`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "num" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Indexing & Slicing" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "A natural operation to do with `list`s is to **access** its elements. That is achieved with another operator that also uses a bracket notation. Each element is associated with an **index**, which is why we say that we \"index into a `list`.\" As with many other programming languages, Python is 0-based, which simply means that whenever we count something, we start to count at `0`.\n", + "\n", + "For example, to obtain the first element in `numbers`, we write the following." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "1" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "numbers[0]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Note that the indexing operation implicitly assumes an **order** among the elements, which is quite intuitive as we specified the numbers in order above.\n", + "\n", + "Another implicit assumption behind `list`s is that the number of elements is *finite*. Because of that, we may use negative indices starting at `-1` to obtain an element in right-to-left order.\n", + "\n", + "So, to obtain the last element in `numbers`, we write the following." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "5" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "numbers[-1]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "`list` objects are **mutable**: We may change *parts* of them *after* they are created. That behavior is *not* a given for many other **types** of objects.\n", + "\n", + "For example, to exchange the first and the last element in `numbers`, we assign new objects to an index." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [], + "source": [ + "numbers[0] = 5" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [], + "source": [ + "numbers[4] = 1" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[5, 2, 3, 4, 1]" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "numbers" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To \"flip\" the value of two variables or indexes, we may also use the following notation." + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [], + "source": [ + "numbers[0], numbers[4] = numbers[4], numbers[0]" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[1, 2, 3, 4, 5]" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "numbers" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "As a generalization, we may also **slice** out some elements in the `list`. That is done with the `[...]` notation as well. Yet, instead of a single integer index, we now provide a *start* and a *stop* index separated by a `:`. While the element corresponding to the *start* index is included, this is not the case for *stop*.\n", + "\n", + "For example, to slice out the middle three elements, we write the following." + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[2, 3, 4]" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "numbers[1:4]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We may combine positive and negative indexes.\n", + "\n", + "So, the following yields the same result." + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[2, 3, 4]" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "numbers[1:-1]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "While ommitting the *start* index makes a slice begin at the first element, ..." + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[1, 2, 3, 4]" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "numbers[:-1]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "... leaving out the *stop* index makes a slice go to the last element." + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[2, 3, 4, 5]" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "numbers[1:]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Providing a third integer as the *step* value after another `:` makes a slice skip some elements.\n", + "\n", + "For example, `[1:-1:2]` means \"go from the second element (including) to the last element (excluding) and take every second element\" ..." + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[2, 4]" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "numbers[1:-1:2]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "... while `[::2]` simply downsamples the `list` by taking every other element." + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[1, 3, 5]" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "numbers[::2]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Expressing Business Logic" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The main point of using `list`s in Python is to write code that does \"something\" for each element in the `list`, which may hold big amounts of data. Expressing the logic of a problem from the real world in code, the \"something\" part, is subsumed by the term [business logic ](https://en.wikipedia.org/wiki/Business_logic), which has *nothing* to do with businesses that make money.\n", + "\n", + "There are two aspects to business logic:\n", + "1. Execute some lines of code many times, and\n", + "2. execute some lines of code only if a certain **condition** applies.\n", + "\n", + "Both of these aspects come in many variants and may be combined in basically any arbitrary fashion." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Iterative Execution" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Iteration** is the generic idea of executing code repeatedly. Most programming languages provide dedicated constructs to achieve that. In Python, the easiest such construct is the so-called `for`-loop." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### The `for` Loop" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "A `for`-loop consists of two parts:\n", + "- a **header** line specifying what is looped over, and\n", + "- a **body** consisting of the **block of code** that is repeated for each element.\n", + "\n", + "In the example below, `for number in numbers:` constitutes the header. The expression after the `in` references the \"thing\" that is looped over (here: a `list` of `numbers`) and the name between `for` and `in` becomes a variable that is assigned a new value in each **iteration** over of the loop. A best practice is to use a meaingful name, which is why we choose the singular `number`. The `:` at the end is the charactistic symbol of a header line in general and requires the next line (and possibly many more lines) to be **indented**.\n", + "\n", + "The indented line constitues the `for`-loop's body. In the example, we simply take each of the numbers in `numbers`, one at a time, and add it to a `total` that is initialized at `0`. In other words, we calculate the sum of all the elements in `numbers`.\n", + "\n", + "Many beginners struggle with the term \"loop.\" To visualize the looping behavior of this code, we use the online tool [PythonTutor ](http://pythontutor.com/visualize.html#code=numbers%20%3D%20%5B1,%202,%203,%204%5D%0A%0Atotal%20%3D%200%0A%0Afor%20number%20in%20numbers%3A%0A%20%20%20%20total%20%3D%20total%20%2B%20number%0A%0Atotal&cumulative=false&curInstr=0&heapPrimitives=nevernest&mode=display&origin=opt-frontend.js&py=3&rawInputLstJSON=%5B%5D&textReferences=false). That tool is helpful for two reasons:\n", + "1. It allows us to execute code in \"slow motion\" (i.e., by clicking the \"next\" button on the left side, only the next atomic step of the code snippet is executed).\n", + "2. It shows what happens inside the computer's memory on the right-hand side." + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "15" + ] + }, + "execution_count": 17, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "total = 0\n", + "\n", + "for number in numbers:\n", + " total = total + number\n", + "\n", + "total" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Python is pretty agnostic about how far the `for`-loop's body is indented. So, both of the next code cells are equivalent to the one above. Yet, a popular convention in the Python world is to always indent code with 4 spaces per indentation level." + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "15" + ] + }, + "execution_count": 18, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "total = 0\n", + "\n", + "for number in numbers:\n", + " total = total + number\n", + "\n", + "total" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "15" + ] + }, + "execution_count": 19, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "total = 0\n", + "\n", + "for number in numbers:\n", + " total = total + number\n", + "\n", + "total" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Conditional Execution" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "As a variation, let's add up only the even numbers. To achieve that, we exploit the fact that even numbers are all numbers that are divisible by `2` and use the `%` operator from before and a new one, namely the `==` operator for *equality comparison*, to express that idea." + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "1" + ] + }, + "execution_count": 20, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "7 % 2" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "0" + ] + }, + "execution_count": 21, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "8 % 2" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Whenever *arithmetic* operators like `%` are combined with *relational* operators like `==`, the arithmetic ones are evaluated first. So, in the two cells below, we first obtain the rest after dividing `7` and `8` by `2` and then compare that to `0`. The result is a so-called **boolean**, either `True` or `False`, which is a computer's way of saying \"yes\" or \"no.\"" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "False" + ] + }, + "execution_count": 22, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "7 % 2 == 0" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 23, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "8 % 2 == 0" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Other relational operators are `!=` to test inequality and `<`, `<=`, `>`, and `>=` to check wether the left or right side is smaller or larger." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### The `if` Statement" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We use such kind of expressions as the **condition** in an `if` statement that constitutes a second layer within our `for`-loop implementation. An `if` statement itself consists of yet another header line with a body. That body's code is only executed if the condition is `True`.\n", + "\n", + "As an example, the next code snippet loops over all the elements in `numbers` and, for each individual `number`, checks if it is even. Only if that is the case, the `number` is added to the `total`. Otherwise, nothing is done with the `number`. The example also shows how we can add so-called **comments** at the end of a line: Anything that comes after the `#` symbol is disregarded by Python. We use such comments to put little notes to ourselves within the code." + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "6" + ] + }, + "execution_count": 24, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "total = 0\n", + "\n", + "for number in numbers:\n", + " if number % 2 == 0: # if the number is even\n", + " total = total + number\n", + "\n", + "total" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### The `else` Clause" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "`if` statements may have more than one header line: For example, the code in the `else`-clause's body is only executed if the condition in the `if`-clause is `False`. In the code cell below, we calculate the sum of all even numbers and subtract the sum of all odd numbers. The result is `(2 + 4) - (1 + 3 + 5)`, or `-1 + 2 - 3 + 4 - 5` resembling the order of the numbers in the `for`-loop." + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "-3" + ] + }, + "execution_count": 25, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "total = 0\n", + "\n", + "for number in numbers:\n", + " if number % 2 == 0: # if the number is even\n", + " total = total + number\n", + " else: # if the number is odd\n", + " total = total - number\n", + "\n", + "total" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "A **function** (cf., the \"*Built-in Functions*\" section further below) that comes in handy with `for`-loops is [print() ](https://docs.python.org/3/library/functions.html#print), which simply \"prints\" out (i.e., \"shows on the screen\") whatever **input** we give it.\n", + "\n", + "In the example next, we loop over the numbers from `1` to `10` and print out either half a `number` or three times a `number` plus 1 depending on the `number` being even or odd." + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "4\n", + "1\n", + "10\n", + "2\n", + "16\n", + "3\n", + "22\n", + "4\n", + "28\n", + "5\n" + ] + } + ], + "source": [ + "for number in [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]:\n", + " if number % 2 == 0:\n", + " print(number // 2)\n", + " else:\n", + " print(3 * number + 1)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To save ourselves writing out all the numbers, we may also use the [range() ](https://docs.python.org/3/library/functions.html#func-range) built-in, which, in the example, takes two inputs separated by comma: A `start` number that is included and a `stop` number that is *not* included." + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "4\n", + "1\n", + "10\n", + "2\n", + "16\n", + "3\n", + "22\n", + "4\n", + "28\n", + "5\n" + ] + } + ], + "source": [ + "for number in range(1, 11):\n", + " if number % 2 == 0:\n", + " print(number // 2)\n", + " else:\n", + " print(3 * number + 1)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### The `elif` Clause" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If we need to check for *several* **alternatives** (i.e., different conditions), we may add an arbitrary number of `elif`-clauses to an `if` statement.\n", + "\n", + "In the next example, we print out messages indicating the *largest* whole number by which a `number` may be divided.\n", + "\n", + "Note that [print() ](https://docs.python.org/3/library/functions.html#print) may take several inputs as well. The `\"...\"` notation is Python's way of modeling **textual data**." + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1 is divisible by neither 2 nor 3\n", + "2 is divisible by 2\n", + "3 is divisible by 3\n", + "4 is divisible by 2\n", + "5 is divisible by neither 2 nor 3\n", + "6 is divisible by 2\n", + "7 is divisible by neither 2 nor 3\n", + "8 is divisible by 2\n", + "9 is divisible by 3\n", + "10 is divisible by 2\n" + ] + } + ], + "source": [ + "for number in range(1, 11):\n", + " if number % 2 == 0:\n", + " print(number, \"is divisible by 2\")\n", + " elif number % 3 == 0:\n", + " print(number, \"is divisible by 3\")\n", + " else:\n", + " print(number, \"is divisible by neither 2 nor 3\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "It is noteworthy that only the *first* block of code whose condition is `True` is executed!\n", + "\n", + "So, we must be careful not to make any logical errors: In the example below, we *never* reach the alternative where the `number` is divisible by `4` because whenever a `number` is divisible by `4` it is also always divisible by `2` as well." + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1 is divisible by neither 2, 3, nor 4\n", + "2 is divisible by 2\n", + "3 is divisible by 3\n", + "4 is divisible by 2\n", + "5 is divisible by neither 2, 3, nor 4\n", + "6 is divisible by 2\n", + "7 is divisible by neither 2, 3, nor 4\n", + "8 is divisible by 2\n", + "9 is divisible by 3\n", + "10 is divisible by 2\n" + ] + } + ], + "source": [ + "for number in range(1, 11):\n", + " if number % 2 == 0:\n", + " print(number, \"is divisible by 2\")\n", + " elif number % 3 == 0:\n", + " print(number, \"is divisible by 3\")\n", + " elif number % 4 == 0:\n", + " print(number, \"is divisible by 4\")\n", + " else:\n", + " print(number, \"is divisible by neither 2, 3, nor 4\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "By re-arranging the order of the `if`- and `elif`- clauses, we obtain the correct output." + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1 is divisible by neither 2, 3, nor 4\n", + "2 is divisible by 2\n", + "3 is divisible by 3\n", + "4 is divisible by 4\n", + "5 is divisible by neither 2, 3, nor 4\n", + "6 is divisible by 3\n", + "7 is divisible by neither 2, 3, nor 4\n", + "8 is divisible by 4\n", + "9 is divisible by 3\n", + "10 is divisible by 2\n" + ] + } + ], + "source": [ + "for number in range(1, 11):\n", + " if number % 4 == 0:\n", + " print(number, \"is divisible by 4\")\n", + " elif number % 3 == 0:\n", + " print(number, \"is divisible by 3\")\n", + " elif number % 2 == 0:\n", + " print(number, \"is divisible by 2\")\n", + " else:\n", + " print(number, \"is divisible by neither 2, 3, nor 4\")" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.12" + }, + "toc": { + "base_numbering": 1, + "nav_menu": {}, + "number_sections": false, + "sideBar": true, + "skip_h1_title": false, + "title_cell": "Table of Contents", + "title_sidebar": "Contents", + "toc_cell": false, + "toc_position": {}, + "toc_section_display": true, + "toc_window_display": false + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/00_python_in_a_nutshell/03_exercises_loops.ipynb b/00_python_in_a_nutshell/03_exercises_loops.ipynb new file mode 100644 index 0000000..58fc7ad --- /dev/null +++ b/00_python_in_a_nutshell/03_exercises_loops.ipynb @@ -0,0 +1,213 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Note**: Click on \"*Kernel*\" > \"*Restart Kernel and Run All*\" in [JupyterLab](https://jupyterlab.readthedocs.io/en/stable/) *after* finishing the exercises to ensure that your solution runs top to bottom *without* any errors. If you cannot run this file on your machine, you may want to open it [in the cloud ](https://mybinder.org/v2/gh/webartifex/intro-to-data-science/main?urlpath=lab/tree/00_python_in_a_nutshell/03_exercises_loops.ipynb)." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Chapter 0: Python in a Nutshell (Coding Exercises)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The exercises below assume that you have read the preceeding content sections.\n", + "\n", + "The `...`'s in the code cells indicate where you need to fill in code snippets. The number of `...`'s within a code cell give you a rough idea of how many lines of code are needed to solve the task. You should not need to create any additional code cells for your final solution. However, you may want to use temporary code cells to try out some ideas." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Simple Loops" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "`for`-loops are extremely versatile in Python. That is different from many other programming languages.\n", + "\n", + "Let's create a `list` holding the numbers from `1` to `12` in an unordered fashion, like `numbers` below, loop over the numbers on a one-by-one basis, and implement simple **filter** logics." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "numbers = [7, 11, 8, 5, 3, 12, 2, 6, 9, 10, 1, 4]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q1**: Fill in the *condition* in the `if` statement such that only numbers divisible by `3` are printed!" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "for number in numbers:\n", + " if ...:\n", + " print(...)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "An easy way to loop over a `list` in a sorted manner, is to wrap it with the built-in [sorted() ](https://docs.python.org/3/library/functions.html#sorted) function.\n", + "\n", + "**Q2**: Fill in the condition of the `if` statement such that only odd numbers are printed out!" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "for number in sorted(numbers):\n", + " if ...:\n", + " print(...)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Whenever we want to loop over numbers representing a [series ](https://en.wikipedia.org/wiki/Series_%28mathematics%29) in the mathematical sense (i.e., a rule to calculate the next number from its predecessor), we may be able to use the [range() ](https://docs.python.org/3/library/functions.html#func-range) built-in.\n", + "\n", + "For example, to loop over the whole numbers from `0` to `9` (both including) in order, we could write them out in a `list` like in the following task.\n", + "\n", + "**Q3**: Fill in the call to the [print() ](https://docs.python.org/3/library/functions.html#print) function such that the squares of the `numbers` are printed out!" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "for number in [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]:\n", + " print(...)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q4**: Read the documentation on the [range() ](https://docs.python.org/3/library/functions.html#func-range) built-in! It may be used with either one, two, or three inputs. What do `start`, `stop`, and `step` mean? Fill in the calls to [range() ](https://docs.python.org/3/library/functions.html#func-range) and [print() ](https://docs.python.org/3/library/functions.html#print) to mimic the output of **Q3**!" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "for number in range(...):\n", + " print(...)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q5**: Fill in the calls to [range() ](https://docs.python.org/3/library/functions.html#func-range) and [print() ](https://docs.python.org/3/library/functions.html#print) to print out *all* numbers from `1` to `10` (both including)!" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "for number in range(...):\n", + " print(...)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q6**: Fill in the calls to [range() ](https://docs.python.org/3/library/functions.html#func-range) and [print() ](https://docs.python.org/3/library/functions.html#print) to print out the *even* numbers from `1` to `10` (both including)! Do *not* use an `if` statement to accomplish this!" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "for number in range(...):\n", + " print(...)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q7**: Fill in the calls to [range() ](https://docs.python.org/3/library/functions.html#func-range) and [print() ](https://docs.python.org/3/library/functions.html#print) to print out the *odd* numbers from `10` to `1` (both including) going backwards!" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "for number in range(...):\n", + " print(...)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.12" + }, + "toc": { + "base_numbering": 1, + "nav_menu": {}, + "number_sections": false, + "sideBar": true, + "skip_h1_title": true, + "title_cell": "Table of Contents", + "title_sidebar": "Contents", + "toc_cell": false, + "toc_position": {}, + "toc_section_display": false, + "toc_window_display": false + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/00_python_in_a_nutshell/04_exercises_fizz_buzz.ipynb b/00_python_in_a_nutshell/04_exercises_fizz_buzz.ipynb new file mode 100644 index 0000000..57df84f --- /dev/null +++ b/00_python_in_a_nutshell/04_exercises_fizz_buzz.ipynb @@ -0,0 +1,147 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Note**: Click on \"*Kernel*\" > \"*Restart Kernel and Run All*\" in [JupyterLab](https://jupyterlab.readthedocs.io/en/stable/) *after* finishing the exercises to ensure that your solution runs top to bottom *without* any errors. If you cannot run this file on your machine, you may want to open it [in the cloud ](https://mybinder.org/v2/gh/webartifex/intro-to-data-science/main?urlpath=lab/tree/00_python_in_a_nutshell/04_exercises_fizz_buzz.ipynb)." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Chapter 0: Python in a Nutshell (Coding Exercises)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The exercises below assume that you have read the preceeding content sections.\n", + "\n", + "The `...`'s in the code cells indicate where you need to fill in code snippets. The number of `...`'s within a code cell give you a rough idea of how many lines of code are needed to solve the task. You should not need to create any additional code cells for your final solution. However, you may want to use temporary code cells to try out some ideas." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Fizz Buzz" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The kids game [Fizz Buzz ](https://en.wikipedia.org/wiki/Fizz_buzz) is said to be often used in job interviews for entry-level positions. However, opinions vary as to how good of a test it is (cf., [source ](https://news.ycombinator.com/item?id=16446774)).\n", + "\n", + "In its simplest form, a group of people starts counting upwards in an alternating fashion. Whenever a number is divisible by $3$, the person must say \"Fizz\" instead of the number. The same holds for numbers divisible by $5$ when the person must say \"Buzz.\" If a number is divisible by both numbers, one must say \"FizzBuzz.\" Probably, this game would also make a good drinking game with the \"right\" beverages." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q1**: Complete the code cell below implementing the Fizz Buzz game with some `if`-`elif`-`else` logic according to the rules above for the numbers from `1` to `33`! The cell should simply print out either the numbers or the words \"Fizz,\" \"Buzz,\" or \"FizzBuzz.\"\n", + "\n", + "Hints:\n", + "- The *order* of the **conditions** is important\n", + "- By what single number can all numbers divisible by both `3` and `5` by divided by?" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "for number in range(...):\n", + " ...\n", + " ...\n", + " ...\n", + " ...\n", + " ...\n", + " ...\n", + " ...\n", + " ..." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q2.1**: Re-write your solution from **Q1** such that the [print() ](https://docs.python.org/3/library/functions.html#print) function is executed only once!\n", + "\n", + "Hints:\n", + "- You can also store **text data** in variables\n", + "- It may be helpful to *overwrite* the `out` variable" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "for out in range(...):\n", + " ...\n", + " ...\n", + " ...\n", + " ...\n", + " ...\n", + " ...\n", + "\n", + " print(out)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q2.2**: What may be advantages of writing code like in the solution to **Q2.1**?" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + " < your answer >" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.12" + }, + "toc": { + "base_numbering": 1, + "nav_menu": {}, + "number_sections": false, + "sideBar": true, + "skip_h1_title": true, + "title_cell": "Table of Contents", + "title_sidebar": "Contents", + "toc_cell": false, + "toc_position": {}, + "toc_section_display": false, + "toc_window_display": false + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/00_python_in_a_nutshell/05_content_functions.ipynb b/00_python_in_a_nutshell/05_content_functions.ipynb new file mode 100644 index 0000000..7961934 --- /dev/null +++ b/00_python_in_a_nutshell/05_content_functions.ipynb @@ -0,0 +1,540 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Note**: Click on \"*Kernel*\" > \"*Restart Kernel and Clear All Outputs*\" in [JupyterLab](https://jupyterlab.readthedocs.io/en/stable/) *before* reading this notebook to reset its output. If you cannot run this file on your machine, you may want to open it [in the cloud ](https://mybinder.org/v2/gh/webartifex/intro-to-data-science/main?urlpath=lab/tree/00_python_in_a_nutshell/05_content_functions.ipynb)." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Chapter 0: Python in a Nutshell (Part 3)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "One big idea in software engineering is to **modularize** code. The purpose of that is manyfold. Two very important motivations are:\n", + "- make a code block **re-usable** and\n", + "- give it a meaningful name.\n", + "\n", + "The latter gets more important as the codebase in a project grows so big that we can only look at a tiny fraction of it at one point in time." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Defining Functions" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "One syntactical construct to achieve modularization is that of a **function definition**. Just like in math, we can \"define\" a function as a set of parametrized instructions that provide some **output** given some **input**.\n", + "\n", + "A function is defined with the `def` statement: After the `def` part comes the name of the function followed by the **parameter list** within parentheses. The first couple of lines in the function's body should be a so-called **docstring** that describes what the function does in plain English. Then, comes the code that is to be made repeatable. In the example below, we simply copy & pasted the code to calculate the sum of all even numbers in a `list` into the example function `add_evens()`. Note that we exchanged the variable name `total` with `result` here to illustrate a point further below. In order for the function to provide back the output to \"the outside world,\" we use the `return` statement (Hint: to see its effect simply re-run the couple of code cells below with and without the `return result` line)." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "def add_evens(numbers):\n", + " \"\"\"Sum up all the even numbers in a list.\n", + "\n", + " Args:\n", + " numbers (list of int's): numbers to be summed up\n", + "\n", + " Returns:\n", + " total (int)\n", + " \"\"\"\n", + " result = 0\n", + "\n", + " for number in numbers:\n", + " if number % 2 == 0: # if the number is even\n", + " result = result + number\n", + "\n", + " return result" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "After defining a function, we can **call** (i.e., \"execute\") it with the `()` operator.\n", + "\n", + "Let's execute the function with `numbers` as the input. We see the same `6` below the cell as we do above where we run the code without a function. Without the `return` statement in the function's body, we would not see any output here.\n", + "\n", + "To see what happens in detail, take a look at [PythonTutor ](https://pythontutor.com/visualize.html#code=numbers%20%3D%20%5B1,%202,%203,%204%5D%0A%0Adef%20add_evens%28numbers%29%3A%0A%20%20%20%20%22%22%22Sum%20up%20all%20the%20even%20numbers%20in%20a%20list.%22%22%22%0A%20%20%20%20result%20%3D%200%0A%0A%20%20%20%20for%20number%20in%20numbers%3A%0A%20%20%20%20%20%20%20%20if%20number%20%25%202%20%3D%3D%200%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20result%20%3D%20result%20%2B%20number%0A%0A%20%20%20%20return%20result%0A%0Atotal%20%3D%20add_evens%28numbers%29&cumulative=false&curInstr=0&heapPrimitives=nevernest&mode=display&origin=opt-frontend.js&py=3&rawInputLstJSON=%5B%5D&textReferences=false) again. You should notice how there are two variables by the name `numbers` in memory. Python manages the memory with a concept called **namespaces** or **scopes**, which are just fancy terms for saying that Python can tell variables from different contexts apart." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "numbers = [1, 2, 3, 4]" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "6" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "add_evens(numbers)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To re-use the *same* instructions with *different* input, we call the function a second time and give it a brand-new `list` of numbers as its input." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "30" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "add_evens([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Note how the variable `result` only exists \"inside\" the `add_evens()` function. Hence, we see the `NameError` here." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "ename": "NameError", + "evalue": "name 'result' is not defined", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m/tmp/user/1000/ipykernel_707190/1049141082.py\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mresult\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;31mNameError\u001b[0m: name 'result' is not defined" + ] + } + ], + "source": [ + "result" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Built-in Functions" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The concept of re-usable functions is so important in programming that Python comes with many [built-in functions ](https://docs.python.org/3/library/functions.html).\n", + "\n", + "Two popular examples are the [sum() ](https://docs.python.org/3/library/functions.html#sum) and [len() ](https://docs.python.org/3/library/functions.html#len) functions that calculate the sum or the number of elements in a `list`." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "10" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "sum(numbers)" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "4" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "len(numbers)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "When working with numbers, the [round() ](https://docs.python.org/3/library/functions.html#round) function rounds `float`ing-point numbers (i.e., real numbers in the mathematical sense) into `int`egers. `float`s are numbers containing a `.` somewhere in its digits." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "7" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "round(7.1)" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "8" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "round(7.9)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The [round() ](https://docs.python.org/3/library/functions.html#round) function takes a second input called `ndigits` that allows us to customize the rounding even further. Then, [round() ](https://docs.python.org/3/library/functions.html#round) returns a `float`ing-point number!" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "7.1" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "round(7.123, 1)" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "7.12" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "round(7.123, 2)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "As we saw before, the [print() ](https://docs.python.org/3/library/functions.html#print) function simply \"prints\" out its input to the screen. Below is the popular \"Hello World\" example that is shown in almost any introduction text on any programming language. The double quotes `\"` are a delimiter that specifies anything in between them as **textual data**. The docstring above in the tripple-double quotes notation is just a special case allowing the text to span several lines.\n", + "\n", + "The quotes themselves are *not* part of the value. So, they are *not* printed out." + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Hello World\n" + ] + } + ], + "source": [ + "print(\"Hello World\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Single quotes `'` are synonyms for double quotes `\"`." + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Hello World\n" + ] + } + ], + "source": [ + "print('Hello World')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The [print() ](https://docs.python.org/3/library/functions.html#print) function is often helpful to **debug** a code snippet (i.e., trying to figure out what it does, step by step)." + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The square of 1 is 1\n", + "The square of 2 is 4\n", + "The square of 3 is 9\n", + "The square of 4 is 16\n" + ] + } + ], + "source": [ + "for number in numbers:\n", + " square = number ** 2\n", + " print(\"The square of\", number, \"is\", square)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## The Standard Library" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In the Python community, we even say that \"Python comes with batteries included,\" meaning that a plain Python installation (like the one you are probably using to execute this notebook) offers all kinds of functionalities for a multitude of application domains. Thus, the name **general purpose** language.\n", + "\n", + "To \"enable\" most of these, however, we need to first **import** them from the so-called [standard library ](https://docs.python.org/3/library/index.html). Let's do a quick example here and look at the [random ](https://docs.python.org/3/library/random.html) module that provides functionalities to simulate and work with random numbers." + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [], + "source": [ + "import random" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To access a function inside the [random ](https://docs.python.org/3/library/random.html) module, for example, the [random() ](https://docs.python.org/3/library/random.html#random.random) function, we use the `.` operator, formally called the attribute access operator. The [random() ](https://docs.python.org/3/library/random.html#random.random) function simply returns a random decimal number between `0` and `1`." + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "0.7021021034327006" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "random.random()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "It could be used, for example, to model a fair coin toss by comparing the number it returns to `0.5` with the `<` operator: In 50% of the cases we see `True` and in the other 50% `False`." + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "False" + ] + }, + "execution_count": 17, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "random.random() < 0.5" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "A second example would be the [choice() ](https://docs.python.org/3/library/random.html#random.choice) function, which draws a random element from a `list` with replacement. We could use it to model a fair die." + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "3" + ] + }, + "execution_count": 18, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "random.choice([1, 2, 3, 4, 5, 6])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In the \"*Extending Core Python with Third-party Packages*\" section in the next chapter, we see how Python can be extended even further by installing and importing **third-party packages**." + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.12" + }, + "toc": { + "base_numbering": 1, + "nav_menu": {}, + "number_sections": false, + "sideBar": true, + "skip_h1_title": false, + "title_cell": "Table of Contents", + "title_sidebar": "Contents", + "toc_cell": false, + "toc_position": {}, + "toc_section_display": true, + "toc_window_display": false + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/00_python_in_a_nutshell/06_exercises_volume.ipynb b/00_python_in_a_nutshell/06_exercises_volume.ipynb new file mode 100644 index 0000000..ded4b96 --- /dev/null +++ b/00_python_in_a_nutshell/06_exercises_volume.ipynb @@ -0,0 +1,292 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Note**: Click on \"*Kernel*\" > \"*Restart Kernel and Run All*\" in [JupyterLab](https://jupyterlab.readthedocs.io/en/stable/) *after* finishing the exercises to ensure that your solution runs top to bottom *without* any errors. If you cannot run this file on your machine, you may want to open it [in the cloud ](https://mybinder.org/v2/gh/webartifex/intro-to-data-science/main?urlpath=lab/tree/00_python_in_a_nutshell/06_exercises_volume.ipynb)." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Chapter 0: Python in a Nutshell (Coding Exercises)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The exercises below assume that you have read the preceeding content sections.\n", + "\n", + "The `...`'s in the code cells indicate where you need to fill in code snippets. The number of `...`'s within a code cell give you a rough idea of how many lines of code are needed to solve the task. You should not need to create any additional code cells for your final solution. However, you may want to use temporary code cells to try out some ideas." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Volume of a Sphere" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The [volume of a sphere ](https://en.wikipedia.org/wiki/Sphere) is defined as $\\frac{4}{3} * \\pi * r^3$.\n", + "\n", + "In **Q2**, you will write a `function` implementing this formula, and in **Q3** and **Q5**, you will execute this `function` with a couple of example inputs.\n", + "\n", + "**Q1**: First, execute the next two code cells that import the `math` module from the [standard library ](https://docs.python.org/3/library/index.html) providing an approximation for $\\pi$!" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import math" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "math.pi" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q2**: Implement the business logic in the `sphere_volume()` function below according to the specifications in the **docstring**!\n", + "\n", + "Hints:\n", + "- `sphere_volume()` takes a mandatory `radius` input and an optional `ndigits` input (defaulting to `5`)\n", + "- Because `math.pi` is constant, it may be used within `sphere_volume()` *without* being an official input\n", + "- The volume is returned as a so-called `float`ing-point number due to the rounding with the built-in [round() ](https://docs.python.org/3/library/functions.html#round) function\n", + "- You may either write your solution as one big expression (where the `...` are) or introduce an intermediate step holding the result before rounding (then, one more line of code is needed above the `return ...` one)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def sphere_volume(radius, ndigits=5):\n", + " \"\"\"Calculate the volume of a sphere.\n", + "\n", + " Args:\n", + " radius (int or float): radius of the sphere\n", + " ndigits (optional, int): number of digits\n", + " when rounding the resulting volume\n", + "\n", + " Returns:\n", + " volume (float)\n", + " \"\"\"\n", + " return ..." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q3**: Execute the function with `radius = 100.0` and 1, 5, 10, 15, and 20 as `ndigits` respectively." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "radius = 100.0" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "sphere_volume(...)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "sphere_volume(...)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "sphere_volume(...)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "sphere_volume(...)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "sphere_volume(...)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q4**: What observation do you make?" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + " < your answer >" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q4**: Using the [range() ](https://docs.python.org/3/library/functions.html#func-range) built-in, write a `for`-loop and calculate the volume of a sphere with `radius = 42.0` for all `ndigits` from `1` through `20`!\n", + "\n", + "Hint: You need to use the built-in [print() ](https://docs.python.org/3/library/functions.html#print) function to make the return values visible" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "radius = 42.0" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "for ... in ...:\n", + " ..." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q5**: What lesson do you learn about `float`ing-point numbers?" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + " < your answer >" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "With the [round() ](https://docs.python.org/3/library/functions.html#round) function, we can see another technicality of the `float`ing-point standard: `float`s are *inherently* imprecise!\n", + "\n", + "**Q6**: Execute the following code cells to see a \"weird\" output! What could be the reasoning behind rounding this way?" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "round(1.5)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "round(2.5)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "round(3.5)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "round(4.5)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.12" + }, + "toc": { + "base_numbering": 1, + "nav_menu": {}, + "number_sections": false, + "sideBar": true, + "skip_h1_title": true, + "title_cell": "Table of Contents", + "title_sidebar": "Contents", + "toc_cell": false, + "toc_position": {}, + "toc_section_display": false, + "toc_window_display": false + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/00_python_in_a_nutshell/07_content_data_types.ipynb b/00_python_in_a_nutshell/07_content_data_types.ipynb new file mode 100644 index 0000000..a40af42 --- /dev/null +++ b/00_python_in_a_nutshell/07_content_data_types.ipynb @@ -0,0 +1,708 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Note**: Click on \"*Kernel*\" > \"*Restart Kernel and Clear All Outputs*\" in [JupyterLab](https://jupyterlab.readthedocs.io/en/stable/) *before* reading this notebook to reset its output. If you cannot run this file on your machine, you may want to open it [in the cloud ](https://mybinder.org/v2/gh/webartifex/intro-to-data-science/main?urlpath=lab/tree/00_python_in_a_nutshell/07_content_data_types.ipynb)." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Chapter 0: Python in a Nutshell (Part 4)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "An important skill for any data scientist is to learn to \"think\" like a computer does. So far, we have seen that Python is a pretty \"intuitive\" language: Many concepts can already be understood after seeing them once or just a couple of times. Many of the aspects that make other languages harder to learn, are somehow \"magically\" automated by Python in the background, most notably the management of the memory.\n", + "\n", + "This section introduces a couple of more \"advanced\" concepts that presumably are *not* so intuitive to beginners." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## \"Simple\" Data Types" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "At first, let's review the concept of **object-orientation**, which is the paradigm by which Python manages the memory.\n", + "\n", + "Take the following three examples. Whereas `a` and `b` have the same **value** (i.e., **semantic meaning**) to us humans, we see in this section that there are a couple of caveats to look out for." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "a = 42\n", + "b = 42.0\n", + "c = 42.87" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "An important idea to understand is that each of the right-hand sides lead to a *new* **object** being created in the computer's memory *first*. An object can be thought of as a \"box\" in memory holding $1$s and $0$s (i.e., physical energy flows inside the computer).\n", + "\n", + "Objects can and do exist without being **referenced** by a variable. Also, an object may even have several variables referencing them, just as a human may have different names in different contexts (e.g., a formal name in the password, a name by which one is known to friends, and maybe a different name by which one is called by one's spouse).\n", + "\n", + "In the example, while both `a` and `b` have the *same* value, they are two *distinct* objects. The `is` operator checks if the objects referenced by two variables are indeed the *same* one, or, in other words, have the same **identity**." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "a == b" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "False" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "a is b" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Every object always has some **data type**, which determines how the object behaves and what we can do with it. The types of `a` and `b` are `int` and `float`, respectively." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "int" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "type(a)" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "float" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "type(b)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "While it seems cumbersome to analyze numbers at this level of detail, the following code cell shows how `float`ing-point numbers, one gold standard of numbers in all of computer science and engineering, behave couter-intutive. Yet, *nothing* is wrong here." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "False" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "0.1 + 0.2 == 0.3" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The data type of an object also determines which **methods** we can invoke on it. A method is just a function that is \"attached\" to an object and can be accessed with the `.` operator seen above. A method necessarily needs the objects it is attached to as in input, which is why it is attached to an object to begin with.\n", + "\n", + "For example, `float` objects come with an `.is_integer()` method that tells us if the number has non-`0` decimals." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "b.is_integer()" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "False" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "c.is_integer()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "`int` objects on the contrary have no notion of the concept of decimals, which is why they do *not* have an `.is_integer()` method. That is what the `AttributeError` tells us." + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "ename": "AttributeError", + "evalue": "'int' object has no attribute 'is_integer'", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mAttributeError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m/tmp/user/1000/ipykernel_306555/2418692311.py\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0ma\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mis_integer\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;31mAttributeError\u001b[0m: 'int' object has no attribute 'is_integer'" + ] + } + ], + "source": [ + "a.is_integer()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "What we could do here, is to take `a` and pass it to the [float() ](https://docs.python.org/3/library/functions.html#float) built-in, a so-called **constructor**, which takes the value of its input and creates a *new* object of the desired `float` type. Yet, we know the answer to `aa.is_integer()` already, even without executing the code cell as `a` has no non-`0` decimals to begin with." + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [], + "source": [ + "aa = float(a)" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "aa.is_integer()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let's create another example `d` to see further examples of methods." + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [], + "source": [ + "d = \"Python rocks\"" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The type of `d` is `str`, which is short for \"**string**\" and is defined in computer science as a sequence of characters." + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "str" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "type(d)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "`str` objects support various methods that \"make sense\" in the context of textual data, for example, the `.lower()` and `.upper()` methods." + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'python rocks'" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "d.lower()" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'PYTHON ROCKS'" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "d.upper()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### \"Complex\" Data Types" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The examples in the previous section are considered \"simple\" as they only model *scalar* values (i.e., an individual object per example). However, we have already seen an example of a more \"complex\" object, namely the `list` called `numbers` from before." + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [], + "source": [ + "numbers = [1, 2, 3, 4]" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "list" + ] + }, + "execution_count": 17, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "type(numbers)" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[1, 2, 3, 4]" + ] + }, + "execution_count": 18, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "numbers" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "`list` objects also come with specific methods on them, for example, the `.append()` method that adds another element at the end of a `list`." + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": {}, + "outputs": [], + "source": [ + "numbers.append(5)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Note how the `.append()` method does not lead to any output below the code cell. That is an indication that `numbers` is \"changed in place.\" The formal term for this property is **mutability**. A good working definition is: Any object whose value can be changed *after* its creation, is a **mutable** objects. Objects *without* this property are called **immutable**.\n", + "\n", + "An example for the latter, is the `tuple` data type. `tuple`s are simply `list`s with the additional property that they cannot be changed. Everything is else is the same as for `list`s. `tuple`s are created with parentheses replacing the brackets." + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": {}, + "outputs": [], + "source": [ + "more_numbers = (7, 8, 9)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "`more_numbers` does not know about the `.append()` method." + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": {}, + "outputs": [ + { + "ename": "AttributeError", + "evalue": "'tuple' object has no attribute 'append'", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mAttributeError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m/tmp/user/1000/ipykernel_306555/2667408552.py\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mmore_numbers\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mappend\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m10\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;31mAttributeError\u001b[0m: 'tuple' object has no attribute 'append'" + ] + } + ], + "source": [ + "more_numbers.append(10)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Whereas both `list` and `tuple` objects perserve the **order** of their elements, the `set` data type does not. Additionally, any object may only be an element of a `set` at most once. The syntax to create `set`s are curly braces, `{` and `}`. By giving up order, `set` objects offer significantly increased processing speed in various situations." + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": {}, + "outputs": [], + "source": [ + "other_numbers = {3, 2, 1, 3, 3, 2}" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{1, 2, 3}" + ] + }, + "execution_count": 23, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "other_numbers" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "One last example of a \"complex\" data type is the `dict`ionary type, which models a mapping relationship among the objects it contains. The syntax to create `dict`s also involves curly braces with the additon of using a `:` to specify the mapping relationships.\n", + "\n", + "For example, to map `int`egers to `str`ings modeling the English words corresponding to the numbers, we could write the following. The objects to the left of the `:` take the role of the **keys** while the ones to the right take the role of the **values**." + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": {}, + "outputs": [], + "source": [ + "to_words = {\n", + " 0: \"zero\",\n", + " 1: \"one\",\n", + " 2: \"two\",\n", + "}" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The main purpose of `dict`s is to **look up** the value mapped to by some key. We can use the indexing notion to achieve that." + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'zero'" + ] + }, + "execution_count": 25, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "to_words[0]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Looking up the values can *not* be done as the `KeyError` below shows." + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": {}, + "outputs": [ + { + "ename": "KeyError", + "evalue": "'zero'", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mKeyError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m/tmp/user/1000/ipykernel_306555/3320204082.py\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mto_words\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m\"zero\"\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;31mKeyError\u001b[0m: 'zero'" + ] + } + ], + "source": [ + "to_words[\"zero\"]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Instead, we would have to create a `dict` mapping the words to numbers, like the one below." + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "metadata": {}, + "outputs": [], + "source": [ + "to_numbers = {\n", + " \"zero\": 0,\n", + " \"one\": 1,\n", + " \"two\": 2,\n", + "}" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "0" + ] + }, + "execution_count": 28, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "to_numbers[\"zero\"]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "`dict`s are among the most optimized data type in the Python world and a major building block in codebases solving real-life problems." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "A big factor in getting good at any programming language is to learn what data types to use in which situations. There is no \"best\" data type; choosing among a couple of data types always comes down to trade-offs." + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.12" + }, + "toc": { + "base_numbering": 1, + "nav_menu": {}, + "number_sections": false, + "sideBar": true, + "skip_h1_title": false, + "title_cell": "Table of Contents", + "title_sidebar": "Contents", + "toc_cell": false, + "toc_position": {}, + "toc_section_display": true, + "toc_window_display": false + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/01_scientific_stack.ipynb b/01_scientific_stack.ipynb deleted file mode 100644 index 694376b..0000000 --- a/01_scientific_stack.ipynb +++ /dev/null @@ -1,662 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Chapter 1: Python's Scientific Stack" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Python itself does not come with any scientific algorithms. However, over time, many third-party libraries emerged that are useful to build machine learning applications. In this context, \"third-party\" means that the libraries are *not* part of Python's standard library.\n", - "\n", - "Among the popular ones are [numpy](https://numpy.org/) (numerical computations, linear algebra), [pandas](https://pandas.pydata.org/) (data processing), [matplotlib](https://matplotlib.org/) (visualisations), and [scikit-learn](https://scikit-learn.org/stable/index.html) (machine learning algorithms).\n", - "\n", - "Before we can import these libraries, we must ensure that they installed on our computers. If you installed Python via the Anaconda Distribution that should already be the case. Otherwise, we can use Python's **package manager** `pip` to install them manually.\n", - "\n", - "`pip` is a so-called command-line interface (CLI), meaning it is a program that is run within a terminal window. JupyterLab allows us to run such a CLI tool from within a notebook by starting a code cell with a single `%` symbol. Here, this does not mean Python's modulo operator but is just an instruction to JupyterLab that the following code is *not* Python." - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Requirement already satisfied: numpy in ./.venv/lib/python3.8/site-packages (1.20.3)\n", - "Note: you may need to restart the kernel to use updated packages.\n" - ] - } - ], - "source": [ - "%pip install numpy" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Requirement already satisfied: pandas in ./.venv/lib/python3.8/site-packages (1.2.4)\n", - "Requirement already satisfied: numpy>=1.16.5 in ./.venv/lib/python3.8/site-packages (from pandas) (1.20.3)\n", - "Requirement already satisfied: python-dateutil>=2.7.3 in ./.venv/lib/python3.8/site-packages (from pandas) (2.8.1)\n", - "Requirement already satisfied: pytz>=2017.3 in ./.venv/lib/python3.8/site-packages (from pandas) (2021.1)\n", - "Requirement already satisfied: six>=1.5 in ./.venv/lib/python3.8/site-packages (from python-dateutil>=2.7.3->pandas) (1.16.0)\n", - "Note: you may need to restart the kernel to use updated packages.\n" - ] - } - ], - "source": [ - "%pip install pandas" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Requirement already satisfied: matplotlib in ./.venv/lib/python3.8/site-packages (3.4.2)\n", - "Requirement already satisfied: python-dateutil>=2.7 in ./.venv/lib/python3.8/site-packages (from matplotlib) (2.8.1)\n", - "Requirement already satisfied: pyparsing>=2.2.1 in ./.venv/lib/python3.8/site-packages (from matplotlib) (2.4.7)\n", - "Requirement already satisfied: pillow>=6.2.0 in ./.venv/lib/python3.8/site-packages (from matplotlib) (8.2.0)\n", - "Requirement already satisfied: kiwisolver>=1.0.1 in ./.venv/lib/python3.8/site-packages (from matplotlib) (1.3.1)\n", - "Requirement already satisfied: numpy>=1.16 in ./.venv/lib/python3.8/site-packages (from matplotlib) (1.20.3)\n", - "Requirement already satisfied: cycler>=0.10 in ./.venv/lib/python3.8/site-packages (from matplotlib) (0.10.0)\n", - "Requirement already satisfied: six in ./.venv/lib/python3.8/site-packages (from cycler>=0.10->matplotlib) (1.16.0)\n", - "Note: you may need to restart the kernel to use updated packages.\n" - ] - } - ], - "source": [ - "%pip install matplotlib" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Requirement already satisfied: scikit-learn in ./.venv/lib/python3.8/site-packages (0.24.2)\n", - "Requirement already satisfied: joblib>=0.11 in ./.venv/lib/python3.8/site-packages (from scikit-learn) (1.0.1)\n", - "Requirement already satisfied: threadpoolctl>=2.0.0 in ./.venv/lib/python3.8/site-packages (from scikit-learn) (2.1.0)\n", - "Requirement already satisfied: numpy>=1.13.3 in ./.venv/lib/python3.8/site-packages (from scikit-learn) (1.20.3)\n", - "Requirement already satisfied: scipy>=0.19.1 in ./.venv/lib/python3.8/site-packages (from scikit-learn) (1.6.1)\n", - "Note: you may need to restart the kernel to use updated packages.\n" - ] - } - ], - "source": [ - "%pip install scikit-learn" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "After we have ensured that the third-party libraries are installed locally, we can simply go ahead with the `import` statement. All the libraries are commonly imported with shorter prefixes for convenient use later on." - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [], - "source": [ - "import numpy as np\n", - "import pandas as pd\n", - "import matplotlib.pyplot as plt" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let's see how the data type provided by these scientific libraries differ from Python's built-in ones.\n", - "\n", - "As an example, we create a `list` object similar to the one from Chapter 0." - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[1, 2, 3]" - ] - }, - "execution_count": 6, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "vector = [1, 2, 3]\n", - "\n", - "vector" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We call the `list` object by the name `vector` as that is what the data mean conceptually. As we remember from our linear algebra courses, vectors should implement scalar-multiplication. So, the following code cell should result in `[3, 6, 9]` as the answer. Surprisingly, the result is a new `list` with all the elements in `vector` repeated three times. That operation is called **concatenation** and is an example of a concept called **operator overloading**. That means that an operator, like `*` in the example, may exhibit a different behavior depending on the data type of its operands." - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[1, 2, 3, 1, 2, 3, 1, 2, 3]" - ] - }, - "execution_count": 7, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "3 * vector" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "`numpy`, among others, provides a data type called an **n-dimensional array**. This may sound fancy at first but when used with only 1 or 2 dimensions, it basically represents vectors and matrices as we know them from linear algebra. Additionally, arrays allow for much faster computations as they are implemented in the very efficient [C language](https://en.wikipedia.org/wiki/C_%28programming_language%29) and optimized for numerical operations." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To create an array, we use the [array()](https://docs.scipy.org/doc/numpy/reference/generated/numpy.array.html#numpy-array) constructor from the imported `np` module and provide it with a `list` of values." - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "array([1, 2, 3])" - ] - }, - "execution_count": 8, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "v1 = np.array([1, 2, 3])\n", - "\n", - "v1" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The vector `v1` can now be multiplied with a scalar yielding a result meaningful in the context of linear algebra." - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "array([3, 6, 9])" - ] - }, - "execution_count": 9, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "v2 = 3 * v1\n", - "\n", - "v2" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To create a matrix, we just use a `list` of (row) `list`s of values." - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "array([[1, 2, 3],\n", - " [4, 5, 6]])" - ] - }, - "execution_count": 10, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "m1 = np.array([\n", - " [1, 2, 3],\n", - " [4, 5, 6],\n", - "])\n", - "\n", - "m1" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now we can use `numpy`'s `dot()` function to multiply a matrix with a vector to obtain a new vector ..." - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "array([14, 32])" - ] - }, - "execution_count": 11, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "v3 = np.dot(m1, v1)\n", - "\n", - "v3" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "... or simply transpose it by accessing its `.T` attribute." - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "array([[1, 4],\n", - " [2, 5],\n", - " [3, 6]])" - ] - }, - "execution_count": 12, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "m1.T" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The rules from maths still apply and it makes a difference if a vector is multiplied from the left or the right by a matrix. The following operation will fail." - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": {}, - "outputs": [ - { - "ename": "ValueError", - "evalue": "shapes (3,) and (2,3) not aligned: 3 (dim 0) != 2 (dim 0)", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mValueError\u001b[0m Traceback (most recent call last)", - "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdot\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mv1\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mm1\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", - "\u001b[0;32m<__array_function__ internals>\u001b[0m in \u001b[0;36mdot\u001b[0;34m(*args, **kwargs)\u001b[0m\n", - "\u001b[0;31mValueError\u001b[0m: shapes (3,) and (2,3) not aligned: 3 (dim 0) != 2 (dim 0)" - ] - } - ], - "source": [ - "np.dot(v1, m1)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "In order to retrieve only a **slice** (i.e., subset) of an array's data, we index into it. For example, the first row of the matrix is ..." - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "array([1, 2, 3])" - ] - }, - "execution_count": 14, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "m1[0, :]" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "... while the second column is:" - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "array([2, 5])" - ] - }, - "execution_count": 15, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "m1[:, 1]" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To acces the lowest element in the right column, two indices can be used." - ] - }, - { - "cell_type": "code", - "execution_count": 16, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "6" - ] - }, - "execution_count": 16, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "m1[1, 2]" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "`numpy` also provides various other functions and constants, such as `linspace()` to create an array of equidistant numbers, `sin()` to calculate the sinus values for all numbers in an array, or simple an approximation for `pi`. To further illustrate the concept of **vectorization**, let us calculate the sinus curve over a range of 100 values, going from negative to positive $3\\pi$." - ] - }, - { - "cell_type": "code", - "execution_count": 17, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "array([-9.42477796, -9.23437841, -9.04397885, -8.8535793 , -8.66317974,\n", - " -8.47278019, -8.28238063, -8.09198108, -7.90158152, -7.71118197,\n", - " -7.52078241, -7.33038286, -7.1399833 , -6.94958375, -6.75918419,\n", - " -6.56878464, -6.37838508, -6.18798553, -5.99758598, -5.80718642,\n", - " -5.61678687, -5.42638731, -5.23598776, -5.0455882 , -4.85518865,\n", - " -4.66478909, -4.47438954, -4.28398998, -4.09359043, -3.90319087,\n", - " -3.71279132, -3.52239176, -3.33199221, -3.14159265, -2.9511931 ,\n", - " -2.76079354, -2.57039399, -2.37999443, -2.18959488, -1.99919533,\n", - " -1.80879577, -1.61839622, -1.42799666, -1.23759711, -1.04719755,\n", - " -0.856798 , -0.66639844, -0.47599889, -0.28559933, -0.09519978,\n", - " 0.09519978, 0.28559933, 0.47599889, 0.66639844, 0.856798 ,\n", - " 1.04719755, 1.23759711, 1.42799666, 1.61839622, 1.80879577,\n", - " 1.99919533, 2.18959488, 2.37999443, 2.57039399, 2.76079354,\n", - " 2.9511931 , 3.14159265, 3.33199221, 3.52239176, 3.71279132,\n", - " 3.90319087, 4.09359043, 4.28398998, 4.47438954, 4.66478909,\n", - " 4.85518865, 5.0455882 , 5.23598776, 5.42638731, 5.61678687,\n", - " 5.80718642, 5.99758598, 6.18798553, 6.37838508, 6.56878464,\n", - " 6.75918419, 6.94958375, 7.1399833 , 7.33038286, 7.52078241,\n", - " 7.71118197, 7.90158152, 8.09198108, 8.28238063, 8.47278019,\n", - " 8.66317974, 8.8535793 , 9.04397885, 9.23437841, 9.42477796])" - ] - }, - "execution_count": 17, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "x = np.linspace(-3 * np.pi, 3 * np.pi, 100)\n", - "\n", - "x" - ] - }, - { - "cell_type": "code", - "execution_count": 18, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "array([-3.67394040e-16, -1.89251244e-01, -3.71662456e-01, -5.40640817e-01,\n", - " -6.90079011e-01, -8.14575952e-01, -9.09631995e-01, -9.71811568e-01,\n", - " -9.98867339e-01, -9.89821442e-01, -9.45000819e-01, -8.66025404e-01,\n", - " -7.55749574e-01, -6.18158986e-01, -4.58226522e-01, -2.81732557e-01,\n", - " -9.50560433e-02, 9.50560433e-02, 2.81732557e-01, 4.58226522e-01,\n", - " 6.18158986e-01, 7.55749574e-01, 8.66025404e-01, 9.45000819e-01,\n", - " 9.89821442e-01, 9.98867339e-01, 9.71811568e-01, 9.09631995e-01,\n", - " 8.14575952e-01, 6.90079011e-01, 5.40640817e-01, 3.71662456e-01,\n", - " 1.89251244e-01, -1.22464680e-16, -1.89251244e-01, -3.71662456e-01,\n", - " -5.40640817e-01, -6.90079011e-01, -8.14575952e-01, -9.09631995e-01,\n", - " -9.71811568e-01, -9.98867339e-01, -9.89821442e-01, -9.45000819e-01,\n", - " -8.66025404e-01, -7.55749574e-01, -6.18158986e-01, -4.58226522e-01,\n", - " -2.81732557e-01, -9.50560433e-02, 9.50560433e-02, 2.81732557e-01,\n", - " 4.58226522e-01, 6.18158986e-01, 7.55749574e-01, 8.66025404e-01,\n", - " 9.45000819e-01, 9.89821442e-01, 9.98867339e-01, 9.71811568e-01,\n", - " 9.09631995e-01, 8.14575952e-01, 6.90079011e-01, 5.40640817e-01,\n", - " 3.71662456e-01, 1.89251244e-01, 1.22464680e-16, -1.89251244e-01,\n", - " -3.71662456e-01, -5.40640817e-01, -6.90079011e-01, -8.14575952e-01,\n", - " -9.09631995e-01, -9.71811568e-01, -9.98867339e-01, -9.89821442e-01,\n", - " -9.45000819e-01, -8.66025404e-01, -7.55749574e-01, -6.18158986e-01,\n", - " -4.58226522e-01, -2.81732557e-01, -9.50560433e-02, 9.50560433e-02,\n", - " 2.81732557e-01, 4.58226522e-01, 6.18158986e-01, 7.55749574e-01,\n", - " 8.66025404e-01, 9.45000819e-01, 9.89821442e-01, 9.98867339e-01,\n", - " 9.71811568e-01, 9.09631995e-01, 8.14575952e-01, 6.90079011e-01,\n", - " 5.40640817e-01, 3.71662456e-01, 1.89251244e-01, 3.67394040e-16])" - ] - }, - "execution_count": 18, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "y = np.sin(x)\n", - "\n", - "y" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "With `matplotlib`'s [plot()](https://matplotlib.org/api/pyplot_api.html#matplotlib.pyplot.plot) function we can visualize the sinus curve." - ] - }, - { - "cell_type": "code", - "execution_count": 19, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[]" - ] - }, - "execution_count": 19, - "metadata": {}, - "output_type": "execute_result" - }, - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAYcAAAD4CAYAAAAHHSreAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjQuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8rg+JYAAAACXBIWXMAAAsTAAALEwEAmpwYAABCWUlEQVR4nO29d3hc13Xo+1sz6MCgVxJsIAGwk5Ioim6SLMmyaOdJ7pHy8iLH9tV1Esc3zk0c6fN7jj+nycmLnZdcO7biJjuOJFtx0XUoy5Is0UWmxGIWgERjAdEx6DPomNnvjzkHHIEACWBmTpnZv++bDzOnLpyy115lry1KKTQajUajicZjtwAajUajcR5aOWg0Go3mKrRy0Gg0Gs1VaOWg0Wg0mqvQykGj0Wg0V5FmtwCrobS0VG3cuNFuMTQajcZVHD9+fEApVbacbV2pHDZu3MixY8fsFkOj0WhchYi0L3db7VbSaDQazVVo5aDRaDSaq9DKQaPRaDRXoZWDRqPRaK5CKweNRqPRXEVclIOIfF1E+kWkYYn1IiL/LCJtInJaRG6MWvegiLQanwfjIY9Go9FoYiNelsM3gXuusf4gUGt8HgL+FUBEioG/BG4B9gN/KSJFcZJJo9FoNKskLspBKfVzYOgam9wHfEtFOAIUikgV8HbgeaXUkFJqGHieaysZjYVcHpzgP169zOnOEbtF0RhMzoR4qamfp45eZmYubLc4GkApRVt/gG8faaelL2C3OHHDqkFwa4GOqN+dxrKlll+FiDxExOpg/fr1iZFSA8BjPz/Pk0c7uOAfByDdK3zuvbt5z43VNkuWurT0Bfi7Q+d45fwg04ZS+NHJbv71d2+iIDvdZulSk3BY8YUXWvjhyS46hiYByE738r9+5wbu3FZhs3Sx45qAtFLqMaXUPqXUvrKyZY3+1qyC/32qm7891ERJbgaf/q3t/NfH38zNG4v50++e4p9fbEVPDmU9kzMhPvrt45zsGOGB/ev51of28/fv3c1rF4d4/5dfoWtk0m4RU5LHf32Jf/lZGxtLcvnrd+3kx3/8ZraU5/HfvnWMbx9Z9kBkx2KV5dAFrIv6XW0s6wJuX7D8ZYtk0iygd3SK//uHDexdV8gT/+0Aad5I3+Gbv7+fh//zNJ9/voXxmTkeObjNZklTi0efPceFgXH+4yO38MYtpfPLq4uy+e//fpx3f/FX/Pjjb6bcl2WjlKlFW3+AR59t4o6t5XztwX2ICABPPnSAjz/xG/6fHzYwPRviI2+psVnS1WOV5fAM8HtG1tIBYFQp1QM8B9wtIkVGIPpuY5nGYpRS/PnTp5ieC/H5D+yZVwwAGWke/vEDe3jfTdV87RcX6RiasFHS1OLnLX4e/3U7H3rTptcpBoA3binlyYcOMDg+w1cOX7BJwtRjNhTmE0+dIifDy6Pv3TWvGAByM9P4yv91E3dsLeefXmhlZGLGRkljI16prE8AvwbqRaRTRD4sIh8VkY8amxwCLgBtwL8BfwiglBoC/go4anw+ayzTWMy3j7Tzi9YBPvXO7dSU5V21XkT4s7vr8YjwpZfbbJAw9RiZmOHPnz5FbXken7ynftFtdqwp4N03rOXfj7TTH5iyWMLU5F9ebOVM1yh/955di1praV4Pf3HPVoLTc3ztlxdtkDA+xCtb6QGlVJVSKl0pVa2U+ppS6stKqS8b65VS6o+UUpuVUruUUsei9v26UmqL8flGPOTRrIzRiVn+7lATt9aV8bu3LB3sryzI4oH96/jesU5tPVjA//diK4PBGb7w23vJSvcuud3H3rqFubDS1oMFdAxN8MWXz/OeG9dyz86qJberr/Txzl1VfONXl1xrPbgmIK1JHD882cXkbIhPvr3+dSbyYvzB7Vu09WABU7Mh/vN4J+/YVcXOtQXX3HZjaa62Hiziu8c6CCvFn929uCUXzcfvrHW19aCVQ4qjlOKJ1y6zY03+dRsh0NaDVfykoZexqTnuv3nd9TdGWw9WMBcK871jndxWV8aawuzrbu9260ErhxTndOcoTb0B7t+//LEj2npIPE+8dpkNJTkcqClZ1vbaekg8h1v89I5Ncf/Ny39X3Gw9aOWQ4jx59DLZ6V7u27tm2ftUFmTxrhvW8MzJbqZmQwmULjW54A/y6sUhfvvmdXg813bzRfPR22qYngvz41M9CZQudXnitQ5K8zK5c1v5svepr/Rxx9Zynj7eSTjsrjFCWjmkMOPTczxzspt37q4iP2tlo2x/a/caxmdC/LzFnyDpUpenjnbg9QjvW+GI9C3lPrZW+ni2QSuHeNM3NsVLzf2876Zq0r0razZ/a3cVPaNTnHJZGRqtHFKYH5/uZnwmxAP7l+fXjuYNm0soyE7nJw29CZAsdZmZC/OfJzq5c2s55fkrH9R2cGcVx9qH6R/TrqV48vTxTkJhtewYUDR3bqsg3Suue1e0ckhhnnitgy3ledy4fuWFcNO9Ht62vYLnz/UxPaddS/HixXN9DARneGAFMaBoDu6qRCl4rtFdDZGTCYcVTx69zBtqSthYmrvi/Quy03nTllIONfS4qvyMVg4pyuXBCU52jPDb+9ZdN311Kd6xq5LA1ByvtA3GWbrU5Ucnu6nIz+TWutXVD6stz2NzWS6HzmjlEC9+0zFCx9AkH7h59YUn37Gzio6hSRq7x+IoWWLRyiFFOdzSD8Bd21dfPfJNW0rxZaZpH3ecmA2F+VXbAHdsLce7gkB0NCLCO3ZV8erFQQaD03GWMDU53NyPR+Ct9csPRC/kbdsr8HqEQ2fc865o5ZCiHG7xs744h40lOas+Rmaalzu3lfPTs33MhvTcArFyon2YwPQct9WtvhECuGdnJWEFPz3bFyfJUpvDLX72riukMCdj1ccoys3gDTUlPNvQ6xrXklYOKcj0XIhXzg9ye33Zql1KJgd3VTEyMcuRC9q1FCuHW/ykeYQ3blne2Ial2F6Vz4aSHFf1Up3KYHCa012j3B6D1WByz85KLg6M0+ySCYG0ckhBjl0aZmImxG2r9GtHc1tdGTkZXp51WSaGEznc4ufGDUUrTiteiIhwcGcVvz4/6MqRuU7il20DKEVc3pW376hEBNfEg7RySEEOt/jJ8HqWPfr2WmSle3nr1nKeP9vnGnPZifQHpmjsHotLIwRwcGclc2HFy816HEosHG72U5ybwa5llJa5HmW+TG7eWMzzLnH3aeWQghxu9nPzpiJyM+Mz19Obt5TiD0xzYWA8LsdLRX7RMgDEp4cKsHNtAflZadrdFwPhsOLnrX7eUlu6opHq1+LNW0pp6h1zhUWnlUOK0TM6SXNfIG6NEDBvgeiGaPW83OKnzJfJjjX5cTme1yPs31Si70kMNHaPMRCcifu7ohS8etH509Zo5ZBimOUuYs2IiWZjSQ4V+ZkcueD8B96JhMKKX7T6ubU29gSBaA7UFHNpcIKeUT3H9Gow073fUhs/5bBnXQGZaR5XKO14zQR3j4g0i0ibiDy8yPoviMhJ49MiIiNR60JR656JhzyapTnc4qcyP4u6iqtne1stIsKBmkgvVccdVs7pzhFGJma5rT5+jRBcsehe1Up7VRxu8bNzbT5lvsy4HTMzzctNG4pc0ZGKWTmIiBf4InAQ2A48ICLbo7dRSn1CKbVXKbUX+Bfg+1GrJ811Sql7Y5VHszRzoTC/aB3gtrr49lAh0hD5A9Nc1HGHFXO4xY9H4C0L5oiOlW1V+TrusEpGJ2c5cXkkri4lkwM1Ja6IO8TDctgPtCmlLiilZoAngfuusf0DwBNxOK9mhTR0jxGYmuMtdfFthCA67uD8HpHTeKVtkF1rCyjKXf0gq8XQcYfV89rFIUJhFVeXkokZd3jN4XGHeCiHtUBH1O9OY9lViMgGYBPws6jFWSJyTESOiMi7ljqJiDxkbHfM79fpeavhePswADdvLI77sTeW5FDuy9QN0QqZmQtzqnOEfQm4J6DjDqvlxOVh0jzC3nWFcT/2lbhD8iuHlXA/8LRSKrqM5wal1D7gd4B/EpHNi+2olHpMKbVPKbWvrCz+2jwVOHF5mLWF2VSsohT09dBxh9VxrmeM6bkwN21YeWXc5aDjDqvjePswO9YWkJXujfuxr8QdnN2Riody6AKii5xXG8sW434WuJSUUl3G3wvAy8ANcZBJswgn2ocT1ghBpCHq13GHFWFac4m6L9uq8vHpuMOKmA2FOdUxwk2rKGW/XA7UlHDO4XGHeCiHo0CtiGwSkQwiCuCqrCMR2QoUAb+OWlYkIpnG91LgTcDZOMikWUD3yCQ9o1PcuL4wYec4UBNxjTjdXHYSxxNozUEk7nDLpmJX5NU7hbPdEWvuxg2FCTuHG+IOMSsHpdQc8DHgOeAc8F2lVKOIfFZEorOP7geeVK/3OWwDjonIKeAl4FGllFYOCeBKDzUxvm2ATaW5Ou6wQk60D3NjAq05iDREFwfG6R3Vs8MthxOXE2vNgTviDnGpn6CUOgQcWrDs0wt+f2aR/V4BdsVDBs21Od4+THa6l61VvoSdw4w7vHoxEneId7pssmFaczcl0JqDqLjDxUHu27torogmiuPtw6wpyKKqIDth5zDjDq9edG5HSo+QThFOXB5mz7qCFU+OvlJu2lBE39g0vXoO4+tihTUHsLXSR3a6l99cHknoeZIFK6w5iLwrTb0BJmecOc2uVg4pwORMiLPdYwk1k012V0eqV57qGEn4udzOicuJt+YA0rwedq7N53TnSELPkwx0j0zSPTpl0btSSCisONszmvBzrQatHFKA050jzIUVNyYw+8JkW1U+aR7hVKczH3gncaJ9mN3VibfmINIQNXaP6Rn7roMZb7DiXdljdKROdjjzXdHKIQU4bjzwN1jwwGcZPWHdS702kzMhGi2y5iBi0U3PhWnudccsZHZxon2ErHQP2+NUHfdalOdnUZmf5dh3RSuHFOBE+zA1ZbkUx7k8w1LsqS7kdOco4bAeDLcUpjVnlXIwR/qe1hbdNTl+eZjd1YWWWHMQyVpy6j3RyiHJUUpx4nJiB/QsZE91IYGpOS4O6sFwS2GlNQewvjiHwpx0x/ZSncDUbIjGrlHLFDZE3H0XB8YZnZy17JzLRSuHJOfS4ARD4zPWPvDrIr5U3RAtzYn2EUutORFh19oCHQu6Bqc7RyPWnMUdKYAzDrwvWjkkOWYDvdt4CK1gS1ke2eleTjk00OYEznSNzDcMVrGnupCWPuemTtrNma7I82p2bqxgl5nd58COlFYOSU5j9xgZaR5q4zi5z/XQqZPXpj8wRd/YNDvjMGn9SthdXUAorGjs1kp7MRq7RqnIz6Tcl5hSJotRkJ3OptJcR6Z+a+WQ5DR0jbK10mdZgM1kj06dXJLG7jGAuM0XvVzMoLR2LS1OQ/coO9dYq7AhktLqxKC0Vg5JjFKKhq5RdtjwwO9eV6hTJ5eg0XBfWJEuGY3TUyftZHImRFt/0HKFDRGXb+/YFP0OqyqglUMS0zk8ydjUHDvXWv/AmwN8nNgjspvG7jE2luSQn5Vu+bl3O7SXajdNvWOEFeyw2NUHkXRWcJ5Fp5VDEmP6lu0wlXXq5NI0dI/a0ggB7FlnpE5OOC910k4aDFef1XEggO1VBXg94ri4g1YOSUxD1xhej1BfmdjaPYshIuyuLuSkwx54uxmdmKVjaNIW9wVcSZ083TViy/mdSmPXKEU56awpsC4YbZKd4aW+wue4jCWtHJKYhu5RasvzEjLV4XLYU11Aa39Qp05GYac1B1dSJ7Vr6fU0dEdic3aVmd+zroAzXaOOmmI3LspBRO4RkWYRaRORhxdZ/0ER8YvISePzkah1D4pIq/F5MB7yaCI0do/ZEow22V6VTyisaOnTQWkTuzKVTAqy06kuyuZsz5gt53ciM3NhWnqD7LAhNmeyvSqfkYlZehw0IVPMykFEvMAXgYPAduABEdm+yKZPKaX2Gp+vGvsWA38J3ALsB/5SRKwbnpjE9I9N4Q9M29YIQaRCK8A53RDN09A9SlVBFiV5mbbJsK0qX9+TKFr7A8yEwrZZc+DMdyUelsN+oE0pdUEpNQM8Cdy3zH3fDjyvlBpSSg0DzwP3xEGmlKfBdF/YFPiESFA6N8PrqAfebuxKLY5me1U+lwbGtbvPoLHLvmC0ydYkVQ5rgY6o353GsoW8V0ROi8jTIrJuhftqVkiD8cBbnUsfjccIhp/r0W4lgPHpOS4MjNuSWhzNtqp8wgqatbsPiHSk8jLT2FCcY5sMeZlprC/OcdS7YlVA+n8DG5VSu4lYB4+v9AAi8pCIHBORY36/P+4CJhuN3aPUlOaSlxmXacJXzbaqfM71jjkq0GYXTb1jKGVfMNpkuwN7qXbS2D3G9qp8PB575zzfVuVz1D2Jh3LoAtZF/a42ls2jlBpUSk0bP78K3LTcfaOO8ZhSap9Sal9ZWVkcxE5uGrrGbLUaTLavyScwNUfn8KTdotiOac3ZGfgEqC7KJi8zzVENkV2Ewoqz3WO23xOIjHe4ODjOxMyc3aIA8VEOR4FaEdkkIhnA/cAz0RuISFXUz3uBc8b354C7RaTICETfbSzTxMDw+AxdI5O2+lBNnBhos4uGrlFKcjOozLc+lz4aj0fYWumsXqpdXBwIMjkbst2ag4jloBSOKTkTs3JQSs0BHyPSqJ8DvquUahSRz4rIvcZmHxeRRhE5BXwc+KCx7xDwV0QUzFHgs8YyTQyYaYp2ZiqZbK30IYKjfKl20dgdsebsyqWPJpKxFEj52frmU4sdYDmYHSmnpBnHxSGtlDoEHFqw7NNR3x8BHlli368DX4+HHJoIZo/QfNjsJCcjjY0luSnfS50NhWnrD/KW2o12iwJEno1vH2mnc3iS9SX2BWLt5lxPgHSvsLnMupL2S1FdlI0vyznuPj1COglp7g1QmpdBqY259NFsq/JxrtcZD7xdXBoYZyYUtqWUyWJsq4rI4ZReql009Y6xuSzP8pL2iyEibKvMd4yVbf8V0cSdpt6AYxohgG2V+bQPThCcdkagzQ7OGX5kp9yX+nl3X2orh+beAFsdck8gorSbesYc4e7TyiHJMMtVbK2036VkYrq3mlPYemjujRRB3FJuv/sCIu6+TaWp7e4bNcpV1DvsXRmfCdExPGG3KFo5JBvtg+NMzznHfQGwbY0ZaHOGuWwHzb0BakpzyUyzpwjiYphjUFIVcxCgsywH52T3aeWQZJhpcE564NcUZJHvoECbHTjN1QeRwXAdQ5MEplJzbgfTknXSfamv9OERZ3SktHJIMpp6A4hAbblzHngRSelib8HpyCBAJylsuBKUbnJIXr3VNPUG8GWlUWXDHA5LkZXudYy7TyuHJKO5N8DGklyyM5zjvoCIudzcm5p59c3zwWjn+LbBWS4MOzCD0U4YdxKNUzpSWjkkGc19AeornNVDhYgLY2ImRPuQ/YE2q3Giqw+gMj+Lwpx0RzREVqOUirwrDrsnEFEOkfnf7XX3aeWQREzOhLg0OO7IB77OkCkVJ/5p7h0jN8PL2sJsu0V5HSJCXYWPlr6g3aJYTvfoFIGpOcdZc8B8567V5vuilUMS0dofQCnn9VABao0UztYUVA5NvQHqKn22V/1cjLqKPFr6AilXNdcMRm9z4LtSN68c7H1XtHJIIpocNtAqmtzMNKqLsmlOsV6q6b5wosKGSC81MDVH75hzpqe0AvNdqXPgfakuyiY73Wv7fBtaOSQRzb0BstI9bCjJtVuURamv8NGSYpkx/YFpRiZmHRkHAqitMN19qaW0m3oCrC3MJj8r3W5RrsLjEeoq8rRbSRM/mnsD1Jb78DrQfQGRhujCQJDZUNhuUSyjyaGZSiamCyPVlHazA8edRFNb4dOWgyZ+NDmsTsxC6ivzmA0pLg2M2y2KZZi+bafel+LcDMp8mSmVKDAzF+a8P+ho5VBf4cMfmGZ4fMY2GbRySBIGg9MMBKcd/cDXpaALo6k3QEV+JkW5GXaLsiRmUDpVuDAQZC6sHKuwwRnZfVo5JAlXcumd6b4A2FyWh0dSa2L7iPvCufcEmE9nTZUBis0OTtwwqauIZPe5XjmIyD0i0iwibSLy8CLr/1REzorIaRF5UUQ2RK0LichJ4/PMwn01y8NscOsqnVH1czGy0r1sLMlNGf92KKxo6w9SX+HcewIR5TA5G6JrJDXm+W7uDZDmEWpKnXtfKvOz8GWl2Wplx6wcRMQLfBE4CGwHHhCR7Qs2+w2wTym1G3ga+PuodZNKqb3G5140q6K1P0hhTjplDpngZylqK/Jo6U8N5dAxNMH0XHg+I8ipmO4+p8xdnGha+4NsLM0lI825jhNzgKKdVnY8rs5+oE0pdUEpNQM8CdwXvYFS6iWllFk34QhQHYfzaqJo7QtQV+68OjELqa/wcWlgnKnZkN2iJBzTJVDncOVQa7owUkRpt/YF5t02TqauwkerjQMU46Ec1gIdUb87jWVL8WHg2ajfWSJyTESOiMi7ltpJRB4ytjvm9/tjEjjZUErR0hdkixse+EofYQXn/ckflG7tj/yPTpngZynys9JZU5CVEu6+qdlIfa8tDqpavBT1FXkMT8ziD07bcn5L7SoR+V1gH/APUYs3KKX2Ab8D/JOIbF5sX6XUY0qpfUqpfWVlZRZI6x78wWlGJ2epc3gjBNGlAVJAOfRFBlrlZabZLcp1ieTVJ/89Oe8PohSusRwAWnrtuS/xUA5dwLqo39XGstchIncBnwLuVUrNq0KlVJfx9wLwMnBDHGRKKcyG1unuC4CNJbmkeyUlMpZa+oKOtxpM6it9nPcHmUvyAYpuelfsTmeNh3I4CtSKyCYRyQDuB16XdSQiNwBfIaIY+qOWF4lIpvG9FHgTcDYOMqUU5sPjBrdSRpqHTaXJn7EUCivO+4Ou6KFCpLGcmQsnfUn11v5IptJGh5aYiaY0L5Pi3Az3Kgel1BzwMeA54BzwXaVUo4h8VkTM7KN/APKA7y1IWd0GHBORU8BLwKNKKa0cVohbMpVM6ip8SR/8nM9UcoFvG664WeyuBJpoWvqcn6kUjZ0DFOPiDFVKHQIOLVj26ajvdy2x3yvArnjIkMq09gWoLc9zfKaSSX2Fjx+f7mF8eo5cF/jjV4P5Qte6xHLYUp6HCDT3Brlnp93SJI7WvsD8DHhuoL7Cx/dPdKGUsvz9dof61CyJmank9Fz6aExZzWyeZMT839xyX3Iy0lhXlJPUZTSmZkNcHppwzT2ByPMTmJ6je9T6kupaObgcN2UqmZi96bZkVg59AdYUZLkiU8mktjwvqe/JeX+QsEsylUzMSbLsuC9aObgcM/vCTb2hDcU5ZHg9tCZx3KG1313WHFwpqZ6sGUtmA+uWOBDYOyucVg4ux22+bYA0r4easlzakjSv3qypVOsiaw4ivdTZkErajKWWvgBej7Cp1PmZSiZFuRmU5mVoy0Gzclr7gxRkuydTyWRLeV7SxhzMTCU35NJHUzufsZSc96WlL8jGkhzXZCqZ2PWuuOsqaa7CrBPjlkwlk9pyHx3DE0zOJF+NpfmyGS6y5iBSUh2gLUndfW39QdcpbIi8K3bUWNLKwcW4MVPJpLYiD5WkNZbmXX0ucyvlZqaxtjA7KS26qdkQ7YPjrn1Xxqbm8AesrbGklYOLMTOV3NYIgb1ZGImmrT9IVUEWPgdOXn89ah0wsX0iuOAfJ6zcp7DhSuFGq5W2Vg4uxk11YhayoSSXNI8kZcZSS1/AlT1UiDSe5/1BQkk2K5z5nLnxXTGzq6zOWNLKwcW0utR9AZEaSxtLc5Oul2rWVHLjPYFIQzQ9F6ZzOLkyllr7gq7LVDIpzcugMCddWw6a5TOfqeRzV6aSSTIOuuoanmRqNuyqgVbRbEnSjKXW/oArM5UgMitcbbn17j73XSnNPK1GLr3bMpVMasvzuDQ4zvRc8mQsme4LN0wmsxh2+bcTTeRdcec9gcjz1NJvbcaSVg4upq3fPfMFLMaWisiscBcHxu0WJW64Zfa3pcjPSqcyPyupYkHTcyHaBydce08g0pEamZhlcHzGsnNq5eBSBoPTDI3PuP6Bh+RyYbT2BSn3ZVKQ7b5MJZPaiuRy910amCAUVq6qIrAQOwYoauXgUtxW9XMxNpXm4pHkcmG09Qdc3QhBxOpp6w8STpKMpSuuPvfeF9MlZuUARa0cXMqVImLufeCz0r1sKMlNmhG5Spk1ldyrsCHSEE3MhOgenbRblLjQ1h9E5MoIcDdSkZ+JLzPN0o5UXJSDiNwjIs0i0iYiDy+yPlNEnjLWvyoiG6PWPWIsbxaRt8dDnlSgrT9IboaXqoIsu0WJiS02ZGEkip7RKcZnQq7uoUKUCyNJLLrW/iDri3PISvfaLcqqERG2WDxAMWblICJe4IvAQWA78ICIbF+w2YeBYaXUFuALwOeMfbcTmXN6B3AP8CXjeJrr0NofYEuFz7WZSia15XlcHBhnNgnKRLcmgTUHsMWssZQkSrutz73jTqKptbgAXzwsh/1Am1LqglJqBngSuG/BNvcBjxvfnwbulEirdh/wpFJqWil1EWgzjpcQvvhSG48+25Sow1tKa7I88BV5zIUVl5IgY2l+UKKL40BglonOTIpZ4eZCYS4MBF2bWhxNbbmPgeA0wxZlLMVDOawFOqJ+dxrLFt1GKTUHjAIly9wXABF5SESOicgxv9+/KkGbegP815nuVe3rJEYnZukPTLvefQHRgTb391Lb+oMU52ZQnJthtygxU1ueR1sSFEVsH5pgNqSS4l3ZWuWjvsJnWTqrawLSSqnHlFL7lFL7ysrKVnWM2vI8OocnmZiZi7N01tLmd2/ZjIVsLotMbJ8M/u1Wl487iaa2Io+2vqDlZaLjzfxMiUlwX95SW8Zzn7jVsmcsHsqhC1gX9bvaWLboNiKSBhQAg8vcN27UlkfKRF/wu9uF4cbpDpciO8NLdZH7y0RfyVRyfyMEkXclMD1H35i1ZaLjjVkSfnOS3BcriYdyOArUisgmEckgEmB+ZsE2zwAPGt/fB/xMRbokzwD3G9lMm4Ba4LU4yLQoV7Iw3O1Lbe0LkpXuYW1Rtt2ixAVzMhM34+by6Yth+ujd/64EWFuYTV5mmt2iuI6YlYMRQ/gY8BxwDviuUqpRRD4rIvcam30NKBGRNuBPgYeNfRuB7wJngZ8Af6SUSlihnQ0luaR7xfWpk639QTaX5eH1uDtTyaS2PI8LA+OuntjezOxxezDaJFmmDE0mV5/VxEWdKqUOAYcWLPt01Pcp4P1L7Ps3wN/EQ47rke71sKk01/UujLb+IDdvLLJbjLixpTyPmbkwHcOTriypDMmTxmpSkptBkQ1louNJKBxx9b2hpsRuUVyJawLS8cLtLozg9BxdI5NJ1Rsye9tuvi+t/QF8WWmuLZ++kEiZaJ+rR693DU8yPRdOqnfFSlJOOWwpz+Py0ARTs+4sE31+vupncrgvIDnKRJvjTtw+KDGaLRV5tLg4Y8mMl7i91pVdpJxyqK3II+zijKX5TKUkeuDzMtNYU5DlasshMvtb8ihsiLjIRidn8QfdmbFkvitbypLrvlhF6ikHl2dhtPQHSPcKG4pz7BYlrmyp8LnWchgan2Eg6O7y6YsxP0DRpUHplr4gZb5MCnLcWz7dTlJOOWwszcHrEdeOyG3rC1JTmkeaN7lunTllqBsntr9SNiPJlIPLC/C19QdcO12rE0iuFmYZZKZ52VCS49oUvZYkmC9gMWrL85ieC9M17L4y0S1G41mXJGmsJuW+THxZaa60ssNh5fqpQe0m5ZQDmNUN3ffAT8zM0Tk8mZQPvJsHKLb1BcjLTHN9+fSF2DWxfTzoHp1kYiaUlB0pq0hR5eDj0uAEM3PuGnR1vn8cpUhKU9kMGrrRhdHSFxlolUyZSiaRdFb33RNToSWbNWclqakcKvIIhRWXBt2VsdSSJCWhF6MgJ51yX6Yre6mtSezbrq3IY3B8hkGXZSzNvytJliRgJSmpHObz6l3WELX2ByOZSiXJlalkEpnY3l1uJTNTKRldfXDlXXGb9dDaH8lUKsxxf/l0u0hJ5XClTLS7GqLWvgA1pXmkJ1mmkklteSSd1U2DrpI1U8lkfvS625RDX/Jac1aRnK3MdchK97K+OMd1D3xLf4AtSfzAbynPMya2n7JblGWTrJlKJmsKssjN8LrKctCZSvEhJZUDGBlLLhqRa2Yq1SXxA2/6h900PWWyZiqZiAhbyvNcdU90plJ8SF3lUOFz1cT2yZypZGL2vt00IjeZM5VMal02el1nKsWHlFUO9RU+ZkPumdg+FYqIFeVmUObLpNlFvdTW/mBSK2yIvCv+wDRDFs1dHCvz74rOVIqJlFUOZiPrloaopc/MVHLnfAfLpa7CPS6M4fEZBoLTSe/brquM/H9uuS9mTSWdqRQbMSkHESkWkedFpNX4e9UMNCKyV0R+LSKNInJaRH47at03ReSiiJw0PntjkWclbC7LwyORB8kNtPYF2FSam7SZSiZ1FT5a+4KEXVBjqSXJM5VM6uZnhXOHcmjtC2irIQ7E2tI8DLyolKoFXjR+L2QC+D2l1A7gHuCfRKQwav2fK6X2Gp+TMcqzbLLSvWwszaWl1yUPfH8wKQe/LaS+wsfkbIhOF9RYak3yTCWTyvwsfFlprrCylVKGqy+574kVxKoc7gMeN74/Drxr4QZKqRalVKvxvRvoB8piPG9cqCv30eKCsQ6TMyE6hieSOlPJxFSAbnBhtCZ5ppKJiFBX4XOFld01ojOV4kWsyqFCKdVjfO8FKq61sYjsBzKA81GL/8ZwN31BRJacY1FEHhKRYyJyzO/3xyh2hLpKH5cGxh0/K9x5fxClkt99AVdcGG7opZqT1ydzppJJRDkEHD9A8cpc3snfkUo011UOIvKCiDQs8rkvejsVeWqWfHJEpAr4NvD7Sikzf/QRYCtwM1AM/MVS+yulHlNK7VNK7Ssri4/hUWfMCnfe7+wekdmLTvasGABfVjprCrJcYTm09CV/ppJJfUUeIxOz+APOrrHUqmsqxY20622glLprqXUi0iciVUqpHqPx719iu3zgv4BPKaWORB3btDqmReQbwJ+tSPoYqZ+f2D7IjjUFVp56RaRKppJJXaXzXRipkqlkUjfv7gtSnu9cN1pLX5DSvEyKcnWmUqzE6lZ6BnjQ+P4g8KOFG4hIBvAD4FtKqacXrKsy/gqReEVDjPKsiI2luaR7xfEujJYkr6m0kLoKH+f7g8w5eICi+cyYaZ7Jjvl/uuFdqa/UVkM8iLW1eRR4m4i0AncZvxGRfSLyVWObDwC3Ah9cJGX1OyJyBjgDlAJ/HaM8KyLd66Gm1PllNJp7A9SnSCMEEeUwEwrTPjRhtyhL0mxkuW1NkftSmpdJSW6Go9+VUFhFlENFvt2iJAXXdStdC6XUIHDnIsuPAR8xvv878O9L7H9HLOePB3WVPk52DNstxpKMTc3SNTLJ79yy3m5RLMN097X0Bthc5sxeYFNvgEJjDopUobYiz9GWw+WhCaZmwymjsBNNavgprkFdeR4dQ5OMT8/ZLcqitKRYDxUwMoCc7cJo7h2jvsKXEplKJvXGAEWnZiw1944BpJSVnUi0cjAeJKeWJG4ylEMqPfDZGUZJdYcGpcNhRUtfMKUUNkTeleD0nGNLqjf1BhBJ/kGJVqGVQ4WzA23NvQF8mWmsLcy2WxRLqS33OfaedI1MEpyeo74ytXzbdVHuPifS3BtgQ3EO2Rleu0VJClJeOawvziEzzePoB76uMrXcFwD1lXlcHBhnes55AxRT0ZoD5kfoO1Vpp1riRqJJeeXg9Qi1FXnzM3o5CaUUTb1jKee+gEgvNRRWXHRgSfVU9W0X5KRTme/MAYpTsyEuDY6zNcWsuUSS8soBIj0i84V3Er1jU4xNzaWscoArKaNOoqk3QHVRNnmZMSX7uZLaijxH3pPWviBhlVqJG4lGKwciPcC+sWmGHTaZyRX3Rer1hmrKcknzyPw1cBLNvYGUbYS2VkZmhXPaAMWmFLXmEolWDsC2qkjje67HWdaD2UOrT8Hsi8w0L1vK8xx3T6bnQlwYGE/ZRmhbVT4zc2HHufuaewNkpXtSpsSMFWjlwBXlcNZhDVFzb4CqgiwKctLtFsUWtlflO045nO8fJxRWKWnNgYPflb4AteU+vJ7UStxIJFo5AGW+TMp8mZzrcZYLoynFsy+2VeXTNzbNYNA5lUCb+yKNYqq6lTaX5ZHuFccph1R/VxKBVg4G2xzWS50NhWnrT+0H/oq7zzlKu6k3QLpX2FSamu6LjDQPW8p9jrong8Fp/IHplFXYiUIrB4NtVT7a+oPMOiTQdnFgnNmQSukHfltV5H93ktJuNuo9pUqF3MXYVuVz3D0BHYyON6n7hC9ge1U+M6GwYyb+mc9USuEKkyV5mZT7Mh3XEKWywobIu+IPTDPgEHdfqg5KTDRaORg4LWOpuXcMr0fYXJ6a7guTbVX5jvFvj07M0jM6lbLBaBPnvSsBinMzKMtLnQq5VqCVg0FNaS4ZaR7H+FKbegLUlOaSmZbadWK2VeVz3h9kZs5+d9+53tQORps4TTk0pWCFXCuISTmISLGIPC8ircbfoiW2C0VN9PNM1PJNIvKqiLSJyFPGrHG2kOb1UFfhnLz6xu4xdq517tSlVrGtysdsSDmiam5jd+TZ2LE2tS2H4twMKvOzHNGRmg2FOdcbYGeK35NEEKvl8DDwolKqFnjR+L0Yk0qpvcbn3qjlnwO+oJTaAgwDH45RnpjYVpnP2e4x2+vV+wPT9I5NsWONfuC3O6iX2tg1Srkvk3Kfc+dQtgqnBKVNq1J3pOJPrMrhPuBx4/vjROaBXhbGvNF3AOa80ivaPxFsq8pncHwGf8DeQFtj9ygAO9boB37TvLvP/oaooXtUN0IG26ryaesP2l41t6HLsOb0uxJ3YlUOFUqpHuN7L1CxxHZZInJMRI6IyLuMZSXAiFLKnIKtE1gbozwx4ZTRn6b7Yru2HEjzeqiv8M37++1iciZEW39QW3MG26rymQvb7+5r7B4lO92bsuNOEsl1lYOIvCAiDYt87oveTkV8MUv5YzYopfYBvwP8k4hsXqmgIvKQoWCO+f3+le6+LLY7ZNBVY/coG0pyKMhOzbIZC4m4MAK2uvuaescIK91DNXHKAMXGrjG2r8nXZTMSwHWVg1LqLqXUzkU+PwL6RKQKwPjbv8Qxuoy/F4CXgRuAQaBQRMy6x9VA1zXkeEwptU8pta+srGwF/+LyKchJZ21htu0ujIauMXbqRmie7VX5DI3P0G+ju6/BsOZ04DPCptJcstLtdfeFw4rG7lF2amsuIcTqVnoGeND4/iDwo4UbiEiRiGQa30uBNwFnDUvjJeB919rfauwOtI1OznJ5aEK7lKJwgrvvbPcohUbnQROZJKu+wt535dLgOOMzIXboOFBCiFU5PAq8TURagbuM34jIPhH5qrHNNuCYiJwiogweVUqdNdb9BfCnItJGJAbxtRjliZltVflcGBhncsaeQNvZ+R6qfuBNtprKodu+hqiha4wda/J1Ln0U5gBFu9x9pjWn40CJIaaprJRSg8Cdiyw/BnzE+P4KsGuJ/S8A+2ORId7sWltAKKw42zPKTRuKLT//lUwl/cCbFGSns7Ekh9OdI7acf2YuTHNvgN9/00Zbzu9UdlUX8OTRDjqGJllfkmP5+Ru7R8nweqgtT+1BiYlCj5BewJ51hQCc6hi15fwNXaNU5mdRqksBvI7d1YWc7rTnnrT2B5gJhbX7YgF7qgsBOGWT0m7sGqO+0kdGmm7GEoG+qguoyM+iIj/Ttl5qZGS0thoWsru6gJ7RKfrHpiw/t5larAOfr8dsmO14V5RSxrgTfU8ShVYOi2BXL3ViZo7z/qBOl1yEeYvOhvvS2DVKboaXjXoKyteR7vWwY02+LVZ218gkIxOzbNfvSsLQymER9lQXcGFgnNHJWUvPe64nYOTS697QQnasyccj2NJLbeiO5NJ7dC79VeypLqShe5RQ2NqgtDkyWltziUMrh0Uwe6lnLO6lmsFonal0NTkZadRV+Cy3HEJhxdnuMW3NLcHu6gImjNHjVnK2exSvR+bTnDXxRyuHRdi9thCwPtDW2DVGcW4GVQW6sNti7Kku5HTniKWpkxcHxpmcDWmFvQS7bQpKN3SPsaUsj6z01C5pn0i0cliEghx7UidPdY7oXPprsHtdASMTs3QMTVp2TvMZ0IHPxakpzcWXmWbpu6KU4nTnSMqXTk80WjksgdVB6cDULM19AW7asOiUGBqupE6etLAhOt4+jC8zTefSL4HHI+yqLrA0KH15aIKB4Ix+VxKMVg5LMJ86GbAmdfJkxwhKoR/4azCfOtkxYtk5j7cPs3d9oS7sdg12VxfS1DtmWfnu4+3DgH5XEo1WDkuw1whKn7aoR3S8fRiRK+fVXI2ZOmmVRaetueWxp7qA2ZCyrEKrtuasQSuHJdixpgCvRywLtB1vH6a+wocvS5fpvhZ7qgs50zXKXCjxc0qf6hjV1twyMLP7rIo7nLg8oq05C9DKYQmyM7zUludZkjoZDitOXh7hRt0IXZfd1QVMzoZo8yc+dVJbc8ujqiBS7uWkBe6+wNQszb1j3LhevyuJRiuHa2BV6mRrf5DA9Bw36Qf+upipk1a4+45f1tbcchAR9lQXWOLuO9UxSlhbc5aglcM12Lu+kJGJWS4OjCf0PDrAtnxqSnPxZaVx4vJwQs8TDit+0z6srbllsnddIef9QUYnEltVYN6aW1+Y0PNotHK4Jvs3RUp2v3pxKKHnOd4+TEluBhtsKHvsNjweYf/G4oTfE23NrYz9m4pRCl67lOB3xbDm8rU1l3C0crgGNaW5lPkyOXJhMKHnOXE50kPVg9+Wx4GaEi4OjNM7mrg0Y9My0dbc8tizrpDMNE9C35VwWPGby9qas4qYlIOIFIvI8yLSavy96q6JyFtF5GTUZ0pE3mWs+6aIXIxatzcWeeKNiHCgpoQjFwYTFncYDE5zcWBcN0Ir4EBNCQCvXkxcQ6StuZWRle7lxvVFCVUObf4ggSltzVlFrJbDw8CLSqla4EXj9+tQSr2klNqrlNoL3AFMAD+N2uTPzfVKqZMxyhN3DtQU0zc2zaXBiYQc/8TlEQCdfbECtq/Jx5eZxpELiXNhnGgf5ob12ppbCQdqSjjbM5awuIMZm9OWgzXEqhzuAx43vj8OvOs6278PeFYplZiWNgGYvdRE9YiOtw+T5hF2V+vCbsvF6xH2byrm1QTdk6HxGS5oa27FHKhJbNzhePswxbkZbNTWnCXEqhwqlFI9xvdeoOI6298PPLFg2d+IyGkR+YKILDk3pog8JCLHROSY3++PQeSVkei4w4n2YXasLdDVJVfIgZoSLgyM05eAmeFO6OyxVZHouMOJ9mFu1NacZVxXOYjICyLSsMjnvujtVMQpv6RjXkSqgF3Ac1GLHwG2AjcDxcBfLLW/UuoxpdQ+pdS+srKy64kdNxIZdwhOz3Hi8jAHaorjetxUIJEW3S/bBshK92hrboVkpXu5YX1hQu5J5/AEFwbG9btiIddVDkqpu5RSOxf5/AjoMxp9s/Hvv8ahPgD8QCk175BUSvWoCNPAN4D9sf07iSFRcYdX2gaYCyturyuP63FTgUTGHQ63+HlDTYm25lZBouIOP28ZAOD2eus6hqlOrG6lZ4AHje8PAj+6xrYPsMClFKVYhEi8oiFGeRLCfHZMnHtEh1v85GZ4tftiFSQq7tA+OM7FgXFur9cKezUcqClBKTga57jD4ZZ+1hZms7ksL67H1SxNrMrhUeBtItIK3GX8RkT2ichXzY1EZCOwDji8YP/viMgZ4AxQCvx1jPIkhETEHZRSHG7x88YtpWSk6eEmq8GMO/THMe7w85ZIPOu2Ot1DXQ171xWSEee4w2wozK/aBrmtvkzHGywkLZadlVKDwJ2LLD8GfCTq9yVg7SLb3RHL+a3iStxhCKVUXB7Q8/5xOocn+ehtm+MgYWoyH3e4OMS9e9bE5ZgvN/vZUJLDxtLcuBwv1YiMdyjkSBzHoBxvHyY4PacVtsXoLusyOVBTTO/YFOf98amzdFj3UGNm+5p8fFlp/Kp1IC7Hm54L8cr5QX1PYuRATQmN3WMMjc/E5XiHW/ykeYQ3bi6Jy/E0y0Mrh2XyVsMH/Vxjb1yOd7jFT01ZLuuKdc72avF6hNvry3nhXB+hcOyZZMcuDTM5G9LKIUbu3FqBUvDC2b64HO9ws5+bNhTp6rgWo5XDMllTmM3edYX8pCF25TA1G+LVC4M6SykOHNxZyeD4DK/FoRDf4RY/GV7PvLtKszp2rs2nuiibZxt6rr/xdegfm+Jszxi36Swly9HKYQW8Y1clZ7pG6RiKLaX1yIVBpufC+oGPA7fXl5GV7olLQ3S42c/Nm4rIzYwpFJfyiAgHd1byy7YBRidjS2n9ueEy1Nac9WjlsAIO7qwCiNl6ONziJzPNwy2b9ICeWMnJSOOt9eU829BLOAbXUs/oJM19Ad0IxYmDu6qYDSl+1hSba+lwi58yXybbq/LjJJlmuWjlsALWFeewc20+h2LopSqleKmpn1v0IKu4cc/OSvyBaY7HMAHQz5oi4zdv1cohLuytLqSqIItDZ1bfkZqZC/OLVj9vqS3VKaw2oJXDCjm4s4rfXB6hZ3RyVfsfax/m0uAEv7W7Ks6SpS53bC0nI83DszE0RN871smW8jzqK3xxlCx18XiEt++o5HCLn+D03KqO8eK5PkYmZvk/dscnTVmzMrRyWCEHd1YCq3ctPfHaZfIy07RyiCO+rHRurS3l2YaeVbmWmnrHONkxwv03r9M91Djyjl1VzMyFeanpWlV1luaJox1UFWRpa84mtHJYITVleWyt9K2qlzo6OcuhMz3cu3cNORk66BlPDu6somd0ilOdIyve98nXOsjwenjPjdXxFyyFuWlDEWW+zFUlC3QMTfCLVj/v37cOr0crbDvQymEVHNxZxdH2oRWXi37mZBdTs2EeuHl9giRLXe7aVkG6Vzh0ZmUN0dRsiB/8pou7d1RQnJuRIOlSE69HuGdHJS81+ZmYWZlr6XvHOwH4wD6tsO1CK4dVcO/eiA/0G7+6tOx9lFI88VoHO9bks0uXgo47BTnp3LG1nKeOdjA2tfz0yZ809DI6OcsD+7XCTgTvumEtk7Mh/uPVy8veJxRWfO9YB7fWllFdpAeJ2oVWDqtgU2ku9+5Zw7d+fYnB4PSy9jnTNcrZnjHuv3ldgqVLXf74jlrGpub45gqU9pNHL7OuOJs36IFvCeGmDUW8cXMJXz58gcmZ0LL2OdzST8/olH5XbEYrh1Xyx3fUMjkb4t9+cXFZ2z95tIOsdA/33XBV/UFNnNi5toC7tlXw1V9cWJb1cHFgnCMXhrj/5vV4tF87YfyPO2sZCE7znVfbl7X9k691UJqXwZ3brjexpCaRaOWwSraU5y3beugYmuCHv+ninbvWkK/rwySUP7krYj08vgzr4X/9rA2vR3jfTdqvnUhuqSlZtvVwtnuMF5v6ee9N1bqUvc3oqx8Dy7EeQmHF//zuKTwifOJttRZKl5rMWw+/vHhN6+Gnjb3854lO/vutNVTkZ1koYWqyHOthajbEJ546SXFuBh+9VZeytxutHGIg2npYasKZr/7iAq9dGuIz9+7QwTWL+JO7ahmdnOWrSyhtf2CaR75/hh1r8vmTu+osli41ibYeAkso7X/8aTPNfQH+/n27KdKZY7YTk3IQkfeLSKOIhEVk3zW2u0dEmkWkTUQejlq+SUReNZY/JSKueyI+fmctobDi/V/5NRf8wdetO9czxj/+tIW376jgvTfqWINV7FxbwDt3V/HPL7byry+fR6krA+OUUjzy/dMEpuf4wm/v1a4LC/mfd9cxPDHDB75yhN7R13emfn1+kK/+8iL/5y3r58vja+wl1jejAXgP8POlNhARL/BF4CCwHXhARLYbqz8HfEEptQUYBj4cozyWs7ksjyceOkBgao73/OsrHLs0ROfwBN8+0s4ffucE+dnp/O27d+mRtxbz+Q/s4d49a/jcT5r41A8bmJiZ43CLn08+fZoXzvXzybfXU6dLZVjKTRuK+foHb+by4Djv/tKvaOod4+LAOF/75UU+8dRJNhTn8Kl3brNbTI2BRPeqVn0QkZeBPzOmB1247g3AZ5RSbzd+P2KsehTwA5VKqbmF212Lffv2qWPHrjqVrbQPjvPBbxylfXAcs4LD+uIcHn3PLt64pdRe4VKUcFjx//60mS+9fB6PQFhBZpqHd9+wlr999y6doWQTZ7vH+NA3j9IfmJp/V2rL8/j8B/bqMUAJRkSOK6WW9PJEY0UNh7VAR9TvTuAWoAQYUUrNRS1f0vciIg8BDwGsX++8AUsbSnL5/h+8kS+93EZFfha315ezuSxXWww24vEIn7xnK1ur8jnVMcKba0t5g66Gazvb1+Tzgz96I185fIGaslxurytnfYmOxzmN6yoHEXkBqFxk1aeUUj+Kv0iLo5R6DHgMIpaDVeddCUW5GXzqnduvv6HGUu7ds4Z79+jKnk6iqiCbz9y7w24xNNfguspBKXVXjOfoAqKHOlYbywaBQhFJM6wHc7lGo9FobMaKVI2jQK2RmZQB3A88oyLBjpeA9xnbPQhYZoloNBqNZmliTWV9t4h0Am8A/ktEnjOWrxGRQwCGVfAx4DngHPBdpVSjcYi/AP5URNqIxCC+Fos8Go1Go4kPcclWshonZitpNBqN01lJtpIeAaTRaDSaq9DKQaPRaDRXoZWDRqPRaK5CKweNRqPRXIUrA9Ii4gcWq/1bCgxYLM5K0PLFjtNldLp84HwZtXyxs5SMG5RSZcs5gCuVw1KIyLHlRuLtQMsXO06X0enygfNl1PLFTjxk1G4ljUaj0VyFVg4ajUajuYpkUw6P2S3AddDyxY7TZXS6fOB8GbV8sROzjEkVc9BoNBpNfEg2y0Gj0Wg0cUArB41Go9FcheuUg4i8X0QaRSQsIvsWrHtERNpEpFlEFp1u1Cgd/qqx3VNGGfFEyfqUiJw0PpdE5OQS210SkTPGdpZVFBSRz4hIV5SM71hiu3uMa9omIg9bJZ9x7n8QkSYROS0iPxCRwiW2s/QaXu+aiEimcf/bjOdtY6Jlijr3OhF5SUTOGu/K/1hkm9tFZDTq3n/aKvmiZLjmPZMI/2xcw9MicqOFstVHXZuTIjImIn+yYBvLr6GIfF1E+kWkIWpZsYg8LyKtxt+iJfZ90NimVUQevO7JlFKu+gDbgHrgZWBf1PLtwCkgE9gEnAe8i+z/XeB+4/uXgT+wSO5/BD69xLpLQKkN1/IzROb+vtY2XuNa1gAZxjXebqGMdwNpxvfPAZ+z+xou55oAfwh82fh+P/CUhdesCrjR+O4DWhaR73bgx1Y/cyu5Z8A7gGcBAQ4Ar9okpxfoJTKAzNZrCNwK3Ag0RC37e+Bh4/vDi70jQDFwwfhbZHwvuta5XGc5KKXOKaWaF1l1H/CkUmpaKXURaAP2R28gkQmd7wCeNhY9DrwrgeJGn/cDwBOJPlcC2A+0KaUuKKVmgCeJXGtLUEr9VF2ZZ/wIkRkD7WY51+Q+Is8XRJ63O8WiCcWVUj1KqRPG9wCReVSWnJ/dwdwHfEtFOEJk5sgqG+S4EzivlFqsKoOlKKV+DgwtWBz9rC3Vpr0deF4pNaSUGgaeB+651rlcpxyuwVqgI+p3J1e/ECXASFRjs9g2ieAtQJ9SqnWJ9Qr4qYgcF5GHLJAnmo8ZJvvXlzBHl3NdreJDRHqSi2HlNVzONZnfxnjeRok8f5ZiuLNuAF5dZPUbROSUiDwrInZM6Hy9e+aUZ+9+lu7Y2X0NASqUUj3G916gYpFtVnwtrzuHtB2IyAtA5SKrPqWUctRUosuU9QGubTW8WSnVJSLlwPMi0mT0EBIqH/CvwF8ReUn/iojr60PxOO9KWM41FJFPAXPAd5Y4TMKuoVsRkTzgP4E/UUqNLVh9goibJGjEmn4I1FosouPvmRGTvBd4ZJHVTriGr0MppUQkLuMTHKkclFJ3rWK3LmBd1O9qY1k0g0RM0zSjN7fYNivierKKSBrwHuCmaxyjy/jbLyI/IOK2iMtLstxrKSL/Bvx4kVXLua4xsYxr+EHgt4A7leFAXeQYCbuGi7Cca2Ju02k8AwVEnj9LEJF0IorhO0qp7y9cH60slFKHRORLIlKqlLKsoNwy7lnCn71lcBA4oZTqW7jCCdfQoE9EqpRSPYbbrX+RbbqIxEhMqonEbZckmdxKzwD3G1kim4ho8NeiNzAalpeA9xmLHgQSbYncBTQppToXWykiuSLiM78TCcA2LLZtvFngv333Euc9CtRKJMsrg4iJ/YwV8kEkKwj4JHCvUmpiiW2svobLuSbPEHm+IPK8/WwpxRZvjNjG14BzSqnPL7FNpRkDEZH9RNoCK5XXcu7ZM8DvGVlLB4DRKPeJVSxp9dt9DaOIftaWatOeA+4WkSLDfXy3sWxprIy0x+NDpBHrBKaBPuC5qHWfIpJF0gwcjFp+CFhjfK8hojTagO8BmQmW95vARxcsWwMcipLnlPFpJOJKsepafhs4A5w2HrCqhfIZv99BJOPlvJXyGeduI+IrPWl8vrxQRjuu4WLXBPgsESUGkGU8X23G81Zj4TV7MxFX4emo6/YO4KPmswh8zLhWp4gE+t9o8X1d9J4tkFGALxrX+AxR2YkWyZhLpLEviFpm6zUkoqh6gFmjHfwwkVjWi0Ar8AJQbGy7D/hq1L4fMp7HNuD3r3cuXT5Do9FoNFeRTG4ljUaj0cQJrRw0Go1GcxVaOWg0Go3mKrRy0Gg0Gs1VaOWg0Wg0mqvQykGj0Wg0V6GVg0aj0Wiu4v8Hg5zqbaUp4PoAAAAASUVORK5CYII=\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "plt.plot(x, y)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us quickly generate some random data and draw a scatter plot with `numpy`'s `random` module." - ] - }, - { - "cell_type": "code", - "execution_count": 20, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 20, - "metadata": {}, - "output_type": "execute_result" - }, - { - "data": { - "image/png": "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\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "x = np.random.normal(42, 3, 100)\n", - "y = np.random.gamma(7, 1, 100)\n", - "\n", - "plt.scatter(x, y)" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.8.9" - }, - "toc": { - "base_numbering": 1, - "nav_menu": {}, - "number_sections": false, - "sideBar": true, - "skip_h1_title": false, - "title_cell": "Table of Contents", - "title_sidebar": "Contents", - "toc_cell": false, - "toc_position": {}, - "toc_section_display": true, - "toc_window_display": false - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} diff --git a/01_scientific_stack/00_content_numpy.ipynb b/01_scientific_stack/00_content_numpy.ipynb new file mode 100644 index 0000000..1872760 --- /dev/null +++ b/01_scientific_stack/00_content_numpy.ipynb @@ -0,0 +1,1354 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Note**: Click on \"*Kernel*\" > \"*Restart Kernel and Clear All Outputs*\" in [JupyterLab](https://jupyterlab.readthedocs.io/en/stable/) *before* reading this notebook to reset its output. If you cannot run this file on your machine, you may want to open it [in the cloud ](https://mybinder.org/v2/gh/webartifex/intro-to-data-science/main?urlpath=lab/tree/01_scientific_stack/00_content_numpy.ipynb)." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Chapter 1: Python's Scientific Stack (Part 1)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Python itself does not come with any scientific algorithms. However, over time, many third-party libraries emerged that are useful to build machine learning applications. In this context, \"third-party\" means that the libraries are *not* part of Python's standard library.\n", + "\n", + "Among the popular ones are [numpy ](https://numpy.org/) (numerical computations, linear algebra), [pandas ](https://pandas.pydata.org/) (data processing), [matplotlib ](https://matplotlib.org/) (visualisations), and [scikit-learn ](https://scikit-learn.org/stable/index.html) (machine learning algorithms)." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Extending Python with Third-party Packages" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Before we can import these libraries, we must ensure that they installed on our computers. If you installed Python via the Anaconda Distribution that should already be the case. Otherwise, we can use Python's **package manager** `pip` to install them manually.\n", + "\n", + "`pip` is a so-called command-line interface (CLI), meaning it is a program that is run within a terminal window. JupyterLab allows us to run such a CLI tool from within a notebook by starting a code cell with a single `%` symbol. Here, this does not mean Python's modulo operator but is just an instruction to JupyterLab that the following code is *not* Python.\n", + "\n", + "So, let's proceed by installing [numpy ](https://numpy.org/) and [matplotlib ](https://matplotlib.org/)." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Requirement already satisfied: numpy in /home/webartifex/repos/intro-to-data-science/.venv/lib/python3.8/site-packages (1.21.1)\n", + "Note: you may need to restart the kernel to use updated packages.\n" + ] + } + ], + "source": [ + "%pip install numpy" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Requirement already satisfied: matplotlib in /home/webartifex/repos/intro-to-data-science/.venv/lib/python3.8/site-packages (3.4.3)\n", + "Requirement already satisfied: python-dateutil>=2.7 in /home/webartifex/repos/intro-to-data-science/.venv/lib/python3.8/site-packages (from matplotlib) (2.8.2)\n", + "Requirement already satisfied: cycler>=0.10 in /home/webartifex/repos/intro-to-data-science/.venv/lib/python3.8/site-packages (from matplotlib) (0.10.0)\n", + "Requirement already satisfied: pyparsing>=2.2.1 in /home/webartifex/repos/intro-to-data-science/.venv/lib/python3.8/site-packages (from matplotlib) (2.4.7)\n", + "Requirement already satisfied: kiwisolver>=1.0.1 in /home/webartifex/repos/intro-to-data-science/.venv/lib/python3.8/site-packages (from matplotlib) (1.3.2)\n", + "Requirement already satisfied: pillow>=6.2.0 in /home/webartifex/repos/intro-to-data-science/.venv/lib/python3.8/site-packages (from matplotlib) (8.3.2)\n", + "Requirement already satisfied: numpy>=1.16 in /home/webartifex/repos/intro-to-data-science/.venv/lib/python3.8/site-packages (from matplotlib) (1.21.1)\n", + "Requirement already satisfied: six in /home/webartifex/repos/intro-to-data-science/.venv/lib/python3.8/site-packages (from cycler>=0.10->matplotlib) (1.16.0)\n", + "Note: you may need to restart the kernel to use updated packages.\n" + ] + } + ], + "source": [ + "%pip install matplotlib" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "After we have ensured that the third-party libraries are installed locally, we can simply go ahead with the `import` statement. All the libraries are commonly imported with shorter prefixes for convenient use later on." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "import matplotlib.pyplot as plt" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let's see how the data type provided by these scientific libraries differ from Python's built-in ones." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Vectors and Matrices with Numpy" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "As an example, let's start by creating a `list` object." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[1, 2, 3, 4, 5]" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "vector = [1, 2, 3, 4, 5]\n", + "\n", + "vector" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We call the `list` object by the name `vector` as that is what the data is supposed to mean conceptually. As we remember from our linear algebra courses, vectors should implement scalar-multiplication. So, the following code cell should result in `[3, 6, 9, 12, 15]` as the answer. Surprisingly, the result is a new `list` with all the elements in `vector` repeated three times. That operation is called **concatenation** and is an example of a concept called **operator overloading**. That means that an operator, like `*` in the example, may exhibit a different behavior depending on the data type of its operands." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5]" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "3 * vector" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "[numpy ](https://numpy.org/), among others, provides a data type called an **n-dimensional array**. This may sound fancy at first but when used with only 1 or 2 dimensions, it basically represents vectors and matrices as we know them from linear algebra. Additionally, arrays allow for much faster computations as they are implemented in the very efficient [C language ](https://en.wikipedia.org/wiki/C_%28programming_language%29) and optimized for numerical operations." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To create an array, we use the [np.array() ](https://docs.scipy.org/doc/numpy/reference/generated/numpy.array.html#numpy-array) constructor and provide it a `list` of values." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([1, 2, 3, 4, 5])" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "v1 = np.array([1, 2, 3, 4, 5])\n", + "\n", + "v1" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "numpy.ndarray" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "type(v1)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The vector `v1` can now be multiplied with a scalar yielding a result meaningful in the context of linear algebra." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([ 3, 6, 9, 12, 15])" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "v2 = 3 * v1\n", + "\n", + "v2" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To model a matrix, we use a `list` of (row) `list`s of values. Note how the output below the cell contains *two* levels of brackets `[` and `]`." + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[ 1, 2, 3, 4, 5],\n", + " [ 6, 7, 8, 9, 10]])" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "m1 = np.array([\n", + " [1, 2, 3, 4, 5],\n", + " [6, 7, 8, 9, 10],\n", + "])\n", + "\n", + "m1" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now we can use the [np.dot() ](https://numpy.org/doc/stable/reference/generated/numpy.dot.html#numpy.dot) function to multiply a matrix with a vector to obtain a new vector ..." + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([ 55, 130])" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "v3 = np.dot(m1, v1)\n", + "\n", + "v3" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "... or simply transpose it by accessing its [.T ](https://numpy.org/doc/stable/reference/generated/numpy.ndarray.T.html#numpy.ndarray.T) attribute." + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[ 1, 6],\n", + " [ 2, 7],\n", + " [ 3, 8],\n", + " [ 4, 9],\n", + " [ 5, 10]])" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "m1.T" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The rules from maths still apply and it makes a difference if a vector is multiplied from the left or the right by a matrix. The following operation will fail." + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "ename": "ValueError", + "evalue": "shapes (5,) and (2,5) not aligned: 5 (dim 0) != 2 (dim 0)", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mValueError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m/tmp/user/1000/ipykernel_1264563/568665770.py\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdot\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mv1\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mm1\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;32m<__array_function__ internals>\u001b[0m in \u001b[0;36mdot\u001b[0;34m(*args, **kwargs)\u001b[0m\n", + "\u001b[0;31mValueError\u001b[0m: shapes (5,) and (2,5) not aligned: 5 (dim 0) != 2 (dim 0)" + ] + } + ], + "source": [ + "np.dot(v1, m1)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Indexing & Slicing" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In order to retrieve only a subset of an array's data, we index or slice into it. This is similar to how we index or slice into `list` objects, in particular, if we deal with one-dimensional arrays like `v1`, `v2`, or `v3`." + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([1, 2, 3, 4, 5])" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "v1" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Indexing may be done with either positive (`0`-based) indexes from the left or negative (`1`-based) indexes from the right.\n", + "\n", + "Here, we obtain the first and the last element in `v1`." + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "1" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "v1[0]" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "5" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "v1[-1]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Slicing uses the same `:` notation as with `list`s taking *start*, *stop*, and *step* values." + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([2, 3, 4])" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "v1[1:-1]" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([3, 4, 5])" + ] + }, + "execution_count": 17, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "v1[2:]" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([1, 2, 3, 4])" + ] + }, + "execution_count": 18, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "v1[:-1]" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([2, 4])" + ] + }, + "execution_count": 19, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "v1[1:-1:2]" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([1, 3, 5])" + ] + }, + "execution_count": 20, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "v1[::2]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Indexing and slicing become slightly more complicated when working with higher dimensional arrays like `m1`. In principle, we must provide either an index or a slice for *each* dimension." + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[ 1, 2, 3, 4, 5],\n", + " [ 6, 7, 8, 9, 10]])" + ] + }, + "execution_count": 21, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "m1" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "For example, to slice out the first row of the matrix, we write `[0, :]`. The `0` implies taking elements in *only* the *first* row and the `:` means taking elements across *all* columns." + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([1, 2, 3, 4, 5])" + ] + }, + "execution_count": 22, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "m1[0, :]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "For sure, we could also *not* leave out the *start* and *stop* values along the second dimension and obtain the same result. But that would not only be unneccessary but also communicate a different meaning, namely to \"take elements from the first through the fifth columns\" instead of \"take elements from all columns.\"" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([1, 2, 3, 4, 5])" + ] + }, + "execution_count": 23, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "m1[0, 0:5]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Whenever we take *all* elements in *later* dimensions (i.e., those more to the right), we may also drop the index or slice instead and keep only the *earlier* ones. However, the previous style is a bit more explicit in that we are working with a two-dimensional array." + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([1, 2, 3, 4, 5])" + ] + }, + "execution_count": 24, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "m1[0]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "As another example, let's slice out elements across *all* rows but in only the *second* column. Colloquially, we can say that we \"slice out the second column\" from the matrix." + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([2, 7])" + ] + }, + "execution_count": 25, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "m1[:, 1]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If we wanted to slice out a smaller matrix from a larger one, we slice along both dimensions. Above, we have only sliced along one dimension while indexing into the other.\n", + "\n", + "For example, to obtain a 2x2 square matrix consisting of the two left-most columns in `m1`, we can write the following." + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[1, 2],\n", + " [6, 7]])" + ] + }, + "execution_count": 26, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "m1[:2, :2]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Similarly, to slice out a 2x2 matrix consisting of the two right-most columns, we write the following." + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[ 4, 5],\n", + " [ 9, 10]])" + ] + }, + "execution_count": 27, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "m1[-2:, -2:]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To access individual elements as scalars, we combine two indexes along both dimensions.\n", + "\n", + "For example, to access the element in the lower-left corner, we write the following." + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "6" + ] + }, + "execution_count": 28, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "m1[1, 0]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Dimensionality vs. Shapes" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Both, the vectors `v1`, `v2`, and `v3`, and the matrix `m1` have the *same* **data type** from a technical point of view, namely `np.ndarray`." + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "numpy.ndarray" + ] + }, + "execution_count": 29, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "type(v1)" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "numpy.ndarray" + ] + }, + "execution_count": 30, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "type(m1)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "So, how can we tell that they have different dimensions without looking at how they are displayed below a code cell?\n", + "\n", + "The `np.ndarray` type comes with a couple of **properties** that we can access via the dot notation. Examples are `.ndim` and `.shape`.\n", + "\n", + "While `.ndim` simply tells us how many dimensions an array has, ..." + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "1" + ] + }, + "execution_count": 31, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "v1.ndim" + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "2" + ] + }, + "execution_count": 32, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "m1.ndim" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "... `.shape` reveals the structure of the elements. The one-element tuple `(5,)` below says that there is one dimension along which there are five elements ..." + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(5,)" + ] + }, + "execution_count": 33, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "v1.shape" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "... whereas the two-element tuple `(2, 5)` indicates that the array's elements are placed along two dimensions spanning a grid of two elements in one and five elements into the other dimension. We know such notations already from our linear algebra courses where we would call `m1` a 2x5 matrix." + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(2, 5)" + ] + }, + "execution_count": 34, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "m1.shape" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "There is a relationship behind the dimensionality of an array we are slicing and indexing and what we get back as a result: Whenever we index into an array along some dimension, the result will have one dimension less than the original.\n", + "\n", + "For example, if we start with a two-dimensional array like `m1` and slice along both dimensions, the result will also have two dimensions, even if it holds only one element." + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[ 1, 2, 3, 4, 5],\n", + " [ 6, 7, 8, 9, 10]])" + ] + }, + "execution_count": 35, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "m1" + ] + }, + { + "cell_type": "code", + "execution_count": 36, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[1]])" + ] + }, + "execution_count": 36, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "m1[:1, :1] # Note the double brackets" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If, on the contrary, we slice only along one of the two dimensions and index into the other, the result is a one-dimensional array. So, both of the below slices have the *same* properties and we cannot tell if one of them was (part of) a row or column in `m1`." + ] + }, + { + "cell_type": "code", + "execution_count": 37, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([6, 7])" + ] + }, + "execution_count": 37, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "m1[1, :2]" + ] + }, + { + "cell_type": "code", + "execution_count": 38, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([ 5, 10])" + ] + }, + "execution_count": 38, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "m1[:, -1]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Finally, indexing along both dimensions gives us back a scalar value." + ] + }, + { + "cell_type": "code", + "execution_count": 39, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "1" + ] + }, + "execution_count": 39, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "m1[0, 0]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Array Constructors & Functions" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "[numpy ](https://numpy.org/) provides various **constructors** (i.e., functions) to create all kinds of arrays.\n", + "\n", + "For example, [np.linspace() ](https://numpy.org/doc/stable/reference/generated/numpy.linspace.html#numpy.linspace) creates an array of equidistant numbers, often used to model the values on a function's x-axis. [np.pi ](https://numpy.org/doc/stable/reference/constants.html#numpy.pi) is an alias for Python's built-in `math.pi`. The cell below creates `100` coordinate points arranged between $-3\\pi$ and $+3\\pi$." + ] + }, + { + "cell_type": "code", + "execution_count": 40, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([-9.42477796, -9.23437841, -9.04397885, -8.8535793 , -8.66317974,\n", + " -8.47278019, -8.28238063, -8.09198108, -7.90158152, -7.71118197,\n", + " -7.52078241, -7.33038286, -7.1399833 , -6.94958375, -6.75918419,\n", + " -6.56878464, -6.37838508, -6.18798553, -5.99758598, -5.80718642,\n", + " -5.61678687, -5.42638731, -5.23598776, -5.0455882 , -4.85518865,\n", + " -4.66478909, -4.47438954, -4.28398998, -4.09359043, -3.90319087,\n", + " -3.71279132, -3.52239176, -3.33199221, -3.14159265, -2.9511931 ,\n", + " -2.76079354, -2.57039399, -2.37999443, -2.18959488, -1.99919533,\n", + " -1.80879577, -1.61839622, -1.42799666, -1.23759711, -1.04719755,\n", + " -0.856798 , -0.66639844, -0.47599889, -0.28559933, -0.09519978,\n", + " 0.09519978, 0.28559933, 0.47599889, 0.66639844, 0.856798 ,\n", + " 1.04719755, 1.23759711, 1.42799666, 1.61839622, 1.80879577,\n", + " 1.99919533, 2.18959488, 2.37999443, 2.57039399, 2.76079354,\n", + " 2.9511931 , 3.14159265, 3.33199221, 3.52239176, 3.71279132,\n", + " 3.90319087, 4.09359043, 4.28398998, 4.47438954, 4.66478909,\n", + " 4.85518865, 5.0455882 , 5.23598776, 5.42638731, 5.61678687,\n", + " 5.80718642, 5.99758598, 6.18798553, 6.37838508, 6.56878464,\n", + " 6.75918419, 6.94958375, 7.1399833 , 7.33038286, 7.52078241,\n", + " 7.71118197, 7.90158152, 8.09198108, 8.28238063, 8.47278019,\n", + " 8.66317974, 8.8535793 , 9.04397885, 9.23437841, 9.42477796])" + ] + }, + "execution_count": 40, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "x = np.linspace(-3 * np.pi, 3 * np.pi, 100)\n", + "\n", + "x" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Besides constructors, [numpy ](https://numpy.org/) provides all kinds of **vectorized** functions. The concept of **vectorization** means that a function is executed once for *each* element in an array. Vectorized functions are one major benefit of using [numpy ](https://numpy.org/): Not only are they optimized heavily on the C level (i.e., \"behind the scenes\") but also allow us to avoid writing explicit `for`-loops that are for some technical reasons considered \"slow\" in Python.\n", + "\n", + "For example, [np.sin() ](https://numpy.org/doc/stable/reference/generated/numpy.sin.html#numpy.sin) calculates the sine for each element in the `x` array. The resulting `y` array has thus the same `.shape` as `x`." + ] + }, + { + "cell_type": "code", + "execution_count": 41, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([-3.67394040e-16, -1.89251244e-01, -3.71662456e-01, -5.40640817e-01,\n", + " -6.90079011e-01, -8.14575952e-01, -9.09631995e-01, -9.71811568e-01,\n", + " -9.98867339e-01, -9.89821442e-01, -9.45000819e-01, -8.66025404e-01,\n", + " -7.55749574e-01, -6.18158986e-01, -4.58226522e-01, -2.81732557e-01,\n", + " -9.50560433e-02, 9.50560433e-02, 2.81732557e-01, 4.58226522e-01,\n", + " 6.18158986e-01, 7.55749574e-01, 8.66025404e-01, 9.45000819e-01,\n", + " 9.89821442e-01, 9.98867339e-01, 9.71811568e-01, 9.09631995e-01,\n", + " 8.14575952e-01, 6.90079011e-01, 5.40640817e-01, 3.71662456e-01,\n", + " 1.89251244e-01, -1.22464680e-16, -1.89251244e-01, -3.71662456e-01,\n", + " -5.40640817e-01, -6.90079011e-01, -8.14575952e-01, -9.09631995e-01,\n", + " -9.71811568e-01, -9.98867339e-01, -9.89821442e-01, -9.45000819e-01,\n", + " -8.66025404e-01, -7.55749574e-01, -6.18158986e-01, -4.58226522e-01,\n", + " -2.81732557e-01, -9.50560433e-02, 9.50560433e-02, 2.81732557e-01,\n", + " 4.58226522e-01, 6.18158986e-01, 7.55749574e-01, 8.66025404e-01,\n", + " 9.45000819e-01, 9.89821442e-01, 9.98867339e-01, 9.71811568e-01,\n", + " 9.09631995e-01, 8.14575952e-01, 6.90079011e-01, 5.40640817e-01,\n", + " 3.71662456e-01, 1.89251244e-01, 1.22464680e-16, -1.89251244e-01,\n", + " -3.71662456e-01, -5.40640817e-01, -6.90079011e-01, -8.14575952e-01,\n", + " -9.09631995e-01, -9.71811568e-01, -9.98867339e-01, -9.89821442e-01,\n", + " -9.45000819e-01, -8.66025404e-01, -7.55749574e-01, -6.18158986e-01,\n", + " -4.58226522e-01, -2.81732557e-01, -9.50560433e-02, 9.50560433e-02,\n", + " 2.81732557e-01, 4.58226522e-01, 6.18158986e-01, 7.55749574e-01,\n", + " 8.66025404e-01, 9.45000819e-01, 9.89821442e-01, 9.98867339e-01,\n", + " 9.71811568e-01, 9.09631995e-01, 8.14575952e-01, 6.90079011e-01,\n", + " 5.40640817e-01, 3.71662456e-01, 1.89251244e-01, 3.67394040e-16])" + ] + }, + "execution_count": 41, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "y = np.sin(x)\n", + "\n", + "y" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next, let's use [matplotlib ](https://matplotlib.org/)'s [plt.plot() ](https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.plot.html#matplotlib.pyplot.plot) function to visualize the sine curve between $-3\\pi$ and $+3\\pi$." + ] + }, + { + "cell_type": "code", + "execution_count": 42, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[]" + ] + }, + "execution_count": 42, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "plt.plot(x, y)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If we use only `10` equidistant points for `x`, the resulting curve does not look like a curve. There is a trade-off behind this: To make nice plots, we need a rather high granularity of data points. That, however, causes more computations in the background making the plotting slower. With toy data like the one here this is not an issue. For real life data that may be different." + ] + }, + { + "cell_type": "code", + "execution_count": 43, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[]" + ] + }, + "execution_count": 43, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "x = np.linspace(-3 * np.pi, 3 * np.pi, 10)\n", + "y = np.sin(x)\n", + "\n", + "plt.plot(x, y)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "[numpy ](https://numpy.org/) provides further constructors. Most notably are the ones in the [np.random ](https://numpy.org/doc/stable/reference/random/index.html#module-numpy.random) module that mirrors the [random ](https://docs.python.org/3/library/random.html) module in the [standard library ](https://docs.python.org/3/library/index.html): For example, [np.random.normal() ](https://numpy.org/doc/stable/reference/random/generated/numpy.random.normal.html#numpy.random.normal) and [np.random.gamma() ](https://numpy.org/doc/stable/reference/random/generated/numpy.random.gamma.html#numpy.random.gamma) return arrays whose elements follow the normal and gamma probability distributions." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us quickly generate some random data points and draw a scatter plot with [matplotlib ](https://matplotlib.org/)'s [plt.scatter() ](https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.scatter.html#matplotlib.pyplot.scatter) function." + ] + }, + { + "cell_type": "code", + "execution_count": 44, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 44, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAXAAAAD7CAYAAABzGc+QAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjQuMywgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/MnkTPAAAACXBIWXMAAAsTAAALEwEAmpwYAAAboElEQVR4nO3df5BddXnH8fdjCGWpSqBsGQhEqNbYEQbSrg4jU4vQaahQyTitlREHCpqOnSrSTiDYjohTx2isYutUJ5UUHCmCGCP+qJEZtKhF7EJCIWKqU4VmAyYMxA6wQBKe/nHvDbt3z7n33PPjnu/3nM9rJpPdc+/d++y5e57zPc/3xzF3R0RE4vOiugMQEZF8lMBFRCKlBC4iEiklcBGRSCmBi4hESglcRCRSQxO4mZ1gZt82sx+Z2XYzu6y7/Sgzu93MftL9/8jqwxURkR4bNg7czI4FjnX3e83sJcA9wCrgYuBxd19nZmuBI939yorjFRGRrqEJfMELzL4CfKr770x3f6Sb5L/j7ssHvfboo4/2E088MW+sIiKtdM899zzm7pP92w8Z5YeY2YnACuBu4Bh3f6T70KPAMSmvWQ2sBli2bBnT09OjvKWISOuZ2UNJ2zN3YprZi4EvAe919/+b+5h3mvGJTXl33+DuU+4+NTm54AQiIiI5ZUrgZraYTvK+0d03dTf/ols66dXJd1cTooiIJMkyCsWA64AH3f3jcx66Dbio+/VFwFfKD09ERNJkqYGfAbwduN/MtnW3vQ9YB9xiZpcCDwFvqSRCERFJNDSBu/v3AEt5+OxywxERkaxGGoUiUrXNW2dYv2UHu/bOctySCdasXM6qFUvrDkskSErgEozNW2e4atP9zO47AMDM3lmu2nQ/gJK4SAKthSLBWL9lx8Hk3TO77wDrt+yoKSKRsCmBSzB27Z0dabtI2ymBSzCOWzIx0naRtlMCl2CsWbmcicWL5m2bWLyINSsHLrEj0lrqxJRg9DoqNQqlXBrZ01xK4BKUVSuWKrmUSCN7mk0lFJEG08ieZlMCF2kwjexpNiVwkQbTyJ5mUwIXaTCN7Gk2dWKKNJhG9jSbErhIw2lkT3OphCIiEiklcBGRSGW5pdpGM9ttZg/M2Xaamf3AzLaZ2bSZvbbaMEVEpF+WFvj1wDl92z4KXOPupwHv734vIiJjNDSBu/udwOP9m4GXdr8+AthVclwiIjJE3lEo7wW2mNnH6JwEXldaRCIikkneTsx3AZe7+wnA5cB1aU80s9XdOvn0nj17cr6diIj0y5vALwI2db/+IpDaienuG9x9yt2nJicnc76diIj0y5vAdwG/1/36LOAn5YQjIiJZDa2Bm9lNwJnA0Wa2E7gaeCfwSTM7BHgGWF1lkCIistDQBO7uF6Q89DslxyIiIiPQTEwRkUgpgYuIREoJXEQkUkrgIiKRUgIXEYmUEriISKSUwEVEIqUELiISKSVwEZFIKYGLiERKCVxEJFJK4CIikVICFxGJlBK4iEiklMBFRCKlBC4iEqmhCdzMNprZbjN7oG/7u83sx2a23cw+Wl2IIiKSJEsL/HrgnLkbzOwNwPnAqe7+auBj5YcmIiKDDE3g7n4n8Hjf5ncB69z92e5zdlcQm4iIDJC3Bv5K4HfN7G4z+3cze02ZQYmIyHBDb2o84HVHAacDrwFuMbPfcHfvf6KZraZ71/ply5bljVNERPrkbYHvBDZ5xw+B54Gjk57o7hvcfcrdpyYnJ/PGKSIiffIm8M3AGwDM7JXAocBjJcUkIiIZDC2hmNlNwJnA0Wa2E7ga2Ahs7A4tfA64KKl8IiIi1RmawN39gpSHLiw5FhERGYFmYoqIREoJXEQkUkrgIiKRUgIXEYmUEriISKSUwEVEIqUELiISKSVwEZFIKYGLiERKCVxEJFJK4CIikVICFxGJlBK4iEiklMBFRCKlBC4iEqm898QUGZvNW2dYv2UHu/bOctySCdasXM6qFUvrDkukdkNb4Ga20cx2d+++0//YX5uZm1ni/TBFitq8dYarNt3PzN5ZHJjZO8tVm+5n89aZukMTqV2WEsr1wDn9G83sBOAPgIdLjknkoPVbdjC778C8bbP7DrB+y46aIhIJx9AE7u53Ao8nPPQJ4ApA98KUyuzaOzvSdpE2ydWJaWbnAzPufl/J8YjMc9ySiZG2i7TJyAnczA4H3ge8P+PzV5vZtJlN79mzZ9S3k5Zbs3I5E4sXzds2sXgRa1YurykikXDkGYXycuAk4D4zAzgeuNfMXuvuj/Y/2d03ABsApqamVG7JSCMvOnq/s/aFyEIjJ3B3vx/49d73ZvZzYMrdHysxrlbrjbzodd71Rl4ArUxcq1Ysjfb31olYqpRlGOFNwF3AcjPbaWaXVh9Wu2nkRTNoCKRUbWgL3N0vGPL4iaVFI4BGXjTFoBOxWuFSBk2lD5BGXjSDTsRSNSXwAGnkRTPoRCxVUwIP0KoVS/nwm09h6ZIJDFi6ZIIPv/kUXXZHRidiqZoWswpUzCMvpENDIKVqSuAiFdKJWKqkEoqISKSUwEVEIqUSiohErc2zXZXARSRabV92QiUUEYlW25edUAtcWq3Nl99N0PbZrmqBS2tpsan4tX22qxK4tFbbL7+boO2zXVVCkcbJWhZp++V3E7R9tqsSuDTKKKMSjlsywUxCsm7L5XdTtHm2q0oo0iijlEXafvkt8ctyR56NZrbbzB6Ys229mf3YzP7LzL5sZksqjVIko1HKIlr1UWKXpYRyPfAp4HNztt0OXOXu+83sI8BVwJXlhycymlHLIm2+/Jb4DW2Bu/udwON9277l7vu73/6Azp3pRWqnsoi0SRmdmJcAN5fwc0QKa/uoBGmXQgnczP4G2A/cOOA5q4HVAMuWLSvydjKCNs8wVFlE2iL3KBQzuxg4D3ibu3va89x9g7tPufvU5ORk3reTEWiGoUg75ErgZnYOcAXwJnd/utyQpCjNMBRphyzDCG8C7gKWm9lOM7uUzqiUlwC3m9k2M/tMxXHKCDTDUKQdhtbA3f2ChM3XVRCLlEQzDEXaQTMxG0hD6UTaQWuhNJCG0om0gxJ4Q2konUjzqYQiIhIpJXARkUgpgYuIREo1cBEpRZuXb6iLEriIFDbKnZCkPErgIpEKqcU7aPkGJfDqKIGLRCi0Fq+Wb6iHOjElCJu3znDGujs4ae3XOWPdHVo5cYjQFixLW6ZByzdUSwlcaqflb0cXWotXyzfUQwlcahdaazIGobV4dYPoeqgGLrULrTUZgzUrl8+rgUP9LV4t3zB+aoFL7UJrTcZALV4BtcAlACG2JusyytBAtXglyx15NprZbjN7YM62o8zsdjP7Sff/I6sNU5pMrckOdebKqGzA/Yg7TzB7PfAk8Dl3P7m77aPA4+6+zszWAke6+5XD3mxqasqnp6dLCFskbkkt7fVbdiTeSWnpkgm+v/asGqKUUJjZPe4+1b99aAvc3e8EHu/bfD5wQ/frG4BVRQMUaYu0lnZS8gZ15kq6vJ2Yx7j7I92vHwWOKSkekcZLGza5yCzx+erMlTSFOzHd3c0stQ5jZquB1QDLli0r+naNM871LMp6r5DW4IhRWov6gDsTixepM1cyy9sC/4WZHQvQ/X932hPdfYO7T7n71OTkZM63a6ZxdlqV9V7qaCsurUXd67xte2euZJc3gd8GXNT9+iLgK+WE0y7jnIFY1ntp1mRxg6adr1qxlO+vPYufrTuX7689S8lbBhpaQjGzm4AzgaPNbCdwNbAOuMXMLgUeAt5SZZBNNc4ZiGW9l2ZNFtdLyipDSVFDE7i7X5Dy0Nklx9I6xy2ZSBx5UEWnVVnvNc6Ym0yTcKQMmkpfo7wruOVZerWs1eK06pxIODSVvkZ5LqXzLuRf1mW7Lv9FwjF0JmaZNBOzuDPW3aHZeiItkzYTUy3wyKgTsTk0nl6KUg08Mlp6tRk0nl7KoAQeGXUiDpf3/prjvC+nxtNLGVRCiYw6EQfL28k77ru8qxQmZVACj5DGEKcb1LIdtM/yvi4vjaeXMiiBS6PkbdnmfV3ejsi23oVIHbflUgKXRsnbss3zuiJllzaWwsZdpmoDdWJKo+Tt5M3zuqIdkW1buEodt+VTC1waJW/LNs/r1BE5Gu2v8gWfwFUzk1Hl7eQd9XXqiByN9lf5gi6haLJDdcY55jkkZf7eGpM/Gu2v8gXdAh/30K62GFdnUmhXT2X/3k3siKzyM2vi/qpb0ItZnbT26yRFZ8DP1p1bWlwhq+KAGseCWP3JEjqtrSy3CKsqiWghsMGKfGZSrbTFrAqVUMzscjPbbmYPmNlNZnZYkZ/Xr+3rflRVQkpKYlBuZ1LeEQdVls3UiTaYRonEJ3cCN7OlwHuAKXc/GVgEvLWswKBZNbM8tdcqDqjNW2ewlMfKPDGmJcWZvbMD90OVSaSqBkFT+hN0gotP0U7MQ4AJMzsEOBzYVTykF6xasbQRd+nO26qs4oBav2VHalmqzBNjWlI0GLgfqkwiVTQIRvlsQ0/0bb/ijVHuBO7uM8DHgIeBR4Bfuvu3ygqspwmTHfK2Kqs4oNISoVNuB2ZSsrTu+8zVvx+qTCJVNAiyfrYxjKhq0hVvWxQpoRwJnA+cBBwH/KqZXZjwvNVmNm1m03v27MkfacTytiqrOKDSEuHSkltZSckyrbt87n5I+p0Bnnp2fynJruwGQdbPNob6clOueNukyDDC3wd+5u57AMxsE/A64PNzn+TuG4AN0BmFUuD9opV3AkMVw67GuYhSf/yLzDiQMOpp7n7oveaar27niaf3Hdy+d3ZfkOtmZP1sB/UJbN46E8zvFMNKl6ENT61TkRr4w8DpZna4mRlwNvBgOWE1S5GWdNktxnG2svrLBknJO2k/rFqxlMMPXdi2CK3FCtk/20En69BKKSGLoRQ1Trlb4O5+t5ndCtwL7Ae20m1py3yhTWAYVysrqWwAsMiM590H7odYRkRk/WyTrnx6ypyc1vTWqSb3zVdoJqa7Xw1cXVIsjRbDpWnZ0pLt8+5DJ2LFtG5Gls+29/h7b96W+HgZJ6Y2LNcay4l9XIJeC0XilpZsHYYOo2viiIhVK5amdhaXcWKKoaO0KA11nE8JvAXqGn+cNqIEhtcumzoiYtCJqejn1IbWaQwn9nEeb0EvZiXF1XlZPbc+nFQOGVa7bGLZKa1mDhT+nPLeVSimmnlo/Un9xn28Bb2YlRQXygJOoy5MFltiKaqMz2nUxai0eFX5qjreKlnMSsIXymX1KLXLNg4VK+NzGrXs1Iaa+biN+3hTCaXhQhnNMcoEojYOFSvrcxql7BTKyb1Jxn28qQWeIPRFh0ZRZafPKPtplNZhGxNLHZ1zaUllyeGLK3vPphv356gWeJ+mjaWtqtMnz37K2joM5aphnOronFuzcjlrbr2PfQfm9048+cz+oKb3x2Tcn6M6MfuE0ukXuir3U97OtbZ1fJbhtGu+xd7ZfQu2j9p5qv1erbROTLXA+7Tx8j2PqvZTLxnM7jtwcPGrpRmSQpYrAiWahX6ZkLwh++fYtCvW2KgG3kczvbKpYj/NHX0CncWvevXDYclg2IiKpJEtl9+8jRMb0M9RRNHPUSNZ6qUE3ieGmV4hqGI/FUkGw64Ikn52r3g4zmGKoXWQF/0cdcVaL5VQ+oQ+0ysURfZTWikjSzJIe+2wjs+0Gzn3jGOYYojlhqJ/72n7/YgJjWQZB3ViSukG1ZoHdVCmTbnvdagNei0w8LHLb96WekegnrRZoWVpYgf55q0zrPnifex7fv7eXbzIWP/Hp6rhUxLNxJSxGDaLclCZZNjl/LAJPmnjzNNu5Nyv6n6OJpYbVq1YyosPW3ghv++Aqw4+BiqhBKQJoySGJdlBSWzY5fywBJg2zjxLghxHP0dTx7fvfbrYSBbJr1ACN7MlwGeBk+n0CV3i7neVEFfrDKuPhp7ce/Gl1Zp7B/OwJDZosk/eBJj2uix3BirTOO9HOk5NPTHFoGgJ5ZPAN939VcCp6J6YuQ1quYa+uFP/8L8kvYO5yKiHvK9Ne93fv+XU0u41mkUVa5yHMKpFI7fqk7sFbmZHAK8HLgZw9+eA58oJq30GlQdCX9wp7d6XPXMP5iKjHvK+NqSRRWWucR7KqJaQ9m/b5B6FYman0bmJ8Y/otL7vAS5z96fSXlPmKJTQSwqjGjRCYVe35d2v6lETWaWt9Q1kmkUp+TRxVIskq2IUyiHAbwOfdvcVwFPA2oQ3Xm1m02Y2vWfPngJv94LQSwp5DLoMDX12aFocvUSSNXmHUA6ISRNHtYxCfy/FEvhOYKe73939/lY6CX0ed9/g7lPuPjU5OVng7V7QxOm7g+qjodcY0+59+fRz+zMfVE08KVct9BN7lfT30pG7Bu7uj5rZ/5rZcnffAZxNp5xSuaa2PNLqo6HXGHtxfOC27fNWtnvi6X2Za7Kh1/lDlHVUS9PKjaC/l56i48DfDdxoZocC/wP8WfGQhmvjsKXQb/DbmzDTvzRp1oOqqSflKvXfNHqR2bwr0d7w0xA6Osumv5eOQgnc3bcBCwrrVWvqeNoYDGrNFTmoyjgpN7GlOUzv90tL0k1tqbaxEZckyqn0VYynbYoqO3aG1R2L1GSL1vnbvFzsoCRd5KQacidh6P1C4xLtVPrQSwp1qPpyeVhrrsiVUdE6f5blYue+T5MMStJ5W6qhl15C7xcal2gTuCxU9eVylrVIenHkOaiKnJSHtSibUDZIMyhJ5z2plvG3VHVJK5ZGXJX7QQm8Qaru2MnSmqvroEqLba6mdnANStJ5T6pF/5ZCb8GPS9X7QQm8QaruCBxH53He1kpSbP0G7Ye6OkDLeN9hSTrPSbXo31JTO09HVfV+UAJvkKIJdlhroeq6Y5HWSv+QOoN50/sH7Ye6WotJ77vm1vv4wG3b+eXsvpHXiSkz1qJ/Sxrm11H1flACb5AqOgL7WwtZEkXeVmXR1src2EaJoa7WYtL77jvgB8fS11l2qOpWa20b5lf1flACb5gqOgJHaS0Uac2W2VoZZT/U1VrM8vPrLDsU+VvSXI2OqvdDlOPApRplrK1RZJ2atPep+ga5VawpkmUMddafH2PZQXM1OqreD2qBy0FltBaKtGbXrFyeeIPcp7qLYlV18JfdSkq7Cpl+6HG+/eM9B6e9H3BfUKtPUtbl9rg7aste+zzWMd9VjsxSApeDyuikHKXml3RQvviwQ3ii7x6LvRvkVnUQlN05m3YVcuMPHj6YrA901+F3OJjEjzx8MU8+s3/eCaysy+2Yh/XFHHvVct/QIY8yb+ggYeo/2KCThPovG9OelzYMMJSbV2Qx6AYXaXprp1fV0oz55g8xx16WtBs6qAUeqVAvKbO2ZtNaqb3SQr+YRi9kmVTUb+5s1io+x5iH9cUce9WUwCMU+iVlliSUdvAdcF/QEo9t9EJSTX1YrbvqE1TMw/pijr1qGoUSoSbckWjQbdhiH72QNPLgbacvS7xrEYznBBXz6n0xx141tcAj1IRLymHrd8SUsJMk/Q5TLztq3s0XDriP7abPMa/eF3PsVSvciWlmi4BpYMbdzxv0XHViliNvp05odfPQ4ilLU38vqU+VnZiXAQ8CLy3hZ0kGecYth1g3j7GlPSg5b946wzVf3T5vGOTc/QxqRUq5CiVwMzseOBf4EPBXpUQkQ+W5pNTqcMUNOgkCC06qPbP7DvCB27bz7P7ngzqBSvyKtsCvBa4AXlI8FBnFqK3XJtTNxyWtlT2s83jQUrb9N3ue+1olcMkrdwI3s/OA3e5+j5mdOeB5q4HVAMuWLcv7dlKQhmJlM6iVXcVJcJwnUNXmm6fIMMIzgDeZ2c+BLwBnmdnn+5/k7hvcfcrdpyYnJwu8nRTR1KFYZd94d1Are9CiV4NOhBOLF3Hk4ckLco3rBDrshtQSp9wJ3N2vcvfj3f1E4K3AHe5+YWmRSamauDpcFUlpUCt70Ekw6TGAJROL+fCbT+HqP3p1rSfQJswdkIU0DrwGdV3KxjjqY5AqOmYHlZqydB5nWUKgjhKG+kCaqZQE7u7fAb5Txs9quhCH88WqiqQ0bIjmoJPgsBNknSdQ9YE0k6bSj5kuZctTxY0Ymlhqgub2gbSdSihjpkvZ8lR1u6qmlZpA09GbSgl8zHQpWx4lpdE08cTUdkrgY6abvZZLSUnaTAl8zNRqFJGyKIHXQK1GESmDRqGIiERKCVxEJFJK4CIikVICFxGJlBK4iEikCt8Tc6Q3M9sDPJTw0NHAY2MLJJ8YYoQ44lSM5VCM5Yghxpe5+4L1uMeawNOY2XTSDTtDEkOMEEecirEcirEcMcSYRiUUEZFIKYGLiEQqlAS+oe4AMoghRogjTsVYDsVYjhhiTBREDVxEREYXSgtcRERGpAQuIhKpsSdwMzvMzH5oZveZ2XYzu6bv8X8wsyfHHVdfDIkxWseHzOy/zexBM3tPgDGebWb3mtk2M/uemb2irhjnxLrIzLaa2de6359kZneb2U/N7GYzOzTAGG80sx1m9oCZbTSzxaHFOGd77cdMT8J+DOaYmSshzuCOmyzqaIE/C5zl7qcCpwHnmNnpAGY2BRxZQ0z90mK8GDgBeJW7/xbwhdoiTI/x08Db3P004F+Bv60twhdcBjw45/uPAJ9w91cATwCX1hLVfP0x3gi8CjgFmADeUUdQffpjDOmY6emP8WLCOWbm6o8zxONmqLEncO/otRYWd/+5mS0C1gNXjDumfmkxAu8CPujuz3eft7umEAfF6MBLu9uPAHbVEN5BZnY8cC7w2e73BpwF3Np9yg3AqlqC6+qPEcDdv9Hdxw78EDi+rvggOcaQjhlIjpGAjpmelDiDOm6yqqUG3r182QbsBm5397uBvwRuc/dH6oipX0qMLwf+1MymzezfzOw3A4zxHcA3zGwn8HZgXY0hAlxLJ8E83/3+14C97r6/+/1OoO67W1zL/BgP6pZO3g58c8wx9buWhTEGdcyQHGNQx0zXtSyMM7TjJpNaEri7H+heqhwPvNbMXg/8CfCPdcSTJCHGk4FfAZ7pTrv9Z2BjjSGmxXg58EZ3Px74F+DjdcVnZucBu939nrpiGCZDjP8E3Onu3x1jWPMkxWhmxxHQMTNgPwZ1zAyIM5jjZhS13lLN3fea2beBNwCvAH7aucLmcDP7abdGWqs5MZ5Dp7W4qfvQl+l80LWbE+MfAqd2W+IAN1Nvy/EM4E1m9kbgMDqXqJ8ElpjZId1W+PHATEgxmtnn3f1CM7samAT+vMb4IHk/bqfTDxLKMZO4HwnvmEmK8+t0avShHDfZuftY/9E5IJZ0v54Avguc1/ecJ8cdV5YY6VxWXdLdfibwnwHG+Bjwyu72S4Ev1bkv58R7JvC17tdfBN7a/fozwF/UHV9CjO8A/gOYqDuutBj7ttd6zAzYj8EcM2lx0mnIBnncDPtXRwv8WOCGbgfMi4Bb3P1rQ14zbokxmtn3gBvN7HLgSeodmZAW4zuBL5nZ83RGeFxSY4xprgS+YGZ/B2wFrqs5niSfobP08V3dFu4md/9gvSFFaR3hHDOJ3H1/JMfNAppKLyISKc3EFBGJlBK4iEiklMBFRCKlBC4iEiklcBGRSCmBi4hESglcRCRS/w+5qM8EHI2MEwAAAABJRU5ErkJggg==\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "x = np.random.normal(42, 3, 100)\n", + "y = np.random.gamma(7, 1, 100)\n", + "\n", + "plt.scatter(x, y)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.12" + }, + "toc": { + "base_numbering": 1, + "nav_menu": {}, + "number_sections": false, + "sideBar": true, + "skip_h1_title": false, + "title_cell": "Table of Contents", + "title_sidebar": "Contents", + "toc_cell": false, + "toc_position": {}, + "toc_section_display": true, + "toc_window_display": false + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/01_scientific_stack/01_exercises_arrays.ipynb b/01_scientific_stack/01_exercises_arrays.ipynb new file mode 100644 index 0000000..3b44856 --- /dev/null +++ b/01_scientific_stack/01_exercises_arrays.ipynb @@ -0,0 +1,279 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Note**: Click on \"*Kernel*\" > \"*Restart Kernel and Run All*\" in [JupyterLab](https://jupyterlab.readthedocs.io/en/stable/) *after* finishing the exercises to ensure that your solution runs top to bottom *without* any errors. If you cannot run this file on your machine, you may want to open it [in the cloud ](https://mybinder.org/v2/gh/webartifex/intro-to-data-science/main?urlpath=lab/tree/01_scientific_stack/01_exercises_arrays.ipynb)." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Chapter 0: Python's Scientific Stack (Coding Exercises)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The exercises below assume that you have read the preceeding content sections.\n", + "\n", + "The `...`'s in the code cells indicate where you need to fill in code snippets. The number of `...`'s within a code cell give you a rough idea of how many lines of code are needed to solve the task. You should not need to create any additional code cells for your final solution. However, you may want to use temporary code cells to try out some ideas." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Working with Arrays" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Another useful constructor [numpy ](https://numpy.org/) provides is [np.arange() ](https://numpy.org/doc/stable/reference/generated/numpy.arange.html#numpy.arange) which works similar to Python's [range() ](https://docs.python.org/3/library/functions.html#func-range) built-in.\n", + "\n", + "**Q1**: Create a one-dimensional array with [np.arange() ](https://numpy.org/doc/stable/reference/generated/numpy.arange.html#numpy.arange) holding the `int`egers from `0` through `9`!" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "v1 = np.arange(...)\n", + "\n", + "v1" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q2**: Create a one-dimensional array with [np.arange() ](https://numpy.org/doc/stable/reference/generated/numpy.arange.html#numpy.arange) holding the `int`egers from `100` through `109`!" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "v2 = np.arange(...)\n", + "\n", + "v2" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q3**: Create a one-dimensional array with [np.arange() ](https://numpy.org/doc/stable/reference/generated/numpy.arange.html#numpy.arange) holding the even `int`egers from `80` through `100`!" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "v3 = np.arange(...)\n", + "\n", + "v3" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q4**: Create a one-dimensional array with [np.arange() ](https://numpy.org/doc/stable/reference/generated/numpy.arange.html#numpy.arange) holding the odd `int`egers between `80` and `100` in backwards order!" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "v4 = np.arange(...)\n", + "\n", + "v4" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "[np.arange() ](https://numpy.org/doc/stable/reference/generated/numpy.arange.html#numpy.arange) is often combined with the `ndarray` method [.reshape() ](https://numpy.org/doc/stable/reference/generated/numpy.ndarray.reshape.html#numpy.ndarray.reshape) that takes a `tuple` as its input specifying the `.shape` of the resulting array.\n", + "\n", + "**Q5**: Create a two-dimensional array modeling a 5x2 matrix by the name `m1` with [np.arange() ](https://numpy.org/doc/stable/reference/generated/numpy.arange.html#numpy.arange) holding the `int`egers from `1` through `10`!" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m1 = np.arange(...).reshape((...))\n", + "\n", + "m1" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q6**: Create a two-dimensional array modeling a 5x5 square matrix by the name `m2` with [np.arange() ](https://numpy.org/doc/stable/reference/generated/numpy.arange.html#numpy.arange) holding the `int`egers from `1` through `25` and flip the elements along the main diagonal!" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m2 = np.arange(...).reshape((...)). ...\n", + "\n", + "m2" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q7**: Slice out the matrix `m3` as the first two rows of `m1`!" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m3 = m1[..., ...]\n", + "\n", + "m3" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q8**: Slice out the matrix `m4` as the last two rows of `m1`!" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m4 = m1[..., ...]\n", + "\n", + "m4" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q9**: Slice out the matrix `m5` from `m1` such that it holds all elements that are on an *odd* row and column!" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m5 = m2[..., ...]\n", + "\n", + "m5" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q10**: Slice out the matrix `m6` from `m1` such that it holds all elements that are on an *even* row and column!" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m6 = m2[..., ...]\n", + "\n", + "m6" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q11**: Slice out the matrix `m7` from `m1` such that it holds all elements that are on an *even* row and an *odd* column!" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m7 = m2[..., ...]\n", + "\n", + "m7" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.12" + }, + "toc": { + "base_numbering": 1, + "nav_menu": {}, + "number_sections": false, + "sideBar": true, + "skip_h1_title": true, + "title_cell": "Table of Contents", + "title_sidebar": "Contents", + "toc_cell": false, + "toc_position": {}, + "toc_section_display": false, + "toc_window_display": false + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/01_scientific_stack/02_content_pandas.ipynb b/01_scientific_stack/02_content_pandas.ipynb new file mode 100644 index 0000000..7939074 --- /dev/null +++ b/01_scientific_stack/02_content_pandas.ipynb @@ -0,0 +1,3480 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Note**: Click on \"*Kernel*\" > \"*Restart Kernel and Clear All Outputs*\" in [JupyterLab](https://jupyterlab.readthedocs.io/en/stable/) *before* reading this notebook to reset its output. If you cannot run this file on your machine, you may want to open it [in the cloud ](https://mybinder.org/v2/gh/webartifex/intro-to-data-science/main?urlpath=lab/tree/01_scientific_stack/02_content_pandas.ipynb)." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Chapter 1: Python's Scientific Stack (Part 2)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "For practitioners, the [numpy ](https://numpy.org/) library may feel a bit too \"technical\" or too close to \"real programming\" and they may prefer something that looks and feels more like Excel. That is where the [pandas ](https://pandas.pydata.org/) library comes in.\n", + "\n", + "Let's first `pip` install and then `import` it." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Requirement already satisfied: pandas in /home/webartifex/repos/intro-to-data-science/.venv/lib/python3.8/site-packages (1.3.3)\n", + "Requirement already satisfied: numpy>=1.17.3 in /home/webartifex/repos/intro-to-data-science/.venv/lib/python3.8/site-packages (from pandas) (1.21.1)\n", + "Requirement already satisfied: python-dateutil>=2.7.3 in /home/webartifex/repos/intro-to-data-science/.venv/lib/python3.8/site-packages (from pandas) (2.8.2)\n", + "Requirement already satisfied: pytz>=2017.3 in /home/webartifex/repos/intro-to-data-science/.venv/lib/python3.8/site-packages (from pandas) (2021.3)\n", + "Requirement already satisfied: six>=1.5 in /home/webartifex/repos/intro-to-data-science/.venv/lib/python3.8/site-packages (from python-dateutil>=2.7.3->pandas) (1.16.0)\n", + "Note: you may need to restart the kernel to use updated packages.\n" + ] + } + ], + "source": [ + "%pip install pandas" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "import pandas as pd" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Excel-like Data with Pandas" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In the same folder as this notebook there is a file named \"*orders.csv*\" that holds the order data of an urban meal delivery platform operating in Bordeaux, France. Open in with a double-click and take a look at its contents right here in JupyterLab!\n", + "\n", + "[pandas ](https://pandas.pydata.org/) provides a [pd.read_csv() ](https://pandas.pydata.org/docs/reference/api/pandas.read_csv.html#pandas.read_csv) function that, as the name suggests, can open and read in CSV data. For Excel files, there is also a [pd.read_excel() ](https://pandas.pydata.org/docs/reference/api/pandas.read_excel.html) function but the CSV format is probably more widespread in use.\n", + "\n", + "Let's read in the \"*orders.csv*\" file with [pd.read_csv() ](https://pandas.pydata.org/docs/reference/api/pandas.read_csv.html#pandas.read_csv) specifying the \"order_id\" column as the **index**. Here, index is a column with *unique* values that allow the identification of each row in a dataset. If we don't specify an index column, [pandas ](https://pandas.pydata.org/) creates a surrogate index as a sequence of integers 1, 2, 3, and so on." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "df = pd.read_csv(\"orders.csv\", index_col=\"order_id\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "`df` models a table-like data structure, comparable to one tab in an Excel file. [pandas ](https://pandas.pydata.org/) and JupyterLab are designed to work well together: The `df` object shows a preview of the dataset below the code cell. The rows are the **records** in the dataset and the columns take the role of the **attributes** each record has. Each column comes with a **domain** of allowable values." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
placed_atrestaurant_idrestauranto_streeto_zipo_cityo_latitudeo_longitudecustomer_idd_streetd_zipd_cityd_latituded_longitudetotalcourier_idpickup_atdelivery_atcancelled
order_id
1925942016-07-18 12:23:131204Max A Table36 Rue Cornac33000Bordeaux44.851402-0.57587010298Rue Rolland 1433000Bordeaux44.842592-0.58052120501423.02016-07-18 12:38:082016-07-18 12:48:220
1926442016-07-18 12:48:551204Max A Table36 Rue Cornac33000Bordeaux44.851402-0.5758706037Rue Rolland 1433000Bordeaux44.842592-0.58052124501426.02016-07-18 13:03:082016-07-18 13:12:010
1926582016-07-18 13:00:131205Taj Mahal24 Rue Du Parlement Sainte-Catherine33000Bordeaux44.840405-0.57394073830Rue Batailley 1233000Bordeaux44.838504-0.59196125501423.02016-07-18 13:19:042016-07-18 13:29:030
1932422016-07-18 20:39:541208Chez Ambre And Michel1 Rue Matignon33000Bordeaux44.850258-0.58620410298Rue Rolland 1433000Bordeaux44.842592-0.58052115501420.02016-07-18 20:55:522016-07-18 21:05:280
1927192016-07-18 13:52:041206La Maison Du Glacier1 Place Saint Pierre33000Bordeaux44.839706-0.5706726037Rue Rolland 1433000Bordeaux44.842592-0.58052124501426.02016-07-18 14:01:232016-07-18 14:08:360
............................................................
2120212016-07-30 22:29:521249Pitaya Sainte Catherine275 Rue Sainte Catherine33000Bordeaux44.831692-0.57320780400Boulevard President Franklin Roosevelt 1533400Bordeaux44.820591-0.58204822501410.02016-07-30 22:50:162016-07-30 23:02:540
2115012016-07-30 20:44:501204Max A Table36 Rue Cornac33000Bordeaux44.851402-0.57587080163Rue Marsan 2233300Bordeaux44.856133-0.57617212501415.02016-07-30 21:02:322016-07-30 21:06:190
2115082016-07-30 20:45:551254Funky Burger5 Rue Du Loup33000Bordeaux44.838081-0.57228180168Rue Des Sablieres 4233800Bordeaux44.825488-0.57526416801461.02016-07-30 21:13:312016-07-30 21:19:450
2115102016-07-30 20:46:051219La Tagliatella14 Rue Guiraude33000Bordeaux44.839388-0.57478180169Rue Pasteur 3533200Bordeaux44.845053-0.60115740851411.02016-07-30 21:11:002016-07-30 21:23:240
2115192016-07-30 20:46:551254Funky Burger5 Rue Du Loup33000Bordeaux44.838081-0.57228180172Rue Monadey 2833800Bordeaux44.828816-0.57078920501817.02016-07-30 21:05:462016-07-30 21:14:070
\n", + "

694 rows × 19 columns

\n", + "
" + ], + "text/plain": [ + " placed_at restaurant_id restaurant \\\n", + "order_id \n", + "192594 2016-07-18 12:23:13 1204 Max A Table \n", + "192644 2016-07-18 12:48:55 1204 Max A Table \n", + "192658 2016-07-18 13:00:13 1205 Taj Mahal \n", + "193242 2016-07-18 20:39:54 1208 Chez Ambre And Michel \n", + "192719 2016-07-18 13:52:04 1206 La Maison Du Glacier \n", + "... ... ... ... \n", + "212021 2016-07-30 22:29:52 1249 Pitaya Sainte Catherine \n", + "211501 2016-07-30 20:44:50 1204 Max A Table \n", + "211508 2016-07-30 20:45:55 1254 Funky Burger \n", + "211510 2016-07-30 20:46:05 1219 La Tagliatella \n", + "211519 2016-07-30 20:46:55 1254 Funky Burger \n", + "\n", + " o_street o_zip o_city o_latitude \\\n", + "order_id \n", + "192594 36 Rue Cornac 33000 Bordeaux 44.851402 \n", + "192644 36 Rue Cornac 33000 Bordeaux 44.851402 \n", + "192658 24 Rue Du Parlement Sainte-Catherine 33000 Bordeaux 44.840405 \n", + "193242 1 Rue Matignon 33000 Bordeaux 44.850258 \n", + "192719 1 Place Saint Pierre 33000 Bordeaux 44.839706 \n", + "... ... ... ... ... \n", + "212021 275 Rue Sainte Catherine 33000 Bordeaux 44.831692 \n", + "211501 36 Rue Cornac 33000 Bordeaux 44.851402 \n", + "211508 5 Rue Du Loup 33000 Bordeaux 44.838081 \n", + "211510 14 Rue Guiraude 33000 Bordeaux 44.839388 \n", + "211519 5 Rue Du Loup 33000 Bordeaux 44.838081 \n", + "\n", + " o_longitude customer_id d_street \\\n", + "order_id \n", + "192594 -0.575870 10298 Rue Rolland 14 \n", + "192644 -0.575870 6037 Rue Rolland 14 \n", + "192658 -0.573940 73830 Rue Batailley 12 \n", + "193242 -0.586204 10298 Rue Rolland 14 \n", + "192719 -0.570672 6037 Rue Rolland 14 \n", + "... ... ... ... \n", + "212021 -0.573207 80400 Boulevard President Franklin Roosevelt 15 \n", + "211501 -0.575870 80163 Rue Marsan 22 \n", + "211508 -0.572281 80168 Rue Des Sablieres 42 \n", + "211510 -0.574781 80169 Rue Pasteur 35 \n", + "211519 -0.572281 80172 Rue Monadey 28 \n", + "\n", + " d_zip d_city d_latitude d_longitude total courier_id \\\n", + "order_id \n", + "192594 33000 Bordeaux 44.842592 -0.580521 2050 1423.0 \n", + "192644 33000 Bordeaux 44.842592 -0.580521 2450 1426.0 \n", + "192658 33000 Bordeaux 44.838504 -0.591961 2550 1423.0 \n", + "193242 33000 Bordeaux 44.842592 -0.580521 1550 1420.0 \n", + "192719 33000 Bordeaux 44.842592 -0.580521 2450 1426.0 \n", + "... ... ... ... ... ... ... \n", + "212021 33400 Bordeaux 44.820591 -0.582048 2250 1410.0 \n", + "211501 33300 Bordeaux 44.856133 -0.576172 1250 1415.0 \n", + "211508 33800 Bordeaux 44.825488 -0.575264 1680 1461.0 \n", + "211510 33200 Bordeaux 44.845053 -0.601157 4085 1411.0 \n", + "211519 33800 Bordeaux 44.828816 -0.570789 2050 1817.0 \n", + "\n", + " pickup_at delivery_at cancelled \n", + "order_id \n", + "192594 2016-07-18 12:38:08 2016-07-18 12:48:22 0 \n", + "192644 2016-07-18 13:03:08 2016-07-18 13:12:01 0 \n", + "192658 2016-07-18 13:19:04 2016-07-18 13:29:03 0 \n", + "193242 2016-07-18 20:55:52 2016-07-18 21:05:28 0 \n", + "192719 2016-07-18 14:01:23 2016-07-18 14:08:36 0 \n", + "... ... ... ... \n", + "212021 2016-07-30 22:50:16 2016-07-30 23:02:54 0 \n", + "211501 2016-07-30 21:02:32 2016-07-30 21:06:19 0 \n", + "211508 2016-07-30 21:13:31 2016-07-30 21:19:45 0 \n", + "211510 2016-07-30 21:11:00 2016-07-30 21:23:24 0 \n", + "211519 2016-07-30 21:05:46 2016-07-30 21:14:07 0 \n", + "\n", + "[694 rows x 19 columns]" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The data type behind `df` is called a [pd.DataFrame ](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.html#pandas.DataFrame). `DataFrame`s are built around [numpy ](https://numpy.org/)'s `ndarray`s providing an interface optimized for **interactive usage** (i.e., a data scientist exploring a dataset step by step)." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "pandas.core.frame.DataFrame" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "type(df)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "`DataFrame`s come with many methdods.\n", + "\n", + "For example, [.head() ](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.head.html#pandas.DataFrame.head) and [.tail() ](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.tail.html#pandas.DataFrame.tail) show the first and last `n` rows, defaulting to `5`." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
placed_atrestaurant_idrestauranto_streeto_zipo_cityo_latitudeo_longitudecustomer_idd_streetd_zipd_cityd_latituded_longitudetotalcourier_idpickup_atdelivery_atcancelled
order_id
1925942016-07-18 12:23:131204Max A Table36 Rue Cornac33000Bordeaux44.851402-0.57587010298Rue Rolland 1433000Bordeaux44.842592-0.58052120501423.02016-07-18 12:38:082016-07-18 12:48:220
1926442016-07-18 12:48:551204Max A Table36 Rue Cornac33000Bordeaux44.851402-0.5758706037Rue Rolland 1433000Bordeaux44.842592-0.58052124501426.02016-07-18 13:03:082016-07-18 13:12:010
1926582016-07-18 13:00:131205Taj Mahal24 Rue Du Parlement Sainte-Catherine33000Bordeaux44.840405-0.57394073830Rue Batailley 1233000Bordeaux44.838504-0.59196125501423.02016-07-18 13:19:042016-07-18 13:29:030
1932422016-07-18 20:39:541208Chez Ambre And Michel1 Rue Matignon33000Bordeaux44.850258-0.58620410298Rue Rolland 1433000Bordeaux44.842592-0.58052115501420.02016-07-18 20:55:522016-07-18 21:05:280
1927192016-07-18 13:52:041206La Maison Du Glacier1 Place Saint Pierre33000Bordeaux44.839706-0.5706726037Rue Rolland 1433000Bordeaux44.842592-0.58052124501426.02016-07-18 14:01:232016-07-18 14:08:360
\n", + "
" + ], + "text/plain": [ + " placed_at restaurant_id restaurant \\\n", + "order_id \n", + "192594 2016-07-18 12:23:13 1204 Max A Table \n", + "192644 2016-07-18 12:48:55 1204 Max A Table \n", + "192658 2016-07-18 13:00:13 1205 Taj Mahal \n", + "193242 2016-07-18 20:39:54 1208 Chez Ambre And Michel \n", + "192719 2016-07-18 13:52:04 1206 La Maison Du Glacier \n", + "\n", + " o_street o_zip o_city o_latitude \\\n", + "order_id \n", + "192594 36 Rue Cornac 33000 Bordeaux 44.851402 \n", + "192644 36 Rue Cornac 33000 Bordeaux 44.851402 \n", + "192658 24 Rue Du Parlement Sainte-Catherine 33000 Bordeaux 44.840405 \n", + "193242 1 Rue Matignon 33000 Bordeaux 44.850258 \n", + "192719 1 Place Saint Pierre 33000 Bordeaux 44.839706 \n", + "\n", + " o_longitude customer_id d_street d_zip d_city \\\n", + "order_id \n", + "192594 -0.575870 10298 Rue Rolland 14 33000 Bordeaux \n", + "192644 -0.575870 6037 Rue Rolland 14 33000 Bordeaux \n", + "192658 -0.573940 73830 Rue Batailley 12 33000 Bordeaux \n", + "193242 -0.586204 10298 Rue Rolland 14 33000 Bordeaux \n", + "192719 -0.570672 6037 Rue Rolland 14 33000 Bordeaux \n", + "\n", + " d_latitude d_longitude total courier_id pickup_at \\\n", + "order_id \n", + "192594 44.842592 -0.580521 2050 1423.0 2016-07-18 12:38:08 \n", + "192644 44.842592 -0.580521 2450 1426.0 2016-07-18 13:03:08 \n", + "192658 44.838504 -0.591961 2550 1423.0 2016-07-18 13:19:04 \n", + "193242 44.842592 -0.580521 1550 1420.0 2016-07-18 20:55:52 \n", + "192719 44.842592 -0.580521 2450 1426.0 2016-07-18 14:01:23 \n", + "\n", + " delivery_at cancelled \n", + "order_id \n", + "192594 2016-07-18 12:48:22 0 \n", + "192644 2016-07-18 13:12:01 0 \n", + "192658 2016-07-18 13:29:03 0 \n", + "193242 2016-07-18 21:05:28 0 \n", + "192719 2016-07-18 14:08:36 0 " + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df.head()" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
placed_atrestaurant_idrestauranto_streeto_zipo_cityo_latitudeo_longitudecustomer_idd_streetd_zipd_cityd_latituded_longitudetotalcourier_idpickup_atdelivery_atcancelled
order_id
2115102016-07-30 20:46:051219La Tagliatella14 Rue Guiraude33000Bordeaux44.839388-0.57478180169Rue Pasteur 3533200Bordeaux44.845053-0.60115740851411.02016-07-30 21:11:002016-07-30 21:23:240
2115192016-07-30 20:46:551254Funky Burger5 Rue Du Loup33000Bordeaux44.838081-0.57228180172Rue Monadey 2833800Bordeaux44.828816-0.57078920501817.02016-07-30 21:05:462016-07-30 21:14:070
\n", + "
" + ], + "text/plain": [ + " placed_at restaurant_id restaurant o_street \\\n", + "order_id \n", + "211510 2016-07-30 20:46:05 1219 La Tagliatella 14 Rue Guiraude \n", + "211519 2016-07-30 20:46:55 1254 Funky Burger 5 Rue Du Loup \n", + "\n", + " o_zip o_city o_latitude o_longitude customer_id \\\n", + "order_id \n", + "211510 33000 Bordeaux 44.839388 -0.574781 80169 \n", + "211519 33000 Bordeaux 44.838081 -0.572281 80172 \n", + "\n", + " d_street d_zip d_city d_latitude d_longitude total \\\n", + "order_id \n", + "211510 Rue Pasteur 35 33200 Bordeaux 44.845053 -0.601157 4085 \n", + "211519 Rue Monadey 28 33800 Bordeaux 44.828816 -0.570789 2050 \n", + "\n", + " courier_id pickup_at delivery_at cancelled \n", + "order_id \n", + "211510 1411.0 2016-07-30 21:11:00 2016-07-30 21:23:24 0 \n", + "211519 1817.0 2016-07-30 21:05:46 2016-07-30 21:14:07 0 " + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df.tail(2)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "[.info() ](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.info.html#pandas.DataFrame.info) shows on overview of the columns. In particular, it shows how many cells are filled in in a column (i.e., are \"non-null\") and what **data type** (i.e., \"dtype\") *all* values in a column have. \"int64\" and \"float64\" imply that there are only `int` and `float` values in a column (taking up to 64 bits or 1s and 0s in memory). \"object\" is [pandas ](https://pandas.pydata.org/)' way of telling us it could not deduce any data type more specific than textual data. For the columns holding timestamps (e.g., \"placed_at\") we will convert the values further below.\n", + "\n", + "Looking at the output, we see that some columns hold the data of **origin**-**destination** pairs, corresponding to restaurants and customers. Other columns store data following the dispatch and delivery process of couriers picking up and delivering meals at various points in time." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "Int64Index: 694 entries, 192594 to 211519\n", + "Data columns (total 19 columns):\n", + " # Column Non-Null Count Dtype \n", + "--- ------ -------------- ----- \n", + " 0 placed_at 694 non-null object \n", + " 1 restaurant_id 694 non-null int64 \n", + " 2 restaurant 694 non-null object \n", + " 3 o_street 694 non-null object \n", + " 4 o_zip 694 non-null int64 \n", + " 5 o_city 694 non-null object \n", + " 6 o_latitude 694 non-null float64\n", + " 7 o_longitude 694 non-null float64\n", + " 8 customer_id 694 non-null int64 \n", + " 9 d_street 694 non-null object \n", + " 10 d_zip 694 non-null int64 \n", + " 11 d_city 694 non-null object \n", + " 12 d_latitude 694 non-null float64\n", + " 13 d_longitude 694 non-null float64\n", + " 14 total 694 non-null int64 \n", + " 15 courier_id 690 non-null float64\n", + " 16 pickup_at 665 non-null object \n", + " 17 delivery_at 663 non-null object \n", + " 18 cancelled 694 non-null int64 \n", + "dtypes: float64(5), int64(6), object(8)\n", + "memory usage: 108.4+ KB\n" + ] + } + ], + "source": [ + "df.info()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "[.describe() ](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.describe.html#pandas.DataFrame.describe) shows statistics on all numerical columns in a `DataFrame`.\n", + "\n", + "For the example orders, such statistics may not be meaningful for all numerical columns as some of them merely hold IDs or zip codes." + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
restaurant_ido_zipo_latitudeo_longitudecustomer_idd_zipd_latituded_longitudetotalcourier_idcancelled
count694.000000694.000000694.000000694.000000694.000000694.000000694.000000694.000000694.000000690.000000694.000000
mean1228.47982733075.21613844.839258-0.57575974751.12680133191.61383344.838623-0.5760402294.6368881484.7550720.044669
std18.001091207.9714350.0074710.00692014604.304963307.3786970.0115450.0107991060.695748154.5862100.206724
min1204.00000033000.00000044.818180-0.5994002377.00000033000.00000044.809813-0.606892350.0000001403.0000000.000000
25%1212.00000033000.00000044.836910-0.57934576648.50000033000.00000044.829981-0.5816121500.0000001415.0000000.000000
50%1224.00000033000.00000044.838287-0.57394078146.00000033000.00000044.838364-0.5750561969.5000001424.0000000.000000
75%1244.00000033000.00000044.841721-0.57228179331.50000033300.00000044.846696-0.5696012750.0000001462.0000000.000000
max1267.00000033800.00000044.855438-0.55057680401.00000033800.00000044.877693-0.5379528370.0000002013.0000001.000000
\n", + "
" + ], + "text/plain": [ + " restaurant_id o_zip o_latitude o_longitude customer_id \\\n", + "count 694.000000 694.000000 694.000000 694.000000 694.000000 \n", + "mean 1228.479827 33075.216138 44.839258 -0.575759 74751.126801 \n", + "std 18.001091 207.971435 0.007471 0.006920 14604.304963 \n", + "min 1204.000000 33000.000000 44.818180 -0.599400 2377.000000 \n", + "25% 1212.000000 33000.000000 44.836910 -0.579345 76648.500000 \n", + "50% 1224.000000 33000.000000 44.838287 -0.573940 78146.000000 \n", + "75% 1244.000000 33000.000000 44.841721 -0.572281 79331.500000 \n", + "max 1267.000000 33800.000000 44.855438 -0.550576 80401.000000 \n", + "\n", + " d_zip d_latitude d_longitude total courier_id \\\n", + "count 694.000000 694.000000 694.000000 694.000000 690.000000 \n", + "mean 33191.613833 44.838623 -0.576040 2294.636888 1484.755072 \n", + "std 307.378697 0.011545 0.010799 1060.695748 154.586210 \n", + "min 33000.000000 44.809813 -0.606892 350.000000 1403.000000 \n", + "25% 33000.000000 44.829981 -0.581612 1500.000000 1415.000000 \n", + "50% 33000.000000 44.838364 -0.575056 1969.500000 1424.000000 \n", + "75% 33300.000000 44.846696 -0.569601 2750.000000 1462.000000 \n", + "max 33800.000000 44.877693 -0.537952 8370.000000 2013.000000 \n", + "\n", + " cancelled \n", + "count 694.000000 \n", + "mean 0.044669 \n", + "std 0.206724 \n", + "min 0.000000 \n", + "25% 0.000000 \n", + "50% 0.000000 \n", + "75% 0.000000 \n", + "max 1.000000 " + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df.describe()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Indexing & Slicing" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "`DataFrame`s support being indexed or sliced, both in the row and column dimensions.\n", + "\n", + "To obtain all data in a single column, we index into the `DataFrame` with the column's name.\n", + "\n", + "For example, `restaurant_col` provides a list of only the restaurant names. Its index are still the \"order_id\"s." + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "order_id\n", + "192594 Max A Table\n", + "192644 Max A Table\n", + "192658 Taj Mahal\n", + "193242 Chez Ambre And Michel\n", + "192719 La Maison Du Glacier\n", + "Name: restaurant, dtype: object" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "restaurant_col = df[\"restaurant\"]\n", + "\n", + "restaurant_col.head()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The data type of a single column is [pd.Series ](https://pandas.pydata.org/docs/reference/api/pandas.Series.html#pandas.Series), which is very similar to a `DataFrame` with only one column. `Series` objects work like built-in `list`s with added functionalities." + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "pandas.core.series.Series" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "type(restaurant_col)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If we index with a `list` of column names, the result is itself another `DataFrame`. That operation is like slicing out a smaller matrix from a larger one as we saw with `ndarray`s before.\n", + "\n", + "For example, let's pull out all location data of the orders' origins (i.e., restaurants)." + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
o_streeto_zipo_cityo_latitudeo_longitude
order_id
19259436 Rue Cornac33000Bordeaux44.851402-0.575870
19264436 Rue Cornac33000Bordeaux44.851402-0.575870
19265824 Rue Du Parlement Sainte-Catherine33000Bordeaux44.840405-0.573940
1932421 Rue Matignon33000Bordeaux44.850258-0.586204
1927191 Place Saint Pierre33000Bordeaux44.839706-0.570672
\n", + "
" + ], + "text/plain": [ + " o_street o_zip o_city o_latitude \\\n", + "order_id \n", + "192594 36 Rue Cornac 33000 Bordeaux 44.851402 \n", + "192644 36 Rue Cornac 33000 Bordeaux 44.851402 \n", + "192658 24 Rue Du Parlement Sainte-Catherine 33000 Bordeaux 44.840405 \n", + "193242 1 Rue Matignon 33000 Bordeaux 44.850258 \n", + "192719 1 Place Saint Pierre 33000 Bordeaux 44.839706 \n", + "\n", + " o_longitude \n", + "order_id \n", + "192594 -0.575870 \n", + "192644 -0.575870 \n", + "192658 -0.573940 \n", + "193242 -0.586204 \n", + "192719 -0.570672 " + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "origins = df[[\"o_street\", \"o_zip\", \"o_city\", \"o_latitude\", \"o_longitude\"]]\n", + "\n", + "origins.head()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To access individual rows, we index not into a `DataFrame` directly but into its [.loc ](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.loc.html#pandas.DataFrame.loc) object (which also exists for `Series`).\n", + "\n", + "Here, `200800` is an \"order_id\" number. The result is a `Series` object where the original `DataFrame`'s columns become the index." + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "placed_at 2016-07-24 19:30:52\n", + "restaurant_id 1204\n", + "restaurant Max A Table\n", + "o_street 36 Rue Cornac\n", + "o_zip 33000\n", + "o_city Bordeaux\n", + "o_latitude 44.851402\n", + "o_longitude -0.57587\n", + "customer_id 76187\n", + "d_street Rue Judaique 213\n", + "d_zip 33000\n", + "d_city Bordeaux\n", + "d_latitude 44.840829\n", + "d_longitude -0.595445\n", + "total 2250\n", + "courier_id 1468.0\n", + "pickup_at 2016-07-24 19:50:52\n", + "delivery_at 2016-07-24 19:58:16\n", + "cancelled 0\n", + "Name: 200800, dtype: object" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df.loc[200800]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We can also index into the `restaurant_col` and `origins` objects from above. As `restaurant_col` is a `Series`, we get back a scalar value." + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'Max A Table'" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "restaurant_col.loc[200800]" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "o_street 36 Rue Cornac\n", + "o_zip 33000\n", + "o_city Bordeaux\n", + "o_latitude 44.851402\n", + "o_longitude -0.57587\n", + "Name: 200800, dtype: object" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "origins.loc[200800]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Slicing also works with [.loc ](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.loc.html#pandas.DataFrame.loc). A tiny difference to Python's built-in slicing, the upper bound is included in the slice as well!" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
placed_atrestaurant_idrestauranto_streeto_zipo_cityo_latitudeo_longitudecustomer_idd_streetd_zipd_cityd_latituded_longitudetotalcourier_idpickup_atdelivery_atcancelled
order_id
2003002016-07-24 13:46:151207Le Jardin Pekinois9 Rue Des Freres Bonie33000Bordeaux44.837078-0.57957276030Rue Villeneuve 133000Bordeaux44.839927-0.58001238201426.02016-07-24 14:12:452016-07-24 14:16:590
2003052016-07-24 13:49:251207Le Jardin Pekinois9 Rue Des Freres Bonie33000Bordeaux44.837078-0.57957276033Rue Du Ha 5433000Bordeaux44.835898-0.57794116891405.02016-07-24 14:12:042016-07-24 14:15:540
2008002016-07-24 19:30:521204Max A Table36 Rue Cornac33000Bordeaux44.851402-0.57587076187Rue Judaique 21333000Bordeaux44.840829-0.59544522501468.02016-07-24 19:50:522016-07-24 19:58:160
\n", + "
" + ], + "text/plain": [ + " placed_at restaurant_id restaurant \\\n", + "order_id \n", + "200300 2016-07-24 13:46:15 1207 Le Jardin Pekinois \n", + "200305 2016-07-24 13:49:25 1207 Le Jardin Pekinois \n", + "200800 2016-07-24 19:30:52 1204 Max A Table \n", + "\n", + " o_street o_zip o_city o_latitude o_longitude \\\n", + "order_id \n", + "200300 9 Rue Des Freres Bonie 33000 Bordeaux 44.837078 -0.579572 \n", + "200305 9 Rue Des Freres Bonie 33000 Bordeaux 44.837078 -0.579572 \n", + "200800 36 Rue Cornac 33000 Bordeaux 44.851402 -0.575870 \n", + "\n", + " customer_id d_street d_zip d_city d_latitude \\\n", + "order_id \n", + "200300 76030 Rue Villeneuve 1 33000 Bordeaux 44.839927 \n", + "200305 76033 Rue Du Ha 54 33000 Bordeaux 44.835898 \n", + "200800 76187 Rue Judaique 213 33000 Bordeaux 44.840829 \n", + "\n", + " d_longitude total courier_id pickup_at \\\n", + "order_id \n", + "200300 -0.580012 3820 1426.0 2016-07-24 14:12:45 \n", + "200305 -0.577941 1689 1405.0 2016-07-24 14:12:04 \n", + "200800 -0.595445 2250 1468.0 2016-07-24 19:50:52 \n", + "\n", + " delivery_at cancelled \n", + "order_id \n", + "200300 2016-07-24 14:16:59 0 \n", + "200305 2016-07-24 14:15:54 0 \n", + "200800 2016-07-24 19:58:16 0 " + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df.loc[200300:200800]" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "order_id\n", + "200300 Le Jardin Pekinois\n", + "200305 Le Jardin Pekinois\n", + "200800 Max A Table\n", + "Name: restaurant, dtype: object" + ] + }, + "execution_count": 17, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "restaurant_col.loc[200300:200800]" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
o_streeto_zipo_cityo_latitudeo_longitude
order_id
2003009 Rue Des Freres Bonie33000Bordeaux44.837078-0.579572
2003059 Rue Des Freres Bonie33000Bordeaux44.837078-0.579572
20080036 Rue Cornac33000Bordeaux44.851402-0.575870
\n", + "
" + ], + "text/plain": [ + " o_street o_zip o_city o_latitude o_longitude\n", + "order_id \n", + "200300 9 Rue Des Freres Bonie 33000 Bordeaux 44.837078 -0.579572\n", + "200305 9 Rue Des Freres Bonie 33000 Bordeaux 44.837078 -0.579572\n", + "200800 36 Rue Cornac 33000 Bordeaux 44.851402 -0.575870" + ] + }, + "execution_count": 18, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "origins.loc[200300:200800]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "[.loc ](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.loc.html#pandas.DataFrame.loc) also allows us to index and slice in both dimensions simultaneously. The first index or slice goes along the row dimension while the second index or slice selects the columns." + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
o_streeto_zipo_cityo_latitudeo_longitude
order_id
2003009 Rue Des Freres Bonie33000Bordeaux44.837078-0.579572
2003059 Rue Des Freres Bonie33000Bordeaux44.837078-0.579572
20080036 Rue Cornac33000Bordeaux44.851402-0.575870
\n", + "
" + ], + "text/plain": [ + " o_street o_zip o_city o_latitude o_longitude\n", + "order_id \n", + "200300 9 Rue Des Freres Bonie 33000 Bordeaux 44.837078 -0.579572\n", + "200305 9 Rue Des Freres Bonie 33000 Bordeaux 44.837078 -0.579572\n", + "200800 36 Rue Cornac 33000 Bordeaux 44.851402 -0.575870" + ] + }, + "execution_count": 19, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df.loc[\n", + " 200300:200800,\n", + " [\"o_street\", \"o_zip\", \"o_city\", \"o_latitude\", \"o_longitude\"]\n", + "]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Type Casting" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "As [.info() ](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.info.html#pandas.DataFrame.info) already revealed above, the timestamp columns could only be parsed as generic objects (i.e., textual data). Also, the \"cancelled\" column which holds only `True` or `False` values does not have a `bool` data type." + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "Int64Index: 694 entries, 192594 to 211519\n", + "Data columns (total 19 columns):\n", + " # Column Non-Null Count Dtype \n", + "--- ------ -------------- ----- \n", + " 0 placed_at 694 non-null object \n", + " 1 restaurant_id 694 non-null int64 \n", + " 2 restaurant 694 non-null object \n", + " 3 o_street 694 non-null object \n", + " 4 o_zip 694 non-null int64 \n", + " 5 o_city 694 non-null object \n", + " 6 o_latitude 694 non-null float64\n", + " 7 o_longitude 694 non-null float64\n", + " 8 customer_id 694 non-null int64 \n", + " 9 d_street 694 non-null object \n", + " 10 d_zip 694 non-null int64 \n", + " 11 d_city 694 non-null object \n", + " 12 d_latitude 694 non-null float64\n", + " 13 d_longitude 694 non-null float64\n", + " 14 total 694 non-null int64 \n", + " 15 courier_id 690 non-null float64\n", + " 16 pickup_at 665 non-null object \n", + " 17 delivery_at 663 non-null object \n", + " 18 cancelled 694 non-null int64 \n", + "dtypes: float64(5), int64(6), object(8)\n", + "memory usage: 124.6+ KB\n" + ] + } + ], + "source": [ + "df.info()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The [pd.to_datetime() ](https://pandas.pydata.org/docs/reference/api/pandas.to_datetime.html#pandas.to_datetime) function **casts** the timestamp columns correctly." + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "order_id\n", + "192594 2016-07-18 12:23:13\n", + "192644 2016-07-18 12:48:55\n", + "192658 2016-07-18 13:00:13\n", + "193242 2016-07-18 20:39:54\n", + "192719 2016-07-18 13:52:04\n", + " ... \n", + "212021 2016-07-30 22:29:52\n", + "211501 2016-07-30 20:44:50\n", + "211508 2016-07-30 20:45:55\n", + "211510 2016-07-30 20:46:05\n", + "211519 2016-07-30 20:46:55\n", + "Name: placed_at, Length: 694, dtype: datetime64[ns]" + ] + }, + "execution_count": 21, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "pd.to_datetime(df[\"placed_at\"])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let's overwrite the original \"placed_at\" column with one that has the correct data type." + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": {}, + "outputs": [], + "source": [ + "df[\"placed_at\"] = pd.to_datetime(df[\"placed_at\"])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The [.astype() ](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.astype.html#pandas.DataFrame.astype) method generalizes this idea and allows us to cast several columns in a `DataFrame`. It takes a `dict`ionary mapping column names to data types as its input. Instead of references to actual data types (e.g., `bool`), it also understands [pandas ](https://pandas.pydata.org/)-specific data types provides as text." + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": {}, + "outputs": [], + "source": [ + "df = df.astype({\n", + " \"pickup_at\": \"datetime64[ns]\",\n", + " \"delivery_at\": \"datetime64[ns]\",\n", + " \"cancelled\": bool,\n", + "})" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, all columns in `df` have more applicable data types." + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "Int64Index: 694 entries, 192594 to 211519\n", + "Data columns (total 19 columns):\n", + " # Column Non-Null Count Dtype \n", + "--- ------ -------------- ----- \n", + " 0 placed_at 694 non-null datetime64[ns]\n", + " 1 restaurant_id 694 non-null int64 \n", + " 2 restaurant 694 non-null object \n", + " 3 o_street 694 non-null object \n", + " 4 o_zip 694 non-null int64 \n", + " 5 o_city 694 non-null object \n", + " 6 o_latitude 694 non-null float64 \n", + " 7 o_longitude 694 non-null float64 \n", + " 8 customer_id 694 non-null int64 \n", + " 9 d_street 694 non-null object \n", + " 10 d_zip 694 non-null int64 \n", + " 11 d_city 694 non-null object \n", + " 12 d_latitude 694 non-null float64 \n", + " 13 d_longitude 694 non-null float64 \n", + " 14 total 694 non-null int64 \n", + " 15 courier_id 690 non-null float64 \n", + " 16 pickup_at 665 non-null datetime64[ns]\n", + " 17 delivery_at 663 non-null datetime64[ns]\n", + " 18 cancelled 694 non-null bool \n", + "dtypes: bool(1), datetime64[ns](3), float64(5), int64(5), object(5)\n", + "memory usage: 119.9+ KB\n" + ] + } + ], + "source": [ + "df.info()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Filtering" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "A common operation when working with `DataFrame`s is to filter for rows fulfilling certain conditions. That is implemented by so-called **boolean filters** in [pandas ](https://pandas.pydata.org/), which is simply a `DataFrame` or `Series` holding only `True` or `False` values.\n", + "\n", + "One way to obtain such objects is to use relational operators with columns.\n", + "\n", + "`max_a_table` holds `True` values for all orders at the restaurant with the ID `1204`." + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "order_id\n", + "192594 True\n", + "192644 True\n", + "192658 False\n", + "193242 False\n", + "192719 False\n", + " ... \n", + "212021 False\n", + "211501 True\n", + "211508 False\n", + "211510 False\n", + "211519 False\n", + "Name: restaurant_id, Length: 694, dtype: bool" + ] + }, + "execution_count": 25, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "max_a_table = df[\"restaurant_id\"] == 1204\n", + "\n", + "max_a_table" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next, let's use a boolean filter to index into `df`. That gives us back a new `DataFame` with all orders belonging to the restaurant \"Max A Table\"." + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
placed_atrestaurant_idrestauranto_streeto_zipo_cityo_latitudeo_longitudecustomer_idd_streetd_zipd_cityd_latituded_longitudetotalcourier_idpickup_atdelivery_atcancelled
order_id
1925942016-07-18 12:23:131204Max A Table36 Rue Cornac33000Bordeaux44.851402-0.5758710298Rue Rolland 1433000Bordeaux44.842592-0.58052120501423.02016-07-18 12:38:082016-07-18 12:48:22False
1926442016-07-18 12:48:551204Max A Table36 Rue Cornac33000Bordeaux44.851402-0.575876037Rue Rolland 1433000Bordeaux44.842592-0.58052124501426.02016-07-18 13:03:082016-07-18 13:12:01False
1943352016-07-19 20:35:211204Max A Table36 Rue Cornac33000Bordeaux44.851402-0.5758774268Place Canteloup 1233800Bordeaux44.833834-0.56567431001420.02016-07-19 20:51:162016-07-19 21:01:08False
1966152016-07-21 19:50:151204Max A Table36 Rue Cornac33000Bordeaux44.851402-0.5758774901Rue Marcelin Jourdan 5533200Bordeaux44.850360-0.59736120501418.02016-07-21 20:12:292016-07-21 20:25:57False
1968392016-07-21 20:27:221204Max A Table36 Rue Cornac33000Bordeaux44.851402-0.5758774966Rue Sainte-Catherine 13733000Bordeaux44.836516-0.57398337501472.02016-07-21 20:41:422016-07-21 21:14:41False
\n", + "
" + ], + "text/plain": [ + " placed_at restaurant_id restaurant o_street \\\n", + "order_id \n", + "192594 2016-07-18 12:23:13 1204 Max A Table 36 Rue Cornac \n", + "192644 2016-07-18 12:48:55 1204 Max A Table 36 Rue Cornac \n", + "194335 2016-07-19 20:35:21 1204 Max A Table 36 Rue Cornac \n", + "196615 2016-07-21 19:50:15 1204 Max A Table 36 Rue Cornac \n", + "196839 2016-07-21 20:27:22 1204 Max A Table 36 Rue Cornac \n", + "\n", + " o_zip o_city o_latitude o_longitude customer_id \\\n", + "order_id \n", + "192594 33000 Bordeaux 44.851402 -0.57587 10298 \n", + "192644 33000 Bordeaux 44.851402 -0.57587 6037 \n", + "194335 33000 Bordeaux 44.851402 -0.57587 74268 \n", + "196615 33000 Bordeaux 44.851402 -0.57587 74901 \n", + "196839 33000 Bordeaux 44.851402 -0.57587 74966 \n", + "\n", + " d_street d_zip d_city d_latitude d_longitude \\\n", + "order_id \n", + "192594 Rue Rolland 14 33000 Bordeaux 44.842592 -0.580521 \n", + "192644 Rue Rolland 14 33000 Bordeaux 44.842592 -0.580521 \n", + "194335 Place Canteloup 12 33800 Bordeaux 44.833834 -0.565674 \n", + "196615 Rue Marcelin Jourdan 55 33200 Bordeaux 44.850360 -0.597361 \n", + "196839 Rue Sainte-Catherine 137 33000 Bordeaux 44.836516 -0.573983 \n", + "\n", + " total courier_id pickup_at delivery_at cancelled \n", + "order_id \n", + "192594 2050 1423.0 2016-07-18 12:38:08 2016-07-18 12:48:22 False \n", + "192644 2450 1426.0 2016-07-18 13:03:08 2016-07-18 13:12:01 False \n", + "194335 3100 1420.0 2016-07-19 20:51:16 2016-07-19 21:01:08 False \n", + "196615 2050 1418.0 2016-07-21 20:12:29 2016-07-21 20:25:57 False \n", + "196839 3750 1472.0 2016-07-21 20:41:42 2016-07-21 21:14:41 False " + ] + }, + "execution_count": 26, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df.loc[df[\"restaurant_id\"] == 1204].head()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Instead of an explicit condition, we can also use a reference to a boolean filter created above." + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
placed_atrestaurant_idrestauranto_streeto_zipo_cityo_latitudeo_longitudecustomer_idd_streetd_zipd_cityd_latituded_longitudetotalcourier_idpickup_atdelivery_atcancelled
order_id
1925942016-07-18 12:23:131204Max A Table36 Rue Cornac33000Bordeaux44.851402-0.5758710298Rue Rolland 1433000Bordeaux44.842592-0.58052120501423.02016-07-18 12:38:082016-07-18 12:48:22False
1926442016-07-18 12:48:551204Max A Table36 Rue Cornac33000Bordeaux44.851402-0.575876037Rue Rolland 1433000Bordeaux44.842592-0.58052124501426.02016-07-18 13:03:082016-07-18 13:12:01False
1943352016-07-19 20:35:211204Max A Table36 Rue Cornac33000Bordeaux44.851402-0.5758774268Place Canteloup 1233800Bordeaux44.833834-0.56567431001420.02016-07-19 20:51:162016-07-19 21:01:08False
1966152016-07-21 19:50:151204Max A Table36 Rue Cornac33000Bordeaux44.851402-0.5758774901Rue Marcelin Jourdan 5533200Bordeaux44.850360-0.59736120501418.02016-07-21 20:12:292016-07-21 20:25:57False
1968392016-07-21 20:27:221204Max A Table36 Rue Cornac33000Bordeaux44.851402-0.5758774966Rue Sainte-Catherine 13733000Bordeaux44.836516-0.57398337501472.02016-07-21 20:41:422016-07-21 21:14:41False
\n", + "
" + ], + "text/plain": [ + " placed_at restaurant_id restaurant o_street \\\n", + "order_id \n", + "192594 2016-07-18 12:23:13 1204 Max A Table 36 Rue Cornac \n", + "192644 2016-07-18 12:48:55 1204 Max A Table 36 Rue Cornac \n", + "194335 2016-07-19 20:35:21 1204 Max A Table 36 Rue Cornac \n", + "196615 2016-07-21 19:50:15 1204 Max A Table 36 Rue Cornac \n", + "196839 2016-07-21 20:27:22 1204 Max A Table 36 Rue Cornac \n", + "\n", + " o_zip o_city o_latitude o_longitude customer_id \\\n", + "order_id \n", + "192594 33000 Bordeaux 44.851402 -0.57587 10298 \n", + "192644 33000 Bordeaux 44.851402 -0.57587 6037 \n", + "194335 33000 Bordeaux 44.851402 -0.57587 74268 \n", + "196615 33000 Bordeaux 44.851402 -0.57587 74901 \n", + "196839 33000 Bordeaux 44.851402 -0.57587 74966 \n", + "\n", + " d_street d_zip d_city d_latitude d_longitude \\\n", + "order_id \n", + "192594 Rue Rolland 14 33000 Bordeaux 44.842592 -0.580521 \n", + "192644 Rue Rolland 14 33000 Bordeaux 44.842592 -0.580521 \n", + "194335 Place Canteloup 12 33800 Bordeaux 44.833834 -0.565674 \n", + "196615 Rue Marcelin Jourdan 55 33200 Bordeaux 44.850360 -0.597361 \n", + "196839 Rue Sainte-Catherine 137 33000 Bordeaux 44.836516 -0.573983 \n", + "\n", + " total courier_id pickup_at delivery_at cancelled \n", + "order_id \n", + "192594 2050 1423.0 2016-07-18 12:38:08 2016-07-18 12:48:22 False \n", + "192644 2450 1426.0 2016-07-18 13:03:08 2016-07-18 13:12:01 False \n", + "194335 3100 1420.0 2016-07-19 20:51:16 2016-07-19 21:01:08 False \n", + "196615 2050 1418.0 2016-07-21 20:12:29 2016-07-21 20:25:57 False \n", + "196839 3750 1472.0 2016-07-21 20:41:42 2016-07-21 21:14:41 False " + ] + }, + "execution_count": 27, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df.loc[max_a_table].head()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Combining the filter with a `list` of columns allows us to further narrow down the `DataFrame`.\n", + "\n", + "For example, the preview below shows us the first five customers \"Max A Table\" had in the target period." + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
customer_idd_streetd_zipd_cityd_latituded_longitude
order_id
19259410298Rue Rolland 1433000Bordeaux44.842592-0.580521
1926446037Rue Rolland 1433000Bordeaux44.842592-0.580521
19433574268Place Canteloup 1233800Bordeaux44.833834-0.565674
19661574901Rue Marcelin Jourdan 5533200Bordeaux44.850360-0.597361
19683974966Rue Sainte-Catherine 13733000Bordeaux44.836516-0.573983
\n", + "
" + ], + "text/plain": [ + " customer_id d_street d_zip d_city d_latitude \\\n", + "order_id \n", + "192594 10298 Rue Rolland 14 33000 Bordeaux 44.842592 \n", + "192644 6037 Rue Rolland 14 33000 Bordeaux 44.842592 \n", + "194335 74268 Place Canteloup 12 33800 Bordeaux 44.833834 \n", + "196615 74901 Rue Marcelin Jourdan 55 33200 Bordeaux 44.850360 \n", + "196839 74966 Rue Sainte-Catherine 137 33000 Bordeaux 44.836516 \n", + "\n", + " d_longitude \n", + "order_id \n", + "192594 -0.580521 \n", + "192644 -0.580521 \n", + "194335 -0.565674 \n", + "196615 -0.597361 \n", + "196839 -0.573983 " + ] + }, + "execution_count": 28, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df.loc[\n", + " max_a_table,\n", + " [\"customer_id\", \"d_street\", \"d_zip\", \"d_city\", \"d_latitude\", \"d_longitude\"]\n", + "].head()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Boolean filters can be created in an arbitray fashion by combining several conditions with `&` and `|` modeling logical AND and OR operators.\n", + "\n", + "The example lists the first five customers of \"Max A Table\" in a target area provided as latitude-longitude coordinates." + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
customer_idd_streetd_zipd_cityd_latituded_longitude
order_id
19661574901Rue Marcelin Jourdan 5533200Bordeaux44.850360-0.597361
20080076187Rue Judaique 21333000Bordeaux44.840829-0.595445
20089376218Rue Notre Dame 2133000Bordeaux44.850260-0.572377
20278876786Rue De Leybardie 2733300Bordeaux44.861360-0.565057
20256376730Rue Lombard 4733300Bordeaux44.858661-0.563095
\n", + "
" + ], + "text/plain": [ + " customer_id d_street d_zip d_city d_latitude \\\n", + "order_id \n", + "196615 74901 Rue Marcelin Jourdan 55 33200 Bordeaux 44.850360 \n", + "200800 76187 Rue Judaique 213 33000 Bordeaux 44.840829 \n", + "200893 76218 Rue Notre Dame 21 33000 Bordeaux 44.850260 \n", + "202788 76786 Rue De Leybardie 27 33300 Bordeaux 44.861360 \n", + "202563 76730 Rue Lombard 47 33300 Bordeaux 44.858661 \n", + "\n", + " d_longitude \n", + "order_id \n", + "196615 -0.597361 \n", + "200800 -0.595445 \n", + "200893 -0.572377 \n", + "202788 -0.565057 \n", + "202563 -0.563095 " + ] + }, + "execution_count": 29, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df.loc[\n", + " (\n", + " max_a_table\n", + " &\n", + " (\n", + " (df[\"d_latitude\"] > 44.85)\n", + " |\n", + " (df[\"d_longitude\"] < -0.59)\n", + " ) \n", + " ),\n", + " [\"customer_id\", \"d_street\", \"d_zip\", \"d_city\", \"d_latitude\", \"d_longitude\"]\n", + "].head()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "[.isin() ](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.isin.html#pandas.DataFrame.isin) is another useful method: It allows us to provide a `list` of values that we are filtering for in a column." + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
placed_atcustomer_idd_streetd_zipd_citytotal
order_id
1926442016-07-18 12:48:556037Rue Rolland 1433000Bordeaux2450
2109452016-07-30 19:30:3979900Rue Du Couvent 1633000Bordeaux1650
2113632016-07-30 20:27:4580095Rue De La Porte Saint-Jean 833000Bordeaux2400
\n", + "
" + ], + "text/plain": [ + " placed_at customer_id d_street \\\n", + "order_id \n", + "192644 2016-07-18 12:48:55 6037 Rue Rolland 14 \n", + "210945 2016-07-30 19:30:39 79900 Rue Du Couvent 16 \n", + "211363 2016-07-30 20:27:45 80095 Rue De La Porte Saint-Jean 8 \n", + "\n", + " d_zip d_city total \n", + "order_id \n", + "192644 33000 Bordeaux 2450 \n", + "210945 33000 Bordeaux 1650 \n", + "211363 33000 Bordeaux 2400 " + ] + }, + "execution_count": 30, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df.loc[\n", + " (\n", + " max_a_table\n", + " &\n", + " df[\"customer_id\"].isin([6037, 79900, 80095])\n", + " ),\n", + " [\"placed_at\", \"customer_id\", \"d_street\", \"d_zip\", \"d_city\", \"total\"]\n", + "].head()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The `~` operator negates a condition. So, in the cell below we see all orders at \"Max A Table\" except the ones from the indicated customers." + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
placed_atcustomer_idd_streetd_zipd_citytotal
order_id
1925942016-07-18 12:23:1310298Rue Rolland 1433000Bordeaux2050
1943352016-07-19 20:35:2174268Place Canteloup 1233800Bordeaux3100
1966152016-07-21 19:50:1574901Rue Marcelin Jourdan 5533200Bordeaux2050
1968392016-07-21 20:27:2274966Rue Sainte-Catherine 13733000Bordeaux3750
1986312016-07-22 21:29:4075047Rue Boudet 2933000Bordeaux2650
\n", + "
" + ], + "text/plain": [ + " placed_at customer_id d_street d_zip \\\n", + "order_id \n", + "192594 2016-07-18 12:23:13 10298 Rue Rolland 14 33000 \n", + "194335 2016-07-19 20:35:21 74268 Place Canteloup 12 33800 \n", + "196615 2016-07-21 19:50:15 74901 Rue Marcelin Jourdan 55 33200 \n", + "196839 2016-07-21 20:27:22 74966 Rue Sainte-Catherine 137 33000 \n", + "198631 2016-07-22 21:29:40 75047 Rue Boudet 29 33000 \n", + "\n", + " d_city total \n", + "order_id \n", + "192594 Bordeaux 2050 \n", + "194335 Bordeaux 3100 \n", + "196615 Bordeaux 2050 \n", + "196839 Bordeaux 3750 \n", + "198631 Bordeaux 2650 " + ] + }, + "execution_count": 31, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df.loc[\n", + " (\n", + " max_a_table\n", + " &\n", + " ~df[\"customer_id\"].isin([6037, 79900, 80095])\n", + " ),\n", + " [\"placed_at\", \"customer_id\", \"d_street\", \"d_zip\", \"d_city\", \"total\"]\n", + "].head()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## DataFrame Methods" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now that we have learned the basics of selecting the data we want from a `DataFrame`, let's look at a couple of methods that allow us to obtain some infos out of a `DataFrame`, in particular, to run some **descriptive statistics**.\n", + "\n", + "[.unique() ](https://pandas.pydata.org/docs/reference/api/pandas.Series.unique.html#pandas.Series.unique) is a simple `Series` method returning an `ndarray` with all values that are in the `Series` once.\n", + "\n", + "Here, we get an overview of how many restaurants there are in Bordeaux in the target time horizon." + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([1204, 1205, 1208, 1206, 1209, 1207, 1211, 1213, 1214, 1212, 1216,\n", + " 1215, 1217, 1218, 1219, 1220, 1221, 1223, 1222, 1224, 1225, 1229,\n", + " 1226, 1227, 1230, 1231, 1232, 1233, 1234, 1235, 1236, 1237, 1239,\n", + " 1241, 1242, 1243, 1245, 1244, 1246, 1247, 1249, 1254, 1250, 1256,\n", + " 1258, 1259, 1260, 1263, 1264, 1266, 1265, 1267])" + ] + }, + "execution_count": 32, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df[\"restaurant_id\"].unique()" + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "52" + ] + }, + "execution_count": 33, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "len(df[\"restaurant_id\"].unique())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To obtain an `ndarray` of all customer IDs of \"Max A Table\", we write the following." + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([10298, 6037, 74268, 74901, 74966, 75047, 76187, 76218, 76442,\n", + " 76396, 76421, 76786, 76822, 76730, 76871, 75687, 77409, 77386,\n", + " 77355, 77556, 78129, 78353, 78608, 78621, 78958, 79119, 79153,\n", + " 76838, 79234, 79486, 79576, 79563, 79653, 79900, 79912, 80026,\n", + " 80204, 80095, 80163])" + ] + }, + "execution_count": 34, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df.loc[\n", + " max_a_table,\n", + " \"customer_id\"\n", + "].unique()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "[.value_counts() ](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.value_counts.html#pandas.DataFrame.value_counts) is similar to [.unique() ](https://pandas.pydata.org/docs/reference/api/pandas.Series.unique.html#pandas.Series.unique) and provides an array sorted by the counts of how often an element occurs in a column or `Series` in descending order.\n", + "\n", + "We use it to list the `10` most popular restaurants and customers in the dataset." + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "1254 78\n", + "1207 47\n", + "1204 39\n", + "1217 37\n", + "1212 32\n", + "1244 25\n", + "1225 25\n", + "1249 23\n", + "1242 19\n", + "1221 18\n", + "Name: restaurant_id, dtype: int64" + ] + }, + "execution_count": 35, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df[\"restaurant_id\"].value_counts().head(10)" + ] + }, + { + "cell_type": "code", + "execution_count": 36, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "73919 14\n", + "10298 12\n", + "6037 8\n", + "77048 5\n", + "4210 4\n", + "74426 4\n", + "9304 3\n", + "76838 3\n", + "75905 3\n", + "74791 3\n", + "Name: customer_id, dtype: int64" + ] + }, + "execution_count": 36, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df[\"customer_id\"].value_counts().head(10)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "[.sum() ](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.sum.html#pandas.DataFrame.sum), [.min() ](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.min.html#pandas.DataFrame.min), [.max() ](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.max.html#pandas.DataFrame.max), [.mean() ](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.mean.html#pandas.DataFrame.mean), and [.round() ](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.round.html#pandas.DataFrame.round) are self-explanatory.\n", + "\n", + "We use it to analyze the overall spendings in Bordeaux and for \"Max A Table\"." + ] + }, + { + "cell_type": "code", + "execution_count": 37, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "15924.78" + ] + }, + "execution_count": 37, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df[\"total\"].sum() / 100 # Convert to Euro" + ] + }, + { + "cell_type": "code", + "execution_count": 38, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "885.0" + ] + }, + "execution_count": 38, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df.loc[\n", + " max_a_table,\n", + " \"total\"\n", + "].sum() / 100" + ] + }, + { + "cell_type": "code", + "execution_count": 39, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "3.5" + ] + }, + "execution_count": 39, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df[\"total\"].min() / 100" + ] + }, + { + "cell_type": "code", + "execution_count": 40, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "83.7" + ] + }, + "execution_count": 40, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df[\"total\"].max() / 100" + ] + }, + { + "cell_type": "code", + "execution_count": 41, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "12.5" + ] + }, + "execution_count": 41, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df.loc[\n", + " max_a_table,\n", + " \"total\"\n", + "].min() / 100" + ] + }, + { + "cell_type": "code", + "execution_count": 42, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "60.0" + ] + }, + "execution_count": 42, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df.loc[\n", + " max_a_table,\n", + " \"total\"\n", + "].max() / 100" + ] + }, + { + "cell_type": "code", + "execution_count": 43, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "22.94636887608069" + ] + }, + "execution_count": 43, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df[\"total\"].mean() / 100" + ] + }, + { + "cell_type": "code", + "execution_count": 44, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "22.95" + ] + }, + "execution_count": 44, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df[\"total\"].mean().round() / 100" + ] + }, + { + "cell_type": "code", + "execution_count": 45, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "22.69" + ] + }, + "execution_count": 45, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df.loc[\n", + " max_a_table,\n", + " \"total\"\n", + "].mean().round() / 100" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.12" + }, + "toc": { + "base_numbering": 1, + "nav_menu": {}, + "number_sections": false, + "sideBar": true, + "skip_h1_title": false, + "title_cell": "Table of Contents", + "title_sidebar": "Contents", + "toc_cell": false, + "toc_position": {}, + "toc_section_display": true, + "toc_window_display": false + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/01_scientific_stack/03_exercises_simple_queries.ipynb b/01_scientific_stack/03_exercises_simple_queries.ipynb new file mode 100644 index 0000000..e588608 --- /dev/null +++ b/01_scientific_stack/03_exercises_simple_queries.ipynb @@ -0,0 +1,215 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Note**: Click on \"*Kernel*\" > \"*Restart Kernel and Run All*\" in [JupyterLab](https://jupyterlab.readthedocs.io/en/stable/) *after* finishing the exercises to ensure that your solution runs top to bottom *without* any errors. If you cannot run this file on your machine, you may want to open it [in the cloud ](https://mybinder.org/v2/gh/webartifex/intro-to-data-science/main?urlpath=lab/tree/01_scientific_stack/03_exercises_simple_queries.ipynb)." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Chapter 0: Python's Scientific Stack (Coding Exercises)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The exercises below assume that you have read the preceeding content sections.\n", + "\n", + "The `...`'s in the code cells indicate where you need to fill in code snippets. The number of `...`'s within a code cell give you a rough idea of how many lines of code are needed to solve the task. You should not need to create any additional code cells for your final solution. However, you may want to use temporary code cells to try out some ideas." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Simple Queries" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import pandas as pd" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The [pd.read_csv() ](https://pandas.pydata.org/docs/reference/api/pandas.read_csv.html#pandas.read_csv) function is very customizable. For example, it takes `dtype` and `parse_dates` inputs, which allows us to parse the timestamp and \"cancelled\" columns correctly right away." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "df = pd.read_csv(\n", + " \"orders.csv\",\n", + " index_col=\"order_id\",\n", + " dtype={\"cancelled\": bool},\n", + " parse_dates=[\"placed_at\", \"pickup_at\", \"delivery_at\"]\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "df.info()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q1**: Write a filter to pull out orders of the restaurant with the name \"Funky Burger\" only!" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "funky_burger = ...\n", + "\n", + "df[funky_burger].head()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q2**: Ensure that there is only one restaurant by this name!\n", + "\n", + "Hint: While several restaurants may share the same name, their ID is still different" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "..." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q3**: How many orders did \"Funky Burger\" *receive* in the target horizon?" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "len(df.loc[...])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q4**: How many orders did \"Funky Burger\" *deliver* in the target horizon?\n", + "\n", + "Hint: \"deliver\" implies that an order must not be cancelled" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "len(...)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q5**: How much revenue did \"Funky Burger\" make?" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "...\n", + " ... & ...,\n", + " \"...\"\n", + "..." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q6**: What was the average order's total at \"Funky Burger\"?" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "...\n", + " ...\n", + " ...\n", + "..." + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.12" + }, + "toc": { + "base_numbering": 1, + "nav_menu": {}, + "number_sections": false, + "sideBar": true, + "skip_h1_title": true, + "title_cell": "Table of Contents", + "title_sidebar": "Contents", + "toc_cell": false, + "toc_position": {}, + "toc_section_display": false, + "toc_window_display": false + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/01_scientific_stack/orders.csv b/01_scientific_stack/orders.csv new file mode 100644 index 0000000..4f1c9b6 --- /dev/null +++ b/01_scientific_stack/orders.csv @@ -0,0 +1,695 @@ +order_id,placed_at,restaurant_id,restaurant,o_street,o_zip,o_city,o_latitude,o_longitude,customer_id,d_street,d_zip,d_city,d_latitude,d_longitude,total,courier_id,pickup_at,delivery_at,cancelled +192594,2016-07-18 12:23:13,1204,Max A Table,36 Rue Cornac,33000,Bordeaux,44.851402,-0.57587,10298,Rue Rolland 14,33000,Bordeaux,44.8425916,-0.5805208,2050,1423,2016-07-18 12:38:08,2016-07-18 12:48:22,0 +192644,2016-07-18 12:48:55,1204,Max A Table,36 Rue Cornac,33000,Bordeaux,44.851402,-0.57587,6037,Rue Rolland 14,33000,Bordeaux,44.8425916,-0.5805208,2450,1426,2016-07-18 13:03:08,2016-07-18 13:12:01,0 +192658,2016-07-18 13:00:13,1205,Taj Mahal,24 Rue Du Parlement Sainte-Catherine,33000,Bordeaux,44.840405,-0.57394,73830,Rue Batailley 12,33000,Bordeaux,44.8385037,-0.5919612,2550,1423,2016-07-18 13:19:04,2016-07-18 13:29:03,0 +193242,2016-07-18 20:39:54,1208,Chez Ambre And Michel,1 Rue Matignon,33000,Bordeaux,44.850258,-0.586204,10298,Rue Rolland 14,33000,Bordeaux,44.8425916,-0.5805208,1550,1420,2016-07-18 20:55:52,2016-07-18 21:05:28,0 +192719,2016-07-18 13:52:04,1206,La Maison Du Glacier,1 Place Saint Pierre,33000,Bordeaux,44.839706,-0.570672,6037,Rue Rolland 14,33000,Bordeaux,44.8425916,-0.5805208,2450,1426,2016-07-18 14:01:23,2016-07-18 14:08:36,0 +193364,2016-07-18 21:04:09,1209,La Gamelle,23 Rue Des Freres Bonie,33000,Bordeaux,44.836849,-0.580108,6037,Rue De La Croix Blanche 7,33000,Bordeaux,44.84433070000001,-0.5892649999999999,4450,1416,2016-07-18 21:33:26,2016-07-18 21:48:22,0 +192999,2016-07-18 19:55:21,1207,Le Jardin Pekinois,9 Rue Des Freres Bonie,33000,Bordeaux,44.837078,-0.579572,73919,Rue Amedee Saint-Germain 121,33800,Bordeaux,44.8183009,-0.5637869999999999,2340,1415,2016-07-18 20:17:00,2016-07-18 20:30:21,0 +193367,2016-07-18 21:04:52,1207,Le Jardin Pekinois,9 Rue Des Freres Bonie,33000,Bordeaux,44.837078,-0.579572,6037,Rue Rolland 14,33000,Bordeaux,44.8425916,-0.5805208,2350,1426,2016-07-18 21:27:45,2016-07-18 21:39:11,0 +193406,2016-07-18 21:13:46,1207,Le Jardin Pekinois,9 Rue Des Freres Bonie,33000,Bordeaux,44.837078,-0.579572,6037,Rue Kleber 13,33200,Bordeaux,44.8476855,-0.6068918,1739,1426,2016-07-18 21:33:42,2016-07-18 22:04:08,0 +193865,2016-07-19 13:35:37,1211,Haru Haru,93 Cours Gambetta,33400,Bordeaux,44.8181798,-0.5851184,6037,Rue Rolland 14,33000,Bordeaux,44.8425916,-0.5805208,1450,1426,2016-07-19 13:49:11,2016-07-19 14:01:25,0 +193881,2016-07-19 13:45:24,1213,Lupo,"23 Place Pey Berland, 33000 Bordeaux",33000,Bordeaux,44.837158,-0.576632,6037,Rue Rolland 14,33000,Bordeaux,44.8425916,-0.5805208,1550,1408,2016-07-19 13:59:17,2016-07-19 14:24:44,0 +193886,2016-07-19 13:52:31,1206,La Maison Du Glacier,1 Place Saint Pierre,33000,Bordeaux,44.839706,-0.570672,73919,Rue Amedee Saint-Germain 121,33800,Bordeaux,44.8183009,-0.5637869999999999,2450,1424,2016-07-19 13:59:06,2016-07-19 14:13:49,0 +194124,2016-07-19 19:47:12,1214,Koh I Noor,3 Rue Du Puits Descujols,33000,Bordeaux,44.841011,-0.570755,74212,Cours Edouard Vaillant 35,33300,Bordeaux,44.8606007,-0.5582429999999999,3150,1403,2016-07-19 20:07:42,2016-07-19 20:17:00,0 +193748,2016-07-19 12:18:58,1211,Haru Haru,93 Cours Gambetta,33400,Bordeaux,44.8181798,-0.5851184,73919,Rue Amedee Saint-Germain 121,33800,Bordeaux,44.8183009,-0.5637869999999999,1650,1426,2016-07-19 12:40:10,2016-07-19 12:49:53,0 +193753,2016-07-19 12:20:20,1212,Cote Terrasse,198 Cours De L'Argonne,33800,Bordeaux,44.824543,-0.578545,73919,Rue Amedee Saint-Germain 121,33800,Bordeaux,44.8183009,-0.5637869999999999,1450,1408,2016-07-19 12:38:17,2016-07-19 12:49:48,0 +194659,2016-07-19 21:49:40,1216,Sushimi,8 Rue Courbin,33000,Bordeaux,44.841721,-0.572962,10298,Rue Rolland 14,33000,Bordeaux,44.8425916,-0.5805208,2080,1416,2016-07-19 22:19:48,2016-07-19 22:29:50,0 +194280,2016-07-19 20:24:08,1215,Moon Wok,17 Place Fernand Lafargue,33000,Bordeaux,44.837299,-0.572124,74253,Rue Lafontaine 35,33800,Bordeaux,44.8268384,-0.5708527,1450,1423,2016-07-19 20:34:34,2016-07-19 20:46:56,0 +194335,2016-07-19 20:35:21,1204,Max A Table,36 Rue Cornac,33000,Bordeaux,44.851402,-0.57587,74268,Place Canteloup 12,33800,Bordeaux,44.8338344,-0.5656738,3100,1420,2016-07-19 20:51:16,2016-07-19 21:01:08,0 +194669,2016-07-19 21:52:30,1217,Henny'S Burger,22 Rue Fondaudege,33000,Bordeaux,44.845875,-0.579345,4210,Rue Rolland 14,33000,Bordeaux,44.8425916,-0.5805208,1750,1403,2016-07-19 22:10:18,,1 +194675,2016-07-19 21:54:35,1218,Le Rizana,7 Rue Gaspard Philippe,33000,Bordeaux,44.833736,-0.56662,22771,Rue Rolland 1,33000,Bordeaux,44.8427648,-0.5794479,1450,1420,2016-07-19 22:06:57,2016-07-19 22:27:18,0 +194466,2016-07-19 21:03:15,1212,Cote Terrasse,198 Cours De L'Argonne,33800,Bordeaux,44.824543,-0.578545,74308,Rue Neuve 15,33130,Bordeaux,44.8108466,-0.5658726,2250,1423,2016-07-19 21:21:43,2016-07-19 21:36:41,0 +194681,2016-07-19 21:56:46,1215,Moon Wok,17 Place Fernand Lafargue,33000,Bordeaux,44.837299,-0.572124,73919,Rue Rolland 14,33000,Bordeaux,44.8425916,-0.5805208,1900,1416,2016-07-19 22:06:38,2016-07-19 22:29:42,0 +194686,2016-07-19 21:57:59,1219,La Tagliatella,14 Rue Guiraude,33000,Bordeaux,44.8393877,-0.5747810999999999,9304,Rue Rolland 14,33000,Bordeaux,44.8425916,-0.5805208,3829,1420,,,1 +194697,2016-07-19 22:01:31,1220,Jardin Phnom Penh,1 Rue Du Cerf Volant,33000,Bordeaux,44.838287,-0.570993,6037,Rue Rolland 14,33000,Bordeaux,44.8425916,-0.5805208,3600,1403,2016-07-19 22:20:54,2016-07-19 22:27:32,0 +194720,2016-07-19 22:11:16,1221,Le Veneto,25 Allee De Tourny,33000,Bordeaux,44.84473,-0.578606,9304,Rue Rolland 14,33000,Bordeaux,44.8425916,-0.5805208,4090,1420,2016-07-19 22:22:53,2016-07-19 22:27:24,0 +194723,2016-07-19 22:12:53,1205,Taj Mahal,24 Rue Du Parlement Sainte-Catherine,33000,Bordeaux,44.840405,-0.57394,4210,Rue Rolland 14,33000,Bordeaux,44.8425916,-0.5805208,1800,1416,2016-07-19 22:24:23,2016-07-19 22:30:08,0 +194826,2016-07-20 11:53:16,1216,Sushimi,8 Rue Courbin,33000,Bordeaux,44.841721,-0.572962,74411,Cours De L'Argonne 197,33000,Bordeaux,44.824824,-0.5788848999999999,1850,1415,2016-07-20 12:18:27,2016-07-20 12:34:39,0 +194935,2016-07-20 12:39:51,1223,Bag'Elles Coffee,19 Rue Du Mirail,33000,Bordeaux,44.83419,-0.571462,73919,Rue Amedee Saint-Germain 121,33800,Bordeaux,44.8183009,-0.5637869999999999,1639,1405,2016-07-20 13:05:38,2016-07-20 13:16:03,0 +194969,2016-07-20 12:59:21,1217,Henny'S Burger,22 Rue Fondaudege,33000,Bordeaux,44.845875,-0.579345,10298,Rue Rolland 14,33000,Bordeaux,44.8425916,-0.5805208,1630,1415,2016-07-20 13:14:01,2016-07-20 13:20:54,0 +194884,2016-07-20 12:18:46,1222,Les Tartines De Marine,"6 Rue Saint-Sernin, Bordeaux",33000,Bordeaux,44.839336,-0.58194,74426,Rue De Tauzia 42,33800,Bordeaux,44.8291733,-0.5581146,3650,1417,2016-07-20 12:37:44,2016-07-20 12:52:01,0 +195003,2016-07-20 13:26:34,1224,Gyoza Factory,6 Rue Georges Bonnac,33000,Bordeaux,44.840355,-0.581659,10298,Rue Rolland 14,33000,Bordeaux,44.8425916,-0.5805208,3279,1415,2016-07-20 13:47:46,2016-07-20 13:52:37,0 +195010,2016-07-20 13:39:04,1207,Le Jardin Pekinois,9 Rue Des Freres Bonie,33000,Bordeaux,44.837078,-0.579572,10298,Rue Rolland 14,33000,Bordeaux,44.8425916,-0.5805208,3100,1418,2016-07-20 14:10:47,2016-07-20 14:18:15,0 +195272,2016-07-20 19:41:47,1212,Cote Terrasse,198 Cours De L'Argonne,33800,Bordeaux,44.824543,-0.578545,74513,Rue Bourges 20,33400,Bordeaux,44.81629059999999,-0.5785701,2050,1411,2016-07-20 20:05:13,2016-07-20 20:18:39,0 +195274,2016-07-20 19:42:34,1207,Le Jardin Pekinois,9 Rue Des Freres Bonie,33000,Bordeaux,44.837078,-0.579572,74519,Rue Cornac 4,33000,Bordeaux,44.8509545,-0.5721066,1490,1419,2016-07-20 20:22:32,2016-07-20 20:31:04,0 +195337,2016-07-20 19:55:31,1223,Bag'Elles Coffee,19 Rue Du Mirail,33000,Bordeaux,44.83419,-0.571462,74541,Cours De La Somme 190,33800,Bordeaux,44.8230039,-0.5722246,2250,1405,2016-07-20 20:15:45,2016-07-20 20:24:59,0 +195177,2016-07-20 19:18:28,1212,Cote Terrasse,198 Cours De L'Argonne,33800,Bordeaux,44.824543,-0.578545,74499,Rue De Ruat 26,33000,Bordeaux,44.83959189999999,-0.5788992000000001,2050,1420,2016-07-20 19:38:57,2016-07-20 19:46:39,0 +195617,2016-07-20 20:44:39,1216,Sushimi,8 Rue Courbin,33000,Bordeaux,44.841721,-0.572962,74618,Cours De Verdun 32,33000,Bordeaux,44.8466972,-0.5766392,1510,1420,2016-07-20 21:06:58,2016-07-20 21:11:43,0 +195239,2016-07-20 19:34:12,1209,La Gamelle,23 Rue Des Freres Bonie,33000,Bordeaux,44.836849,-0.580108,74513,Rue Bourges 20,33400,Bordeaux,44.81629059999999,-0.5785701,1350,1411,2016-07-20 19:50:39,2016-07-20 20:18:45,0 +195675,2016-07-20 20:55:12,1212,Cote Terrasse,198 Cours De L'Argonne,33800,Bordeaux,44.824543,-0.578545,74631,Rue Saint-Jean 85,33800,Bordeaux,44.8248735,-0.5683764,1550,1403,2016-07-20 21:11:42,2016-07-20 21:15:25,0 +195632,2016-07-20 20:46:49,1225,Billy Factory,5 Place Louis Barthou,33000,Bordeaux,44.827942,-0.59441,74622,Cours Gambetta 164,33400,Bordeaux,44.81533599999999,-0.5858416,3570,1405,2016-07-20 21:05:14,2016-07-20 21:11:07,0 +196085,2016-07-21 12:06:00,1229,Les Mijotes Du Bocal,2 Bis Rue De Cursol,33000,Bordeaux,44.834278,-0.57038,74738,Boulevard Albert 1Er 19,33800,Bordeaux,44.8143014,-0.5710408,1950,1463,2016-07-21 12:18:16,2016-07-21 12:35:29,0 +195862,2016-07-20 21:33:39,1211,Haru Haru,93 Cours Gambetta,33400,Bordeaux,44.8181798,-0.5851184,73919,Rue Rolland 14,33000,Bordeaux,44.8425916,-0.5805208,2850,1403,2016-07-20 21:45:18,2016-07-20 21:53:27,0 +195867,2016-07-20 21:35:21,1226,Ici Argentine,84 Boulevard Du President Wilson,33000,Bordeaux,44.840084,-0.5994,73919,Rue Rolland 14,33000,Bordeaux,44.8425916,-0.5805208,2950,1420,2016-07-20 21:54:28,2016-07-20 22:00:06,0 +195871,2016-07-20 21:36:50,1227,Cilicie,4 Rue Des Bahutiers,33000,Bordeaux,44.839531,-0.570651,73919,Rue Rolland 14,33000,Bordeaux,44.8425916,-0.5805208,3750,1416,2016-07-20 21:53:13,2016-07-20 22:06:27,0 +196093,2016-07-21 12:09:28,1222,Les Tartines De Marine,"6 Rue Saint-Sernin, Bordeaux",33000,Bordeaux,44.839336,-0.58194,74426,Rue De Tauzia 42,33800,Bordeaux,44.8291733,-0.5581146,3450,1430,2016-07-21 12:25:10,2016-07-21 12:41:21,0 +196143,2016-07-21 12:35:44,1230,Is&I Kitchen,12 Place Paul Et Jean-Paul Avisseau,33300,Bordeaux,44.855438,-0.567234,74760,Rue Abel Antoune 14,33110,Bordeaux,44.8674088,-0.5824912,1800,1420,2016-07-21 12:56:42,2016-07-21 13:09:23,0 +196165,2016-07-21 12:42:50,1217,Henny'S Burger,22 Rue Fondaudege,33000,Bordeaux,44.845875,-0.579345,73919,Rue Amedee Saint-Germain 121B,33800,Bordeaux,44.8182663,-0.5638276999999999,1630,1415,2016-07-21 12:58:04,2016-07-21 13:13:35,0 +196383,2016-07-21 18:55:20,1207,Le Jardin Pekinois,9 Rue Des Freres Bonie,33000,Bordeaux,44.837078,-0.579572,74826,Cours Aristide Briand 80,33000,Bordeaux,44.8316303,-0.5756167999999999,1540,1468,2016-07-21 19:22:23,2016-07-21 19:26:44,0 +196172,2016-07-21 12:44:53,1231,Umami Ramen,8 Place Fernand Lafargue,33000,Bordeaux,44.83691,-0.573943,73919,Rue Amedee Saint-Germain 121B,33800,Bordeaux,44.8182663,-0.5638276999999999,1820,1405,2016-07-21 12:52:34,2016-07-21 13:22:26,0 +196268,2016-07-21 13:40:56,1229,Les Mijotes Du Bocal,2 Bis Rue De Cursol,33000,Bordeaux,44.834278,-0.57038,10298,Rue Rolland 14,33000,Bordeaux,44.8425916,-0.5805208,1550,1405,2016-07-21 13:50:26,2016-07-21 13:59:29,0 +196474,2016-07-21 19:22:35,1207,Le Jardin Pekinois,9 Rue Des Freres Bonie,33000,Bordeaux,44.837078,-0.579572,74850,Rue Lecocq 72 Ter,33000,Bordeaux,44.8344849,-0.5854412,1739,1430,2016-07-21 19:41:57,2016-07-21 19:59:43,0 +196517,2016-07-21 19:32:25,1206,La Maison Du Glacier,1 Place Saint Pierre,33000,Bordeaux,44.839706,-0.570672,74866,Rue Pelleport 120,33800,Bordeaux,44.821873,-0.5631925999999999,2750,1418,2016-07-21 19:41:13,2016-07-21 19:56:09,0 +196288,2016-07-21 13:58:34,1224,Gyoza Factory,6 Rue Georges Bonnac,33000,Bordeaux,44.840355,-0.581659,74791,Cours D'Albret 83,33000,Bordeaux,44.83473619999999,-0.5807051999999999,2000,1405,,,1 +196571,2016-07-21 19:45:25,1232,Anh Kha,48 Rue Saint Sernin,33000,Bordeaux,44.841103,-0.582515,74883,Rue Albert De Mun 26,33000,Bordeaux,44.8487459,-0.5816116,1250,1403,2016-07-21 20:04:02,2016-07-21 20:08:23,0 +196302,2016-07-21 14:18:06,1225,Billy Factory,5 Place Louis Barthou,33000,Bordeaux,44.827942,-0.59441,74798,Rue De La Rousselle 9,33000,Bordeaux,44.8375181,-0.5692362,1295,1405,2016-07-21 14:34:09,2016-07-21 14:47:58,0 +196792,2016-07-21 20:18:31,1226,Ici Argentine,84 Boulevard Du President Wilson,33000,Bordeaux,44.840084,-0.5994,74958,Rue Poudensan 7,33000,Bordeaux,44.8485698,-0.5869224,1350,1468,2016-07-21 20:39:25,2016-07-21 20:49:01,0 +196615,2016-07-21 19:50:15,1204,Max A Table,36 Rue Cornac,33000,Bordeaux,44.851402,-0.57587,74901,Rue Marcelin Jourdan 55,33200,Bordeaux,44.8503596,-0.5973613999999999,2050,1418,2016-07-21 20:12:29,2016-07-21 20:25:57,0 +196703,2016-07-21 20:03:55,1233,Punjab,39 Rue Saint Remi,33000,Bordeaux,44.841393,-0.572534,74931,Rue De Ruat 26,33000,Bordeaux,44.83959189999999,-0.5788992000000001,3950,1411,2016-07-21 20:17:35,2016-07-21 20:28:49,0 +196705,2016-07-21 20:04:11,1233,Punjab,39 Rue Saint Remi,33000,Bordeaux,44.841393,-0.572534,74932,Cours Balguerie Stuttenberg 96,33300,Bordeaux,44.8578336,-0.5671222,3400,1430,2016-07-21 20:16:55,2016-07-21 20:28:25,0 +196713,2016-07-21 20:05:58,1234,Mille Et Une Saveurs,"96 Avenue Thiers, 33100 Bordeaux",33100,Bordeaux,44.843746,-0.554713,74934,Rue Du Capitaine Ferrand 22,33100,Bordeaux,44.8518856,-0.5388995,1300,1415,2016-07-21 20:21:25,2016-07-21 20:33:55,0 +196839,2016-07-21 20:27:22,1204,Max A Table,36 Rue Cornac,33000,Bordeaux,44.851402,-0.57587,74966,Rue Sainte-Catherine 137,33000,Bordeaux,44.83651589999999,-0.5739832000000001,3750,1472,2016-07-21 20:41:42,2016-07-21 21:14:41,0 +197125,2016-07-21 21:15:16,1208,Chez Ambre And Michel,1 Rue Matignon,33000,Bordeaux,44.850258,-0.586204,75047,Rue Boudet 29,33000,Bordeaux,44.8467347,-0.5763701999999999,2650,1403,,,1 +196851,2016-07-21 20:29:35,1219,La Tagliatella,14 Rue Guiraude,33000,Bordeaux,44.8393877,-0.5747810999999999,74970,Avenue De Tivoli 14,33110,Bordeaux,44.8576458,-0.5915104,1639,1403,2016-07-21 20:52:48,2016-07-21 21:02:03,0 +196901,2016-07-21 20:36:38,1219,La Tagliatella,14 Rue Guiraude,33000,Bordeaux,44.8393877,-0.5747810999999999,74988,Cours De L'Yser 42,33800,Bordeaux,44.8282049,-0.5686705,1345,1411,2016-07-21 20:54:27,2016-07-21 21:05:07,0 +196997,2016-07-21 20:51:08,1231,Umami Ramen,8 Place Fernand Lafargue,33000,Bordeaux,44.83691,-0.573943,75014,Rue Des Argentiers 26,33000,Bordeaux,44.8389043,-0.5696971,3140,1430,2016-07-21 21:04:25,2016-07-21 21:12:11,0 +197232,2016-07-21 21:35:11,1217,Henny'S Burger,22 Rue Fondaudege,33000,Bordeaux,44.845875,-0.579345,75078,Rue De Candale 11,33000,Bordeaux,44.8319862,-0.5722993,1530,1403,2016-07-21 22:06:11,2016-07-21 22:15:31,0 +197084,2016-07-21 21:06:01,1235,Melodie,17 Rue Leupold,33000,Bordeaux,44.840603,-0.570444,75036,Place Gambetta 20,33000,Bordeaux,44.8404572,-0.5805786,1250,1430,2016-07-21 21:20:55,2016-07-21 21:32:55,0 +197338,2016-07-21 22:14:06,1216,Sushimi,8 Rue Courbin,33000,Bordeaux,44.841721,-0.572962,75109,Rue Mouneyra 93,33000,Bordeaux,44.8323712,-0.5852105,1590,1416,2016-07-21 22:34:21,2016-07-21 22:42:10,0 +197351,2016-07-21 22:22:47,1236,Marhaba,27 Rue Des Faures,33800,Bordeaux,44.834766,-0.565754,75115,Rue Pierre Duhem 10,33000,Bordeaux,44.8283819,-0.5827968,2700,1472,2016-07-21 22:49:29,2016-07-21 23:01:57,0 +197449,2016-07-22 11:55:55,1212,Cote Terrasse,198 Cours De L'Argonne,33800,Bordeaux,44.824543,-0.578545,74426,Rue De Tauzia 42,33800,Bordeaux,44.8291733,-0.5581146,5150,1458,2016-07-22 12:11:55,2016-07-22 12:21:27,0 +197096,2016-07-21 21:07:48,1235,Melodie,17 Rue Leupold,33000,Bordeaux,44.840603,-0.570444,75038,Place Gambetta 20,33000,Bordeaux,44.8404572,-0.5805786,1250,1416,2016-07-21 21:27:30,2016-07-21 21:35:31,0 +197101,2016-07-21 21:08:37,1231,Umami Ramen,8 Place Fernand Lafargue,33000,Bordeaux,44.83691,-0.573943,75039,Rue Lafontaine 9,33800,Bordeaux,44.8268699,-0.5718456,1889,1415,2016-07-21 21:20:28,2016-07-21 21:40:57,0 +197952,2016-07-22 19:39:38,1207,Le Jardin Pekinois,9 Rue Des Freres Bonie,33000,Bordeaux,44.837078,-0.579572,75290,Rue Du Docteur Charles Nancel Penard 21,33000,Bordeaux,44.8397886,-0.5814379,2130,1414,2016-07-22 19:57:08,2016-07-22 20:15:17,0 +197597,2016-07-22 12:59:45,1237,Label Terre,2 Cours D'Alsace Lorraine,33000,Bordeaux,44.837952,-0.567716,75192,Rue Cruchinet 3 Bis,33800,Bordeaux,44.8282803,-0.5740767999999999,1250,1468,2016-07-22 13:08:51,2016-07-22 13:16:20,0 +198072,2016-07-22 20:00:00,1207,Le Jardin Pekinois,9 Rue Des Freres Bonie,33000,Bordeaux,44.837078,-0.579572,75328,Rue Fondaudege 42,33000,Bordeaux,44.8469544,-0.5807835,2890,1471,2016-07-22 20:15:10,2016-07-22 20:22:48,0 +198113,2016-07-22 20:04:59,1232,Anh Kha,48 Rue Saint Sernin,33000,Bordeaux,44.841103,-0.582515,75344,Rue Georges Mandel 155,33000,Bordeaux,44.8421745,-0.5954264,4150,1407,2016-07-22 20:30:20,2016-07-22 20:37:11,0 +197824,2016-07-22 19:09:17,1217,Henny'S Burger,22 Rue Fondaudege,33000,Bordeaux,44.845875,-0.579345,75253,Cours De L'Argonne 48,33000,Bordeaux,44.8288365,-0.5738496,2030,1426,2016-07-22 19:40:08,2016-07-22 19:47:35,0 +198122,2016-07-22 20:05:55,1233,Punjab,39 Rue Saint Remi,33000,Bordeaux,44.841393,-0.572534,75347,Rue De Begles 9,33800,Bordeaux,44.8287747,-0.5680915999999999,2530,1430,2016-07-22 20:18:08,2016-07-22 20:31:14,0 +198184,2016-07-22 20:14:40,1207,Le Jardin Pekinois,9 Rue Des Freres Bonie,33000,Bordeaux,44.837078,-0.579572,75366,Rue Guillaume Leblanc 186,33000,Bordeaux,44.83092449999999,-0.5963856,2780,1468,2016-07-22 20:45:55,2016-07-22 20:51:51,0 +198242,2016-07-22 20:23:53,1225,Billy Factory,5 Place Louis Barthou,33000,Bordeaux,44.827942,-0.59441,75380,Rue Du Grand Maurian 8,33000,Bordeaux,44.83066849999999,-0.6043449,450,1422,2016-07-22 20:41:14,2016-07-22 21:01:46,0 +198257,2016-07-22 20:25:52,1239,Tam Tam Saigon,7 Rue Paulin,33000,Bordeaux,44.846516,-0.588076,75389,Boulevard Godard 187,33110,Bordeaux,44.8637918,-0.5812958,2790,1471,2016-07-22 20:37:14,2016-07-22 20:57:56,0 +198202,2016-07-22 20:18:21,1207,Le Jardin Pekinois,9 Rue Des Freres Bonie,33000,Bordeaux,44.837078,-0.579572,75370,Rue Monadey 18,33800,Bordeaux,44.8288717,-0.571275,2530,1417,2016-07-22 20:47:02,2016-07-22 20:53:17,0 +198631,2016-07-22 21:29:40,1204,Max A Table,36 Rue Cornac,33000,Bordeaux,44.851402,-0.57587,75047,Rue Boudet 29,33000,Bordeaux,44.8467347,-0.5763701999999999,2650,1471,2016-07-22 21:42:21,2016-07-22 21:51:58,0 +198676,2016-07-22 21:39:06,1226,Ici Argentine,84 Boulevard Du President Wilson,33000,Bordeaux,44.840084,-0.5994,75519,Rue Margaux 16,33000,Bordeaux,44.8401238,-0.5752217,2950,1426,2016-07-22 21:57:07,2016-07-22 22:06:23,0 +198436,2016-07-22 20:52:46,1233,Punjab,39 Rue Saint Remi,33000,Bordeaux,44.841393,-0.572534,75446,Rue Repond 28,33000,Bordeaux,44.845829,-0.5914465999999999,2760,1426,2016-07-22 21:11:33,2016-07-22 21:19:27,0 +198678,2016-07-22 21:39:12,1224,Gyoza Factory,6 Rue Georges Bonnac,33000,Bordeaux,44.840355,-0.581659,74791,Cours D'Albret 83,33000,Bordeaux,44.83473619999999,-0.5807051999999999,1200,1417,,,1 +198686,2016-07-22 21:40:29,1216,Sushimi,8 Rue Courbin,33000,Bordeaux,44.841721,-0.572962,75522,Cours Du Medoc 75,33300,Bordeaux,44.8595135,-0.567983,1280,1471,2016-07-22 21:58:23,2016-07-22 22:14:24,0 +198718,2016-07-22 21:47:35,1224,Gyoza Factory,6 Rue Georges Bonnac,33000,Bordeaux,44.840355,-0.581659,75535,Cours D'Albret 83,33000,Bordeaux,44.83473619999999,-0.5807051999999999,1250,1422,,,1 +198544,2016-07-22 21:12:52,1232,Anh Kha,48 Rue Saint Sernin,33000,Bordeaux,44.841103,-0.582515,75483,Rue Colette 2,33800,Bordeaux,44.8249279,-0.5767403999999999,1450,1422,2016-07-22 21:23:35,2016-07-22 21:39:43,0 +198747,2016-07-22 21:54:22,1217,Henny'S Burger,22 Rue Fondaudege,33000,Bordeaux,44.845875,-0.579345,75550,Rue Des Pontets 18,33000,Bordeaux,44.8357182,-0.5658378,1250,1417,2016-07-22 22:10:07,2016-07-22 22:18:51,0 +198820,2016-07-22 22:29:19,1236,Marhaba,27 Rue Des Faures,33800,Bordeaux,44.834766,-0.565754,75578,Rue Donissan 56,33000,Bordeaux,44.8287449,-0.5747449,1650,,,,1 +198963,2016-07-23 12:54:54,1225,Billy Factory,5 Place Louis Barthou,33000,Bordeaux,44.827942,-0.59441,75606,Rue Des Freres Bonie 37,33000,Bordeaux,44.8366789,-0.5806582,1520,1412,2016-07-23 13:14:27,2016-07-23 13:33:02,0 +199379,2016-07-23 19:26:30,1207,Le Jardin Pekinois,9 Rue Des Freres Bonie,33000,Bordeaux,44.837078,-0.579572,75711,Avenue Felix Faure 21,33200,Bordeaux,44.8525499,-0.5959232999999999,1830,1409,2016-07-23 19:46:22,2016-07-23 19:57:25,0 +199018,2016-07-23 13:26:10,1220,Jardin Phnom Penh,1 Rue Du Cerf Volant,33000,Bordeaux,44.838287,-0.570993,75615,Rue Des Caperans 19,33000,Bordeaux,44.8406437,-0.5715003,1950,1418,2016-07-23 13:38:43,2016-07-23 13:45:16,0 +199038,2016-07-23 13:35:23,1220,Jardin Phnom Penh,1 Rue Du Cerf Volant,33000,Bordeaux,44.838287,-0.570993,75621,32 Rue De La Boetie 32,33000,Bordeaux,44.8391885,-0.5812602,1500,1430,2016-07-23 13:43:01,2016-07-23 13:55:16,0 +199091,2016-07-23 14:17:04,1225,Billy Factory,5 Place Louis Barthou,33000,Bordeaux,44.827942,-0.59441,75632,Rue Lafontaine 86,33800,Bordeaux,44.8270589,-0.5680672999999999,1270,1471,2016-07-23 14:28:50,2016-07-23 14:49:22,0 +199163,2016-07-23 16:12:12,1225,Billy Factory,5 Place Louis Barthou,33000,Bordeaux,44.827942,-0.59441,75653,Cours De L'Yser 130,33800,Bordeaux,44.82495369999999,-0.5695693,5880,,,,1 +199430,2016-07-23 19:40:32,1214,Koh I Noor,3 Rue Du Puits Descujols,33000,Bordeaux,44.841011,-0.570755,75730,Rue Prunier 120,33300,Bordeaux,44.85971230000001,-0.5741263999999999,2840,1415,2016-07-23 20:04:46,2016-07-23 20:16:47,0 +199280,2016-07-23 18:59:59,1234,Mille Et Une Saveurs,"96 Avenue Thiers, 33100 Bordeaux",33100,Bordeaux,44.843746,-0.554713,75687,Rue De La Rousselle 56,33000,Bordeaux,44.8371635,-0.5677504999999999,3850,1458,2016-07-23 19:15:16,2016-07-23 19:33:24,0 +199487,2016-07-23 19:51:51,1225,Billy Factory,5 Place Louis Barthou,33000,Bordeaux,44.827942,-0.59441,75747,Rue De La Prevote 6,33000,Bordeaux,44.8440582,-0.5852999,1989,1416,2016-07-23 20:06:33,2016-07-23 20:24:50,0 +199308,2016-07-23 19:10:07,1217,Henny'S Burger,22 Rue Fondaudege,33000,Bordeaux,44.845875,-0.579345,75694,Rue De Saincric 22,33000,Bordeaux,44.8320497,-0.5746960999999999,1830,1468,2016-07-23 19:34:10,2016-07-23 19:41:52,0 +199576,2016-07-23 20:10:03,1217,Henny'S Burger,22 Rue Fondaudege,33000,Bordeaux,44.845875,-0.579345,75772,Avenue D'Ares 153,33200,Bordeaux,44.8370445,-0.6065231000000001,1530,1468,2016-07-23 20:23:23,2016-07-23 20:32:33,0 +199733,2016-07-23 20:44:37,1223,Bag'Elles Coffee,19 Rue Du Mirail,33000,Bordeaux,44.83419,-0.571462,75837,Place De La Bourse 18,33000,Bordeaux,44.8418608,-0.5705232,2390,1471,2016-07-23 21:15:40,2016-07-23 21:24:09,0 +199670,2016-07-23 20:32:01,1225,Billy Factory,5 Place Louis Barthou,33000,Bordeaux,44.827942,-0.59441,75811,Rue De La Boetie 25,33000,Bordeaux,44.83935049999999,-0.5809105,1910,1416,2016-07-23 20:45:19,2016-07-23 20:59:44,0 +199796,2016-07-23 20:58:37,1225,Billy Factory,5 Place Louis Barthou,33000,Bordeaux,44.827942,-0.59441,75860,Place Canteloup 12,33800,Bordeaux,44.8338344,-0.5656738,1650,1468,2016-07-23 21:18:56,2016-07-23 21:27:46,0 +199804,2016-07-23 21:01:08,1221,Le Veneto,25 Allee De Tourny,33000,Bordeaux,44.84473,-0.578606,75865,Rue Elie Gintrac 5,33000,Bordeaux,44.830883,-0.5716422,2610,1415,2016-07-23 21:19:11,2016-07-23 21:26:40,0 +199821,2016-07-23 21:05:09,1217,Henny'S Burger,22 Rue Fondaudege,33000,Bordeaux,44.845875,-0.579345,75872,Cours De La Somme 24,33800,Bordeaux,44.8296549,-0.5713018,1450,1416,2016-07-23 21:17:37,2016-07-23 21:27:33,0 +199827,2016-07-23 21:06:10,1217,Henny'S Burger,22 Rue Fondaudege,33000,Bordeaux,44.845875,-0.579345,75874,Rue Borie 44,33300,Bordeaux,44.8544655,-0.5697350999999999,1530,1426,2016-07-23 21:23:42,2016-07-23 21:31:13,0 +199839,2016-07-23 21:09:13,1217,Henny'S Burger,22 Rue Fondaudege,33000,Bordeaux,44.845875,-0.579345,75880,Rue Bergeret 23,33000,Bordeaux,44.8322016,-0.5685524,1330,1422,2016-07-23 21:23:04,2016-07-23 21:35:34,0 +199845,2016-07-23 21:10:42,1217,Henny'S Burger,22 Rue Fondaudege,33000,Bordeaux,44.845875,-0.579345,75882,Rue Borie 44,33300,Bordeaux,44.8544655,-0.5697350999999999,1530,1409,2016-07-23 21:26:44,2016-07-23 21:33:05,0 +199869,2016-07-23 21:15:22,1233,Punjab,39 Rue Saint Remi,33000,Bordeaux,44.841393,-0.572534,75889,Rue Du Tondu 24,33000,Bordeaux,44.832338,-0.5815905,2510,1458,2016-07-23 21:27:44,2016-07-23 21:36:29,0 +199672,2016-07-23 20:32:12,1220,Jardin Phnom Penh,1 Rue Du Cerf Volant,33000,Bordeaux,44.838287,-0.570993,75812,Rue Rene Roy De Clotte 14,33000,Bordeaux,44.8296648,-0.5755587999999999,1700,1468,2016-07-23 20:47:31,2016-07-23 20:56:44,0 +199688,2016-07-23 20:35:15,1212,Cote Terrasse,198 Cours De L'Argonne,33800,Bordeaux,44.824543,-0.578545,75819,Rue Georges Bonnac 55,33000,Bordeaux,44.840485,-0.5839241,1450,1409,2016-07-23 20:54:42,2016-07-23 21:07:39,0 +199876,2016-07-23 21:16:26,1217,Henny'S Burger,22 Rue Fondaudege,33000,Bordeaux,44.845875,-0.579345,75893,Boulevard Godard 40,33300,Bordeaux,44.859547,-0.5891523,1420,1461,2016-07-23 21:35:05,2016-07-23 21:40:43,0 +199881,2016-07-23 21:16:57,1217,Henny'S Burger,22 Rue Fondaudege,33000,Bordeaux,44.845875,-0.579345,75895,Rue Borie 44,33300,Bordeaux,44.8544655,-0.5697350999999999,1530,1472,2016-07-23 21:37:08,2016-07-23 21:45:52,0 +199904,2016-07-23 21:21:33,1224,Gyoza Factory,6 Rue Georges Bonnac,33000,Bordeaux,44.840355,-0.581659,75905,Rue De La Prevote 3,33000,Bordeaux,44.8441797,-0.5850267,1800,1416,2016-07-23 21:37:08,2016-07-23 21:40:57,0 +200224,2016-07-24 13:09:05,1220,Jardin Phnom Penh,1 Rue Du Cerf Volant,33000,Bordeaux,44.838287,-0.570993,4210,Rue Amedee Saint-Germain 121,33800,Bordeaux,44.8183009,-0.5637869999999999,1700,1412,2016-07-24 13:27:15,2016-07-24 13:43:32,0 +200020,2016-07-23 21:56:25,1217,Henny'S Burger,22 Rue Fondaudege,33000,Bordeaux,44.845875,-0.579345,75951,Cite Mouneyra 6,33000,Bordeaux,44.8323473,-0.5844635,1830,1426,2016-07-23 22:15:46,2016-07-23 22:23:17,0 +200300,2016-07-24 13:46:15,1207,Le Jardin Pekinois,9 Rue Des Freres Bonie,33000,Bordeaux,44.837078,-0.579572,76030,Rue Villeneuve 1,33000,Bordeaux,44.8399273,-0.5800124999999999,3820,1426,2016-07-24 14:12:45,2016-07-24 14:16:59,0 +200305,2016-07-24 13:49:25,1207,Le Jardin Pekinois,9 Rue Des Freres Bonie,33000,Bordeaux,44.837078,-0.579572,76033,Rue Du Ha 54,33000,Bordeaux,44.8358976,-0.5779413999999999,1689,1405,2016-07-24 14:12:04,2016-07-24 14:15:54,0 +200800,2016-07-24 19:30:52,1204,Max A Table,36 Rue Cornac,33000,Bordeaux,44.851402,-0.57587,76187,Rue Judaique 213,33000,Bordeaux,44.8408287,-0.5954455,2250,1468,2016-07-24 19:50:52,2016-07-24 19:58:16,0 +200635,2016-07-24 18:56:49,1241,My Terroir,24 Place De La Ferme De Richemont,33000,Bordeaux,44.835506,-0.575218,76141,Rue Contrescarpe 9,33000,Bordeaux,44.8310904,-0.5691697,1750,1468,2016-07-24 19:09:03,2016-07-24 19:19:13,0 +200893,2016-07-24 19:46:32,1204,Max A Table,36 Rue Cornac,33000,Bordeaux,44.851402,-0.57587,76218,Rue Notre Dame 21,33000,Bordeaux,44.8502597,-0.5723775,1300,1415,2016-07-24 20:00:26,2016-07-24 20:09:13,0 +200747,2016-07-24 19:21:44,1216,Sushimi,8 Rue Courbin,33000,Bordeaux,44.841721,-0.572962,76172,Rue Du Pavillon 17,33000,Bordeaux,44.829336,-0.5778071,1280,1461,2016-07-24 19:43:23,2016-07-24 19:48:43,0 +200927,2016-07-24 19:50:29,1220,Jardin Phnom Penh,1 Rue Du Cerf Volant,33000,Bordeaux,44.838287,-0.570993,76233,Rue Henri Dunant 30,33100,Bordeaux,44.8394279,-0.5551889,3000,1418,2016-07-24 20:00:36,2016-07-24 20:13:52,0 +201182,2016-07-24 20:21:04,1236,Marhaba,27 Rue Des Faures,33800,Bordeaux,44.834766,-0.565754,76311,Cours Du Medoc 15Bis,33300,Bordeaux,44.8567725,-0.5650073,1250,1418,2016-07-24 20:36:08,2016-07-24 20:52:45,0 +201199,2016-07-24 20:23:58,1220,Jardin Phnom Penh,1 Rue Du Cerf Volant,33000,Bordeaux,44.838287,-0.570993,76319,Place Andre Meunier Dit Mureine 40,33800,Bordeaux,44.828553,-0.5616951,2350,1426,2016-07-24 20:36:16,2016-07-24 20:47:37,0 +201207,2016-07-24 20:24:48,1236,Marhaba,27 Rue Des Faures,33800,Bordeaux,44.834766,-0.565754,76323,Cours De L'Intendance 38,33000,Bordeaux,44.84161539999999,-0.5776260999999999,3750,1415,2016-07-24 20:44:26,2016-07-24 20:53:43,0 +200928,2016-07-24 19:50:32,1227,Cilicie,4 Rue Des Bahutiers,33000,Bordeaux,44.839531,-0.570651,76234,50 Rue Du Temps Passe 50,33000,Bordeaux,44.8512904,-0.5872427,1450,1426,2016-07-24 20:05:16,2016-07-24 20:15:12,0 +201096,2016-07-24 20:12:03,1236,Marhaba,27 Rue Des Faures,33800,Bordeaux,44.834766,-0.565754,76287,Rue De Begles 248,33800,Bordeaux,44.8188697,-0.5660468000000001,2450,1409,2016-07-24 20:28:11,2016-07-24 20:36:53,0 +201231,2016-07-24 20:26:39,1236,Marhaba,27 Rue Des Faures,33800,Bordeaux,44.834766,-0.565754,76334,Rue Du Ha 29,33000,Bordeaux,44.8361233,-0.5772771999999999,2700,1416,2016-07-24 20:41:50,2016-07-24 20:46:53,0 +201553,2016-07-24 21:08:47,1204,Max A Table,36 Rue Cornac,33000,Bordeaux,44.851402,-0.57587,76442,Rue Emile Fourcand 98,33000,Bordeaux,44.8473528,-0.5872161,2050,1426,2016-07-24 21:21:09,2016-07-24 21:27:17,0 +201422,2016-07-24 20:51:44,1204,Max A Table,36 Rue Cornac,33000,Bordeaux,44.851402,-0.57587,76396,Rue Marguerite Crauste 1,33000,Bordeaux,44.8363155,-0.5869059999999999,2250,1416,2016-07-24 21:03:56,2016-07-24 21:17:36,0 +201486,2016-07-24 20:59:54,1204,Max A Table,36 Rue Cornac,33000,Bordeaux,44.851402,-0.57587,76421,Rue Mouneyra 93,33000,Bordeaux,44.8323712,-0.5852105,2050,1415,2016-07-24 21:12:05,2016-07-24 21:20:29,0 +201698,2016-07-24 21:36:59,1220,Jardin Phnom Penh,1 Rue Du Cerf Volant,33000,Bordeaux,44.838287,-0.570993,76498,Rue De Blaye 19,33100,Bordeaux,44.8476772,-0.5444045,2750,1416,2016-07-24 21:49:58,2016-07-24 21:59:37,0 +201951,2016-07-25 12:09:25,1207,Le Jardin Pekinois,9 Rue Des Freres Bonie,33000,Bordeaux,44.837078,-0.579572,76563,Cours De Luze 71,33300,Bordeaux,44.8578078,-0.5798426999999999,1450,1424,2016-07-25 12:29:38,2016-07-25 12:40:12,0 +201966,2016-07-25 12:17:25,1222,Les Tartines De Marine,"6 Rue Saint-Sernin, Bordeaux",33000,Bordeaux,44.839336,-0.58194,74426,Rue De Tauzia 42,33800,Bordeaux,44.8291733,-0.5581146,2950,1422,2016-07-25 12:35:30,2016-07-25 12:50:39,0 +201704,2016-07-24 21:37:53,1236,Marhaba,27 Rue Des Faures,33800,Bordeaux,44.834766,-0.565754,76501,Rue Lafaurie Monbadon 17,33000,Bordeaux,44.8435447,-0.5799662,2050,1409,2016-07-24 21:50:52,2016-07-24 22:00:14,0 +202030,2016-07-25 12:46:34,1221,Le Veneto,25 Allee De Tourny,33000,Bordeaux,44.84473,-0.578606,76581,Rue Ferrere 6 Bis,33000,Bordeaux,44.8481767,-0.5714347,1510,1465,2016-07-25 13:06:20,2016-07-25 13:17:48,0 +201756,2016-07-24 21:51:18,1218,Le Rizana,7 Rue Gaspard Philippe,33000,Bordeaux,44.833736,-0.56662,76515,Rue De La Benauge 74,33100,Bordeaux,44.8406595,-0.5551796999999999,1850,1415,2016-07-24 22:04:43,2016-07-24 22:17:25,0 +202057,2016-07-25 12:58:33,1222,Les Tartines De Marine,"6 Rue Saint-Sernin, Bordeaux",33000,Bordeaux,44.839336,-0.58194,76587,Cours Saint-Louis 38,33300,Bordeaux,44.85734619999999,-0.5703104999999999,1250,1461,2016-07-25 13:19:32,2016-07-25 13:26:35,0 +202059,2016-07-25 12:58:41,1211,Haru Haru,93 Cours Gambetta,33400,Bordeaux,44.8181798,-0.5851184,73830,Rue Courbin 8,33000,Bordeaux,44.8416582,-0.5729175,3600,1426,2016-07-25 13:21:13,2016-07-25 13:29:38,0 +202076,2016-07-25 13:07:46,1209,La Gamelle,23 Rue Des Freres Bonie,33000,Bordeaux,44.836849,-0.580108,10298,Rue Des Argentiers 16,33000,Bordeaux,44.8391736,-0.5698286,3250,1422,,,1 +202079,2016-07-25 13:10:14,1209,La Gamelle,23 Rue Des Freres Bonie,33000,Bordeaux,44.836849,-0.580108,76594,Cours Saint-Louis 38,33300,Bordeaux,44.85734619999999,-0.5703104999999999,1350,1463,,,1 +201762,2016-07-24 21:52:41,1220,Jardin Phnom Penh,1 Rue Du Cerf Volant,33000,Bordeaux,44.838287,-0.570993,76517,Rue D'Arcachon 43,33000,Bordeaux,44.8267293,-0.584368,1250,1426,2016-07-24 22:01:45,2016-07-24 22:10:58,0 +202100,2016-07-25 13:21:39,1222,Les Tartines De Marine,"6 Rue Saint-Sernin, Bordeaux",33000,Bordeaux,44.839336,-0.58194,75535,Cours D'Albret 83,33000,Bordeaux,44.83473619999999,-0.5807051999999999,1250,1407,2016-07-25 13:35:12,2016-07-25 13:39:19,0 +202389,2016-07-25 19:41:19,1217,Henny'S Burger,22 Rue Fondaudege,33000,Bordeaux,44.845875,-0.579345,76674,Cours De La Somme 24,33800,Bordeaux,44.8296549,-0.5713018,1450,1416,2016-07-25 20:00:43,2016-07-25 20:08:36,0 +202119,2016-07-25 13:37:37,1222,Les Tartines De Marine,"6 Rue Saint-Sernin, Bordeaux",33000,Bordeaux,44.839336,-0.58194,10298,Rue Des Argentiers 16,33000,Bordeaux,44.8391736,-0.5698286,2850,1426,2016-07-25 13:52:38,2016-07-25 13:57:41,0 +202267,2016-07-25 19:11:05,1225,Billy Factory,5 Place Louis Barthou,33000,Bordeaux,44.827942,-0.59441,76640,Rue De La Devise 35,33000,Bordeaux,44.8402324,-0.5723187,1650,1430,2016-07-25 19:25:08,2016-07-25 19:36:56,0 +202432,2016-07-25 19:49:41,1207,Le Jardin Pekinois,9 Rue Des Freres Bonie,33000,Bordeaux,44.837078,-0.579572,76686,Rue Lafaurie Monbadon 39,33000,Bordeaux,44.8443198,-0.5798648,2440,1458,2016-07-25 20:14:45,2016-07-25 20:20:46,0 +202453,2016-07-25 19:53:34,1212,Cote Terrasse,198 Cours De L'Argonne,33800,Bordeaux,44.824543,-0.578545,76691,Rue De Begles 223,33800,Bordeaux,44.819907,-0.5659968,1350,1424,2016-07-25 20:16:46,2016-07-25 20:26:05,0 +202788,2016-07-25 20:47:48,1204,Max A Table,36 Rue Cornac,33000,Bordeaux,44.851402,-0.57587,76786,Rue De Leybardie 27,33300,Bordeaux,44.8613599,-0.5650568,1300,1430,2016-07-25 21:02:32,2016-07-25 21:11:06,0 +202471,2016-07-25 19:57:12,1217,Henny'S Burger,22 Rue Fondaudege,33000,Bordeaux,44.845875,-0.579345,76697,Cours De La Marne 99,33800,Bordeaux,44.82912350000001,-0.566924,1530,1461,2016-07-25 20:11:00,2016-07-25 20:17:58,0 +202829,2016-07-25 20:54:08,1212,Cote Terrasse,198 Cours De L'Argonne,33800,Bordeaux,44.824543,-0.578545,76794,Rue De La Tour Du Pin 25,33000,Bordeaux,44.835629,-0.5652444999999999,1950,1416,2016-07-25 21:17:45,2016-07-25 21:26:38,0 +202836,2016-07-25 20:55:24,1225,Billy Factory,5 Place Louis Barthou,33000,Bordeaux,44.827942,-0.59441,76796,Rue Louis Cabie 42,33800,Bordeaux,44.812272,-0.5716739,5770,1411,2016-07-25 21:12:11,2016-07-25 21:25:30,0 +202478,2016-07-25 19:58:10,1214,Koh I Noor,3 Rue Du Puits Descujols,33000,Bordeaux,44.841011,-0.570755,76700,Rue Belle Etoile 1,33800,Bordeaux,44.8290799,-0.5590144,1390,1460,2016-07-25 20:16:29,2016-07-25 20:34:09,0 +202846,2016-07-25 20:57:10,1219,La Tagliatella,14 Rue Guiraude,33000,Bordeaux,44.8393877,-0.5747810999999999,76798,Rue Leberthon 46,33000,Bordeaux,44.8291378,-0.5753912,4535,1458,2016-07-25 21:21:53,2016-07-25 21:30:30,0 +202485,2016-07-25 19:59:55,1209,La Gamelle,23 Rue Des Freres Bonie,33000,Bordeaux,44.836849,-0.580108,76703,Rue Belle Etoile 1,33800,Bordeaux,44.8290799,-0.5590144,1750,1411,2016-07-25 20:21:09,2016-07-25 20:30:42,0 +202493,2016-07-25 20:01:36,1212,Cote Terrasse,198 Cours De L'Argonne,33800,Bordeaux,44.824543,-0.578545,76706,Rue De Begles 223,33800,Bordeaux,44.819907,-0.5659968,1250,1419,2016-07-25 20:21:56,2016-07-25 20:31:58,0 +202504,2016-07-25 20:03:10,1207,Le Jardin Pekinois,9 Rue Des Freres Bonie,33000,Bordeaux,44.837078,-0.579572,76710,Rue De Begles 223,33800,Bordeaux,44.819907,-0.5659968,2230,1416,2016-07-25 20:33:55,2016-07-25 20:42:53,0 +202901,2016-07-25 21:10:39,1212,Cote Terrasse,198 Cours De L'Argonne,33800,Bordeaux,44.824543,-0.578545,76813,Rue Des Trois-Conils 20,33000,Bordeaux,44.8387071,-0.5755399999999999,1550,1424,2016-07-25 21:39:56,2016-07-25 21:47:30,0 +202904,2016-07-25 21:11:03,1242,Fufu Saint Remi,37 Rue Saint Remi,33000,Bordeaux,44.841438,-0.572537,10298,Rue Des Argentiers 16,33000,Bordeaux,44.8391736,-0.5698286,2400,1460,2016-07-25 21:23:56,2016-07-25 21:33:22,0 +202907,2016-07-25 21:11:43,1212,Cote Terrasse,198 Cours De L'Argonne,33800,Bordeaux,44.824543,-0.578545,76816,Rue Puysegur 39,33800,Bordeaux,44.8211297,-0.5807266999999999,1950,1411,2016-07-25 21:46:40,2016-07-25 21:51:38,0 +202909,2016-07-25 21:12:51,1212,Cote Terrasse,198 Cours De L'Argonne,33800,Bordeaux,44.824543,-0.578545,76817,Rue Du Commandant Arnould 29,33000,Bordeaux,44.8358789,-0.5774694,1450,1416,2016-07-25 21:50:40,2016-07-25 21:57:07,0 +202536,2016-07-25 20:09:10,1212,Cote Terrasse,198 Cours De L'Argonne,33800,Bordeaux,44.824543,-0.578545,76720,Rue Jules Guesde 68,33800,Bordeaux,44.8292454,-0.563711,1350,1430,2016-07-25 20:25:11,2016-07-25 20:32:57,0 +202924,2016-07-25 21:14:37,1234,Mille Et Une Saveurs,"96 Avenue Thiers, 33100 Bordeaux",33100,Bordeaux,44.843746,-0.554713,74519,Rue Cornac 4,33000,Bordeaux,44.8509545,-0.5721066,1350,1460,,,1 +202925,2016-07-25 21:14:46,1204,Max A Table,36 Rue Cornac,33000,Bordeaux,44.851402,-0.57587,76822,Rue De Ruat 11,33000,Bordeaux,44.84036680000001,-0.5792899,2150,1424,2016-07-25 21:54:55,2016-07-25 22:02:05,0 +202563,2016-07-25 20:13:41,1204,Max A Table,36 Rue Cornac,33000,Bordeaux,44.851402,-0.57587,76730,Rue Lombard 47,33300,Bordeaux,44.8586611,-0.5630948,1450,1458,2016-07-25 20:26:07,2016-07-25 20:31:50,0 +202948,2016-07-25 21:22:54,1212,Cote Terrasse,198 Cours De L'Argonne,33800,Bordeaux,44.824543,-0.578545,74268,Place Canteloup 12,33800,Bordeaux,44.8338344,-0.5656738,2450,1458,2016-07-25 21:55:13,2016-07-25 22:03:37,0 +202998,2016-07-25 21:36:14,1232,Anh Kha,48 Rue Saint Sernin,33000,Bordeaux,44.841103,-0.582515,76838,Rue Des Argentiers 16,33000,Bordeaux,44.8391736,-0.5698286,2100,1460,2016-07-25 21:57:50,2016-07-25 22:07:17,0 +202609,2016-07-25 20:19:40,1207,Le Jardin Pekinois,9 Rue Des Freres Bonie,33000,Bordeaux,44.837078,-0.579572,76739,Rue Belle Etoile 1,33800,Bordeaux,44.8290799,-0.5590144,1730,1461,2016-07-25 20:43:12,2016-07-25 20:50:26,0 +203420,2016-07-26 13:51:59,1213,Lupo,"23 Place Pey Berland, 33000 Bordeaux",33000,Bordeaux,44.837158,-0.576632,76977,Avenue Thiers 220,33100,Bordeaux,44.8474955,-0.5486833,1839,1415,2016-07-26 14:10:32,2016-07-26 14:22:09,0 +203032,2016-07-25 21:43:52,1241,My Terroir,24 Place De La Ferme De Richemont,33000,Bordeaux,44.835506,-0.575218,76851,Cours De Verdun 4,33000,Bordeaux,44.8453849,-0.5774521,1350,1416,2016-07-25 22:03:59,2016-07-25 22:10:17,0 +203059,2016-07-25 21:53:30,1217,Henny'S Burger,22 Rue Fondaudege,33000,Bordeaux,44.845875,-0.579345,76864,Rue Cornac 4,33000,Bordeaux,44.8509545,-0.5721066,1830,1411,2016-07-25 22:08:07,2016-07-25 22:13:50,0 +203089,2016-07-25 22:06:02,1204,Max A Table,36 Rue Cornac,33000,Bordeaux,44.851402,-0.57587,76871,Rue Georges Bonnac 281,33000,Bordeaux,44.8373509,-0.5948427,1750,1416,2016-07-25 22:25:26,2016-07-25 22:44:35,0 +203095,2016-07-25 22:10:00,1207,Le Jardin Pekinois,9 Rue Des Freres Bonie,33000,Bordeaux,44.837078,-0.579572,22771,Rue Amedee Saint-Germain 121,33800,Bordeaux,44.8183009,-0.5637869999999999,4570,1458,2016-07-25 22:29:38,2016-07-25 22:37:30,0 +203434,2016-07-26 14:11:18,1221,Le Veneto,25 Allee De Tourny,33000,Bordeaux,44.84473,-0.578606,76981,Rue Crozilhac 4,33000,Bordeaux,44.8505297,-0.5807067,1480,1468,2016-07-26 14:34:52,2016-07-26 14:39:14,0 +203180,2016-07-26 11:41:35,1243,Bagel And Goodies,"53 Cours Le Rouzic, 33100 Bordeaux",33100,Bordeaux,44.842804,-0.550576,76908,Rue De Conde 9,33000,Bordeaux,44.8435849,-0.5733138,1270,1461,2016-07-26 11:58:23,2016-07-26 12:06:57,0 +203506,2016-07-26 18:44:03,1212,Cote Terrasse,198 Cours De L'Argonne,33800,Bordeaux,44.824543,-0.578545,77012,Rue Du Tondu 39,33000,Bordeaux,44.8320552,-0.5825760999999999,2250,1468,2016-07-26 19:05:50,2016-07-26 19:10:51,0 +203585,2016-07-26 19:14:49,1217,Henny'S Burger,22 Rue Fondaudege,33000,Bordeaux,44.845875,-0.579345,77043,Rue Guillaume Leblanc 131,33000,Bordeaux,44.8316538,-0.5951721,1530,1419,2016-07-26 19:28:06,2016-07-26 19:37:42,0 +203290,2016-07-26 12:27:00,1219,La Tagliatella,14 Rue Guiraude,33000,Bordeaux,44.8393877,-0.5747810999999999,76943,Rue Naujac 203,33000,Bordeaux,44.85024420000001,-0.5930807,2880,1415,2016-07-26 12:50:12,2016-07-26 13:01:29,0 +203303,2016-07-26 12:32:16,1216,Sushimi,8 Rue Courbin,33000,Bordeaux,44.841721,-0.572962,76943,Rue Naujac 203,33000,Bordeaux,44.85024420000001,-0.5930807,2390,1468,2016-07-26 12:57:50,2016-07-26 13:13:14,0 +203595,2016-07-26 19:16:39,1245,Eatsalad,55 Rue Saint Remi,33000,Bordeaux,44.841286,-0.573413,77048,Rue Frere 108,33000,Bordeaux,44.8539023,-0.5798308999999999,3040,1426,2016-07-26 19:33:38,2016-07-26 19:44:58,0 +203329,2016-07-26 12:44:29,1244,Fufu Chartrons,71 Cours Portal,33300,Bordeaux,44.85516,-0.572128,76953,Rue Bouthier 151,33100,Bordeaux,44.8513888,-0.5558318999999999,4550,1418,2016-07-26 13:03:32,2016-07-26 13:20:14,0 +203334,2016-07-26 12:46:11,1244,Fufu Chartrons,71 Cours Portal,33300,Bordeaux,44.85516,-0.572128,76955,Rue De La Prevote 3,33000,Bordeaux,44.8441797,-0.5850267,1450,1458,2016-07-26 13:12:55,2016-07-26 13:21:16,0 +203602,2016-07-26 19:19:26,1221,Le Veneto,25 Allee De Tourny,33000,Bordeaux,44.84473,-0.578606,77048,Rue Frere 108,33000,Bordeaux,44.8539023,-0.5798308999999999,2910,1426,2016-07-26 19:38:45,2016-07-26 19:44:21,0 +203668,2016-07-26 19:32:30,1209,La Gamelle,23 Rue Des Freres Bonie,33000,Bordeaux,44.836849,-0.580108,77077,Cours De La Somme 156,33800,Bordeaux,44.8246015,-0.5725093,3100,1458,2016-07-26 19:48:50,2016-07-26 19:55:56,0 +203696,2016-07-26 19:36:01,1217,Henny'S Burger,22 Rue Fondaudege,33000,Bordeaux,44.845875,-0.579345,77088,Rue Gensan 19,33000,Bordeaux,44.835461,-0.5668841,1450,1420,2016-07-26 19:50:43,2016-07-26 20:01:54,0 +203793,2016-07-26 19:54:41,1212,Cote Terrasse,198 Cours De L'Argonne,33800,Bordeaux,44.824543,-0.578545,77120,Rue Des Augustins 12,33000,Bordeaux,44.8323478,-0.57126,2550,1458,2016-07-26 20:24:58,2016-07-26 20:29:17,0 +203822,2016-07-26 19:58:42,1246,Thai Paradise,70 Rue Des Ayres,33000,Bordeaux,44.836327,-0.575572,77130,Quai Richelieu 17,33000,Bordeaux,44.8391694,-0.5684714,3850,1419,2016-07-26 20:15:19,2016-07-26 20:22:13,0 +203699,2016-07-26 19:36:20,1239,Tam Tam Saigon,7 Rue Paulin,33000,Bordeaux,44.846516,-0.588076,77090,Rue Ducau 61,33000,Bordeaux,44.8534777,-0.5759679999999999,2290,1471,2016-07-26 20:12:56,2016-07-26 20:18:44,0 +203825,2016-07-26 19:58:55,1244,Fufu Chartrons,71 Cours Portal,33300,Bordeaux,44.85516,-0.572128,77133,Cours Xavier Arnozan 41,33000,Bordeaux,44.8492097,-0.5735707,2600,1817,2016-07-26 20:13:53,2016-07-26 20:20:12,0 +203710,2016-07-26 19:38:32,1216,Sushimi,8 Rue Courbin,33000,Bordeaux,44.841721,-0.572962,77092,Rue Vieillard 9,33300,Bordeaux,44.8607278,-0.5617738999999999,1820,1411,2016-07-26 19:58:37,2016-07-26 20:14:51,0 +203726,2016-07-26 19:41:24,1242,Fufu Saint Remi,37 Rue Saint Remi,33000,Bordeaux,44.841438,-0.572537,77096,Rue Du Puits Descazeaux 6,33000,Bordeaux,44.8367617,-0.5681312,1300,1415,2016-07-26 19:55:26,2016-07-26 20:03:00,0 +203871,2016-07-26 20:06:36,1231,Umami Ramen,8 Place Fernand Lafargue,33000,Bordeaux,44.83691,-0.573943,77151,Rue Perey 42,33000,Bordeaux,44.82424959999999,-0.5851284,3140,1415,2016-07-26 20:24:30,2016-07-26 20:36:38,0 +203744,2016-07-26 19:45:44,1208,Chez Ambre And Michel,1 Rue Matignon,33000,Bordeaux,44.850258,-0.586204,75290,Rue Du Docteur Charles Nancel Penard 21,33000,Bordeaux,44.8397886,-0.5814379,2250,1426,2016-07-26 20:05:41,2016-07-26 20:14:04,0 +203756,2016-07-26 19:48:35,1221,Le Veneto,25 Allee De Tourny,33000,Bordeaux,44.84473,-0.578606,77105,Allee Serr 59,33100,Bordeaux,44.8430048,-0.5582541,1580,1468,2016-07-26 20:14:48,2016-07-26 20:23:07,0 +203914,2016-07-26 20:13:33,1206,La Maison Du Glacier,1 Place Saint Pierre,33000,Bordeaux,44.839706,-0.570672,77174,Quai Des Chartrons 96,33300,Bordeaux,44.8552969,-0.5663155999999999,3550,1418,2016-07-26 20:25:36,2016-07-26 20:36:34,0 +203917,2016-07-26 20:14:01,1236,Marhaba,27 Rue Des Faures,33800,Bordeaux,44.834766,-0.565754,77176,Rue Monadey 3,33800,Bordeaux,44.8284338,-0.5720206,1500,1420,2016-07-26 20:28:13,2016-07-26 20:34:21,0 +204186,2016-07-26 20:47:55,1206,La Maison Du Glacier,1 Place Saint Pierre,33000,Bordeaux,44.839706,-0.570672,75905,Rue De La Prevote 3,33000,Bordeaux,44.8441797,-0.5850267,2450,1420,2016-07-26 20:55:25,2016-07-26 21:05:09,0 +203950,2016-07-26 20:18:27,1239,Tam Tam Saigon,7 Rue Paulin,33000,Bordeaux,44.846516,-0.588076,77188,Rue Robert Lateulade 5,33000,Bordeaux,44.8391431,-0.5865663999999999,2190,1426,2016-07-26 20:47:15,2016-07-26 21:07:09,0 +203984,2016-07-26 20:21:36,1208,Chez Ambre And Michel,1 Rue Matignon,33000,Bordeaux,44.850258,-0.586204,77195,Rue Pomme D'Or 42,33300,Bordeaux,44.8538481,-0.5700326000000001,1250,1471,2016-07-26 20:40:16,2016-07-26 20:48:00,0 +204194,2016-07-26 20:48:59,1208,Chez Ambre And Michel,1 Rue Matignon,33000,Bordeaux,44.850258,-0.586204,77281,Rue Du Lavoir 10,33000,Bordeaux,44.8520066,-0.5835382,2250,1471,2016-07-26 21:07:07,2016-07-26 21:11:01,0 +204210,2016-07-26 20:51:44,1217,Henny'S Burger,22 Rue Fondaudege,33000,Bordeaux,44.845875,-0.579345,77289,Rue Ausone 29,33000,Bordeaux,44.8375476,-0.5679664,1750,1817,2016-07-26 21:13:44,2016-07-26 21:34:18,0 +204064,2016-07-26 20:32:38,1217,Henny'S Burger,22 Rue Fondaudege,33000,Bordeaux,44.845875,-0.579345,77228,Rue Henri Guillemin 10,33300,Bordeaux,44.8635365,-0.5770312,1530,1409,2016-07-26 21:03:54,2016-07-26 21:13:39,0 +204215,2016-07-26 20:52:25,1235,Melodie,17 Rue Leupold,33000,Bordeaux,44.840603,-0.570444,77291,Rue De Vincennes 36,33000,Bordeaux,44.8393325,-0.5961301,1850,1461,2016-07-26 21:14:08,2016-07-26 21:21:21,0 +204091,2016-07-26 20:36:47,1208,Chez Ambre And Michel,1 Rue Matignon,33000,Bordeaux,44.850258,-0.586204,77239,Rue Dupaty 70,33300,Bordeaux,44.859334,-0.5619312,2450,1468,2016-07-26 20:53:51,2016-07-26 21:02:49,0 +204094,2016-07-26 20:37:13,1244,Fufu Chartrons,71 Cours Portal,33300,Bordeaux,44.85516,-0.572128,77241,Rue Blanqui 57,33300,Bordeaux,44.8686512,-0.5512760999999999,2500,1411,2016-07-26 20:50:56,2016-07-26 21:08:01,0 +204109,2016-07-26 20:39:11,1204,Max A Table,36 Rue Cornac,33000,Bordeaux,44.851402,-0.57587,75687,Rue De La Rousselle 56,33000,Bordeaux,44.8371635,-0.5677504999999999,2250,1418,2016-07-26 20:50:55,2016-07-26 21:02:19,0 +204220,2016-07-26 20:53:48,1247,Noonies,16 Avenue Tiers,33100,Bordeaux,44.841251,-0.558816,77293,Rue Mauriac 4,33000,Bordeaux,44.8356333,-0.5673574,1450,1419,2016-07-26 21:13:07,2016-07-26 21:19:02,0 +204229,2016-07-26 20:54:38,1242,Fufu Saint Remi,37 Rue Saint Remi,33000,Bordeaux,44.841438,-0.572537,77297,Passage Moreau 3,33800,Bordeaux,44.8300096,-0.5708578000000001,1550,1472,2016-07-26 21:03:31,2016-07-26 21:16:50,0 +204120,2016-07-26 20:40:05,1246,Thai Paradise,70 Rue Des Ayres,33000,Bordeaux,44.836327,-0.575572,77250,Rue Abbe De L'Epee 85,33000,Bordeaux,44.84239119999999,-0.583046,2350,1458,2016-07-26 20:57:16,2016-07-26 21:04:41,0 +204232,2016-07-26 20:54:45,1231,Umami Ramen,8 Place Fernand Lafargue,33000,Bordeaux,44.83691,-0.573943,77299,Rue Montmejean 54,33100,Bordeaux,44.8413488,-0.5554852,3590,1418,2016-07-26 21:16:48,2016-07-26 21:24:32,0 +204295,2016-07-26 21:03:40,1232,Anh Kha,48 Rue Saint Sernin,33000,Bordeaux,44.841103,-0.582515,77324,Rue Du Palais Gallien 161,33000,Bordeaux,44.8470899,-0.5817365,1250,1420,2016-07-26 21:13:43,2016-07-26 21:17:05,0 +204515,2016-07-26 21:34:32,1215,Moon Wok,17 Place Fernand Lafargue,33000,Bordeaux,44.837299,-0.572124,77402,Rue Du Peugue 22,33000,Bordeaux,44.8328613,-0.5871291,1530,1411,2016-07-26 21:54:50,2016-07-26 22:09:15,0 +204539,2016-07-26 21:39:07,1204,Max A Table,36 Rue Cornac,33000,Bordeaux,44.851402,-0.57587,77409,Rue Lafayette 8,33000,Bordeaux,44.8436175,-0.5709337,2800,1458,2016-07-26 21:52:59,2016-07-26 21:57:58,0 +204306,2016-07-26 21:05:24,1244,Fufu Chartrons,71 Cours Portal,33300,Bordeaux,44.85516,-0.572128,77327,Rue Henri Guillemin 10,33300,Bordeaux,44.8635365,-0.5770312,1300,1468,2016-07-26 21:14:31,2016-07-26 21:20:34,0 +204561,2016-07-26 21:44:48,1212,Cote Terrasse,198 Cours De L'Argonne,33800,Bordeaux,44.824543,-0.578545,77365,Passage Hermitte 1,33000,Bordeaux,44.8324285,-0.5953436999999999,1550,1471,2016-07-26 21:59:26,2016-07-26 22:11:23,0 +204568,2016-07-26 21:46:35,1244,Fufu Chartrons,71 Cours Portal,33300,Bordeaux,44.85516,-0.572128,77422,Rue Dupaty 132,33300,Bordeaux,44.8613118,-0.5584047,5850,1461,2016-07-26 22:03:05,2016-07-26 22:07:45,0 +204357,2016-07-26 21:11:38,1231,Umami Ramen,8 Place Fernand Lafargue,33000,Bordeaux,44.83691,-0.573943,77343,Rue Bergeret 20,33000,Bordeaux,44.8326405,-0.5689734,1889,1426,2016-07-26 21:25:24,2016-07-26 21:30:44,0 +204584,2016-07-26 21:50:49,1204,Max A Table,36 Rue Cornac,33000,Bordeaux,44.851402,-0.57587,77386,Cours Edouard Vaillant 103,33300,Bordeaux,44.86274299999999,-0.5599192,4650,1415,2016-07-26 21:59:40,2016-07-26 22:15:56,0 +204605,2016-07-26 21:59:19,1231,Umami Ramen,8 Place Fernand Lafargue,33000,Bordeaux,44.83691,-0.573943,77438,Rue Bragard 4,33000,Bordeaux,44.8328572,-0.5701372,1850,1458,2016-07-26 22:15:43,2016-07-26 22:21:17,0 +204366,2016-07-26 21:12:47,1217,Henny'S Burger,22 Rue Fondaudege,33000,Bordeaux,44.845875,-0.579345,77344,Rue Notre Dame 91,33000,Bordeaux,44.8525666,-0.5707285000000001,1400,1420,2016-07-26 21:28:10,2016-07-26 21:34:44,0 +204649,2016-07-26 22:17:38,1242,Fufu Saint Remi,37 Rue Saint Remi,33000,Bordeaux,44.841438,-0.572537,76864,Place Jean Moulin 4,33000,Bordeaux,44.8383642,-0.5780067,1400,1411,2016-07-26 22:30:50,2016-07-26 22:39:03,0 +204391,2016-07-26 21:16:00,1204,Max A Table,36 Rue Cornac,33000,Bordeaux,44.851402,-0.57587,77355,Rue Manon Cormier 40 Bis,33000,Bordeaux,44.8317588,-0.5894056999999999,2050,1409,2016-07-26 21:30:00,2016-07-26 21:40:06,0 +204421,2016-07-26 21:20:25,1208,Chez Ambre And Michel,1 Rue Matignon,33000,Bordeaux,44.850258,-0.586204,77365,Passage Hermitte 1,33000,Bordeaux,44.8324285,-0.5953436999999999,1750,1411,,,1 +204793,2016-07-27 12:03:43,1249,Pitaya Sainte Catherine,275 Rue Sainte Catherine,33000,Bordeaux,44.831692,-0.573207,77502,Rue Du Palais Gallien 102,33000,Bordeaux,44.8450558,-0.5813096,1500,1418,2016-07-27 12:18:46,2016-07-27 12:30:06,0 +204443,2016-07-26 21:21:27,1216,Sushimi,8 Rue Courbin,33000,Bordeaux,44.841721,-0.572962,77372,Rue Naujac 114,33000,Bordeaux,44.8485952,-0.5890605,1730,1415,2016-07-26 21:44:38,2016-07-26 21:50:49,0 +204827,2016-07-27 12:14:15,1219,La Tagliatella,14 Rue Guiraude,33000,Bordeaux,44.8393877,-0.5747810999999999,77048,Rue Frere 108,33000,Bordeaux,44.8539023,-0.5798308999999999,4640,1417,2016-07-27 12:33:54,2016-07-27 12:43:41,0 +204445,2016-07-26 21:21:41,1216,Sushimi,8 Rue Courbin,33000,Bordeaux,44.841721,-0.572962,77374,Rue Naujac 119,33000,Bordeaux,44.8490118,-0.5890955,350,1417,2016-07-26 21:42:52,2016-07-26 21:51:34,0 +204450,2016-07-26 21:22:11,1216,Sushimi,8 Rue Courbin,33000,Bordeaux,44.841721,-0.572962,77376,Rue Naujac 114,33000,Bordeaux,44.8485952,-0.5890605,1280,1415,2016-07-26 21:43:06,2016-07-26 21:50:47,0 +204470,2016-07-26 21:26:07,1217,Henny'S Burger,22 Rue Fondaudege,33000,Bordeaux,44.845875,-0.579345,77386,Cours Edouard Vaillant 103,33300,Bordeaux,44.86274299999999,-0.5599192,4900,1468,,,1 +204856,2016-07-27 12:22:58,1242,Fufu Saint Remi,37 Rue Saint Remi,33000,Bordeaux,44.841438,-0.572537,77526,Quai Richelieu 55,33000,Bordeaux,44.8371276,-0.5666549,1250,1461,2016-07-27 12:41:40,2016-07-27 12:45:26,0 +205251,2016-07-27 19:19:42,1239,Tam Tam Saigon,7 Rue Paulin,33000,Bordeaux,44.846516,-0.588076,77668,Rue Du Pas-Saint-Georges 30,33000,Bordeaux,44.8394088,-0.571848,1789,1471,2016-07-27 19:48:26,2016-07-27 19:58:08,0 +204907,2016-07-27 12:37:24,1223,Bag'Elles Coffee,19 Rue Du Mirail,33000,Bordeaux,44.83419,-0.571462,77542,Rue Beyssac 23,33800,Bordeaux,44.8327494,-0.5635261,1480,1424,2016-07-27 12:59:50,2016-07-27 13:07:24,0 +204919,2016-07-27 12:40:49,1245,Eatsalad,55 Rue Saint Remi,33000,Bordeaux,44.841286,-0.573413,66716,Rue Des Freres Bonie 37,33000,Bordeaux,44.8366789,-0.5806582,1450,1430,2016-07-27 12:49:19,2016-07-27 12:56:34,0 +205252,2016-07-27 19:19:48,1223,Bag'Elles Coffee,19 Rue Du Mirail,33000,Bordeaux,44.83419,-0.571462,77669,Rue Saint-James 57,33000,Bordeaux,44.8352389,-0.5717896,1300,1458,2016-07-27 19:42:37,2016-07-27 19:46:56,0 +204931,2016-07-27 12:44:41,1220,Jardin Phnom Penh,1 Rue Du Cerf Volant,33000,Bordeaux,44.838287,-0.570993,77553,Rue Ramonet 24,33000,Bordeaux,44.8524202,-0.5699839999999999,1950,1418,2016-07-27 12:58:20,2016-07-27 13:11:29,0 +204938,2016-07-27 12:46:58,1207,Le Jardin Pekinois,9 Rue Des Freres Bonie,33000,Bordeaux,44.837078,-0.579572,77555,Rue Dubourdieu 58,33800,Bordeaux,44.8216242,-0.5789402,1450,1471,2016-07-27 13:07:04,2016-07-27 13:16:43,0 +205276,2016-07-27 19:24:37,1219,La Tagliatella,14 Rue Guiraude,33000,Bordeaux,44.8393877,-0.5747810999999999,77676,Allee Serr 63,33100,Bordeaux,44.8430759,-0.5582185,2490,1410,2016-07-27 19:47:51,2016-07-27 19:57:52,0 +204940,2016-07-27 12:49:08,1204,Max A Table,36 Rue Cornac,33000,Bordeaux,44.851402,-0.57587,77556,Rue Borie 57,33300,Bordeaux,44.8550543,-0.5704612,2100,1417,2016-07-27 13:05:03,2016-07-27 13:08:36,0 +204950,2016-07-27 12:54:25,1207,Le Jardin Pekinois,9 Rue Des Freres Bonie,33000,Bordeaux,44.837078,-0.579572,77559,Cours De La Somme 28,33800,Bordeaux,44.8294953,-0.5717909,2430,1458,2016-07-27 13:14:45,2016-07-27 13:22:38,0 +204954,2016-07-27 12:55:52,1243,Bagel And Goodies,"53 Cours Le Rouzic, 33100 Bordeaux",33100,Bordeaux,44.842804,-0.550576,77560,Quai De Brazza 87,33100,Bordeaux,44.8576232,-0.5465464,1450,1465,2016-07-27 13:13:21,2016-07-27 13:23:59,0 +204967,2016-07-27 12:59:22,1249,Pitaya Sainte Catherine,275 Rue Sainte Catherine,33000,Bordeaux,44.831692,-0.573207,4210,Rue Des Argentiers 16,33000,Bordeaux,44.8391736,-0.5698286,1450,1463,2016-07-27 13:12:34,2016-07-27 13:26:04,0 +205303,2016-07-27 19:30:58,1244,Fufu Chartrons,71 Cours Portal,33300,Bordeaux,44.85516,-0.572128,77686,Cours De Quebec 23,33000,Bordeaux,44.8776932,-0.5713868,3800,1419,2016-07-27 19:58:32,2016-07-27 20:12:50,0 +205003,2016-07-27 13:22:54,1212,Cote Terrasse,198 Cours De L'Argonne,33800,Bordeaux,44.824543,-0.578545,73919,Rue Amedee Saint-Germain 121B,33800,Bordeaux,44.8182663,-0.5638276999999999,1750,1471,2016-07-27 13:36:16,2016-07-27 13:43:04,0 +205018,2016-07-27 13:32:20,1212,Cote Terrasse,198 Cours De L'Argonne,33800,Bordeaux,44.824543,-0.578545,77580,Rue Du Pere Louis Jabrun 4,33000,Bordeaux,44.8397561,-0.5765158,1250,1426,2016-07-27 13:52:49,2016-07-27 14:01:50,0 +205306,2016-07-27 19:31:29,1225,Billy Factory,5 Place Louis Barthou,33000,Bordeaux,44.827942,-0.59441,77687,Cours De L'Yser 183,33800,Bordeaux,44.8228196,-0.5713121,1450,1415,2016-07-27 19:49:09,2016-07-27 19:56:25,0 +205039,2016-07-27 13:45:17,1246,Thai Paradise,70 Rue Des Ayres,33000,Bordeaux,44.836327,-0.575572,9304,Rue Des Argentiers 16,33000,Bordeaux,44.8391736,-0.5698286,2050,1417,2016-07-27 13:59:37,2016-07-27 14:05:56,0 +205315,2016-07-27 19:32:53,1208,Chez Ambre And Michel,1 Rue Matignon,33000,Bordeaux,44.850258,-0.586204,77690,Boulevard Marechal Leclerc 88,33000,Bordeaux,44.82980209999999,-0.5958214,1450,1417,2016-07-27 19:54:05,2016-07-27 20:08:24,0 +205050,2016-07-27 13:53:00,1249,Pitaya Sainte Catherine,275 Rue Sainte Catherine,33000,Bordeaux,44.831692,-0.573207,77591,Rue Henri Iv 59,33000,Bordeaux,44.8319225,-0.5756333,1500,1418,2016-07-27 14:02:40,2016-07-27 14:08:35,0 +205053,2016-07-27 13:56:47,1223,Bag'Elles Coffee,19 Rue Du Mirail,33000,Bordeaux,44.83419,-0.571462,77592,Cours De La Somme 218,33800,Bordeaux,44.8223315,-0.5723672,1689,1461,2016-07-27 14:15:46,2016-07-27 14:21:24,0 +205064,2016-07-27 14:04:15,1211,Haru Haru,93 Cours Gambetta,33400,Bordeaux,44.8181798,-0.5851184,77597,Cours De L'Yser 73,33800,Bordeaux,44.8271783,-0.5694722,1550,1458,2016-07-27 14:20:18,2016-07-27 14:29:45,0 +205365,2016-07-27 19:40:36,1220,Jardin Phnom Penh,1 Rue Du Cerf Volant,33000,Bordeaux,44.838287,-0.570993,77714,Rue Chantre 13,33000,Bordeaux,44.83034929999999,-0.5691102,1250,1461,2016-07-27 19:55:44,2016-07-27 20:00:46,0 +205090,2016-07-27 14:25:34,1214,Koh I Noor,3 Rue Du Puits Descujols,33000,Bordeaux,44.841011,-0.570755,77602,Rue Moulinie 30,33000,Bordeaux,44.8325768,-0.5741698,1250,1417,2016-07-27 14:42:19,2016-07-27 14:51:28,0 +205390,2016-07-27 19:43:11,1212,Cote Terrasse,198 Cours De L'Argonne,33800,Bordeaux,44.824543,-0.578545,77722,Rue De Madrid 9,33000,Bordeaux,44.8317275,-0.5957901,1500,1468,2016-07-27 20:05:41,2016-07-27 20:14:51,0 +205394,2016-07-27 19:43:45,1216,Sushimi,8 Rue Courbin,33000,Bordeaux,44.841721,-0.572962,77725,Rue Giner De Los Rios 5,33800,Bordeaux,44.8279822,-0.5719232,2310,1474,2016-07-27 20:06:15,2016-07-27 20:18:37,0 +205417,2016-07-27 19:47:45,1235,Melodie,17 Rue Leupold,33000,Bordeaux,44.840603,-0.570444,77734,Rue Villedieu 40,33000,Bordeaux,44.8309041,-0.5759581,3450,1472,2016-07-27 20:01:10,2016-07-27 20:10:00,0 +205218,2016-07-27 19:08:58,1227,Cilicie,4 Rue Des Bahutiers,33000,Bordeaux,44.839531,-0.570651,77658,Rue Carnot 67,33400,Bordeaux,44.8210682,-0.586424,3250,1409,2016-07-27 19:30:32,2016-07-27 19:47:31,0 +205224,2016-07-27 19:10:54,1218,Le Rizana,7 Rue Gaspard Philippe,33000,Bordeaux,44.833736,-0.56662,77660,Rue Carnot 2,33400,Bordeaux,44.8230567,-0.5860741,1850,1420,2016-07-27 19:38:59,2016-07-27 19:47:49,0 +205226,2016-07-27 19:11:29,1223,Bag'Elles Coffee,19 Rue Du Mirail,33000,Bordeaux,44.83419,-0.571462,77662,Cours D'Alsace-Et-Lorraine 82,33000,Bordeaux,44.8375334,-0.572369,1330,1422,2016-07-27 19:27:07,2016-07-27 19:33:12,0 +205435,2016-07-27 19:50:38,1219,La Tagliatella,14 Rue Guiraude,33000,Bordeaux,44.8393877,-0.5747810999999999,77743,Rue Leo Saignat 50,33000,Bordeaux,44.8270126,-0.5952024,2340,1458,2016-07-27 20:13:53,2016-07-27 20:24:13,0 +205496,2016-07-27 19:57:45,1227,Cilicie,4 Rue Des Bahutiers,33000,Bordeaux,44.839531,-0.570651,77765,Rue Frere 82,33000,Bordeaux,44.8533852,-0.5781620000000001,2550,1412,2016-07-27 20:18:00,2016-07-27 20:41:12,0 +205628,2016-07-27 20:13:35,1244,Fufu Chartrons,71 Cours Portal,33300,Bordeaux,44.85516,-0.572128,77815,Rue Du Jardin Public 57,33000,Bordeaux,44.8525707,-0.5755049,2900,1966,2016-07-27 20:31:08,2016-07-27 20:40:04,0 +205630,2016-07-27 20:13:42,1207,Le Jardin Pekinois,9 Rue Des Freres Bonie,33000,Bordeaux,44.837078,-0.579572,77816,Rue Calve 39,33000,Bordeaux,44.850965,-0.5904863,2030,1461,2016-07-27 20:46:23,2016-07-27 20:58:29,0 +205646,2016-07-27 20:16:08,1208,Chez Ambre And Michel,1 Rue Matignon,33000,Bordeaux,44.850258,-0.586204,77820,Rue Bergeret 3,33000,Bordeaux,44.8329254,-0.5695346,2750,1409,2016-07-27 20:34:44,2016-07-27 20:48:15,0 +205504,2016-07-27 19:58:54,1219,La Tagliatella,14 Rue Guiraude,33000,Bordeaux,44.8393877,-0.5747810999999999,77770,Rue Roger Allo 41,33000,Bordeaux,44.8458473,-0.5885961,1645,1917,2016-07-27 20:16:31,2016-07-27 20:25:40,0 +205514,2016-07-27 20:00:33,1246,Thai Paradise,70 Rue Des Ayres,33000,Bordeaux,44.836327,-0.575572,77777,Rue Robert Lateulade 6,33000,Bordeaux,44.8385397,-0.5861143999999999,3250,1409,2016-07-27 20:13:53,2016-07-27 20:21:00,0 +205520,2016-07-27 20:01:42,1209,La Gamelle,23 Rue Des Freres Bonie,33000,Bordeaux,44.836849,-0.580108,77780,Cours De Verdun 32,33000,Bordeaux,44.8466972,-0.5766392,1600,1817,,,1 +205546,2016-07-27 20:04:06,1207,Le Jardin Pekinois,9 Rue Des Freres Bonie,33000,Bordeaux,44.837078,-0.579572,77788,Rue Pierre 36,33000,Bordeaux,44.8393653,-0.5932457,3629,1415,2016-07-27 20:32:07,2016-07-27 20:39:51,0 +205741,2016-07-27 20:24:41,1254,Funky Burger,5 Rue Du Loup,33000,Bordeaux,44.838081,-0.572281,77862,Rue Perey 42,33000,Bordeaux,44.82424959999999,-0.5851284,1550,1468,2016-07-27 20:45:09,2016-07-27 20:54:40,0 +205753,2016-07-27 20:25:49,1254,Funky Burger,5 Rue Du Loup,33000,Bordeaux,44.838081,-0.572281,77868,Rue Frere 47,33000,Bordeaux,44.8530775,-0.5762526,2010,1430,2016-07-27 20:45:18,2016-07-27 21:05:19,0 +205754,2016-07-27 20:25:55,1249,Pitaya Sainte Catherine,275 Rue Sainte Catherine,33000,Bordeaux,44.831692,-0.573207,77869,Rue De Begles 81,33800,Bordeaux,44.8258091,-0.5677734,1450,1474,2016-07-27 20:37:08,2016-07-27 20:51:17,0 +205758,2016-07-27 20:26:15,1250,Que Toi,39 Cours D'Alsace-Et-Lorraine,33000,Bordeaux,44.837921,-0.572655,77871,Rue Du Jardin Public 178,33300,Bordeaux,44.8578723,-0.5720590999999999,5350,1471,2016-07-27 20:43:46,2016-07-27 20:55:26,0 +205760,2016-07-27 20:26:47,1214,Koh I Noor,3 Rue Du Puits Descujols,33000,Bordeaux,44.841011,-0.570755,77872,Rue Naujac 40,33000,Bordeaux,44.84788390000001,-0.5857363999999999,1850,1420,2016-07-27 20:40:33,2016-07-27 20:48:11,0 +205767,2016-07-27 20:27:49,1208,Chez Ambre And Michel,1 Rue Matignon,33000,Bordeaux,44.850258,-0.586204,77874,Rue Ducau 70,33000,Bordeaux,44.8532956,-0.5758964999999999,1650,1917,2016-07-27 20:46:55,2016-07-27 20:52:47,0 +205568,2016-07-27 20:07:05,1235,Melodie,17 Rue Leupold,33000,Bordeaux,44.840603,-0.570444,77798,Rue Des Ayres 73,33000,Bordeaux,44.8367191,-0.5750383,2650,1411,2016-07-27 20:24:38,2016-07-27 20:33:49,0 +205571,2016-07-27 20:07:17,1254,Funky Burger,5 Rue Du Loup,33000,Bordeaux,44.838081,-0.572281,77800,Rue Lamourous 12,33000,Bordeaux,44.8295359,-0.5805296,1270,1470,2016-07-27 20:24:43,2016-07-27 20:42:07,0 +205815,2016-07-27 20:32:50,1225,Billy Factory,5 Place Louis Barthou,33000,Bordeaux,44.827942,-0.59441,77897,Rue Judaique 243,33000,Bordeaux,44.8404965,-0.5974155999999999,1650,1411,2016-07-27 21:30:39,2016-07-27 21:41:48,0 +205978,2016-07-27 20:54:22,1231,Umami Ramen,8 Place Fernand Lafargue,33000,Bordeaux,44.83691,-0.573943,77971,Rue Du Marechal Joffre 52,33000,Bordeaux,44.834927,-0.5781915,1850,1422,2016-07-27 21:05:06,2016-07-27 21:13:03,0 +205827,2016-07-27 20:34:01,1254,Funky Burger,5 Rue Du Loup,33000,Bordeaux,44.838081,-0.572281,77905,Rue Malbec 57,33800,Bordeaux,44.82623419999999,-0.5624823999999999,3160,1411,2016-07-27 20:59:55,2016-07-27 21:13:09,0 +205829,2016-07-27 20:34:23,1249,Pitaya Sainte Catherine,275 Rue Sainte Catherine,33000,Bordeaux,44.831692,-0.573207,77907,Rue De Begles 81,33800,Bordeaux,44.8258091,-0.5677734,1850,1409,2016-07-27 20:52:54,2016-07-27 20:58:15,0 +205836,2016-07-27 20:34:53,1244,Fufu Chartrons,71 Cours Portal,33300,Bordeaux,44.85516,-0.572128,77910,Rue Armand Dulamon 11,33300,Bordeaux,44.8635804,-0.5607253,1450,1966,2016-07-27 20:48:47,2016-07-27 20:57:02,0 +205841,2016-07-27 20:35:41,1207,Le Jardin Pekinois,9 Rue Des Freres Bonie,33000,Bordeaux,44.837078,-0.579572,77912,Rue Mathieu 53,33000,Bordeaux,44.8309188,-0.5931757999999999,2490,1419,2016-07-27 20:51:52,2016-07-27 20:57:54,0 +205874,2016-07-27 20:40:30,1254,Funky Burger,5 Rue Du Loup,33000,Bordeaux,44.838081,-0.572281,77928,Rue De La Boetie 16,33000,Bordeaux,44.839216,-0.5806095,1450,1472,2016-07-27 21:01:40,2016-07-27 21:07:46,0 +205891,2016-07-27 20:42:30,1212,Cote Terrasse,198 Cours De L'Argonne,33800,Bordeaux,44.824543,-0.578545,77780,Cours De Verdun 32,33000,Bordeaux,44.8466972,-0.5766392,1450,1474,2016-07-27 21:04:31,2016-07-27 21:17:44,0 +205980,2016-07-27 20:54:32,1254,Funky Burger,5 Rue Du Loup,33000,Bordeaux,44.838081,-0.572281,77972,Rue Du Docteur Albert Barraud 136,33000,Bordeaux,44.8482827,-0.5829337,1260,1460,2016-07-27 21:10:00,2016-07-27 21:20:48,0 +205911,2016-07-27 20:45:51,1217,Henny'S Burger,22 Rue Fondaudege,33000,Bordeaux,44.845875,-0.579345,77946,Rue Grangeneuve 6,33000,Bordeaux,44.8519285,-0.5791967,2650,1458,2016-07-27 21:01:38,2016-07-27 21:08:36,0 +205984,2016-07-27 20:55:27,1244,Fufu Chartrons,71 Cours Portal,33300,Bordeaux,44.85516,-0.572128,77973,Rue Du Professeur Demons 12,33000,Bordeaux,44.8466116,-0.5789202999999999,5150,1917,2016-07-27 21:30:21,2016-07-27 21:38:17,0 +205923,2016-07-27 20:47:23,1250,Que Toi,39 Cours D'Alsace-Et-Lorraine,33000,Bordeaux,44.837921,-0.572655,77951,Rue De Catros 40,33000,Bordeaux,44.8544157,-0.5824753,3000,1415,2016-07-27 21:05:46,2016-07-27 21:17:19,0 +206020,2016-07-27 21:01:41,1234,Mille Et Une Saveurs,"96 Avenue Thiers, 33100 Bordeaux",33100,Bordeaux,44.843746,-0.554713,77984,Rue Rodrigues-Pereire 31,33000,Bordeaux,44.84428870000001,-0.5848409999999999,2500,1966,2016-07-27 21:21:55,2016-07-27 21:36:18,0 +205954,2016-07-27 20:51:28,1244,Fufu Chartrons,71 Cours Portal,33300,Bordeaux,44.85516,-0.572128,77959,Rue Du Haillan 2,33000,Bordeaux,44.8466941,-0.5918818,2900,1471,2016-07-27 21:30:20,2016-07-27 21:38:09,0 +205959,2016-07-27 20:52:05,1242,Fufu Saint Remi,37 Rue Saint Remi,33000,Bordeaux,44.841438,-0.572537,77962,Rue Edmond Michelet 18,33000,Bordeaux,44.8400284,-0.5814081,1350,1417,2016-07-27 21:03:40,2016-07-27 21:12:04,0 +205960,2016-07-27 20:52:24,1242,Fufu Saint Remi,37 Rue Saint Remi,33000,Bordeaux,44.841438,-0.572537,77963,Cours De La Somme 134,33800,Bordeaux,44.8257984,-0.5724935,3550,1412,2016-07-27 21:06:16,2016-07-27 21:21:02,0 +206057,2016-07-27 21:05:46,1217,Henny'S Burger,22 Rue Fondaudege,33000,Bordeaux,44.845875,-0.579345,77994,Rue De La Liberte 131,33200,Bordeaux,44.8374348,-0.6019112,1830,1817,2016-07-27 21:20:10,2016-07-27 21:34:28,0 +206352,2016-07-27 22:00:12,1207,Le Jardin Pekinois,9 Rue Des Freres Bonie,33000,Bordeaux,44.837078,-0.579572,78114,Rue Des Menuts 21,33000,Bordeaux,44.8343454,-0.5679803,1789,1460,2016-07-27 22:23:23,2016-07-27 22:34:52,0 +206067,2016-07-27 21:07:01,1254,Funky Burger,5 Rue Du Loup,33000,Bordeaux,44.838081,-0.572281,78000,Rue Cheverus 8,33000,Bordeaux,44.8394967,-0.575815,1310,1420,2016-07-27 21:30:30,2016-07-27 21:34:45,0 +206073,2016-07-27 21:07:39,1244,Fufu Chartrons,71 Cours Portal,33300,Bordeaux,44.85516,-0.572128,77772,Rue Josephine 87,33300,Bordeaux,44.86097789999999,-0.5609343999999999,1300,1415,2016-07-27 21:23:35,2016-07-27 21:29:04,0 +206092,2016-07-27 21:09:40,1250,Que Toi,39 Cours D'Alsace-Et-Lorraine,33000,Bordeaux,44.837921,-0.572655,78008,Rue Barreyre 61,33300,Bordeaux,44.85535600000001,-0.5690356,1650,1426,2016-07-27 21:19:57,2016-07-27 21:30:36,0 +206406,2016-07-27 22:27:39,1204,Max A Table,36 Rue Cornac,33000,Bordeaux,44.851402,-0.57587,78129,Rue De Conde 3,33000,Bordeaux,44.8433328,-0.5732737,1450,1460,2016-07-27 22:51:25,2016-07-27 23:00:09,0 +206407,2016-07-27 22:28:33,1231,Umami Ramen,8 Place Fernand Lafargue,33000,Bordeaux,44.83691,-0.573943,78130,Rue Sainte-Catherine 154,33000,Bordeaux,44.8361307,-0.5734376999999999,2050,1412,2016-07-27 22:50:08,2016-07-27 22:58:54,0 +206130,2016-07-27 21:15:29,1226,Ici Argentine,84 Boulevard Du President Wilson,33000,Bordeaux,44.840084,-0.5994,77281,Rue Du Lavoir 20,33000,Bordeaux,44.8523132,-0.5831382,3800,1468,2016-07-27 21:34:03,2016-07-27 21:43:40,0 +206478,2016-07-28 11:36:16,1245,Eatsalad,55 Rue Saint Remi,33000,Bordeaux,44.841286,-0.573413,78162,Rue De Conde 9,33000,Bordeaux,44.8435849,-0.5733138,1730,1917,2016-07-28 11:51:10,2016-07-28 11:59:15,0 +206479,2016-07-28 11:36:38,1243,Bagel And Goodies,"53 Cours Le Rouzic, 33100 Bordeaux",33100,Bordeaux,44.842804,-0.550576,77910,Rue Armand Dulamon 11,33300,Bordeaux,44.8635804,-0.5607253,1920,1416,,,1 +206509,2016-07-28 11:49:11,1245,Eatsalad,55 Rue Saint Remi,33000,Bordeaux,44.841286,-0.573413,78170,Cours Du Marechal Foch 21,33000,Bordeaux,44.8471158,-0.5755477,2030,1417,2016-07-28 12:05:06,2016-07-28 12:13:35,0 +206515,2016-07-28 11:52:29,1239,Tam Tam Saigon,7 Rue Paulin,33000,Bordeaux,44.846516,-0.588076,78173,Place Des Basques 19,33000,Bordeaux,44.8387129,-0.5703524999999999,2670,1416,2016-07-28 12:30:00,2016-07-28 12:41:37,0 +206136,2016-07-27 21:16:51,1254,Funky Burger,5 Rue Du Loup,33000,Bordeaux,44.838081,-0.572281,78022,Cours Pasteur 12,33000,Bordeaux,44.8361566,-0.5752764,1320,1410,2016-07-27 21:34:23,2016-07-27 21:38:59,0 +206151,2016-07-27 21:18:54,1221,Le Veneto,25 Allee De Tourny,33000,Bordeaux,44.84473,-0.578606,78028,Rue De La Maison Daurade 5,33000,Bordeaux,44.8418629,-0.5740972,1510,1474,2016-07-27 21:25:45,2016-07-27 21:48:39,0 +206565,2016-07-28 12:11:21,1233,Punjab,39 Rue Saint Remi,33000,Bordeaux,44.841393,-0.572534,78192,Rue Leyteire 73,33000,Bordeaux,44.8326012,-0.5697637,4050,1412,2016-07-28 12:26:42,2016-07-28 12:48:41,0 +206569,2016-07-28 12:12:06,1222,Les Tartines De Marine,"6 Rue Saint-Sernin, Bordeaux",33000,Bordeaux,44.839336,-0.58194,78195,Rue Edouard Larroque 36,33000,Bordeaux,44.8315573,-0.6022223,1850,1426,2016-07-28 12:24:16,2016-07-28 12:34:23,0 +206580,2016-07-28 12:14:57,1239,Tam Tam Saigon,7 Rue Paulin,33000,Bordeaux,44.846516,-0.588076,77048,Rue Frere 108,33000,Bordeaux,44.8539023,-0.5798308999999999,2940,1817,,,1 +206186,2016-07-27 21:24:29,1249,Pitaya Sainte Catherine,275 Rue Sainte Catherine,33000,Bordeaux,44.831692,-0.573207,78042,Rue Poquelin Moliere 37,33000,Bordeaux,44.8398871,-0.5787188999999999,1450,1412,2016-07-27 21:39:37,2016-07-27 21:51:58,0 +206614,2016-07-28 12:26:12,1233,Punjab,39 Rue Saint Remi,33000,Bordeaux,44.841393,-0.572534,78211,Rue Garat 11,33000,Bordeaux,44.8304779,-0.5695108,3100,1430,2016-07-28 12:40:25,2016-07-28 12:49:25,0 +206210,2016-07-27 21:31:37,1218,Le Rizana,7 Rue Gaspard Philippe,33000,Bordeaux,44.833736,-0.56662,78052,Rue Sainte-Catherine 234,33000,Bordeaux,44.8332529,-0.572593,1850,1458,2016-07-27 21:44:55,2016-07-27 21:49:55,0 +206647,2016-07-28 12:34:06,1254,Funky Burger,5 Rue Du Loup,33000,Bordeaux,44.838081,-0.572281,78219,Rue Corcelle 7,33000,Bordeaux,44.8383454,-0.5712411,1250,1461,2016-07-28 12:57:08,2016-07-28 13:20:06,0 +206219,2016-07-27 21:32:33,1221,Le Veneto,25 Allee De Tourny,33000,Bordeaux,44.84473,-0.578606,78057,Rue De Cestas 18,33000,Bordeaux,44.8350231,-0.59985,4490,1461,2016-07-27 22:04:59,2016-07-27 22:12:42,0 +206222,2016-07-27 21:33:04,1226,Ici Argentine,84 Boulevard Du President Wilson,33000,Bordeaux,44.840084,-0.5994,78059,Rue Des Freres Bonie 23,33000,Bordeaux,44.836885,-0.5800599,1500,1817,2016-07-27 21:44:05,2016-07-27 21:53:02,0 +206691,2016-07-28 12:50:35,1249,Pitaya Sainte Catherine,275 Rue Sainte Catherine,33000,Bordeaux,44.831692,-0.573207,73919,Rue Amedee Saint-Germain 121B,33800,Bordeaux,44.8182663,-0.5638276999999999,1650,1430,2016-07-28 12:58:16,2016-07-28 13:05:57,0 +206692,2016-07-28 12:51:45,1254,Funky Burger,5 Rue Du Loup,33000,Bordeaux,44.838081,-0.572281,10298,Rue Des Argentiers 16,33000,Bordeaux,44.8391736,-0.5698286,2470,1461,2016-07-28 13:15:25,2016-07-28 13:20:13,0 +206228,2016-07-27 21:34:10,1211,Haru Haru,93 Cours Gambetta,33400,Bordeaux,44.8181798,-0.5851184,78060,Rue De Begles 375,33800,Bordeaux,44.8139493,-0.5649765,2000,1419,2016-07-27 21:46:17,2016-07-27 22:00:51,0 +206698,2016-07-28 12:52:59,1256,Pitaya Stalingrad,36 Place De Stalingrad,33100,Bordeaux,44.840912,-0.559553,78233,Quai Des Queyries 87,33100,Bordeaux,44.8490447,-0.5606165,1500,1917,2016-07-28 13:10:54,2016-07-28 13:20:24,0 +206704,2016-07-28 12:55:07,1254,Funky Burger,5 Rue Du Loup,33000,Bordeaux,44.838081,-0.572281,78236,Rue Du Commandant Arnould 12,33000,Bordeaux,44.8368145,-0.5774722,1670,1817,2016-07-28 13:14:46,2016-07-28 13:18:15,0 +206245,2016-07-27 21:36:32,1219,La Tagliatella,14 Rue Guiraude,33000,Bordeaux,44.8393877,-0.5747810999999999,78069,Rue Mondenard 52,33000,Bordeaux,44.8460264,-0.5884206,1695,1470,2016-07-27 21:52:17,2016-07-27 22:03:19,0 +206726,2016-07-28 13:03:55,1209,La Gamelle,23 Rue Des Freres Bonie,33000,Bordeaux,44.836849,-0.580108,76838,Rue Des Argentiers 16,33000,Bordeaux,44.8391736,-0.5698286,1600,1416,2016-07-28 13:22:47,2016-07-28 13:30:38,0 +206265,2016-07-27 21:39:41,1214,Koh I Noor,3 Rue Du Puits Descujols,33000,Bordeaux,44.841011,-0.570755,78077,Rue Jardel 36,33100,Bordeaux,44.8418309,-0.5601655000000001,2039,1426,2016-07-27 21:58:41,2016-07-27 22:05:56,0 +206741,2016-07-28 13:09:18,1213,Lupo,"23 Place Pey Berland, 33000 Bordeaux",33000,Bordeaux,44.837158,-0.576632,78249,Rue Batailley 8,33000,Bordeaux,44.8386542,-0.5920658999999999,1430,1471,2016-07-28 13:24:37,2016-07-28 13:32:39,0 +206267,2016-07-27 21:39:54,1244,Fufu Chartrons,71 Cours Portal,33300,Bordeaux,44.85516,-0.572128,78078,Rue Albert De Mun 8,33000,Bordeaux,44.8481127,-0.5811906000000001,2250,1917,2016-07-27 21:51:45,2016-07-27 22:00:37,0 +206751,2016-07-28 13:14:36,1233,Punjab,39 Rue Saint Remi,33000,Bordeaux,44.841393,-0.572534,78252,Rue Ulysse Gayon 26,33000,Bordeaux,44.8518779,-0.5914444999999999,2490,1430,2016-07-28 13:31:04,2016-07-28 13:43:57,0 +206271,2016-07-27 21:40:58,1254,Funky Burger,5 Rue Du Loup,33000,Bordeaux,44.838081,-0.572281,78079,Rue Reniere 29,33000,Bordeaux,44.8360806,-0.56895,3150,1410,2016-07-27 22:00:02,2016-07-27 22:05:53,0 +206761,2016-07-28 13:17:33,1254,Funky Burger,5 Rue Du Loup,33000,Bordeaux,44.838081,-0.572281,78255,Cours D'Alsace-Et-Lorraine 31,33000,Bordeaux,44.8380653,-0.5700327,2250,1417,2016-07-28 13:39:32,2016-07-28 13:43:09,0 +206770,2016-07-28 13:20:37,1242,Fufu Saint Remi,37 Rue Saint Remi,33000,Bordeaux,44.841438,-0.572537,75039,Rue Lafontaine 9,33800,Bordeaux,44.8268699,-0.5718456,1450,1461,2016-07-28 13:34:49,2016-07-28 13:41:59,0 +206291,2016-07-27 21:44:23,1217,Henny'S Burger,22 Rue Fondaudege,33000,Bordeaux,44.845875,-0.579345,78086,Cours De La Somme 261,33800,Bordeaux,44.8202033,-0.5725819,3820,1415,,,1 +206784,2016-07-28 13:25:57,1221,Le Veneto,25 Allee De Tourny,33000,Bordeaux,44.84473,-0.578606,78263,Rue Mauriac 4,33000,Bordeaux,44.8356333,-0.5673574,1430,1463,2016-07-28 13:41:22,2016-07-28 13:59:39,0 +206786,2016-07-28 13:26:58,1222,Les Tartines De Marine,"6 Rue Saint-Sernin, Bordeaux",33000,Bordeaux,44.839336,-0.58194,78265,Rue Du Docteur Charles Nancel Penard 29,33000,Bordeaux,44.8393967,-0.5816392,1550,1462,2016-07-28 13:38:47,2016-07-28 13:42:05,0 +206789,2016-07-28 13:29:15,1213,Lupo,"23 Place Pey Berland, 33000 Bordeaux",33000,Bordeaux,44.837158,-0.576632,78268,Place Jean Moulin 4,33000,Bordeaux,44.8383642,-0.5780067,1900,1426,2016-07-28 13:47:03,2016-07-28 13:47:09,0 +206794,2016-07-28 13:31:57,1234,Mille Et Une Saveurs,"96 Avenue Thiers, 33100 Bordeaux",33100,Bordeaux,44.843746,-0.554713,78270,Rue Notre Dame 13,33000,Bordeaux,44.8500435,-0.5727966,1650,1917,2016-07-28 13:42:12,2016-07-28 14:00:31,0 +206311,2016-07-27 21:48:49,1242,Fufu Saint Remi,37 Rue Saint Remi,33000,Bordeaux,44.841438,-0.572537,78096,Cours Victor Hugo 92,33000,Bordeaux,44.8344979,-0.5703237999999999,1550,1474,2016-07-27 21:57:18,2016-07-27 22:08:40,0 +206807,2016-07-28 13:37:40,1216,Sushimi,8 Rue Courbin,33000,Bordeaux,44.841721,-0.572962,78277,Rue Bergeret 34,33000,Bordeaux,44.8321154,-0.568346,1280,1416,2016-07-28 13:57:07,2016-07-28 14:08:10,0 +206831,2016-07-28 13:51:21,1209,La Gamelle,23 Rue Des Freres Bonie,33000,Bordeaux,44.836849,-0.580108,78285,Rue De Conde 9,33000,Bordeaux,44.8435849,-0.5733138,1550,1409,2016-07-28 14:09:10,2016-07-28 14:17:21,0 +206834,2016-07-28 13:54:28,1217,Henny'S Burger,22 Rue Fondaudege,33000,Bordeaux,44.845875,-0.579345,78287,Cours De Luze 71,33300,Bordeaux,44.8578078,-0.5798426999999999,1420,1817,2016-07-28 14:08:33,2016-07-28 14:29:30,0 +206850,2016-07-28 14:11:52,1249,Pitaya Sainte Catherine,275 Rue Sainte Catherine,33000,Bordeaux,44.831692,-0.573207,78290,Rue De Ruat 22,33000,Bordeaux,44.83991959999999,-0.5789662000000001,1500,1405,2016-07-28 14:20:27,2016-07-28 14:27:31,0 +206316,2016-07-27 21:50:46,1227,Cilicie,4 Rue Des Bahutiers,33000,Bordeaux,44.839531,-0.570651,51633,Rue Albert Pitres 38,33000,Bordeaux,44.8522358,-0.5763587,6050,1966,2016-07-27 22:12:48,2016-07-27 22:23:30,0 +206334,2016-07-27 21:56:07,1212,Cote Terrasse,198 Cours De L'Argonne,33800,Bordeaux,44.824543,-0.578545,78107,Rue Lafiteau 2,33800,Bordeaux,44.8247548,-0.5543089999999999,1950,1458,2016-07-27 22:08:52,2016-07-27 22:18:57,0 +206862,2016-07-28 14:27:13,1207,Le Jardin Pekinois,9 Rue Des Freres Bonie,33000,Bordeaux,44.837078,-0.579572,78295,Rue Georges Bonnac 281,33000,Bordeaux,44.8373509,-0.5948427,2430,,,,1 +206863,2016-07-28 14:27:49,1209,La Gamelle,23 Rue Des Freres Bonie,33000,Bordeaux,44.836849,-0.580108,78296,Rue Dumaine 9,33000,Bordeaux,44.8512636,-0.5843792,1600,,,,1 +206336,2016-07-27 21:56:38,1250,Que Toi,39 Cours D'Alsace-Et-Lorraine,33000,Bordeaux,44.837921,-0.572655,78109,Avenue Vercingetorix 39,33000,Bordeaux,44.8289688,-0.6008475999999999,1550,1426,2016-07-27 22:13:10,2016-07-27 22:24:45,0 +206341,2016-07-27 21:57:56,1211,Haru Haru,93 Cours Gambetta,33400,Bordeaux,44.8181798,-0.5851184,78110,Route De Toulouse 141,33400,Bordeaux,44.8098132,-0.5744535,2250,1412,2016-07-27 22:15:43,2016-07-27 22:36:05,0 +207120,2016-07-28 19:32:38,1249,Pitaya Sainte Catherine,275 Rue Sainte Catherine,33000,Bordeaux,44.831692,-0.573207,78400,Rue Julie 12,33800,Bordeaux,44.8278151,-0.5716082,2500,1418,2016-07-28 19:40:55,2016-07-28 19:45:36,0 +206961,2016-07-28 18:58:30,1225,Billy Factory,5 Place Louis Barthou,33000,Bordeaux,44.827942,-0.59441,78332,Rue Berruer 140,33000,Bordeaux,44.8325533,-0.6053062,1450,1407,2016-07-28 19:12:34,2016-07-28 19:29:08,0 +206968,2016-07-28 18:59:35,1242,Fufu Saint Remi,37 Rue Saint Remi,33000,Bordeaux,44.841438,-0.572537,78337,Cours De L'Argonne 133,33000,Bordeaux,44.8267816,-0.5766757,2550,1422,2016-07-28 19:07:49,2016-07-28 19:21:49,0 +206985,2016-07-28 19:03:10,1214,Koh I Noor,3 Rue Du Puits Descujols,33000,Bordeaux,44.841011,-0.570755,77740,Rue Vital Carles 16,33000,Bordeaux,44.8409704,-0.5783828,3550,1420,2016-07-28 19:29:33,2016-07-28 19:38:11,0 +207008,2016-07-28 19:08:39,1204,Max A Table,36 Rue Cornac,33000,Bordeaux,44.851402,-0.57587,78353,Cours Xavier Arnozan 16,33000,Bordeaux,44.8486769,-0.5738774999999999,2150,1412,2016-07-28 19:39:14,2016-07-28 19:55:56,0 +207011,2016-07-28 19:09:49,1245,Eatsalad,55 Rue Saint Remi,33000,Bordeaux,44.841286,-0.573413,76720,Rue Jules Guesde 68,33800,Bordeaux,44.8292454,-0.563711,1540,1420,2016-07-28 19:49:54,2016-07-28 19:58:17,0 +207012,2016-07-28 19:10:27,1208,Chez Ambre And Michel,1 Rue Matignon,33000,Bordeaux,44.850258,-0.586204,78355,Rue Delord 97,33300,Bordeaux,44.8617642,-0.5602136,2350,1471,2016-07-28 19:29:26,2016-07-28 19:40:57,0 +207024,2016-07-28 19:13:27,1244,Fufu Chartrons,71 Cours Portal,33300,Bordeaux,44.85516,-0.572128,78361,Cours Saint-Louis 139,33300,Bordeaux,44.8617212,-0.5679938,4250,1410,2016-07-28 19:32:09,2016-07-28 19:39:25,0 +207129,2016-07-28 19:34:41,1225,Billy Factory,5 Place Louis Barthou,33000,Bordeaux,44.827942,-0.59441,78402,Place Pey Berland 12,33000,Bordeaux,44.8384243,-0.5767298,2110,1407,2016-07-28 19:49:15,2016-07-28 20:01:12,0 +207131,2016-07-28 19:35:00,1227,Cilicie,4 Rue Des Bahutiers,33000,Bordeaux,44.839531,-0.570651,74966,Rue Sainte-Catherine 137,33000,Bordeaux,44.83651589999999,-0.5739832000000001,3250,1412,,,1 +207073,2016-07-28 19:22:22,1242,Fufu Saint Remi,37 Rue Saint Remi,33000,Bordeaux,44.841438,-0.572537,78384,Rue Castillon 20,33000,Bordeaux,44.8404581,-0.5758994,1550,1817,2016-07-28 19:38:58,2016-07-28 19:45:50,0 +207225,2016-07-28 19:50:52,1254,Funky Burger,5 Rue Du Loup,33000,Bordeaux,44.838081,-0.572281,78435,Cours De Verdun 136,33000,Bordeaux,44.852142,-0.5733604,1250,1407,2016-07-28 20:11:05,2016-07-28 20:21:16,0 +207079,2016-07-28 19:23:50,1258,Pitaya Saint-Remi,42 Rue Saint Remi,33000,Bordeaux,44.84127,-0.572691,78387,Rue Judaique 207,33000,Bordeaux,44.8408778,-0.5951913999999999,2350,1430,2016-07-28 19:37:34,2016-07-28 19:44:59,0 +207461,2016-07-28 20:18:02,1225,Billy Factory,5 Place Louis Barthou,33000,Bordeaux,44.827942,-0.59441,78530,Rue Rosa Bonheur 18,33000,Bordeaux,44.8491669,-0.5880926,1989,1471,2016-07-28 20:56:16,2016-07-28 21:10:59,0 +207476,2016-07-28 20:19:00,1233,Punjab,39 Rue Saint Remi,33000,Bordeaux,44.841393,-0.572534,78537,Rue De Landiras 24,33000,Bordeaux,44.8292767,-0.5847496,3660,1422,2016-07-28 20:35:35,2016-07-28 20:54:17,0 +207490,2016-07-28 20:21:35,1208,Chez Ambre And Michel,1 Rue Matignon,33000,Bordeaux,44.850258,-0.586204,78541,Rue Marengo 12,33000,Bordeaux,44.8335207,-0.5687675,1450,1418,2016-07-28 20:50:35,2016-07-28 21:04:50,0 +207507,2016-07-28 20:24:06,1213,Lupo,"23 Place Pey Berland, 33000 Bordeaux",33000,Bordeaux,44.837158,-0.576632,78546,Rue Jean Jacques Rousseau 7,33000,Bordeaux,44.84354159999999,-0.5778329,2160,1416,2016-07-28 20:43:28,2016-07-28 20:49:21,0 +207245,2016-07-28 19:53:18,1213,Lupo,"23 Place Pey Berland, 33000 Bordeaux",33000,Bordeaux,44.837158,-0.576632,78446,Rue Bouquiere 44,33000,Bordeaux,44.8364828,-0.5697892,1360,1410,2016-07-28 20:14:12,2016-07-28 20:18:17,0 +207530,2016-07-28 20:26:34,1236,Marhaba,27 Rue Des Faures,33800,Bordeaux,44.834766,-0.565754,78560,Cours De L'Yser 135,33800,Bordeaux,44.82485740000001,-0.5705146,2450,1461,2016-07-28 20:47:15,2016-07-28 20:50:50,0 +207263,2016-07-28 19:55:23,1244,Fufu Chartrons,71 Cours Portal,33300,Bordeaux,44.85516,-0.572128,78454,Rue Du Docteur Albert Barraud 133,33000,Bordeaux,44.84833219999999,-0.5836110999999999,4850,1415,2016-07-28 20:09:35,2016-07-28 20:17:48,0 +207545,2016-07-28 20:27:43,1249,Pitaya Sainte Catherine,275 Rue Sainte Catherine,33000,Bordeaux,44.831692,-0.573207,77666,Rue Du Xiv Juillet 116,33400,Bordeaux,44.8205734,-0.5884878,1600,1422,2016-07-28 20:45:21,2016-07-28 21:01:05,0 +207547,2016-07-28 20:27:45,1242,Fufu Saint Remi,37 Rue Saint Remi,33000,Bordeaux,44.841438,-0.572537,78565,Rue Abbe De L'Epee 58,33000,Bordeaux,44.8416727,-0.5826009999999999,2550,1407,2016-07-28 20:39:08,2016-07-28 20:47:38,0 +207550,2016-07-28 20:28:20,1222,Les Tartines De Marine,"6 Rue Saint-Sernin, Bordeaux",33000,Bordeaux,44.839336,-0.58194,78195,Rue De La Demi Lune 18,33400,Bordeaux,44.8205633,-0.5878728,2550,1426,2016-07-28 20:52:46,2016-07-28 21:09:55,0 +207551,2016-07-28 20:28:24,1241,My Terroir,24 Place De La Ferme De Richemont,33000,Bordeaux,44.835506,-0.575218,78567,Rue Bigot 10,33000,Bordeaux,44.8318092,-0.5692421999999999,3950,1415,2016-07-28 20:39:54,2016-07-28 20:45:40,0 +207554,2016-07-28 20:28:49,1223,Bag'Elles Coffee,19 Rue Du Mirail,33000,Bordeaux,44.83419,-0.571462,78568,Rue Commandant Charcot 37,33000,Bordeaux,44.8262919,-0.5889038,1260,1458,2016-07-28 20:49:11,2016-07-28 20:59:55,0 +207265,2016-07-28 19:55:41,1217,Henny'S Burger,22 Rue Fondaudege,33000,Bordeaux,44.845875,-0.579345,78455,Allee Serr 63,33100,Bordeaux,44.8430759,-0.5582185,2450,1412,2016-07-28 20:13:08,2016-07-28 20:34:39,0 +207283,2016-07-28 19:57:13,1216,Sushimi,8 Rue Courbin,33000,Bordeaux,44.841721,-0.572962,78461,Cours Balguerie Stuttenberg 125,33300,Bordeaux,44.8599903,-0.5651621,1370,1460,2016-07-28 20:13:09,2016-07-28 20:27:13,0 +207583,2016-07-28 20:32:49,1236,Marhaba,27 Rue Des Faures,33800,Bordeaux,44.834766,-0.565754,78580,Rue Casteja 10,33000,Bordeaux,44.8425388,-0.5821083,5000,1430,2016-07-28 20:58:29,2016-07-28 21:09:27,0 +207595,2016-07-28 20:34:21,1250,Que Toi,39 Cours D'Alsace-Et-Lorraine,33000,Bordeaux,44.837921,-0.572655,78586,Impasse Sainte-Ursule 18,33000,Bordeaux,44.8317342,-0.5848804,3250,2013,2016-07-28 20:44:16,2016-07-28 21:02:01,0 +207285,2016-07-28 19:57:33,1244,Fufu Chartrons,71 Cours Portal,33300,Bordeaux,44.85516,-0.572128,77048,Rue Frere 108,33000,Bordeaux,44.8539023,-0.5798308999999999,5150,1418,2016-07-28 20:12:24,2016-07-28 20:18:49,0 +207297,2016-07-28 19:58:39,1232,Anh Kha,48 Rue Saint Sernin,33000,Bordeaux,44.841103,-0.582515,78467,Cours De L'Argonne 60,33000,Bordeaux,44.8285656,-0.5741868,3050,1458,2016-07-28 20:20:01,2016-07-28 20:26:47,0 +207637,2016-07-28 20:39:04,1233,Punjab,39 Rue Saint Remi,33000,Bordeaux,44.841393,-0.572534,78598,Avenue Thiers 226,33100,Bordeaux,44.8480225,-0.5485361,6300,1405,2016-07-28 20:52:26,2016-07-28 21:04:13,0 +207313,2016-07-28 20:00:31,1259,Perditempo,25 Quai Richelieu,33000,Bordeaux,44.838787,-0.568008,25864,Rue Teulere 7,33000,Bordeaux,44.8358028,-0.5699863,3600,1426,2016-07-28 20:29:25,2016-07-28 20:33:32,0 +207654,2016-07-28 20:41:02,1244,Fufu Chartrons,71 Cours Portal,33300,Bordeaux,44.85516,-0.572128,78603,Rue Turenne 49,33000,Bordeaux,44.8460455,-0.5830609999999999,1600,1412,2016-07-28 21:05:11,2016-07-28 21:20:35,0 +207670,2016-07-28 20:42:50,1204,Max A Table,36 Rue Cornac,33000,Bordeaux,44.851402,-0.57587,78608,Rue Poyenne 27,33300,Bordeaux,44.8564324,-0.5655224,2450,1416,2016-07-28 21:14:31,2016-07-28 21:20:14,0 +207677,2016-07-28 20:43:49,1254,Funky Burger,5 Rue Du Loup,33000,Bordeaux,44.838081,-0.572281,78611,Rue Notre Dame 15,33000,Bordeaux,44.8500308,-0.5724791,1290,1409,2016-07-28 20:53:10,2016-07-28 21:12:11,0 +207336,2016-07-28 20:03:35,1254,Funky Burger,5 Rue Du Loup,33000,Bordeaux,44.838081,-0.572281,78483,Rue Paul Denuce 5,33800,Bordeaux,44.8233937,-0.5790662,2260,1817,2016-07-28 20:15:10,2016-07-28 20:24:55,0 +207695,2016-07-28 20:46:02,1212,Cote Terrasse,198 Cours De L'Argonne,33800,Bordeaux,44.824543,-0.578545,78618,Rue De Suzon 230,33400,Bordeaux,44.8120343,-0.5779974,1450,1461,2016-07-28 21:04:12,2016-07-28 21:10:54,0 +207700,2016-07-28 20:46:45,1204,Max A Table,36 Rue Cornac,33000,Bordeaux,44.851402,-0.57587,78621,Cours Balguerie Stuttenberg 286,33300,Bordeaux,44.8638811,-0.5589876000000001,1850,1416,2016-07-28 21:14:25,2016-07-28 21:24:13,0 +207351,2016-07-28 20:05:21,1219,La Tagliatella,14 Rue Guiraude,33000,Bordeaux,44.8393877,-0.5747810999999999,78489,Rue De Metz 17,33000,Bordeaux,44.8378442,-0.5971111,2395,1471,2016-07-28 20:28:56,2016-07-28 20:40:53,0 +207711,2016-07-28 20:47:57,1239,Tam Tam Saigon,7 Rue Paulin,33000,Bordeaux,44.846516,-0.588076,78629,Avenue De Tivoli 117,33110,Bordeaux,44.8619123,-0.5929316,5630,1471,2016-07-28 21:36:38,2016-07-28 21:46:22,0 +207718,2016-07-28 20:48:33,1221,Le Veneto,25 Allee De Tourny,33000,Bordeaux,44.84473,-0.578606,78633,Cours De L'Intendance 26,33000,Bordeaux,44.8415735,-0.5766424,3390,1407,2016-07-28 21:09:26,2016-07-28 21:18:30,0 +207719,2016-07-28 20:48:37,1208,Chez Ambre And Michel,1 Rue Matignon,33000,Bordeaux,44.850258,-0.586204,78634,Rue Bergeret 20,33000,Bordeaux,44.8326405,-0.5689734,1550,1430,2016-07-28 21:17:02,2016-07-28 21:31:20,0 +207727,2016-07-28 20:49:32,1217,Henny'S Burger,22 Rue Fondaudege,33000,Bordeaux,44.845875,-0.579345,78639,Rue Permentade 32,33000,Bordeaux,44.8325401,-0.5683798,1450,1420,2016-07-28 21:06:11,2016-07-28 21:15:23,0 +207729,2016-07-28 20:49:49,1246,Thai Paradise,70 Rue Des Ayres,33000,Bordeaux,44.836327,-0.575572,78641,Rue Milliere 35,33000,Bordeaux,44.8297433,-0.5767682,4150,1415,2016-07-28 21:07:04,2016-07-28 21:15:24,0 +207730,2016-07-28 20:49:58,1225,Billy Factory,5 Place Louis Barthou,33000,Bordeaux,44.827942,-0.59441,78642,Rue Du Tondu 158,33000,Bordeaux,44.8286112,-0.5876055,2450,1458,2016-07-28 21:05:41,2016-07-28 21:17:08,0 +207353,2016-07-28 20:05:28,1254,Funky Burger,5 Rue Du Loup,33000,Bordeaux,44.838081,-0.572281,78490,Rue Castelnau D'Auros 6,33000,Bordeaux,44.841255,-0.5817717,1270,2013,2016-07-28 20:19:12,2016-07-28 20:26:57,0 +207366,2016-07-28 20:06:39,1233,Punjab,39 Rue Saint Remi,33000,Bordeaux,44.841393,-0.572534,75889,Rue Du Tondu 24,33000,Bordeaux,44.832338,-0.5815905,1860,1420,2016-07-28 20:22:15,2016-07-28 20:37:09,0 +207754,2016-07-28 20:52:56,1211,Haru Haru,93 Cours Gambetta,33400,Bordeaux,44.8181798,-0.5851184,78650,Rue Sainte-Catherine 221,33000,Bordeaux,44.8333233,-0.5732607,1950,1426,2016-07-28 21:14:18,2016-07-28 21:29:20,0 +207764,2016-07-28 20:53:44,1239,Tam Tam Saigon,7 Rue Paulin,33000,Bordeaux,44.846516,-0.588076,78655,Avenue Sadi Carnot 8,33110,Bordeaux,44.8638177,-0.5940788,1450,1460,2016-07-28 21:35:00,2016-07-28 21:47:37,0 +207377,2016-07-28 20:08:10,1254,Funky Burger,5 Rue Du Loup,33000,Bordeaux,44.838081,-0.572281,77409,Rue Lafayette 8,33000,Bordeaux,44.8436175,-0.5709337,2420,1422,2016-07-28 20:19:51,2016-07-28 20:27:43,0 +207805,2016-07-28 20:59:56,1254,Funky Burger,5 Rue Du Loup,33000,Bordeaux,44.838081,-0.572281,78671,Rue Pelleport 108,33800,Bordeaux,44.8221305,-0.5625848999999999,1560,1817,2016-07-28 21:08:40,2016-07-28 21:26:41,0 +207808,2016-07-28 21:00:06,1242,Fufu Saint Remi,37 Rue Saint Remi,33000,Bordeaux,44.841438,-0.572537,78673,Rue Pascal Mothes 1,33800,Bordeaux,44.8246358,-0.5724106999999999,3150,1407,2016-07-28 21:20:49,2016-07-28 21:32:43,0 +207382,2016-07-28 20:08:40,1254,Funky Burger,5 Rue Du Loup,33000,Bordeaux,44.838081,-0.572281,78498,Rue Lafayette 8,33000,Bordeaux,44.8436175,-0.5709337,2420,1422,,,1 +207825,2016-07-28 21:02:41,1254,Funky Burger,5 Rue Du Loup,33000,Bordeaux,44.838081,-0.572281,78680,Rue Pelleport 108,33800,Bordeaux,44.8221305,-0.5625848999999999,1490,1817,2016-07-28 21:13:02,2016-07-28 21:26:41,0 +207398,2016-07-28 20:10:50,1225,Billy Factory,5 Place Louis Barthou,33000,Bordeaux,44.827942,-0.59441,78506,Cours D'Albret 100,33000,Bordeaux,44.8327483,-0.5794673,3050,1430,2016-07-28 20:27:52,2016-07-28 20:33:37,0 +207437,2016-07-28 20:15:30,1247,Noonies,16 Avenue Tiers,33100,Bordeaux,44.841251,-0.558816,78519,Rue Borie 57,33300,Bordeaux,44.8550543,-0.5704612,1590,1412,2016-07-28 20:40:50,2016-07-28 20:57:16,0 +207834,2016-07-28 21:04:00,1222,Les Tartines De Marine,"6 Rue Saint-Sernin, Bordeaux",33000,Bordeaux,44.839336,-0.58194,78685,Rue Bergeret 3,33000,Bordeaux,44.8329254,-0.5695346,2850,1412,2016-07-28 21:29:59,2016-07-28 21:47:34,0 +207438,2016-07-28 20:15:36,1254,Funky Burger,5 Rue Du Loup,33000,Bordeaux,44.838081,-0.572281,78520,Rue Sainte-Colombe 8,33000,Bordeaux,44.8371882,-0.5699911999999999,1340,1426,2016-07-28 20:39:20,2016-07-28 20:42:36,0 +207440,2016-07-28 20:15:43,1231,Umami Ramen,8 Place Fernand Lafargue,33000,Bordeaux,44.83691,-0.573943,78521,Rue Edouard Mayaudon 36,33100,Bordeaux,44.8481926,-0.5489845,3650,1410,2016-07-28 20:32:21,2016-07-28 20:43:22,0 +207885,2016-07-28 21:11:48,1249,Pitaya Sainte Catherine,275 Rue Sainte Catherine,33000,Bordeaux,44.831692,-0.573207,78702,Rue Furtado 3,33800,Bordeaux,44.82517439999999,-0.562736,1550,1426,2016-07-28 21:26:22,2016-07-28 21:37:10,0 +207444,2016-07-28 20:16:12,1249,Pitaya Sainte Catherine,275 Rue Sainte Catherine,33000,Bordeaux,44.831692,-0.573207,78523,Boulevard George V 21,33000,Bordeaux,44.82691579999999,-0.5918899,2500,1420,2016-07-28 20:31:07,2016-07-28 20:42:26,0 +207908,2016-07-28 21:15:01,1254,Funky Burger,5 Rue Du Loup,33000,Bordeaux,44.838081,-0.572281,78709,Cours Pasteur 21 Bis,33000,Bordeaux,44.8356037,-0.5756361999999999,2130,1422,2016-07-28 21:24:38,2016-07-28 21:31:39,0 +207450,2016-07-28 20:17:00,1211,Haru Haru,93 Cours Gambetta,33400,Bordeaux,44.8181798,-0.5851184,78525,Rue De Metz 17,33000,Bordeaux,44.8378442,-0.5971111,1750,1817,2016-07-28 20:30:27,2016-07-28 20:50:46,0 +208201,2016-07-28 22:25:16,1239,Tam Tam Saigon,7 Rue Paulin,33000,Bordeaux,44.846516,-0.588076,78823,Rue De La Croix Blanche 22,33000,Bordeaux,44.8441355,-0.5898898,4690,1416,2016-07-28 22:50:17,2016-07-28 22:55:36,0 +207926,2016-07-28 21:17:02,1233,Punjab,39 Rue Saint Remi,33000,Bordeaux,44.841393,-0.572534,78715,Rue Turenne 14,33000,Bordeaux,44.8457902,-0.5812155999999999,2550,2013,2016-07-28 21:38:36,2016-07-28 21:46:52,0 +207942,2016-07-28 21:19:07,1231,Umami Ramen,8 Place Fernand Lafargue,33000,Bordeaux,44.83691,-0.573943,78720,Rue Des Sablieres 63,33800,Bordeaux,44.8247479,-0.5757321,1360,1420,2016-07-28 21:32:28,2016-07-28 21:51:04,0 +208314,2016-07-29 11:45:59,1239,Tam Tam Saigon,7 Rue Paulin,33000,Bordeaux,44.846516,-0.588076,78878,Rue Lecocq 130,33000,Bordeaux,44.8328744,-0.5897378,8370,1418,2016-07-29 12:32:50,2016-07-29 12:40:37,0 +207987,2016-07-28 21:26:38,1254,Funky Burger,5 Rue Du Loup,33000,Bordeaux,44.838081,-0.572281,78740,Rue Ravez 20,33000,Bordeaux,44.83644630000001,-0.5724156,2280,1458,2016-07-28 21:36:36,2016-07-28 21:43:38,0 +207988,2016-07-28 21:27:01,1254,Funky Burger,5 Rue Du Loup,33000,Bordeaux,44.838081,-0.572281,78741,Rue Jean De Malet 1,33800,Bordeaux,44.8301777,-0.5654178,2110,1458,2016-07-28 21:40:29,2016-07-28 21:50:06,0 +207989,2016-07-28 21:27:03,1214,Koh I Noor,3 Rue Du Puits Descujols,33000,Bordeaux,44.841011,-0.570755,78742,Rue Judaique 268,33000,Bordeaux,44.8400846,-0.597563,1900,1415,2016-07-28 21:41:00,2016-07-28 21:50:53,0 +208018,2016-07-28 21:33:02,1242,Fufu Saint Remi,37 Rue Saint Remi,33000,Bordeaux,44.841438,-0.572537,78757,Rue Ausone 30,33000,Bordeaux,44.8377437,-0.5677322,1450,1416,2016-07-28 21:43:49,2016-07-28 21:49:43,0 +208358,2016-07-29 12:04:44,1207,Le Jardin Pekinois,9 Rue Des Freres Bonie,33000,Bordeaux,44.837078,-0.579572,78896,Rue Turenne 279,33000,Bordeaux,44.8497522,-0.5954946999999999,4300,1817,2016-07-29 12:37:27,2016-07-29 12:51:39,0 +208100,2016-07-28 21:49:11,1217,Henny'S Burger,22 Rue Fondaudege,33000,Bordeaux,44.845875,-0.579345,78785,Rue Le Reynard 6,33800,Bordeaux,44.8336251,-0.5638126999999999,1830,2013,2016-07-28 22:02:32,2016-07-28 22:16:22,0 +208107,2016-07-28 21:51:29,1256,Pitaya Stalingrad,36 Place De Stalingrad,33100,Bordeaux,44.840912,-0.559553,78788,Rue Porte De La Monnaie 29,33800,Bordeaux,44.8321496,-0.5631799,2350,1416,2016-07-28 22:06:40,2016-07-28 22:13:43,0 +208112,2016-07-28 21:52:36,1254,Funky Burger,5 Rue Du Loup,33000,Bordeaux,44.838081,-0.572281,78790,Cours De La Marne 71,33800,Bordeaux,44.8297535,-0.5685724,4090,1817,2016-07-28 22:05:01,2016-07-28 22:11:28,0 +208366,2016-07-29 12:06:46,1231,Umami Ramen,8 Place Fernand Lafargue,33000,Bordeaux,44.83691,-0.573943,2377,Rue Malbec 35,33800,Bordeaux,44.8268294,-0.5619661,2750,1465,2016-07-29 12:19:57,2016-07-29 12:33:00,0 +208118,2016-07-28 21:54:54,1218,Le Rizana,7 Rue Gaspard Philippe,33000,Bordeaux,44.833736,-0.56662,78792,Rue De La Benauge 175,33100,Bordeaux,44.8415454,-0.5502176,2650,1817,2016-07-28 22:18:24,2016-07-28 22:30:22,0 +208392,2016-07-29 12:16:06,1217,Henny'S Burger,22 Rue Fondaudege,33000,Bordeaux,44.845875,-0.579345,78913,Rue Charles Marionneau 4,33000,Bordeaux,44.8419347,-0.5864636,1450,1461,2016-07-29 12:49:48,2016-07-29 12:54:20,0 +208145,2016-07-28 22:04:36,1254,Funky Burger,5 Rue Du Loup,33000,Bordeaux,44.838081,-0.572281,78799,Cours De L'Yser 186,33800,Bordeaux,44.822439,-0.5706013999999999,2410,1409,2016-07-28 22:27:58,2016-07-28 22:36:31,0 +208147,2016-07-28 22:05:05,1218,Le Rizana,7 Rue Gaspard Philippe,33000,Bordeaux,44.833736,-0.56662,78800,Rue Terrasson 90,33800,Bordeaux,44.8202167,-0.5767623,1450,2013,2016-07-28 22:28:16,2016-07-28 22:37:28,0 +208393,2016-07-29 12:16:09,1260,L'Epicerie Bordelaise,14 Rue Ravez,33000,Bordeaux,44.837101,-0.57272,78914,Rue Sainte-Colombe 6,33000,Bordeaux,44.8373396,-0.5699076,1450,1420,2016-07-29 12:31:37,2016-07-29 12:35:26,0 +208399,2016-07-29 12:17:53,1223,Bag'Elles Coffee,19 Rue Du Mirail,33000,Bordeaux,44.83419,-0.571462,73919,Rue Amedee Saint-Germain 121B,33800,Bordeaux,44.8182663,-0.5638276999999999,2760,1462,2016-07-29 12:33:58,2016-07-29 12:43:42,0 +208176,2016-07-28 22:13:41,1254,Funky Burger,5 Rue Du Loup,33000,Bordeaux,44.838081,-0.572281,78811,Place Fernand Lafargue 7,33000,Bordeaux,44.8368697,-0.5716759,2060,1460,2016-07-28 22:32:55,2016-07-28 22:39:50,0 +208417,2016-07-29 12:21:44,1256,Pitaya Stalingrad,36 Place De Stalingrad,33100,Bordeaux,44.840912,-0.559553,78923,Rue De La Rousselle 74,33000,Bordeaux,44.8368599,-0.5670333,3250,1471,2016-07-29 13:16:11,2016-07-29 13:20:49,0 +208191,2016-07-28 22:19:36,1254,Funky Burger,5 Rue Du Loup,33000,Bordeaux,44.838081,-0.572281,78818,Rue Barreyre 57,33300,Bordeaux,44.8553864,-0.5687884000000001,2030,1458,2016-07-28 22:31:15,2016-07-28 22:40:34,0 +208436,2016-07-29 12:28:54,1254,Funky Burger,5 Rue Du Loup,33000,Bordeaux,44.838081,-0.572281,78929,Rue Dublan 13,33800,Bordeaux,44.8277396,-0.5732661,3030,1420,2016-07-29 12:51:18,2016-07-29 12:58:35,0 +208572,2016-07-29 13:13:37,1250,Que Toi,39 Cours D'Alsace-Et-Lorraine,33000,Bordeaux,44.837921,-0.572655,78975,Cours De L'Argonne 133,33000,Bordeaux,44.8267816,-0.5766757,2050,1430,2016-07-29 13:19:00,2016-07-29 13:33:16,0 +208437,2016-07-29 12:30:11,1254,Funky Burger,5 Rue Du Loup,33000,Bordeaux,44.838081,-0.572281,77151,Rue Perey 42,33000,Bordeaux,44.82424959999999,-0.5851284,2200,1416,2016-07-29 12:58:45,2016-07-29 13:08:29,0 +208594,2016-07-29 13:29:11,1216,Sushimi,8 Rue Courbin,33000,Bordeaux,44.841721,-0.572962,78983,Rue De La Porte Dijeaux 68,33000,Bordeaux,44.8407296,-0.5788188,1320,1420,,,1 +208600,2016-07-29 13:32:40,1213,Lupo,"23 Place Pey Berland, 33000 Bordeaux",33000,Bordeaux,44.837158,-0.576632,78984,Rue Sainte-Catherine 220,33000,Bordeaux,44.8336525,-0.5730919999999999,1360,1463,2016-07-29 13:44:18,2016-07-29 13:52:07,0 +208602,2016-07-29 13:36:14,1221,Le Veneto,25 Allee De Tourny,33000,Bordeaux,44.84473,-0.578606,78985,Rue Du Jardin Public 107,33000,Bordeaux,44.8540971,-0.5746055,2910,1471,2016-07-29 13:48:57,2016-07-29 14:05:12,0 +208438,2016-07-29 12:30:27,1225,Billy Factory,5 Place Louis Barthou,33000,Bordeaux,44.827942,-0.59441,78930,Rue Du Loup 64,33000,Bordeaux,44.8379284,-0.5744606999999999,1750,1465,2016-07-29 12:56:00,2016-07-29 13:05:43,0 +208608,2016-07-29 13:41:29,1254,Funky Burger,5 Rue Du Loup,33000,Bordeaux,44.838081,-0.572281,78989,Rue De La Rousselle 39,33000,Bordeaux,44.8370395,-0.5683842,2160,1465,2016-07-29 14:05:32,2016-07-29 14:09:13,0 +208451,2016-07-29 12:36:04,1207,Le Jardin Pekinois,9 Rue Des Freres Bonie,33000,Bordeaux,44.837078,-0.579572,78854,Rue Mandron 87,33000,Bordeaux,44.8538185,-0.5811208,1450,1414,2016-07-29 12:49:50,2016-07-29 13:23:52,0 +208617,2016-07-29 13:44:37,1242,Fufu Saint Remi,37 Rue Saint Remi,33000,Bordeaux,44.841438,-0.572537,78994,Rue Du Mirail 48,33000,Bordeaux,44.833023,-0.5708925,1450,1430,2016-07-29 13:53:57,2016-07-29 14:03:30,0 +208620,2016-07-29 13:46:59,1212,Cote Terrasse,198 Cours De L'Argonne,33800,Bordeaux,44.824543,-0.578545,78996,Rue De Carros 11,33800,Bordeaux,44.8205624,-0.5786616,1350,1418,2016-07-29 14:10:36,2016-07-29 14:15:52,0 +208457,2016-07-29 12:37:16,1235,Melodie,17 Rue Leupold,33000,Bordeaux,44.840603,-0.570444,78938,Cours De La Marne 190,33800,Bordeaux,44.82803639999999,-0.5596099999999999,3450,1418,2016-07-29 12:54:09,2016-07-29 13:02:05,0 +208461,2016-07-29 12:38:14,1222,Les Tartines De Marine,"6 Rue Saint-Sernin, Bordeaux",33000,Bordeaux,44.839336,-0.58194,78940,Rue Edouard Larroque 36,33000,Bordeaux,44.8315573,-0.6022223,1550,1462,2016-07-29 12:58:44,2016-07-29 13:07:00,0 +208465,2016-07-29 12:40:38,1254,Funky Burger,5 Rue Du Loup,33000,Bordeaux,44.838081,-0.572281,78942,Rue Sainte-Catherine 115,33000,Bordeaux,44.8374691,-0.5738075,1370,1430,2016-07-29 13:06:37,2016-07-29 13:09:45,0 +208697,2016-07-29 18:33:10,1226,Ici Argentine,84 Boulevard Du President Wilson,33000,Bordeaux,44.840084,-0.5994,79026,Cours Marc Nouaux 86,33000,Bordeaux,44.8471704,-0.5969618999999999,7000,1420,2016-07-29 19:00:13,2016-07-29 19:06:53,0 +208698,2016-07-29 18:33:21,1244,Fufu Chartrons,71 Cours Portal,33300,Bordeaux,44.85516,-0.572128,77614,Rue De Laseppe 42,33000,Bordeaux,44.8529914,-0.5836756,4500,1998,2016-07-29 18:53:49,2016-07-29 19:11:06,0 +208705,2016-07-29 18:39:03,1242,Fufu Saint Remi,37 Rue Saint Remi,33000,Bordeaux,44.841438,-0.572537,79028,Rue Monadey 29,33800,Bordeaux,44.8283983,-0.5708394999999999,2950,1405,2016-07-29 18:50:34,2016-07-29 19:01:25,0 +208494,2016-07-29 12:47:48,1244,Fufu Chartrons,71 Cours Portal,33300,Bordeaux,44.85516,-0.572128,78947,Rue De Gironde 37,33300,Bordeaux,44.8646468,-0.5518704999999999,2950,1424,2016-07-29 12:57:27,2016-07-29 13:05:45,0 +208724,2016-07-29 18:48:53,1207,Le Jardin Pekinois,9 Rue Des Freres Bonie,33000,Bordeaux,44.837078,-0.579572,79034,Rue Constantin 37,33000,Bordeaux,44.8506478,-0.5738262000000001,1540,1412,2016-07-29 19:08:20,2016-07-29 19:22:10,0 +208521,2016-07-29 12:55:52,1223,Bag'Elles Coffee,19 Rue Du Mirail,33000,Bordeaux,44.83419,-0.571462,78957,Rue Amedee Saint-Germain 57,33800,Bordeaux,44.8229738,-0.5592062999999999,3500,1418,2016-07-29 13:19:20,2016-07-29 13:29:07,0 +208783,2016-07-29 19:08:38,1242,Fufu Saint Remi,37 Rue Saint Remi,33000,Bordeaux,44.841438,-0.572537,78337,Cours De L'Argonne 133,33000,Bordeaux,44.8267816,-0.5766757,1500,1403,2016-07-29 19:15:54,2016-07-29 19:23:32,0 +208800,2016-07-29 19:13:21,1205,Taj Mahal,24 Rue Du Parlement Sainte-Catherine,33000,Bordeaux,44.840405,-0.57394,79072,Rue Duplessy 22,33000,Bordeaux,44.848126,-0.5804165,4590,1405,2016-07-29 19:34:14,2016-07-29 19:40:37,0 +208524,2016-07-29 12:56:08,1204,Max A Table,36 Rue Cornac,33000,Bordeaux,44.851402,-0.57587,78958,Cours Aristide Briand 59,33000,Bordeaux,44.8313421,-0.5761406,2050,1461,2016-07-29 13:17:23,2016-07-29 13:34:47,0 +208531,2016-07-29 12:58:44,1209,La Gamelle,23 Rue Des Freres Bonie,33000,Bordeaux,44.836849,-0.580108,10298,Rue Des Argentiers 16,33000,Bordeaux,44.8391736,-0.5698286,1689,1817,2016-07-29 13:05:41,2016-07-29 13:15:32,0 +208854,2016-07-29 19:22:27,1216,Sushimi,8 Rue Courbin,33000,Bordeaux,44.841721,-0.572962,79092,Cours Du Medoc 15Bis,33300,Bordeaux,44.8567725,-0.5650073,1410,1420,2016-07-29 19:51:49,2016-07-29 20:03:29,0 +208547,2016-07-29 13:04:55,1260,L'Epicerie Bordelaise,14 Rue Ravez,33000,Bordeaux,44.837101,-0.57272,78965,Rue Monadey 12,33800,Bordeaux,44.8288059,-0.5715572,2550,1420,2016-07-29 13:16:05,2016-07-29 13:25:11,0 +208865,2016-07-29 19:25:06,1215,Moon Wok,17 Place Fernand Lafargue,33000,Bordeaux,44.837299,-0.572124,79097,Rue Carnot 1,33400,Bordeaux,44.8229657,-0.5861759999999999,3050,1817,2016-07-29 19:48:48,2016-07-29 19:59:54,0 +208963,2016-07-29 19:42:25,1219,La Tagliatella,14 Rue Guiraude,33000,Bordeaux,44.8393877,-0.5747810999999999,79128,Rue Pauline Kergomard 35,33800,Bordeaux,44.823186,-0.574915,3180,1422,2016-07-29 20:01:47,2016-07-29 20:14:20,0 +208912,2016-07-29 19:34:58,1205,Taj Mahal,24 Rue Du Parlement Sainte-Catherine,33000,Bordeaux,44.840405,-0.57394,79109,Avenue Charles De Gaulle 114,33200,Bordeaux,44.8494454,-0.6033054999999999,3650,1415,2016-07-29 19:51:02,2016-07-29 20:01:33,0 +208932,2016-07-29 19:37:35,1223,Bag'Elles Coffee,19 Rue Du Mirail,33000,Bordeaux,44.83419,-0.571462,79116,Rue Giner De Los Rios 50,33800,Bordeaux,44.8280535,-0.5693978,1450,1917,2016-07-29 19:52:20,2016-07-29 19:57:25,0 +208938,2016-07-29 19:38:09,1204,Max A Table,36 Rue Cornac,33000,Bordeaux,44.851402,-0.57587,79119,Rue Maryse Bastie 20,33300,Bordeaux,44.86264569999999,-0.5795558,2150,1405,2016-07-29 19:50:58,2016-07-29 20:06:24,0 +208979,2016-07-29 19:44:36,1260,L'Epicerie Bordelaise,14 Rue Ravez,33000,Bordeaux,44.837101,-0.57272,79135,Rue Georges Bonnac 177,33000,Bordeaux,44.8387976,-0.5898502,1630,1430,2016-07-29 19:50:53,2016-07-29 19:59:58,0 +209324,2016-07-29 20:24:47,1214,Koh I Noor,3 Rue Du Puits Descujols,33000,Bordeaux,44.841011,-0.570755,79257,Passage Birly 50,33800,Bordeaux,44.8218884,-0.5746236000000001,2290,1917,2016-07-29 20:46:59,2016-07-29 20:59:22,0 +208986,2016-07-29 19:44:54,1225,Billy Factory,5 Place Louis Barthou,33000,Bordeaux,44.827942,-0.59441,79139,Rue Vilaris 19 Bis,33800,Bordeaux,44.825563,-0.5636495,2850,1817,2016-07-29 20:06:29,2016-07-29 20:21:52,0 +209342,2016-07-29 20:26:14,1254,Funky Burger,5 Rue Du Loup,33000,Bordeaux,44.838081,-0.572281,79265,Rue Saint-Sernin 20,33000,Bordeaux,44.8398386,-0.5819402,2130,1412,2016-07-29 20:39:58,2016-07-29 20:54:23,0 +208987,2016-07-29 19:44:55,1227,Cilicie,4 Rue Des Bahutiers,33000,Bordeaux,44.839531,-0.570651,79140,Cours Journu Auber 18,33300,Bordeaux,44.8582889,-0.5682868,2450,1416,2016-07-29 20:01:30,2016-07-29 20:20:04,0 +209350,2016-07-29 20:27:27,1205,Taj Mahal,24 Rue Du Parlement Sainte-Catherine,33000,Bordeaux,44.840405,-0.57394,79268,Rue De Cardoze 14,33200,Bordeaux,44.83799339999999,-0.6021928999999999,2800,1403,2016-07-29 20:46:15,2016-07-29 20:55:17,0 +209013,2016-07-29 19:48:56,1233,Punjab,39 Rue Saint Remi,33000,Bordeaux,44.841393,-0.572534,79145,Rue De Lalande 41,33000,Bordeaux,44.8335047,-0.5753986999999999,1500,1412,2016-07-29 20:02:36,2016-07-29 20:19:50,0 +209363,2016-07-29 20:28:57,1225,Billy Factory,5 Place Louis Barthou,33000,Bordeaux,44.827942,-0.59441,79215,Rue Saint Remi 66,33000,Bordeaux,44.8411214,-0.5739778000000001,1570,1426,,,1 +209387,2016-07-29 20:31:06,1254,Funky Burger,5 Rue Du Loup,33000,Bordeaux,44.838081,-0.572281,79284,Rue Fonfrede 11,33800,Bordeaux,44.8256705,-0.5719398,1370,1420,2016-07-29 20:50:49,2016-07-29 20:58:06,0 +209390,2016-07-29 20:31:24,1250,Que Toi,39 Cours D'Alsace-Et-Lorraine,33000,Bordeaux,44.837921,-0.572655,79287,Quai Richelieu 55,33000,Bordeaux,44.8371276,-0.5666549,1550,1416,2016-07-29 20:40:39,2016-07-29 20:43:24,0 +209017,2016-07-29 19:50:05,1246,Thai Paradise,70 Rue Des Ayres,33000,Bordeaux,44.836327,-0.575572,79147,Rue Du Muguet 17,33000,Bordeaux,44.8367251,-0.5686976,3850,1410,2016-07-29 20:09:56,2016-07-29 20:15:21,0 +209403,2016-07-29 20:33:44,1207,Le Jardin Pekinois,9 Rue Des Freres Bonie,33000,Bordeaux,44.837078,-0.579572,79293,Rue Sanche De Pomiers 30,33000,Bordeaux,44.8318677,-0.5689497,1989,1412,2016-07-29 20:59:11,2016-07-29 21:10:33,0 +209405,2016-07-29 20:33:53,1229,Les Mijotes Du Bocal,2 Bis Rue De Cursol,33000,Bordeaux,44.834278,-0.57038,79295,Place Pierre Jacques Dormoy 18,33800,Bordeaux,44.82643909999999,-0.5639328,1950,1409,2016-07-29 20:54:43,,1 +209412,2016-07-29 20:35:34,1263,Noorn Akorn,8 Cours D'Albret,33000,Bordeaux,44.838734,-0.581611,79298,Rue Verteuil 1,33000,Bordeaux,44.8389448,-0.5809113,2750,1430,2016-07-29 20:50:11,2016-07-29 20:54:31,0 +209027,2016-07-29 19:51:27,1231,Umami Ramen,8 Place Fernand Lafargue,33000,Bordeaux,44.83691,-0.573943,79151,Rue Emile Zola 34,33400,Bordeaux,44.8231508,-0.5887801,3800,1403,2016-07-29 19:58:07,2016-07-29 20:09:35,0 +209426,2016-07-29 20:37:08,1254,Funky Burger,5 Rue Du Loup,33000,Bordeaux,44.838081,-0.572281,79303,Cours Aristide Briand 102 B,33000,Bordeaux,44.8313444,-0.5745409,1470,1405,2016-07-29 20:49:00,2016-07-29 20:54:35,0 +209432,2016-07-29 20:38:21,1209,La Gamelle,23 Rue Des Freres Bonie,33000,Bordeaux,44.836849,-0.580108,79307,Rue Albert De Mun 26,33000,Bordeaux,44.8487459,-0.5816116,2039,1430,,,1 +209033,2016-07-29 19:51:49,1204,Max A Table,36 Rue Cornac,33000,Bordeaux,44.851402,-0.57587,79153,Rue Barreyre 182,33300,Bordeaux,44.8584901,-0.5739877999999999,3950,1416,2016-07-29 20:11:01,2016-07-29 20:15:20,0 +209095,2016-07-29 19:57:33,1250,Que Toi,39 Cours D'Alsace-Et-Lorraine,33000,Bordeaux,44.837921,-0.572655,79169,Rue Barreyre 61,33300,Bordeaux,44.85535600000001,-0.5690356,2650,1998,2016-07-29 20:07:50,2016-07-29 20:20:29,0 +209479,2016-07-29 20:43:10,1254,Funky Burger,5 Rue Du Loup,33000,Bordeaux,44.838081,-0.572281,79324,Cours Victor Hugo 150,33000,Bordeaux,44.8348979,-0.5741788,1600,1415,2016-07-29 21:04:33,2016-07-29 21:09:33,0 +209499,2016-07-29 20:45:12,1244,Fufu Chartrons,71 Cours Portal,33300,Bordeaux,44.85516,-0.572128,79334,Rue Latour 5,33000,Bordeaux,44.8504343,-0.5704513,1450,1998,2016-07-29 20:57:05,2016-07-29 21:04:42,0 +209185,2016-07-29 20:07:11,1205,Taj Mahal,24 Rue Du Parlement Sainte-Catherine,33000,Bordeaux,44.840405,-0.57394,79207,Rue De Tauzia 45,33800,Bordeaux,44.8291658,-0.558665,2400,1430,2016-07-29 20:15:02,2016-07-29 20:29:29,0 +209543,2016-07-29 20:49:50,1254,Funky Burger,5 Rue Du Loup,33000,Bordeaux,44.838081,-0.572281,79357,Rue Rene Roy De Clotte 17,33000,Bordeaux,44.8295877,-0.5754490999999999,1440,1817,2016-07-29 21:05:31,2016-07-29 21:14:56,0 +209562,2016-07-29 20:51:58,1206,La Maison Du Glacier,1 Place Saint Pierre,33000,Bordeaux,44.839706,-0.570672,79369,Rue Jean Burguet 8,33000,Bordeaux,44.8344422,-0.5781535,1650,1415,2016-07-29 21:01:23,2016-07-29 21:17:30,0 +209569,2016-07-29 20:52:49,1207,Le Jardin Pekinois,9 Rue Des Freres Bonie,33000,Bordeaux,44.837078,-0.579572,79372,Rue Boudet 35,33000,Bordeaux,44.8473251,-0.5759476,1340,1458,2016-07-29 21:18:56,2016-07-29 21:25:06,0 +209591,2016-07-29 20:55:38,1220,Jardin Phnom Penh,1 Rue Du Cerf Volant,33000,Bordeaux,44.838287,-0.570993,79382,Rue De La Fraternite 35,33400,Bordeaux,44.8199976,-0.5817819,1950,1470,2016-07-29 21:06:11,2016-07-29 21:20:43,0 +209592,2016-07-29 20:55:39,1236,Marhaba,27 Rue Des Faures,33800,Bordeaux,44.834766,-0.565754,79383,Place Nansouty 234,33800,Bordeaux,44.8204061,-0.5716893,5750,1412,2016-07-29 21:15:56,2016-07-29 21:30:18,0 +209593,2016-07-29 20:56:04,1221,Le Veneto,25 Allee De Tourny,33000,Bordeaux,44.84473,-0.578606,79384,Quai Des Chartrons 95,33300,Bordeaux,44.8546068,-0.5657744,1330,1430,2016-07-29 21:07:05,2016-07-29 21:28:11,0 +209191,2016-07-29 20:07:53,1213,Lupo,"23 Place Pey Berland, 33000 Bordeaux",33000,Bordeaux,44.837158,-0.576632,79211,Rue Minvielle 30,33000,Bordeaux,44.8536486,-0.5723744,2160,1424,2016-07-29 20:18:19,2016-07-29 20:27:07,0 +209635,2016-07-29 21:00:46,1212,Cote Terrasse,198 Cours De L'Argonne,33800,Bordeaux,44.824543,-0.578545,79399,Rue Beyssac 22,33800,Bordeaux,44.8327439,-0.5633967,2050,1917,2016-07-29 21:20:12,2016-07-29 21:34:39,0 +209651,2016-07-29 21:02:42,1211,Haru Haru,93 Cours Gambetta,33400,Bordeaux,44.8181798,-0.5851184,79404,Cours De La Somme 134,33800,Bordeaux,44.8257984,-0.5724935,4050,1420,2016-07-29 21:16:19,2016-07-29 21:26:29,0 +209653,2016-07-29 21:02:44,1260,L'Epicerie Bordelaise,14 Rue Ravez,33000,Bordeaux,44.837101,-0.57272,79406,Rue Tanesse 13,33000,Bordeaux,44.8314504,-0.5775499,1350,1461,2016-07-29 21:12:36,2016-07-29 21:16:37,0 +209206,2016-07-29 20:08:38,1225,Billy Factory,5 Place Louis Barthou,33000,Bordeaux,44.827942,-0.59441,79215,Rue Saint Remi 66,33000,Bordeaux,44.8411214,-0.5739778000000001,1820,1403,2016-07-29 20:16:36,2016-07-29 20:38:06,0 +209666,2016-07-29 21:03:45,1216,Sushimi,8 Rue Courbin,33000,Bordeaux,44.841721,-0.572962,79412,Rue Camille Sauvageau 73,33800,Bordeaux,44.83221109999999,-0.5635616999999999,4180,1416,2016-07-29 21:30:40,2016-07-29 21:38:59,0 +209671,2016-07-29 21:04:22,1254,Funky Burger,5 Rue Du Loup,33000,Bordeaux,44.838081,-0.572281,79414,Rue Des Trois-Conils 20,33000,Bordeaux,44.8387071,-0.5755399999999999,3760,1409,2016-07-29 21:28:28,2016-07-29 21:31:16,0 +209216,2016-07-29 20:10:03,1223,Bag'Elles Coffee,19 Rue Du Mirail,33000,Bordeaux,44.83419,-0.571462,77625,Rue De Grassi 23,33000,Bordeaux,44.8405499,-0.5771273,3210,1420,2016-07-29 20:25:33,2016-07-29 20:32:26,0 +209679,2016-07-29 21:05:23,1217,Henny'S Burger,22 Rue Fondaudege,33000,Bordeaux,44.845875,-0.579345,79416,Rue Heriard Dubreuil 25,33000,Bordeaux,44.8479427,-0.5928829999999999,4390,1458,2016-07-29 21:27:24,2016-07-29 21:32:43,0 +209234,2016-07-29 20:12:59,1207,Le Jardin Pekinois,9 Rue Des Freres Bonie,33000,Bordeaux,44.837078,-0.579572,79222,Cours Saint-Louis 16,33300,Bordeaux,44.8563692,-0.5708489,2130,1458,2016-07-29 20:30:45,2016-07-29 20:38:52,0 +209689,2016-07-29 21:06:48,1254,Funky Burger,5 Rue Du Loup,33000,Bordeaux,44.838081,-0.572281,79419,Rue Servandoni 64,33000,Bordeaux,44.8337777,-0.5840013000000001,3810,1409,2016-07-29 21:44:26,2016-07-29 21:50:59,0 +209254,2016-07-29 20:15:20,1211,Haru Haru,93 Cours Gambetta,33400,Bordeaux,44.8181798,-0.5851184,79228,Rue Valentin Hauy 1,33000,Bordeaux,44.8347436,-0.6018987,1450,1422,2016-07-29 20:26:46,2016-07-29 20:41:31,0 +209692,2016-07-29 21:07:00,1239,Tam Tam Saigon,7 Rue Paulin,33000,Bordeaux,44.846516,-0.588076,79420,Rue Du Bocage 57,33200,Bordeaux,44.8541641,-0.5983086,1490,1426,,,1 +209697,2016-07-29 21:08:08,1207,Le Jardin Pekinois,9 Rue Des Freres Bonie,33000,Bordeaux,44.837078,-0.579572,79422,Rue Colbert 5,33000,Bordeaux,44.8465328,-0.588842,3529,1403,2016-07-29 21:34:58,2016-07-29 21:43:14,0 +209711,2016-07-29 21:09:18,1214,Koh I Noor,3 Rue Du Puits Descujols,33000,Bordeaux,44.841011,-0.570755,79428,Rue Des Bahutiers 35,33000,Bordeaux,44.83866769999999,-0.5709273,2880,1998,2016-07-29 21:32:45,2016-07-29 21:38:25,0 +209255,2016-07-29 20:15:22,1254,Funky Burger,5 Rue Du Loup,33000,Bordeaux,44.838081,-0.572281,79229,Rue De Laseppe 70,33000,Bordeaux,44.8529788,-0.5850312,2390,1410,2016-07-29 20:27:53,2016-07-29 20:37:57,0 +209256,2016-07-29 20:15:49,1235,Melodie,17 Rue Leupold,33000,Bordeaux,44.840603,-0.570444,79230,Rue Naujac 178,33000,Bordeaux,44.8495864,-0.5924585,1850,1415,2016-07-29 20:27:04,2016-07-29 20:35:23,0 +209735,2016-07-29 21:11:37,1254,Funky Burger,5 Rue Du Loup,33000,Bordeaux,44.838081,-0.572281,79439,Rue Servandoni 66,33000,Bordeaux,44.8338125,-0.584163,1250,1472,2016-07-29 21:33:16,2016-07-29 21:40:08,0 +209257,2016-07-29 20:15:54,1223,Bag'Elles Coffee,19 Rue Du Mirail,33000,Bordeaux,44.83419,-0.571462,79231,Rue Bergeon 2,33800,Bordeaux,44.8298519,-0.5697599,1830,1409,2016-07-29 20:39:21,2016-07-29 20:42:58,0 +209260,2016-07-29 20:16:00,1219,La Tagliatella,14 Rue Guiraude,33000,Bordeaux,44.8393877,-0.5747810999999999,79232,Avenue De Tivoli 14,33110,Bordeaux,44.8576458,-0.5915104,2440,1472,2016-07-29 20:31:39,2016-07-29 20:43:27,0 +209781,2016-07-29 21:18:00,1204,Max A Table,36 Rue Cornac,33000,Bordeaux,44.851402,-0.57587,76838,Rue Des Argentiers 16,33000,Bordeaux,44.8391736,-0.5698286,6000,1426,2016-07-29 21:28:05,2016-07-29 21:54:56,0 +209785,2016-07-29 21:18:25,1244,Fufu Chartrons,71 Cours Portal,33300,Bordeaux,44.85516,-0.572128,79460,Rue Jean Jacques Rousseau 7,33000,Bordeaux,44.84354159999999,-0.5778329,1600,1430,2016-07-29 21:36:16,2016-07-29 21:44:17,0 +209266,2016-07-29 20:16:54,1211,Haru Haru,93 Cours Gambetta,33400,Bordeaux,44.8181798,-0.5851184,79233,Rue Du Professeur Daguin 50,33800,Bordeaux,44.8142965,-0.5620291,2050,1902,2016-07-29 20:51:50,2016-07-29 20:59:58,0 +209795,2016-07-29 21:20:46,1234,Mille Et Une Saveurs,"96 Avenue Thiers, 33100 Bordeaux",33100,Bordeaux,44.843746,-0.554713,79463,Rue Du Chai Des Farines 17,33000,Bordeaux,44.8390942,-0.5693821,4350,1817,2016-07-29 21:47:28,2016-07-29 21:56:42,0 +209267,2016-07-29 20:16:56,1204,Max A Table,36 Rue Cornac,33000,Bordeaux,44.851402,-0.57587,79234,Rue Condorcet 43,33000,Bordeaux,44.857335,-0.5776279999999999,2050,1998,2016-07-29 20:32:25,2016-07-29 20:40:21,0 +209808,2016-07-29 21:22:30,1260,L'Epicerie Bordelaise,14 Rue Ravez,33000,Bordeaux,44.837101,-0.57272,79469,Rue Fondaudege 144,33000,Bordeaux,44.8489417,-0.5846662,1650,1471,2016-07-29 21:34:51,2016-07-29 21:51:25,0 +209270,2016-07-29 20:17:35,1249,Pitaya Sainte Catherine,275 Rue Sainte Catherine,33000,Bordeaux,44.831692,-0.573207,79235,Place Gavinies 20,33000,Bordeaux,44.8328338,-0.5946578,1600,1426,2016-07-29 20:28:05,2016-07-29 20:41:01,0 +209826,2016-07-29 21:25:15,1254,Funky Burger,5 Rue Du Loup,33000,Bordeaux,44.838081,-0.572281,79474,Cours Pasteur 40,33000,Bordeaux,44.8329886,-0.573878,2690,1998,2016-07-29 21:51:13,2016-07-29 22:07:15,0 +209280,2016-07-29 20:19:07,1244,Fufu Chartrons,71 Cours Portal,33300,Bordeaux,44.85516,-0.572128,79240,Rue Pourmann 9,33300,Bordeaux,44.8677266,-0.5489567,1250,1424,2016-07-29 20:33:37,2016-07-29 20:46:12,0 +209843,2016-07-29 21:27:36,1223,Bag'Elles Coffee,19 Rue Du Mirail,33000,Bordeaux,44.83419,-0.571462,79307,Rue Albert De Mun 26,33000,Bordeaux,44.8487459,-0.5816116,2230,1470,2016-07-29 21:49:49,2016-07-29 21:59:13,0 +209844,2016-07-29 21:27:56,1241,My Terroir,24 Place De La Ferme De Richemont,33000,Bordeaux,44.835506,-0.575218,79481,Cours De L'Argonne 17,33000,Bordeaux,44.829904,-0.5734106,1750,1415,2016-07-29 21:44:18,2016-07-29 21:49:10,0 +209858,2016-07-29 21:29:39,1204,Max A Table,36 Rue Cornac,33000,Bordeaux,44.851402,-0.57587,79486,Rue De Leybardie 27,33300,Bordeaux,44.8613599,-0.5650568,1350,1410,2016-07-29 21:56:54,2016-07-29 22:16:36,0 +209289,2016-07-29 20:20:01,1254,Funky Burger,5 Rue Du Loup,33000,Bordeaux,44.838081,-0.572281,79243,Rue Judaique 213,33000,Bordeaux,44.8408287,-0.5954455,1900,1471,2016-07-29 20:34:10,2016-07-29 20:44:35,0 +209859,2016-07-29 21:29:42,1213,Lupo,"23 Place Pey Berland, 33000 Bordeaux",33000,Bordeaux,44.837158,-0.576632,79487,Rue Ernest Renan 55,33000,Bordeaux,44.84949839999999,-0.5923147,2380,1409,,,1 +209860,2016-07-29 21:29:46,1245,Eatsalad,55 Rue Saint Remi,33000,Bordeaux,44.841286,-0.573413,79488,Rue Turenne 127,33000,Bordeaux,44.8467424,-0.5870031,1450,1471,2016-07-29 21:41:00,2016-07-29 21:57:30,0 +209873,2016-07-29 21:31:33,1207,Le Jardin Pekinois,9 Rue Des Freres Bonie,33000,Bordeaux,44.837078,-0.579572,79494,Rue De Cauderes 34,33400,Bordeaux,44.81545440000001,-0.5744315,1340,1472,2016-07-29 21:45:51,2016-07-29 21:59:13,0 +209290,2016-07-29 20:20:03,1211,Haru Haru,93 Cours Gambetta,33400,Bordeaux,44.8181798,-0.5851184,79244,Rue Roustaing 59,33400,Bordeaux,44.8175414,-0.590035,3050,1817,2016-07-29 20:32:42,2016-07-29 20:37:47,0 +209878,2016-07-29 21:33:02,1250,Que Toi,39 Cours D'Alsace-Et-Lorraine,33000,Bordeaux,44.837921,-0.572655,79496,Rue Bertrand De Goth 89,33800,Bordeaux,44.8200043,-0.5775741,2350,1817,2016-07-29 21:59:07,2016-07-29 22:22:26,0 +209886,2016-07-29 21:33:44,1254,Funky Burger,5 Rue Du Loup,33000,Bordeaux,44.838081,-0.572281,79500,Rue Charles Marionneau 41,33000,Bordeaux,44.8404897,-0.5868244,4010,1430,2016-07-29 22:02:26,2016-07-29 22:12:39,0 +209888,2016-07-29 21:34:35,1221,Le Veneto,25 Allee De Tourny,33000,Bordeaux,44.84473,-0.578606,79501,Rue Des Argentiers 1,33000,Bordeaux,44.8395709,-0.5703804,1810,1458,2016-07-29 21:40:26,2016-07-29 22:08:36,0 +209900,2016-07-29 21:36:36,1223,Bag'Elles Coffee,19 Rue Du Mirail,33000,Bordeaux,44.83419,-0.571462,79507,Rue Theresia Cabarrus 53,33000,Bordeaux,44.8238595,-0.5966503,1860,1415,2016-07-29 22:12:00,2016-07-29 22:36:03,0 +209294,2016-07-29 20:20:29,1221,Le Veneto,25 Allee De Tourny,33000,Bordeaux,44.84473,-0.578606,79246,Rue Du Docteur Charles Nancel Penard 21,33000,Bordeaux,44.8397886,-0.5814379,1530,1420,2016-07-29 20:40:08,2016-07-29 20:47:05,0 +209910,2016-07-29 21:37:54,1254,Funky Burger,5 Rue Du Loup,33000,Bordeaux,44.838081,-0.572281,79512,Rue Tustal 19,33000,Bordeaux,44.838474,-0.5752626,1570,1426,2016-07-29 22:02:58,2016-07-29 22:09:28,0 +210051,2016-07-29 22:09:51,1236,Marhaba,27 Rue Des Faures,33800,Bordeaux,44.834766,-0.565754,77984,Rue Rodrigues-Pereire 31,33000,Bordeaux,44.84428870000001,-0.5848409999999999,3400,1409,2016-07-29 22:30:54,2016-07-29 22:39:56,0 +209936,2016-07-29 21:41:35,1231,Umami Ramen,8 Place Fernand Lafargue,33000,Bordeaux,44.83691,-0.573943,79525,Rue Esprit Des Lois 14,33000,Bordeaux,44.8429576,-0.5723083,3200,1426,2016-07-29 22:08:53,2016-07-29 22:17:59,0 +209939,2016-07-29 21:42:00,1249,Pitaya Sainte Catherine,275 Rue Sainte Catherine,33000,Bordeaux,44.831692,-0.573207,79528,Rue Edmond Costedoat 29,33000,Bordeaux,44.8310742,-0.5784439,3250,1817,2016-07-29 22:09:33,2016-07-29 22:15:31,0 +209947,2016-07-29 21:45:07,1212,Cote Terrasse,198 Cours De L'Argonne,33800,Bordeaux,44.824543,-0.578545,79531,Passage Lafontaine 10,33800,Bordeaux,44.8266776,-0.5713045,1450,1472,2016-07-29 22:08:51,2016-07-29 22:13:05,0 +209948,2016-07-29 21:45:07,1205,Taj Mahal,24 Rue Du Parlement Sainte-Catherine,33000,Bordeaux,44.840405,-0.57394,79532,Rue Henri Iv 29,33000,Bordeaux,44.8322203,-0.5768331,3590,1409,2016-07-29 22:00:33,2016-07-29 22:08:07,0 +210068,2016-07-29 22:19:05,1204,Max A Table,36 Rue Cornac,33000,Bordeaux,44.851402,-0.57587,79576,Rue Emile Fourcand 87,33000,Bordeaux,44.8477529,-0.5870999,1650,1426,2016-07-29 22:33:53,2016-07-29 22:42:58,0 +209991,2016-07-29 21:54:10,1254,Funky Burger,5 Rue Du Loup,33000,Bordeaux,44.838081,-0.572281,79551,Rue Milliere 35,33000,Bordeaux,44.8297433,-0.5767682,1450,1416,2016-07-29 22:19:58,2016-07-29 22:29:14,0 +210080,2016-07-29 22:22:02,1254,Funky Burger,5 Rue Du Loup,33000,Bordeaux,44.838081,-0.572281,4420,Rue Tustal 19,33000,Bordeaux,44.838474,-0.5752626,2400,1472,2016-07-29 22:41:21,2016-07-29 22:45:05,0 +210025,2016-07-29 22:02:31,1204,Max A Table,36 Rue Cornac,33000,Bordeaux,44.851402,-0.57587,79563,Rue Tastet 18,33000,Bordeaux,44.8353074,-0.5814444999999999,1300,1470,2016-07-29 22:19:43,2016-07-29 22:31:42,0 +210142,2016-07-30 11:44:52,1207,Le Jardin Pekinois,9 Rue Des Freres Bonie,33000,Bordeaux,44.837078,-0.579572,79604,Rue Permentade 43,33000,Bordeaux,44.8325515,-0.569302,1540,1458,2016-07-30 12:02:31,2016-07-30 12:09:54,0 +210217,2016-07-30 12:24:28,1264,Koeben,32 Rue De Palais Gallien,33000,Bordeaux,44.8428,-0.581592,79628,Rue De Landiras 36,33000,Bordeaux,44.82899099999999,-0.5849419,6640,1471,2016-07-30 13:09:49,2016-07-30 13:21:29,0 +210441,2016-07-30 13:41:02,1258,Pitaya Saint-Remi,42 Rue Saint Remi,33000,Bordeaux,44.84127,-0.572691,79695,Rue Du Jardin Public 107,33000,Bordeaux,44.8540971,-0.5746055,2300,1416,2016-07-30 13:52:23,2016-07-30 13:58:24,0 +210454,2016-07-30 13:46:26,1222,Les Tartines De Marine,"6 Rue Saint-Sernin, Bordeaux",33000,Bordeaux,44.839336,-0.58194,78195,Rue Edouard Larroque 36,33000,Bordeaux,44.8315573,-0.6022223,1850,1407,2016-07-30 13:56:11,2016-07-30 14:06:33,0 +210459,2016-07-30 13:48:15,1254,Funky Burger,5 Rue Du Loup,33000,Bordeaux,44.838081,-0.572281,79700,Rue De La Fusterie 9,33000,Bordeaux,44.835886,-0.5659738,1490,1430,2016-07-30 14:01:04,2016-07-30 14:08:06,0 +210460,2016-07-30 13:48:30,1250,Que Toi,39 Cours D'Alsace-Et-Lorraine,33000,Bordeaux,44.837921,-0.572655,79701,Rue Beaubadat 5,33000,Bordeaux,44.8393017,-0.5777057999999999,2400,1462,2016-07-30 13:55:18,2016-07-30 14:12:12,0 +210473,2016-07-30 13:52:33,1245,Eatsalad,55 Rue Saint Remi,33000,Bordeaux,44.841286,-0.573413,79708,Rue Donissan 65,33000,Bordeaux,44.8287407,-0.5749175,1830,1462,2016-07-30 14:07:52,2016-07-30 14:19:16,0 +210476,2016-07-30 13:53:01,1220,Jardin Phnom Penh,1 Rue Du Cerf Volant,33000,Bordeaux,44.838287,-0.570993,79709,Rue Laclotte 13,33000,Bordeaux,44.8485326,-0.5816281,1950,1416,2016-07-30 14:07:47,2016-07-30 14:15:52,0 +210483,2016-07-30 13:55:26,1254,Funky Burger,5 Rue Du Loup,33000,Bordeaux,44.838081,-0.572281,79713,Rue Tastet 17,33000,Bordeaux,44.8352922,-0.5819312999999999,2320,1430,2016-07-30 14:11:29,2016-07-30 14:23:13,0 +210229,2016-07-30 12:28:06,1249,Pitaya Sainte Catherine,275 Rue Sainte Catherine,33000,Bordeaux,44.831692,-0.573207,79629,Rue Du Loup 38,33000,Bordeaux,44.8378633,-0.5733415000000001,1450,1462,2016-07-30 12:36:17,2016-07-30 12:40:33,0 +210510,2016-07-30 14:05:02,1260,L'Epicerie Bordelaise,14 Rue Ravez,33000,Bordeaux,44.837101,-0.57272,79720,Cours De La Marne 71,33000,Bordeaux,44.8299256,-0.5684971999999999,3800,1462,2016-07-30 14:24:32,2016-07-30 14:30:46,0 +210239,2016-07-30 12:30:49,1216,Sushimi,8 Rue Courbin,33000,Bordeaux,44.841721,-0.572962,79632,Rue Sauteyron 39,33000,Bordeaux,44.83046359999999,-0.5744745,2790,1462,2016-07-30 12:44:20,2016-07-30 12:51:23,0 +210523,2016-07-30 14:12:28,1266,Sambo'S Shop,8 Rue Jean Burguet,33000,Bordeaux,44.834511,-0.578444,79728,Rue Saint-Nicolas 20,33800,Bordeaux,44.82736449999999,-0.5748215999999999,2750,1430,2016-07-30 14:26:44,2016-07-30 14:33:21,0 +210250,2016-07-30 12:33:41,1265,Chez Frango,23 Cours Portal,33000,Bordeaux,44.853027,-0.573322,79635,Cours Edouard Vaillant 35,33300,Bordeaux,44.8606007,-0.5582429999999999,1600,1405,2016-07-30 12:56:01,2016-07-30 13:03:56,0 +210256,2016-07-30 12:35:31,1260,L'Epicerie Bordelaise,14 Rue Ravez,33000,Bordeaux,44.837101,-0.57272,79637,Rue Des Sablieres 41,33800,Bordeaux,44.825741,-0.5761274,1600,1430,2016-07-30 12:43:33,2016-07-30 12:54:26,0 +210258,2016-07-30 12:36:24,1265,Chez Frango,23 Cours Portal,33000,Bordeaux,44.853027,-0.573322,79639,Rue Prunier 101,33300,Bordeaux,44.8599122,-0.5739065999999999,2100,1420,2016-07-30 12:57:07,2016-07-30 13:02:57,0 +210586,2016-07-30 15:04:30,1260,L'Epicerie Bordelaise,14 Rue Ravez,33000,Bordeaux,44.837101,-0.57272,75905,Rue De La Prevote 3,33000,Bordeaux,44.8441797,-0.5850267,1650,1902,2016-07-30 15:18:29,2016-07-30 15:27:14,0 +210270,2016-07-30 12:41:00,1207,Le Jardin Pekinois,9 Rue Des Freres Bonie,33000,Bordeaux,44.837078,-0.579572,79644,Rue Lecocq 72 Ter,33000,Bordeaux,44.8344849,-0.5854412,1730,1461,2016-07-30 13:04:02,2016-07-30 13:06:47,0 +210296,2016-07-30 12:49:27,1204,Max A Table,36 Rue Cornac,33000,Bordeaux,44.851402,-0.57587,79653,Avenue Charles De Gaulle 78,33200,Bordeaux,44.8490356,-0.601607,1250,1403,2016-07-30 13:01:17,2016-07-30 13:11:24,0 +210650,2016-07-30 16:46:33,1267,Lekkers,68 Quai Des Chartrons,33300,Bordeaux,44.853039,-0.56808,79770,Rue De Tivoli 42,33000,Bordeaux,44.8548974,-0.5906612,1910,1902,,,1 +210660,2016-07-30 17:07:41,1213,Lupo,"23 Place Pey Berland, 33000 Bordeaux",33000,Bordeaux,44.837158,-0.576632,78268,Quai Louis Xviii 5,33000,Bordeaux,44.8439813,-0.5709155,1789,1917,,,1 +210303,2016-07-30 12:51:46,1266,Sambo'S Shop,8 Rue Jean Burguet,33000,Bordeaux,44.834511,-0.578444,79656,Cite Mouneyra 6,33000,Bordeaux,44.8323473,-0.5844635,2050,1417,2016-07-30 13:10:07,2016-07-30 13:16:14,0 +210305,2016-07-30 12:51:56,1260,L'Epicerie Bordelaise,14 Rue Ravez,33000,Bordeaux,44.837101,-0.57272,79657,Rue Fonfrede 72,33800,Bordeaux,44.8255934,-0.5687881,2550,1458,2016-07-30 13:00:49,2016-07-30 13:13:32,0 +210314,2016-07-30 12:54:30,1254,Funky Burger,5 Rue Du Loup,33000,Bordeaux,44.838081,-0.572281,78930,Rue Du Loup 64,33000,Bordeaux,44.8379284,-0.5744606999999999,2060,1416,2016-07-30 13:19:15,2016-07-30 13:28:05,0 +210320,2016-07-30 12:56:08,1258,Pitaya Saint-Remi,42 Rue Saint Remi,33000,Bordeaux,44.84127,-0.572691,79661,Rue Capdeville 50,33000,Bordeaux,44.8439792,-0.5884277,2000,1416,2016-07-30 13:13:03,2016-07-30 13:33:39,0 +210738,2016-07-30 18:36:49,1225,Billy Factory,5 Place Louis Barthou,33000,Bordeaux,44.827942,-0.59441,75192,Rue Cruchinet 3 Bis,33800,Bordeaux,44.8282803,-0.5740767999999999,1450,1426,2016-07-30 18:58:05,2016-07-30 19:04:57,0 +210740,2016-07-30 18:37:20,1215,Moon Wok,17 Place Fernand Lafargue,33000,Bordeaux,44.837299,-0.572124,79812,Rue Theresia Cabarrus 53,33000,Bordeaux,44.8238595,-0.5966503,1290,1430,2016-07-30 18:50:09,2016-07-30 19:05:07,0 +210344,2016-07-30 13:01:48,1254,Funky Burger,5 Rue Du Loup,33000,Bordeaux,44.838081,-0.572281,79670,Rue De Lalande 22,33000,Bordeaux,44.8340583,-0.5749860999999999,1490,1462,2016-07-30 13:10:37,2016-07-30 13:19:38,0 +210760,2016-07-30 18:46:02,1225,Billy Factory,5 Place Louis Barthou,33000,Bordeaux,44.827942,-0.59441,79594,Rue Bernard Adour 72,33200,Bordeaux,44.8385352,-0.6030561999999999,2070,1407,2016-07-30 19:04:03,2016-07-30 19:15:06,0 +210772,2016-07-30 18:50:33,1207,Le Jardin Pekinois,9 Rue Des Freres Bonie,33000,Bordeaux,44.837078,-0.579572,79828,Rue Thiac 41,33000,Bordeaux,44.843956,-0.5843895,6020,1414,2016-07-30 19:21:59,2016-07-30 19:35:21,0 +210353,2016-07-30 13:04:13,1231,Umami Ramen,8 Place Fernand Lafargue,33000,Bordeaux,44.83691,-0.573943,77592,Cours De La Somme 218,33800,Bordeaux,44.8223315,-0.5723672,2650,1462,2016-07-30 13:15:49,2016-07-30 13:26:03,0 +210397,2016-07-30 13:21:36,1242,Fufu Saint Remi,37 Rue Saint Remi,33000,Bordeaux,44.841438,-0.572537,79680,Rue Poquelin Moliere 4,33000,Bordeaux,44.8399797,-0.5762754,1550,1405,2016-07-30 13:36:04,2016-07-30 13:40:41,0 +210831,2016-07-30 19:10:00,1205,Taj Mahal,24 Rue Du Parlement Sainte-Catherine,33000,Bordeaux,44.840405,-0.57394,79846,Rue Tiffonet 3,33800,Bordeaux,44.82997080000001,-0.5721143,3940,1902,2016-07-30 19:26:24,2016-07-30 19:42:45,0 +210400,2016-07-30 13:22:45,1223,Bag'Elles Coffee,19 Rue Du Mirail,33000,Bordeaux,44.83419,-0.571462,79681,Rue Saumenude 4,33800,Bordeaux,44.8320106,-0.5668432999999999,1300,1430,2016-07-30 13:51:13,2016-07-30 13:56:21,0 +210868,2016-07-30 19:16:40,1265,Chez Frango,23 Cours Portal,33000,Bordeaux,44.853027,-0.573322,79861,Rue Vital Mareille 7,33300,Bordeaux,44.8663259,-0.5727107,1850,1403,2016-07-30 19:28:53,2016-07-30 19:36:24,0 +210407,2016-07-30 13:25:44,1217,Henny'S Burger,22 Rue Fondaudege,33000,Bordeaux,44.845875,-0.579345,79684,Rue Castillon 48,33110,Bordeaux,44.859618,-0.593731,1750,1424,2016-07-30 13:36:21,2016-07-30 13:48:23,0 +210875,2016-07-30 19:17:48,1217,Henny'S Burger,22 Rue Fondaudege,33000,Bordeaux,44.845875,-0.579345,79865,Rue Casteja 10,33000,Bordeaux,44.8425388,-0.5821083,2210,1414,2016-07-30 19:50:09,2016-07-30 20:01:14,0 +210414,2016-07-30 13:29:24,1254,Funky Burger,5 Rue Du Loup,33000,Bordeaux,44.838081,-0.572281,79686,Rue Courbin 7,33000,Bordeaux,44.8415367,-0.5730461,1810,1461,2016-07-30 13:54:31,2016-07-30 13:57:26,0 +210890,2016-07-30 19:21:13,1250,Que Toi,39 Cours D'Alsace-Et-Lorraine,33000,Bordeaux,44.837921,-0.572655,79870,Cours De La Somme 25,33000,Bordeaux,44.8293983,-0.5725353,1650,2007,2016-07-30 19:27:33,2016-07-30 19:42:57,0 +210903,2016-07-30 19:23:56,1254,Funky Burger,5 Rue Du Loup,33000,Bordeaux,44.838081,-0.572281,79876,Cours Pasteur 25,33000,Bordeaux,44.8354524,-0.5754927,3779,1426,2016-07-30 19:34:47,2016-07-30 19:38:49,0 +210415,2016-07-30 13:29:25,1245,Eatsalad,55 Rue Saint Remi,33000,Bordeaux,44.841286,-0.573413,78940,Rue Edouard Larroque 36,33000,Bordeaux,44.8315573,-0.6022223,1540,1461,2016-07-30 14:04:21,2016-07-30 14:14:03,0 +211164,2016-07-30 20:03:28,1265,Chez Frango,23 Cours Portal,33000,Bordeaux,44.853027,-0.573322,79229,Rue De Laseppe 70,33000,Bordeaux,44.8529788,-0.5850312,5650,1407,2016-07-30 20:27:41,2016-07-30 20:36:23,0 +210926,2016-07-30 19:28:06,1244,Fufu Chartrons,71 Cours Portal,33300,Bordeaux,44.85516,-0.572128,79890,Avenue Du President Robert Schuman 100,33110,Bordeaux,44.8577966,-0.5965661999999999,2700,1403,2016-07-30 19:46:31,2016-07-30 19:54:57,0 +210933,2016-07-30 19:28:54,1212,Cote Terrasse,198 Cours De L'Argonne,33800,Bordeaux,44.824543,-0.578545,79893,Rue Babin 36,33000,Bordeaux,44.822148,-0.5970131,1950,1420,2016-07-30 19:45:56,2016-07-30 19:55:21,0 +210945,2016-07-30 19:30:39,1204,Max A Table,36 Rue Cornac,33000,Bordeaux,44.851402,-0.57587,79900,Rue Du Couvent 16,33000,Bordeaux,44.8507446,-0.5710947,1650,1416,2016-07-30 19:46:00,2016-07-30 19:49:15,0 +210953,2016-07-30 19:31:59,1254,Funky Burger,5 Rue Du Loup,33000,Bordeaux,44.838081,-0.572281,79905,Rue Hippolyte Minier 33,33800,Bordeaux,44.8235407,-0.5678198999999999,1480,1462,2016-07-30 19:45:23,2016-07-30 19:58:26,0 +210958,2016-07-30 19:32:38,1219,La Tagliatella,14 Rue Guiraude,33000,Bordeaux,44.8393877,-0.5747810999999999,79906,Cours Du Medoc 75,33300,Bordeaux,44.8595135,-0.567983,1989,1422,2016-07-30 19:50:06,2016-07-30 20:07:45,0 +210959,2016-07-30 19:32:47,1254,Funky Burger,5 Rue Du Loup,33000,Bordeaux,44.838081,-0.572281,79907,Cours De La Marne 15,33800,Bordeaux,44.830309,-0.5712351,1330,1462,2016-07-30 19:45:28,2016-07-30 19:53:40,0 +211198,2016-07-30 20:07:49,1256,Pitaya Stalingrad,36 Place De Stalingrad,33100,Bordeaux,44.840912,-0.559553,80014,Rue Laplace 14,33100,Bordeaux,44.8479178,-0.5379524,3250,2007,2016-07-30 20:24:57,2016-07-30 20:57:12,0 +210963,2016-07-30 19:33:23,1212,Cote Terrasse,198 Cours De L'Argonne,33800,Bordeaux,44.824543,-0.578545,79911,Rue Georges Bonnac 74,33000,Bordeaux,44.8397053,-0.5855431,1450,1417,2016-07-30 19:51:43,2016-07-30 20:04:26,0 +210964,2016-07-30 19:33:29,1204,Max A Table,36 Rue Cornac,33000,Bordeaux,44.851402,-0.57587,79912,Rue Judaique 96,33000,Bordeaux,44.8411608,-0.5865775999999999,2500,1416,2016-07-30 19:45:54,2016-07-30 19:56:19,0 +210982,2016-07-30 19:35:50,1221,Le Veneto,25 Allee De Tourny,33000,Bordeaux,44.84473,-0.578606,79920,Rue Gaspard Philippe 3,33000,Bordeaux,44.833956,-0.566577,2910,2013,2016-07-30 19:55:16,2016-07-30 20:15:48,0 +211218,2016-07-30 20:10:33,1212,Cote Terrasse,198 Cours De L'Argonne,33800,Bordeaux,44.824543,-0.578545,80022,Rue Giner De Los Rios 25,33800,Bordeaux,44.82787,-0.5710516,2350,1420,2016-07-30 20:29:17,2016-07-30 20:34:50,0 +210997,2016-07-30 19:39:46,1207,Le Jardin Pekinois,9 Rue Des Freres Bonie,33000,Bordeaux,44.837078,-0.579572,79929,Rue Servandoni 64,33000,Bordeaux,44.8337777,-0.5840013000000001,2130,1471,2016-07-30 19:57:04,2016-07-30 20:02:55,0 +210999,2016-07-30 19:40:01,1211,Haru Haru,93 Cours Gambetta,33400,Bordeaux,44.8181798,-0.5851184,79931,Rue Des Trois-Conils 10,33000,Bordeaux,44.8387233,-0.5749896999999999,1950,1817,2016-07-30 19:55:54,2016-07-30 20:07:35,0 +211004,2016-07-30 19:41:01,1260,L'Epicerie Bordelaise,14 Rue Ravez,33000,Bordeaux,44.837101,-0.57272,79934,Cours D'Albret 83,33000,Bordeaux,44.83473619999999,-0.5807051999999999,1350,1426,2016-07-30 19:50:30,2016-07-30 19:54:24,0 +211009,2016-07-30 19:41:49,1205,Taj Mahal,24 Rue Du Parlement Sainte-Catherine,33000,Bordeaux,44.840405,-0.57394,79936,Rue Neuve 14,33000,Bordeaux,44.83716260000001,-0.5692237,6240,1415,2016-07-30 20:00:20,2016-07-30 20:09:16,0 +211224,2016-07-30 20:11:05,1204,Max A Table,36 Rue Cornac,33000,Bordeaux,44.851402,-0.57587,80026,Rue Dupaty 127,33300,Bordeaux,44.8610947,-0.5590109,3050,1403,2016-07-30 20:24:43,2016-07-30 20:32:19,0 +211022,2016-07-30 19:44:20,1258,Pitaya Saint-Remi,42 Rue Saint Remi,33000,Bordeaux,44.84127,-0.572691,79941,Rue De La Vieille Tour 14,33000,Bordeaux,44.8411971,-0.5796273,1300,1411,2016-07-30 20:06:16,2016-07-30 20:12:02,0 +211229,2016-07-30 20:11:34,1254,Funky Burger,5 Rue Du Loup,33000,Bordeaux,44.838081,-0.572281,80029,Rue Guadet 18,33000,Bordeaux,44.8534528,-0.5787933,1590,1817,2016-07-30 20:27:23,2016-07-30 20:38:22,0 +211233,2016-07-30 20:11:55,1254,Funky Burger,5 Rue Du Loup,33000,Bordeaux,44.838081,-0.572281,80031,Place Saint-Pierre 1,33000,Bordeaux,44.8396897,-0.5706097,1350,1462,2016-07-30 20:22:40,2016-07-30 20:24:45,0 +211052,2016-07-30 19:47:44,1242,Fufu Saint Remi,37 Rue Saint Remi,33000,Bordeaux,44.841438,-0.572537,74791,Cours D'Albret 83,33000,Bordeaux,44.83473619999999,-0.5807051999999999,1050,1424,2016-07-30 19:59:28,2016-07-30 20:06:35,0 +211055,2016-07-30 19:47:53,1254,Funky Burger,5 Rue Du Loup,33000,Bordeaux,44.838081,-0.572281,79951,Rue Matignon 19,33000,Bordeaux,44.850675,-0.5852400999999999,2020,1407,2016-07-30 20:03:24,2016-07-30 20:15:49,0 +211064,2016-07-30 19:49:13,1211,Haru Haru,93 Cours Gambetta,33400,Bordeaux,44.8181798,-0.5851184,79956,Rue Jules Ferry 8,33400,Bordeaux,44.8186746,-0.5802976,1650,1420,2016-07-30 20:00:41,2016-07-30 20:04:44,0 +211075,2016-07-30 19:51:38,1260,L'Epicerie Bordelaise,14 Rue Ravez,33000,Bordeaux,44.837101,-0.57272,79964,Rue Desse 52,33000,Bordeaux,44.8284946,-0.588137,2100,1461,2016-07-30 20:03:36,2016-07-30 20:23:05,0 +211242,2016-07-30 20:12:51,1249,Pitaya Sainte Catherine,275 Rue Sainte Catherine,33000,Bordeaux,44.831692,-0.573207,80036,Cours De L'Argonne 134,33800,Bordeaux,44.8263696,-0.5767346,2300,1458,2016-07-30 20:30:03,2016-07-30 20:36:34,0 +211269,2016-07-30 20:15:40,1221,Le Veneto,25 Allee De Tourny,33000,Bordeaux,44.84473,-0.578606,80044,Cours De L'Intendance 62,33000,Bordeaux,44.8416129,-0.5791577,1330,1430,2016-07-30 20:25:24,2016-07-30 20:44:55,0 +211102,2016-07-30 19:56:43,1244,Fufu Chartrons,71 Cours Portal,33300,Bordeaux,44.85516,-0.572128,79974,Rue De Lurbe 22,33000,Bordeaux,44.8431163,-0.580502,1550,1430,2016-07-30 20:11:35,2016-07-30 20:21:24,0 +211115,2016-07-30 19:58:13,1254,Funky Burger,5 Rue Du Loup,33000,Bordeaux,44.838081,-0.572281,78989,Rue De La Rousselle 39,33000,Bordeaux,44.8370395,-0.5683842,1939,1817,2016-07-30 20:16:46,2016-07-30 20:23:14,0 +211120,2016-07-30 19:59:14,1227,Cilicie,4 Rue Des Bahutiers,33000,Bordeaux,44.839531,-0.570651,79982,Rue Calve 39,33000,Bordeaux,44.850965,-0.5904863,3450,1415,2016-07-30 20:21:14,2016-07-30 20:31:33,0 +211281,2016-07-30 20:17:36,1225,Billy Factory,5 Place Louis Barthou,33000,Bordeaux,44.827942,-0.59441,80050,Rue Saint-Remi 25,33000,Bordeaux,44.84142869999999,-0.5719069,1650,1470,2016-07-30 20:47:01,2016-07-30 21:08:53,0 +211132,2016-07-30 20:00:22,1217,Henny'S Burger,22 Rue Fondaudege,33000,Bordeaux,44.845875,-0.579345,79989,Rue Maurice 47,33300,Bordeaux,44.8587196,-0.5637679,1450,1403,2016-07-30 20:13:28,2016-07-30 20:29:10,0 +211134,2016-07-30 20:00:35,1214,Koh I Noor,3 Rue Du Puits Descujols,33000,Bordeaux,44.841011,-0.570755,79990,Rue Batailley 5,33000,Bordeaux,44.8385634,-0.5927257,3340,1998,2016-07-30 20:14:34,2016-07-30 20:32:27,0 +211138,2016-07-30 20:00:57,1249,Pitaya Sainte Catherine,275 Rue Sainte Catherine,33000,Bordeaux,44.831692,-0.573207,79992,Rue De Pessac 18-20,33000,Bordeaux,44.8306244,-0.5791144000000001,3550,1461,2016-07-30 20:11:46,2016-07-30 20:28:05,0 +211139,2016-07-30 20:01:02,1249,Pitaya Sainte Catherine,275 Rue Sainte Catherine,33000,Bordeaux,44.831692,-0.573207,79993,Rue Du Mirail 19,33000,Bordeaux,44.8341514,-0.5713275999999999,1400,2013,2016-07-30 20:24:15,2016-07-30 20:29:31,0 +211147,2016-07-30 20:02:02,1207,Le Jardin Pekinois,9 Rue Des Freres Bonie,33000,Bordeaux,44.837078,-0.579572,79996,Rue Henri Iv 68,33000,Bordeaux,44.83197639999999,-0.5750737,1340,1458,2016-07-30 20:21:22,2016-07-30 20:26:32,0 +211152,2016-07-30 20:02:22,1256,Pitaya Stalingrad,36 Place De Stalingrad,33100,Bordeaux,44.840912,-0.559553,79998,Hlm Midi 3,33270,Bordeaux,44.8377811,-0.5398575999999999,3250,2007,2016-07-30 20:25:10,2016-07-30 20:38:25,0 +211283,2016-07-30 20:17:44,1227,Cilicie,4 Rue Des Bahutiers,33000,Bordeaux,44.839531,-0.570651,80051,Place De La Victoire 16,33000,Bordeaux,44.8304515,-0.5731404,1450,1462,2016-07-30 20:30:59,2016-07-30 20:46:10,0 +211153,2016-07-30 20:02:38,1267,Lekkers,68 Quai Des Chartrons,33300,Bordeaux,44.853039,-0.56808,78788,Rue Porte De La Monnaie 29,33800,Bordeaux,44.8321496,-0.5631799,2190,1422,,,1 +211288,2016-07-30 20:18:11,1207,Le Jardin Pekinois,9 Rue Des Freres Bonie,33000,Bordeaux,44.837078,-0.579572,80053,Rue Barrau 5,33000,Bordeaux,44.8260581,-0.5782250999999999,2490,1409,2016-07-30 20:40:14,2016-07-30 20:47:55,0 +211301,2016-07-30 20:20:53,1263,Noorn Akorn,8 Cours D'Albret,33000,Bordeaux,44.838734,-0.581611,80061,Cours D'Alsace-Et-Lorraine 7,33000,Bordeaux,44.8380932,-0.5680670999999999,3750,1411,2016-07-30 20:35:45,2016-07-30 20:49:45,0 +211304,2016-07-30 20:21:06,1220,Jardin Phnom Penh,1 Rue Du Cerf Volant,33000,Bordeaux,44.838287,-0.570993,80062,Rue Minvielle 24,33000,Bordeaux,44.8533359,-0.5722665000000001,3000,2013,2016-07-30 20:46:30,2016-07-30 20:59:14,0 +211553,2016-07-30 20:50:28,1207,Le Jardin Pekinois,9 Rue Des Freres Bonie,33000,Bordeaux,44.837078,-0.579572,80184,Rue Honore Picon 18,33100,Bordeaux,44.8415421,-0.5598141999999999,5180,1417,2016-07-30 21:33:02,2016-07-30 21:44:09,0 +211554,2016-07-30 20:50:34,1214,Koh I Noor,3 Rue Du Puits Descujols,33000,Bordeaux,44.841011,-0.570755,80185,Passage Hermitte 76,33000,Bordeaux,44.8323778,-0.5979375,2540,1470,2016-07-30 21:14:19,2016-07-30 21:29:16,0 +211555,2016-07-30 20:50:37,1207,Le Jardin Pekinois,9 Rue Des Freres Bonie,33000,Bordeaux,44.837078,-0.579572,80186,Rue De La Ville De Mirmont 10,33000,Bordeaux,44.84692930000001,-0.5795985,3429,1409,2016-07-30 21:17:18,2016-07-30 21:33:37,0 +211306,2016-07-30 20:21:10,1212,Cote Terrasse,198 Cours De L'Argonne,33800,Bordeaux,44.824543,-0.578545,80063,Cours De L'Argonne 14,33000,Bordeaux,44.8298523,-0.5729818,1250,1458,2016-07-30 20:45:27,2016-07-30 20:50:41,0 +211309,2016-07-30 20:21:31,1207,Le Jardin Pekinois,9 Rue Des Freres Bonie,33000,Bordeaux,44.837078,-0.579572,80065,Rue Turenne 60,33000,Bordeaux,44.8456362,-0.5839462999999999,2190,1424,2016-07-30 20:44:49,2016-07-30 20:50:16,0 +211311,2016-07-30 20:21:41,1239,Tam Tam Saigon,7 Rue Paulin,33000,Bordeaux,44.846516,-0.588076,80066,Rue De Riviere 14 Bis,33000,Bordeaux,44.8545895,-0.5888850999999999,1450,1415,2016-07-30 20:37:39,2016-07-30 20:47:48,0 +211590,2016-07-30 20:54:42,1204,Max A Table,36 Rue Cornac,33000,Bordeaux,44.851402,-0.57587,80204,Rue Du Jardin Public 183,33300,Bordeaux,44.8566262,-0.5733922,1550,1415,2016-07-30 21:12:01,2016-07-30 21:16:21,0 +211593,2016-07-30 20:55:11,1239,Tam Tam Saigon,7 Rue Paulin,33000,Bordeaux,44.846516,-0.588076,80206,Rue Pierre 48,33000,Bordeaux,44.83888109999999,-0.5931356999999999,3640,1424,2016-07-30 21:22:09,2016-07-30 21:27:48,0 +211315,2016-07-30 20:21:58,1231,Umami Ramen,8 Place Fernand Lafargue,33000,Bordeaux,44.83691,-0.573943,80068,Rue Toulouse Lautrec 12,33000,Bordeaux,44.8401153,-0.5807992,2850,1471,2016-07-30 20:36:25,2016-07-30 20:47:29,0 +211596,2016-07-30 20:55:46,1254,Funky Burger,5 Rue Du Loup,33000,Bordeaux,44.838081,-0.572281,80207,Cours De La Marne 71,33800,Bordeaux,44.8297535,-0.5685724,2260,1414,2016-07-30 21:17:59,2016-07-30 21:25:04,0 +211604,2016-07-30 20:57:10,1254,Funky Burger,5 Rue Du Loup,33000,Bordeaux,44.838081,-0.572281,80213,Rue Sauteyron 42,33000,Bordeaux,44.8309061,-0.5743011,2540,1462,2016-07-30 21:19:03,2016-07-30 21:24:21,0 +211320,2016-07-30 20:22:52,1214,Koh I Noor,3 Rue Du Puits Descujols,33000,Bordeaux,44.841011,-0.570755,80072,Rue Du Tondu 95,33000,Bordeaux,44.8306107,-0.584649,4150,1416,2016-07-30 20:40:37,2016-07-30 20:53:09,0 +211620,2016-07-30 20:59:12,1207,Le Jardin Pekinois,9 Rue Des Freres Bonie,33000,Bordeaux,44.837078,-0.579572,80220,Rue Lefol 17,33800,Bordeaux,44.822116,-0.5640639,2830,1416,2016-07-30 21:37:15,2016-07-30 21:47:33,0 +211335,2016-07-30 20:24:11,1246,Thai Paradise,70 Rue Des Ayres,33000,Bordeaux,44.836327,-0.575572,80079,Avenue Jeanne D'Arc 20,33000,Bordeaux,44.8267427,-0.593746,1950,1998,,,1 +211626,2016-07-30 20:59:59,1217,Henny'S Burger,22 Rue Fondaudege,33000,Bordeaux,44.845875,-0.579345,80224,Rue Cadroin 52,33000,Bordeaux,44.8280881,-0.5768124,3520,1430,2016-07-30 21:34:45,2016-07-30 21:47:07,0 +211638,2016-07-30 21:01:57,1245,Eatsalad,55 Rue Saint Remi,33000,Bordeaux,44.841286,-0.573413,80228,Cours De L'Argonne 63,33000,Bordeaux,44.8286506,-0.5746177,2130,1416,2016-07-30 21:11:05,2016-07-30 21:45:42,0 +211657,2016-07-30 21:04:25,1254,Funky Burger,5 Rue Du Loup,33000,Bordeaux,44.838081,-0.572281,79528,Rue Edmond Costedoat 29,33000,Bordeaux,44.8310742,-0.5784439,2720,2013,2016-07-30 21:33:26,2016-07-30 21:42:03,0 +211359,2016-07-30 20:27:07,1221,Le Veneto,25 Allee De Tourny,33000,Bordeaux,44.84473,-0.578606,79219,Rue Du Pont De La Mousque 24,33000,Bordeaux,44.8418427,-0.5727019999999999,4590,1817,2016-07-30 20:48:18,2016-07-30 20:55:12,0 +211673,2016-07-30 21:05:57,1266,Sambo'S Shop,8 Rue Jean Burguet,33000,Bordeaux,44.834511,-0.578444,80242,Rue Lafontaine 35,33800,Bordeaux,44.8268384,-0.5708527,3690,1471,2016-07-30 21:27:01,2016-07-30 21:33:00,0 +211687,2016-07-30 21:07:51,1254,Funky Burger,5 Rue Du Loup,33000,Bordeaux,44.838081,-0.572281,80247,Cours De L'Yser 205,33800,Bordeaux,44.8220466,-0.5715914999999999,1480,1420,2016-07-30 21:34:54,2016-07-30 21:44:07,0 +211363,2016-07-30 20:27:45,1204,Max A Table,36 Rue Cornac,33000,Bordeaux,44.851402,-0.57587,80095,Rue De La Porte Saint-Jean 8,33000,Bordeaux,44.837728,-0.5682188,2400,1817,2016-07-30 20:42:51,2016-07-30 21:01:17,0 +211694,2016-07-30 21:09:38,1244,Fufu Chartrons,71 Cours Portal,33300,Bordeaux,44.85516,-0.572128,80251,Rue Delord 68,33300,Bordeaux,44.8605192,-0.5597696999999999,1850,1415,2016-07-30 21:22:25,2016-07-30 21:26:54,0 +211380,2016-07-30 20:30:03,1254,Funky Burger,5 Rue Du Loup,33000,Bordeaux,44.838081,-0.572281,80104,Rue Du Docteur Albert Barraud 143,33000,Bordeaux,44.8484576,-0.5831115,1490,1461,2016-07-30 20:50:57,2016-07-30 20:58:50,0 +211386,2016-07-30 20:30:34,1227,Cilicie,4 Rue Des Bahutiers,33000,Bordeaux,44.839531,-0.570651,80108,Place Charles Gruet 22,33000,Bordeaux,44.8466782,-0.5809398,4250,1422,2016-07-30 20:43:46,2016-07-30 20:59:31,0 +211753,2016-07-30 21:20:02,1254,Funky Burger,5 Rue Du Loup,33000,Bordeaux,44.838081,-0.572281,80273,Rue Du Chai Des Farines 22,33000,Bordeaux,44.8391999,-0.5689409,3240,1458,2016-07-30 21:41:43,2016-07-30 21:45:44,0 +211388,2016-07-30 20:30:59,1207,Le Jardin Pekinois,9 Rue Des Freres Bonie,33000,Bordeaux,44.837078,-0.579572,80109,Allee D'Orleans 28,33000,Bordeaux,44.8436986,-0.5727521,2130,1414,2016-07-30 20:49:12,2016-07-30 20:58:19,0 +211759,2016-07-30 21:20:32,1254,Funky Burger,5 Rue Du Loup,33000,Bordeaux,44.838081,-0.572281,80277,Cours De La Somme 127,33800,Bordeaux,44.8257462,-0.5732807,2980,1817,2016-07-30 21:46:13,2016-07-30 21:56:24,0 +211767,2016-07-30 21:21:58,1207,Le Jardin Pekinois,9 Rue Des Freres Bonie,33000,Bordeaux,44.837078,-0.579572,80280,Rue De Lescure 26,33000,Bordeaux,44.8328755,-0.6005678,1739,1410,2016-07-30 21:46:04,2016-07-30 22:04:43,0 +211397,2016-07-30 20:31:55,1254,Funky Burger,5 Rue Du Loup,33000,Bordeaux,44.838081,-0.572281,80111,Rue Des Trois-Conils 4,33000,Bordeaux,44.8388325,-0.5746124,1420,1417,2016-07-30 20:46:18,2016-07-30 20:51:03,0 +211770,2016-07-30 21:22:34,1219,La Tagliatella,14 Rue Guiraude,33000,Bordeaux,44.8393877,-0.5747810999999999,74631,Rue Saint-Jean 85,33800,Bordeaux,44.8248735,-0.5683764,1800,1998,2016-07-30 21:41:41,2016-07-30 21:54:29,0 +211786,2016-07-30 21:24:08,1258,Pitaya Saint-Remi,42 Rue Saint Remi,33000,Bordeaux,44.84127,-0.572691,80288,Rue De Lyon 65,33000,Bordeaux,44.8479107,-0.5920831,2300,1462,2016-07-30 21:33:42,2016-07-30 21:41:45,0 +211405,2016-07-30 20:32:53,1215,Moon Wok,17 Place Fernand Lafargue,33000,Bordeaux,44.837299,-0.572124,80114,Rue Jean Dollfus 2,33100,Bordeaux,44.8458207,-0.5572484,2580,1410,2016-07-30 20:50:34,2016-07-30 20:58:30,0 +211791,2016-07-30 21:25:33,1223,Bag'Elles Coffee,19 Rue Du Mirail,33000,Bordeaux,44.83419,-0.571462,80292,Rue Pauline Kergomard 3,33800,Bordeaux,44.82313449999999,-0.5768487000000001,1440,1817,2016-07-30 21:51:11,2016-07-30 22:00:44,0 +211802,2016-07-30 21:26:59,1250,Que Toi,39 Cours D'Alsace-Et-Lorraine,33000,Bordeaux,44.837921,-0.572655,80299,Rue De Lalande 54,33000,Bordeaux,44.8328105,-0.5750839999999999,3100,1416,2016-07-30 22:01:34,2016-07-30 22:08:09,0 +211408,2016-07-30 20:33:26,1258,Pitaya Saint-Remi,42 Rue Saint Remi,33000,Bordeaux,44.84127,-0.572691,80116,Rue Binaud 42,33300,Bordeaux,44.8584843,-0.5703737999999999,1450,2013,2016-07-30 20:50:32,2016-07-30 21:04:59,0 +211811,2016-07-30 21:29:15,1254,Funky Burger,5 Rue Du Loup,33000,Bordeaux,44.838081,-0.572281,80303,Passage Birly 28,33800,Bordeaux,44.8210383,-0.5745384,2860,1471,2016-07-30 21:56:38,2016-07-30 22:07:10,0 +211817,2016-07-30 21:30:19,1260,L'Epicerie Bordelaise,14 Rue Ravez,33000,Bordeaux,44.837101,-0.57272,80307,Rue Jean Soula 24,33000,Bordeaux,44.8417678,-0.5902303,4900,2013,2016-07-30 21:50:53,2016-07-30 22:12:54,0 +211822,2016-07-30 21:31:27,1265,Chez Frango,23 Cours Portal,33000,Bordeaux,44.853027,-0.573322,80311,Rue Du Professeur Demons 4,33000,Bordeaux,44.846326,-0.5792183,4050,1415,2016-07-30 21:49:19,2016-07-30 21:53:32,0 +211824,2016-07-30 21:31:42,1258,Pitaya Saint-Remi,42 Rue Saint Remi,33000,Bordeaux,44.84127,-0.572691,80312,Rue Thiac 24,33000,Bordeaux,44.8436228,-0.5830795,1450,1424,2016-07-30 21:40:35,2016-07-30 21:45:45,0 +211410,2016-07-30 20:33:36,1221,Le Veneto,25 Allee De Tourny,33000,Bordeaux,44.84473,-0.578606,80118,Rue Du Palais Gallien 157,33000,Bordeaux,44.8470835,-0.5819766,2110,1424,2016-07-30 20:54:16,2016-07-30 20:58:39,0 +211834,2016-07-30 21:33:48,1212,Cote Terrasse,198 Cours De L'Argonne,33800,Bordeaux,44.824543,-0.578545,78506,Cours D'Albret 100,33000,Bordeaux,44.8327483,-0.5794673,2950,1470,2016-07-30 21:53:21,2016-07-30 22:05:03,0 +211838,2016-07-30 21:34:15,1207,Le Jardin Pekinois,9 Rue Des Freres Bonie,33000,Bordeaux,44.837078,-0.579572,80307,Rue Jean Soula 24,33000,Bordeaux,44.8417678,-0.5902303,2200,2013,2016-07-30 22:05:25,2016-07-30 22:11:41,0 +211845,2016-07-30 21:35:38,1260,L'Epicerie Bordelaise,14 Rue Ravez,33000,Bordeaux,44.837101,-0.57272,80322,Place Paul Et Jean Paul Avisseau 12,33300,Bordeaux,44.8553722,-0.5670307,5050,1424,2016-07-30 22:03:22,2016-07-30 22:13:35,0 +211414,2016-07-30 20:34:02,1234,Mille Et Une Saveurs,"96 Avenue Thiers, 33100 Bordeaux",33100,Bordeaux,44.843746,-0.554713,80119,Rue Gay Lussac 20,33100,Bordeaux,44.8479962,-0.5389155999999999,2320,1407,2016-07-30 20:54:50,2016-07-30 21:06:37,0 +211415,2016-07-30 20:34:16,1249,Pitaya Sainte Catherine,275 Rue Sainte Catherine,33000,Bordeaux,44.831692,-0.573207,80120,Rue Saint-Nicolas 28,33800,Bordeaux,44.8274105,-0.5744838,3350,1462,2016-07-30 20:45:57,2016-07-30 20:53:25,0 +211873,2016-07-30 21:42:41,1234,Mille Et Une Saveurs,"96 Avenue Thiers, 33100 Bordeaux",33100,Bordeaux,44.843746,-0.554713,80336,Rue Saint-James 16,33000,Bordeaux,44.8363773,-0.5713289000000001,1700,1458,2016-07-30 22:30:53,2016-07-30 22:36:00,0 +211428,2016-07-30 20:35:51,1223,Bag'Elles Coffee,19 Rue Du Mirail,33000,Bordeaux,44.83419,-0.571462,80131,Rue Moulinie 34,33000,Bordeaux,44.8325767,-0.5743935,1830,1458,2016-07-30 20:55:55,2016-07-30 20:59:15,0 +211884,2016-07-30 21:45:16,1215,Moon Wok,17 Place Fernand Lafargue,33000,Bordeaux,44.837299,-0.572124,80341,Avenue Emile Counord 66,33300,Bordeaux,44.8583131,-0.5747824,1510,1422,2016-07-30 22:19:06,2016-07-30 22:32:43,0 +211886,2016-07-30 21:45:22,1254,Funky Burger,5 Rue Du Loup,33000,Bordeaux,44.838081,-0.572281,80342,Rue De Lurbe 42,33000,Bordeaux,44.84320169999999,-0.5813754,1260,1462,2016-07-30 22:09:17,2016-07-30 22:15:13,0 +211887,2016-07-30 21:45:36,1258,Pitaya Saint-Remi,42 Rue Saint Remi,33000,Bordeaux,44.84127,-0.572691,80343,Place De La Bourse 1,33000,Bordeaux,44.8410114,-0.5698930999999999,1450,1415,2016-07-30 22:01:24,2016-07-30 22:20:26,0 +211448,2016-07-30 20:37:32,1249,Pitaya Sainte Catherine,275 Rue Sainte Catherine,33000,Bordeaux,44.831692,-0.573207,80138,Rue De La Rousselle 39,33000,Bordeaux,44.8370395,-0.5683842,1300,1458,2016-07-30 20:52:59,2016-07-30 21:08:09,0 +211919,2016-07-30 21:52:34,1254,Funky Burger,5 Rue Du Loup,33000,Bordeaux,44.838081,-0.572281,80357,Cours De L'Yser 59,33800,Bordeaux,44.82763749999999,-0.5692632,4530,1415,2016-07-30 22:24:57,2016-07-30 22:31:10,0 +211458,2016-07-30 20:38:38,1236,Marhaba,27 Rue Des Faures,33800,Bordeaux,44.834766,-0.565754,80142,Rue Du Loup 80,33000,Bordeaux,44.8375925,-0.5751784999999999,3050,1420,2016-07-30 21:08:35,2016-07-30 21:13:31,0 +211937,2016-07-30 21:56:30,1249,Pitaya Sainte Catherine,275 Rue Sainte Catherine,33000,Bordeaux,44.831692,-0.573207,80364,Rue De Begles 207,33800,Bordeaux,44.8204686,-0.5658826,1550,1998,2016-07-30 22:09:49,2016-07-30 22:20:30,0 +211959,2016-07-30 22:07:41,1254,Funky Burger,5 Rue Du Loup,33000,Bordeaux,44.838081,-0.572281,80374,Rue Cornac 4,33000,Bordeaux,44.8509545,-0.5721066,1730,1409,2016-07-30 22:24:02,2016-07-30 22:42:09,0 +211961,2016-07-30 22:08:35,1254,Funky Burger,5 Rue Du Loup,33000,Bordeaux,44.838081,-0.572281,80376,Rue Mauriac 4,33000,Bordeaux,44.8356333,-0.5673574,2110,1817,2016-07-30 22:25:56,2016-07-30 22:34:44,0 +211470,2016-07-30 20:40:06,1249,Pitaya Sainte Catherine,275 Rue Sainte Catherine,33000,Bordeaux,44.831692,-0.573207,80150,Rue Bertrand De Goth 77,33800,Bordeaux,44.8206584,-0.5781041,1450,1403,2016-07-30 21:04:27,2016-07-30 21:11:31,0 +211483,2016-07-30 20:41:19,1254,Funky Burger,5 Rue Du Loup,33000,Bordeaux,44.838081,-0.572281,80154,Cours Georges Clemenceau 19,33000,Bordeaux,44.8426144,-0.5797966,4370,1417,2016-07-30 20:58:38,2016-07-30 21:05:40,0 +211990,2016-07-30 22:15:41,1231,Umami Ramen,8 Place Fernand Lafargue,33000,Bordeaux,44.83691,-0.573943,79140,Cours Journu Auber 18B,33300,Bordeaux,44.8583873,-0.5683251,2150,1471,2016-07-30 22:27:42,2016-07-30 22:39:56,0 +212001,2016-07-30 22:21:42,1205,Taj Mahal,24 Rue Du Parlement Sainte-Catherine,33000,Bordeaux,44.840405,-0.57394,80396,Cours De L'Argonne 38,33000,Bordeaux,44.829183,-0.5735610999999999,2050,1416,2016-07-30 22:42:26,2016-07-30 22:56:09,0 +212010,2016-07-30 22:25:20,1205,Taj Mahal,24 Rue Du Parlement Sainte-Catherine,33000,Bordeaux,44.840405,-0.57394,80400,Boulevard President Franklin Roosevelt 15,33400,Bordeaux,44.82059090000001,-0.5820482,2000,1410,2016-07-30 22:43:33,2016-07-30 23:02:32,0 +212012,2016-07-30 22:25:58,1254,Funky Burger,5 Rue Du Loup,33000,Bordeaux,44.838081,-0.572281,80401,Rue Neuve 39,33000,Bordeaux,44.8362618,-0.5694502,1450,1415,2016-07-30 22:40:48,2016-07-30 22:46:24,0 +211488,2016-07-30 20:42:34,1254,Funky Burger,5 Rue Du Loup,33000,Bordeaux,44.838081,-0.572281,80158,Rue Cazemajor 13,33800,Bordeaux,44.825148,-0.5676435,1450,1998,2016-07-30 21:04:11,2016-07-30 21:14:31,0 +212021,2016-07-30 22:29:52,1249,Pitaya Sainte Catherine,275 Rue Sainte Catherine,33000,Bordeaux,44.831692,-0.573207,80400,Boulevard President Franklin Roosevelt 15,33400,Bordeaux,44.82059090000001,-0.5820482,2250,1410,2016-07-30 22:50:16,2016-07-30 23:02:54,0 +211501,2016-07-30 20:44:50,1204,Max A Table,36 Rue Cornac,33000,Bordeaux,44.851402,-0.57587,80163,Rue Marsan 22,33300,Bordeaux,44.8561327,-0.576172,1250,1415,2016-07-30 21:02:32,2016-07-30 21:06:19,0 +211508,2016-07-30 20:45:55,1254,Funky Burger,5 Rue Du Loup,33000,Bordeaux,44.838081,-0.572281,80168,Rue Des Sablieres 42,33800,Bordeaux,44.825488,-0.5752645,1680,1461,2016-07-30 21:13:31,2016-07-30 21:19:45,0 +211510,2016-07-30 20:46:05,1219,La Tagliatella,14 Rue Guiraude,33000,Bordeaux,44.8393877,-0.5747810999999999,80169,Rue Pasteur 35,33200,Bordeaux,44.8450528,-0.6011569999999999,4085,1411,2016-07-30 21:11:00,2016-07-30 21:23:24,0 +211519,2016-07-30 20:46:55,1254,Funky Burger,5 Rue Du Loup,33000,Bordeaux,44.838081,-0.572281,80172,Rue Monadey 28,33800,Bordeaux,44.8288161,-0.5707895,2050,1817,2016-07-30 21:05:46,2016-07-30 21:14:07,0 diff --git a/02_a_first_example.ipynb b/03_classification/00_content.ipynb similarity index 99% rename from 02_a_first_example.ipynb rename to 03_classification/00_content.ipynb index 5339d00..90d4f54 100644 --- a/02_a_first_example.ipynb +++ b/03_classification/00_content.ipynb @@ -1150,7 +1150,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -1164,7 +1164,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.8.9" + "version": "3.8.12" }, "toc": { "base_numbering": 1, diff --git a/static/3_types_of_machine_learning.png b/03_classification/static/3_types_of_machine_learning.png similarity index 100% rename from static/3_types_of_machine_learning.png rename to 03_classification/static/3_types_of_machine_learning.png diff --git a/static/classification_vs_regression.png b/03_classification/static/classification_vs_regression.png similarity index 100% rename from static/classification_vs_regression.png rename to 03_classification/static/classification_vs_regression.png diff --git a/static/examples.png b/03_classification/static/examples.png similarity index 100% rename from static/examples.png rename to 03_classification/static/examples.png diff --git a/static/generalization.png b/03_classification/static/generalization.png similarity index 100% rename from static/generalization.png rename to 03_classification/static/generalization.png diff --git a/static/iris.png b/03_classification/static/iris.png similarity index 100% rename from static/iris.png rename to 03_classification/static/iris.png diff --git a/static/iris_data.png b/03_classification/static/iris_data.png similarity index 100% rename from static/iris_data.png rename to 03_classification/static/iris_data.png diff --git a/static/knn.png b/03_classification/static/knn.png similarity index 100% rename from static/knn.png rename to 03_classification/static/knn.png diff --git a/static/python_ml_book.png b/03_classification/static/python_ml_book.png similarity index 100% rename from static/python_ml_book.png rename to 03_classification/static/python_ml_book.png diff --git a/static/r_ml_book.png b/03_classification/static/r_ml_book.png similarity index 100% rename from static/r_ml_book.png rename to 03_classification/static/r_ml_book.png diff --git a/static/spam.png b/03_classification/static/spam.png similarity index 100% rename from static/spam.png rename to 03_classification/static/spam.png diff --git a/static/what_is_machine_learning.png b/03_classification/static/what_is_machine_learning.png similarity index 100% rename from static/what_is_machine_learning.png rename to 03_classification/static/what_is_machine_learning.png diff --git a/README.md b/README.md index fdd6a87..d8ff599 100644 --- a/README.md +++ b/README.md @@ -9,10 +9,19 @@ To learn about Python and programming in detail, ### Table of Contents -- *Chapter 0*: [Python in a Nutshell](00_python_in_a_nutshell.ipynb) -- *Chapter 1*: [Python's Scientific Stack](01_scientific_stack.ipynb) -- *Chapter 2*: [A first Example: Classifying Flowers](02_a_first_example.ipynb) -- *Chapter 3*: [Case Study: House Prices in Ames, Iowa ](https://github.com/webartifex/ames-housing) +- *Chapter 0*: **Python in a Nutshell** + - *Content*: [Basic Arithmetic](00_python_in_a_nutshell/00_content_arithmetic.ipynb) + - *Exercises*: [Python as a Calculator](00_python_in_a_nutshell/01_exercises_calculator.ipynb) + - *Content*: [Business Logic](00_python_in_a_nutshell/02_content_logic.ipynb) + - *Exercises*: [Simple Loops](00_python_in_a_nutshell/03_exercises_loops.ipynb) + - *Exercises*: [Fizz Buzz](00_python_in_a_nutshell/04_exercises_fizz_buzz.ipynb) + - *Content*: [Functions](00_python_in_a_nutshell/05_content_functions.ipynb) + - *Exercises*: [Volume of a Sphere](00_python_in_a_nutshell/06_exercises_volume.ipynb) + - *Content*: [Data Types](00_python_in_a_nutshell/07_content_data_types.ipynb) +- *Chapter 1*: [Python's Scientific Stack](01_scientific_stack/00_content.ipynb) +- *Chapter 2*: **Time Series Analyis** +- *Chapter 3*: [A first Example: Classifying Flowers](02_classification/00_content.ipynb) +- *Chapter 4*: [Case Study: House Prices in Ames, Iowa ](https://github.com/webartifex/ames-housing) ### Objective diff --git a/poetry.lock b/poetry.lock index 5d0e1e9..9b3cceb 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,6 +1,6 @@ [[package]] name = "anyio" -version = "3.1.0" +version = "3.3.2" description = "High level compatibility layer for multiple asynchronous event loop implementations" category = "main" optional = false @@ -25,29 +25,20 @@ python-versions = "*" [[package]] name = "argon2-cffi" -version = "20.1.0" +version = "21.1.0" description = "The secure Argon2 password hashing algorithm." category = "main" optional = false -python-versions = "*" +python-versions = ">=3.5" [package.dependencies] cffi = ">=1.0.0" -six = "*" [package.extras] -dev = ["coverage[toml] (>=5.0.2)", "hypothesis", "pytest", "sphinx", "wheel", "pre-commit"] -docs = ["sphinx"] +dev = ["coverage[toml] (>=5.0.2)", "hypothesis", "pytest", "sphinx", "furo", "wheel", "pre-commit"] +docs = ["sphinx", "furo"] tests = ["coverage[toml] (>=5.0.2)", "hypothesis", "pytest"] -[[package]] -name = "async-generator" -version = "1.10" -description = "Async generators and context managers for Python 3.5+" -category = "main" -optional = false -python-versions = ">=3.5" - [[package]] name = "attrs" version = "21.2.0" @@ -83,20 +74,28 @@ python-versions = "*" [[package]] name = "bleach" -version = "3.3.0" +version = "4.1.0" description = "An easy safelist-based HTML-sanitizing tool." category = "main" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +python-versions = ">=3.6" [package.dependencies] packaging = "*" six = ">=1.9.0" webencodings = "*" +[[package]] +name = "certifi" +version = "2021.5.30" +description = "Python package for providing Mozilla's CA Bundle." +category = "main" +optional = false +python-versions = "*" + [[package]] name = "cffi" -version = "1.14.5" +version = "1.14.6" description = "Foreign Function Interface for Python calling C code." category = "main" optional = false @@ -105,6 +104,17 @@ python-versions = "*" [package.dependencies] pycparser = "*" +[[package]] +name = "charset-normalizer" +version = "2.0.6" +description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." +category = "main" +optional = false +python-versions = ">=3.5.0" + +[package.extras] +unicode_backport = ["unicodedata2"] + [[package]] name = "colorama" version = "0.4.4" @@ -124,9 +134,17 @@ python-versions = "*" [package.dependencies] six = "*" +[[package]] +name = "debugpy" +version = "1.4.3" +description = "An implementation of the Debug Adapter Protocol for Python" +category = "main" +optional = false +python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*" + [[package]] name = "decorator" -version = "5.0.9" +version = "5.1.0" description = "Decorators for Humans" category = "main" optional = false @@ -150,33 +168,36 @@ python-versions = ">=2.7" [[package]] name = "idna" -version = "3.1" +version = "3.2" description = "Internationalized Domain Names in Applications (IDNA)" category = "main" optional = false -python-versions = ">=3.4" - -[[package]] -name = "ipykernel" -version = "5.5.5" -description = "IPython Kernel for Jupyter" -category = "main" -optional = false python-versions = ">=3.5" +[[package]] +name = "ipykernel" +version = "6.4.1" +description = "IPython Kernel for Jupyter" +category = "main" +optional = false +python-versions = ">=3.7" + [package.dependencies] appnope = {version = "*", markers = "platform_system == \"Darwin\""} -ipython = ">=5.0.0" -jupyter-client = "*" -tornado = ">=4.2" -traitlets = ">=4.1.0" +debugpy = ">=1.0.0,<2.0" +ipython = ">=7.23.1,<8.0" +ipython-genutils = "*" +jupyter-client = "<8.0" +matplotlib-inline = ">=0.1.0,<0.2.0" +tornado = ">=4.2,<7.0" +traitlets = ">=4.1.0,<6.0" [package.extras] -test = ["pytest (!=5.3.4)", "pytest-cov", "flaky", "nose", "jedi (<=0.17.2)"] +test = ["pytest (!=5.3.4)", "pytest-cov", "flaky", "nose", "ipyparallel"] [[package]] name = "ipython" -version = "7.23.1" +version = "7.28.0" description = "IPython: Productive Interactive Computing" category = "main" optional = false @@ -196,7 +217,7 @@ pygments = "*" traitlets = ">=4.2" [package.extras] -all = ["Sphinx (>=1.3)", "ipykernel", "ipyparallel", "ipywidgets", "nbconvert", "nbformat", "nose (>=0.10.1)", "notebook", "numpy (>=1.16)", "pygments", "qtconsole", "requests", "testpath"] +all = ["Sphinx (>=1.3)", "ipykernel", "ipyparallel", "ipywidgets", "nbconvert", "nbformat", "nose (>=0.10.1)", "notebook", "numpy (>=1.17)", "pygments", "qtconsole", "requests", "testpath"] doc = ["Sphinx (>=1.3)"] kernel = ["ipykernel"] nbconvert = ["nbconvert"] @@ -204,7 +225,7 @@ nbformat = ["nbformat"] notebook = ["notebook", "ipywidgets"] parallel = ["ipyparallel"] qtconsole = ["qtconsole"] -test = ["nose (>=0.10.1)", "requests", "testpath", "pygments", "nbformat", "ipykernel", "numpy (>=1.16)"] +test = ["nose (>=0.10.1)", "requests", "testpath", "pygments", "nbformat", "ipykernel", "numpy (>=1.17)"] [[package]] name = "ipython-genutils" @@ -253,7 +274,7 @@ python-versions = ">=3.6" [[package]] name = "json5" -version = "0.9.5" +version = "0.9.6" description = "A Python implementation of the JSON5 data format." category = "main" optional = false @@ -264,30 +285,30 @@ dev = ["hypothesis"] [[package]] name = "jsonschema" -version = "3.2.0" +version = "4.0.1" description = "An implementation of JSON Schema validation for Python" category = "main" optional = false -python-versions = "*" +python-versions = ">=3.7" [package.dependencies] attrs = ">=17.4.0" -pyrsistent = ">=0.14.0" -six = ">=1.11.0" +pyrsistent = ">=0.14.0,<0.17.0 || >0.17.0,<0.17.1 || >0.17.1,<0.17.2 || >0.17.2" [package.extras] -format = ["idna", "jsonpointer (>1.13)", "rfc3987", "strict-rfc3339", "webcolors"] -format_nongpl = ["idna", "jsonpointer (>1.13)", "webcolors", "rfc3986-validator (>0.1.0)", "rfc3339-validator"] +format = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3987", "uri-template", "webcolors (>=1.11)"] +format_nongpl = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3986-validator (>0.1.0)", "uri-template", "webcolors (>=1.11)"] [[package]] name = "jupyter-client" -version = "6.2.0" +version = "7.0.5" description = "Jupyter protocol implementation and client libraries" category = "main" optional = false python-versions = ">=3.6.1" [package.dependencies] +entrypoints = "*" jupyter-core = ">=4.6.0" nest-asyncio = ">=1.5" python-dateutil = ">=2.1" @@ -296,24 +317,24 @@ tornado = ">=4.1" traitlets = "*" [package.extras] -doc = ["sphinx (>=1.3.6)", "sphinx-rtd-theme", "sphinxcontrib-github-alt"] -test = ["async-generator", "ipykernel", "ipython", "mock", "pytest-asyncio", "pytest-timeout", "pytest", "mypy", "pre-commit", "jedi (<0.18)"] +doc = ["myst-parser", "sphinx (>=1.3.6)", "sphinx-rtd-theme", "sphinxcontrib-github-alt"] +test = ["codecov", "coverage", "ipykernel", "ipython", "mock", "mypy", "pre-commit", "pytest", "pytest-asyncio", "pytest-cov", "pytest-timeout", "jedi (<0.18)"] [[package]] name = "jupyter-core" -version = "4.7.1" +version = "4.8.1" description = "Jupyter core package. A base package on which Jupyter projects rely." category = "main" optional = false python-versions = ">=3.6" [package.dependencies] -pywin32 = {version = ">=1.0", markers = "sys_platform == \"win32\""} +pywin32 = {version = ">=1.0", markers = "sys_platform == \"win32\" and platform_python_implementation != \"PyPy\""} traitlets = "*" [[package]] name = "jupyter-server" -version = "1.8.0" +version = "1.11.0" description = "The backend—i.e. core services, APIs, and REST endpoints—to Jupyter web applications." category = "main" optional = false @@ -330,6 +351,7 @@ nbconvert = "*" nbformat = "*" prometheus-client = "*" pyzmq = ">=17" +requests-unixsocket = "*" Send2Trash = "*" terminado = ">=0.8.3" tornado = ">=6.1.0" @@ -337,11 +359,11 @@ traitlets = ">=4.2.1" websocket-client = "*" [package.extras] -test = ["coverage", "pytest", "pytest-cov", "pytest-mock", "requests", "pytest-tornasync", "pytest-console-scripts", "ipykernel"] +test = ["coverage", "pytest (>=6.0)", "pytest-cov", "pytest-mock", "requests", "pytest-tornasync", "pytest-console-scripts", "ipykernel"] [[package]] name = "jupyterlab" -version = "3.0.16" +version = "3.1.14" description = "JupyterLab computational environment" category = "main" optional = false @@ -359,6 +381,7 @@ tornado = ">=6.1.0" [package.extras] test = ["coverage", "pytest (>=6.0)", "pytest-cov", "pytest-console-scripts", "pytest-check-links (>=0.5)", "jupyterlab-server[test] (>=2.2,<3.0)", "requests", "requests-cache", "virtualenv", "check-manifest"] +ui-tests = ["build"] [[package]] name = "jupyterlab-pygments" @@ -373,7 +396,7 @@ pygments = ">=2.4.1,<3" [[package]] name = "jupyterlab-server" -version = "2.5.2" +version = "2.8.2" description = "A set of server components for JupyterLab and JupyterLab like applications ." category = "main" optional = false @@ -381,6 +404,7 @@ python-versions = ">=3.6" [package.dependencies] babel = "*" +entrypoints = ">=0.2.2" jinja2 = ">=2.10" json5 = "*" jsonschema = ">=3.0.1" @@ -389,15 +413,15 @@ packaging = "*" requests = "*" [package.extras] -test = ["codecov", "ipykernel", "pytest (>=5.3.2)", "pytest-cov", "jupyter-server", "openapi-core (>=0.13.8,<0.14.0)", "pytest-console-scripts", "strict-rfc3339", "ruamel.yaml", "wheel"] +test = ["codecov", "ipykernel", "pytest (>=5.3.2)", "pytest-cov", "jupyter-server", "openapi-core (>=0.14.0,<0.15.0)", "pytest-console-scripts", "strict-rfc3339", "ruamel.yaml", "wheel"] [[package]] name = "kiwisolver" -version = "1.3.1" +version = "1.3.2" description = "A fast implementation of the Cassowary constraint solver" category = "main" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" [[package]] name = "markupsafe" @@ -409,7 +433,7 @@ python-versions = ">=3.6" [[package]] name = "matplotlib" -version = "3.4.2" +version = "3.4.3" description = "Python plotting package" category = "main" optional = false @@ -425,7 +449,7 @@ python-dateutil = ">=2.7" [[package]] name = "matplotlib-inline" -version = "0.1.2" +version = "0.1.3" description = "Inline Matplotlib backend for Jupyter" category = "main" optional = false @@ -444,7 +468,7 @@ python-versions = "*" [[package]] name = "nbclassic" -version = "0.3.1" +version = "0.3.2" description = "Jupyter Notebook as a Jupyter Server Extension." category = "main" optional = false @@ -459,14 +483,13 @@ test = ["pytest", "pytest-tornasync", "pytest-console-scripts"] [[package]] name = "nbclient" -version = "0.5.3" +version = "0.5.4" description = "A client library for executing notebooks. Formerly nbconvert's ExecutePreprocessor." category = "main" optional = false python-versions = ">=3.6.1" [package.dependencies] -async-generator = "*" jupyter-client = ">=6.1.5" nbformat = ">=5.0" nest-asyncio = "*" @@ -479,11 +502,11 @@ test = ["codecov", "coverage", "ipython", "ipykernel", "ipywidgets", "pytest (>= [[package]] name = "nbconvert" -version = "6.0.7" +version = "6.2.0" description = "Converting Jupyter Notebooks" category = "main" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" [package.dependencies] bleach = "*" @@ -498,14 +521,14 @@ nbformat = ">=4.4" pandocfilters = ">=1.4.1" pygments = ">=2.4.1" testpath = "*" -traitlets = ">=4.2" +traitlets = ">=5.0" [package.extras] -all = ["pytest", "pytest-cov", "pytest-dependency", "ipykernel", "ipywidgets (>=7)", "pyppeteer (==0.2.2)", "tornado (>=4.0)", "sphinx (>=1.5.1)", "sphinx-rtd-theme", "nbsphinx (>=0.2.12)", "ipython"] +all = ["pytest", "pytest-cov", "pytest-dependency", "ipykernel", "ipywidgets (>=7)", "pyppeteer (==0.2.6)", "tornado (>=4.0)", "sphinx (>=1.5.1)", "sphinx-rtd-theme", "nbsphinx (>=0.2.12)", "ipython"] docs = ["sphinx (>=1.5.1)", "sphinx-rtd-theme", "nbsphinx (>=0.2.12)", "ipython"] serve = ["tornado (>=4.0)"] -test = ["pytest", "pytest-cov", "pytest-dependency", "ipykernel", "ipywidgets (>=7)", "pyppeteer (==0.2.2)"] -webpdf = ["pyppeteer (==0.2.2)"] +test = ["pytest", "pytest-cov", "pytest-dependency", "ipykernel", "ipywidgets (>=7)", "pyppeteer (==0.2.6)"] +webpdf = ["pyppeteer (==0.2.6)"] [[package]] name = "nbformat" @@ -535,7 +558,7 @@ python-versions = ">=3.5" [[package]] name = "notebook" -version = "6.4.0" +version = "6.4.4" description = "A web-based notebook environment for interactive computing" category = "main" optional = false @@ -564,7 +587,7 @@ test = ["pytest", "coverage", "requests", "nbval", "selenium", "pytest-cov", "re [[package]] name = "numpy" -version = "1.20.3" +version = "1.21.1" description = "NumPy is the fundamental package for array computing with Python." category = "main" optional = false @@ -572,34 +595,34 @@ python-versions = ">=3.7" [[package]] name = "packaging" -version = "20.9" +version = "21.0" description = "Core utilities for Python packages" category = "main" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +python-versions = ">=3.6" [package.dependencies] pyparsing = ">=2.0.2" [[package]] name = "pandas" -version = "1.2.4" +version = "1.3.3" description = "Powerful data structures for data analysis, time series, and statistics" category = "main" optional = false python-versions = ">=3.7.1" [package.dependencies] -numpy = ">=1.16.5" +numpy = ">=1.17.3" python-dateutil = ">=2.7.3" pytz = ">=2017.3" [package.extras] -test = ["pytest (>=5.0.1)", "pytest-xdist", "hypothesis (>=3.58)"] +test = ["hypothesis (>=3.58)", "pytest (>=6.0)", "pytest-xdist"] [[package]] name = "pandocfilters" -version = "1.4.3" +version = "1.5.0" description = "Utilities for writing pandoc filters in python" category = "main" optional = false @@ -638,7 +661,7 @@ python-versions = "*" [[package]] name = "pillow" -version = "8.2.0" +version = "8.3.2" description = "Python Imaging Library (Fork)" category = "main" optional = false @@ -646,7 +669,7 @@ python-versions = ">=3.6" [[package]] name = "prometheus-client" -version = "0.10.1" +version = "0.11.0" description = "Python client for the Prometheus monitoring system." category = "main" optional = false @@ -657,11 +680,11 @@ twisted = ["twisted"] [[package]] name = "prompt-toolkit" -version = "3.0.18" +version = "3.0.20" description = "Library for building powerful interactive command lines in Python" category = "main" optional = false -python-versions = ">=3.6.1" +python-versions = ">=3.6.2" [package.dependencies] wcwidth = "*" @@ -692,7 +715,7 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" [[package]] name = "pygments" -version = "2.9.0" +version = "2.10.0" description = "Pygments is a syntax highlighting package written in Python." category = "main" optional = false @@ -708,15 +731,15 @@ python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" [[package]] name = "pyrsistent" -version = "0.17.3" +version = "0.18.0" description = "Persistent/Functional/Immutable data structures" category = "main" optional = false -python-versions = ">=3.5" +python-versions = ">=3.6" [[package]] name = "python-dateutil" -version = "2.8.1" +version = "2.8.2" description = "Extensions to the standard Python datetime module" category = "main" optional = false @@ -727,7 +750,7 @@ six = ">=1.5" [[package]] name = "pytz" -version = "2021.1" +version = "2021.3" description = "World timezone definitions, modern and historical" category = "main" optional = false @@ -735,7 +758,7 @@ python-versions = "*" [[package]] name = "pywin32" -version = "300" +version = "301" description = "Python for Window Extensions" category = "main" optional = false @@ -743,7 +766,7 @@ python-versions = "*" [[package]] name = "pywinpty" -version = "1.1.1" +version = "1.1.4" description = "Pseudo terminal support for Windows from Python." category = "main" optional = false @@ -751,7 +774,7 @@ python-versions = ">=3.6" [[package]] name = "pyzmq" -version = "22.0.3" +version = "22.3.0" description = "Python bindings for 0MQ" category = "main" optional = false @@ -763,35 +786,53 @@ py = {version = "*", markers = "implementation_name == \"pypy\""} [[package]] name = "requests" -version = "2.15.1" +version = "2.26.0" description = "Python HTTP for Humans." category = "main" optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" + +[package.dependencies] +certifi = ">=2017.4.17" +charset-normalizer = {version = ">=2.0.0,<2.1.0", markers = "python_version >= \"3\""} +idna = {version = ">=2.5,<4", markers = "python_version >= \"3\""} +urllib3 = ">=1.21.1,<1.27" + +[package.extras] +socks = ["PySocks (>=1.5.6,!=1.5.7)", "win-inet-pton"] +use_chardet_on_py3 = ["chardet (>=3.0.2,<5)"] + +[[package]] +name = "requests-unixsocket" +version = "0.2.0" +description = "Use requests to talk HTTP via a UNIX domain socket" +category = "main" +optional = false python-versions = "*" -[package.extras] -security = ["cryptography (>=1.3.4)", "idna (>=2.0.0)", "pyOpenSSL (>=0.14)"] -socks = ["PySocks (>=1.5.6,!=1.5.7)", "win-inet-pton"] +[package.dependencies] +requests = ">=1.1" +urllib3 = ">=1.8" [[package]] name = "scikit-learn" -version = "0.24.2" +version = "1.0" description = "A set of python modules for machine learning and data mining" category = "main" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" [package.dependencies] joblib = ">=0.11" -numpy = ">=1.13.3" -scipy = ">=0.19.1" +numpy = ">=1.14.6" +scipy = ">=1.1.0" threadpoolctl = ">=2.0.0" [package.extras] -benchmark = ["matplotlib (>=2.1.1)", "pandas (>=0.25.0)", "memory-profiler (>=0.57.0)"] -docs = ["matplotlib (>=2.1.1)", "scikit-image (>=0.13)", "pandas (>=0.25.0)", "seaborn (>=0.9.0)", "memory-profiler (>=0.57.0)", "sphinx (>=3.2.0)", "sphinx-gallery (>=0.7.0)", "numpydoc (>=1.0.0)", "Pillow (>=7.1.2)", "sphinx-prompt (>=1.3.0)"] -examples = ["matplotlib (>=2.1.1)", "scikit-image (>=0.13)", "pandas (>=0.25.0)", "seaborn (>=0.9.0)"] -tests = ["matplotlib (>=2.1.1)", "scikit-image (>=0.13)", "pandas (>=0.25.0)", "pytest (>=5.0.1)", "pytest-cov (>=2.9.0)", "flake8 (>=3.8.2)", "mypy (>=0.770)", "pyamg (>=4.0.0)"] +benchmark = ["matplotlib (>=2.2.2)", "pandas (>=0.25.0)", "memory-profiler (>=0.57.0)"] +docs = ["matplotlib (>=2.2.2)", "scikit-image (>=0.14.5)", "pandas (>=0.25.0)", "seaborn (>=0.9.0)", "memory-profiler (>=0.57.0)", "sphinx (>=4.0.1)", "sphinx-gallery (>=0.7.0)", "numpydoc (>=1.0.0)", "Pillow (>=7.1.2)", "sphinx-prompt (>=1.3.0)", "sphinxext-opengraph (>=0.4.2)"] +examples = ["matplotlib (>=2.2.2)", "scikit-image (>=0.14.5)", "pandas (>=0.25.0)", "seaborn (>=0.9.0)"] +tests = ["matplotlib (>=2.2.2)", "scikit-image (>=0.14.5)", "pandas (>=0.25.0)", "pytest (>=5.0.1)", "pytest-cov (>=2.9.0)", "flake8 (>=3.8.2)", "black (>=21.6b0)", "mypy (>=0.770)", "pyamg (>=4.0.0)"] [[package]] name = "scipy" @@ -806,12 +847,17 @@ numpy = ">=1.16.5" [[package]] name = "send2trash" -version = "1.5.0" +version = "1.8.0" description = "Send file to trash natively under Mac OS X, Windows and Linux." category = "main" optional = false python-versions = "*" +[package.extras] +nativelib = ["pyobjc-framework-cocoa", "pywin32"] +objc = ["pyobjc-framework-cocoa"] +win32 = ["pywin32"] + [[package]] name = "six" version = "1.16.0" @@ -830,7 +876,7 @@ python-versions = ">=3.5" [[package]] name = "terminado" -version = "0.10.0" +version = "0.12.1" description = "Tornado websocket backend for the Xterm.js Javascript terminal emulator library." category = "main" optional = false @@ -857,11 +903,11 @@ test = ["pytest", "pathlib2"] [[package]] name = "threadpoolctl" -version = "2.1.0" +version = "3.0.0" description = "threadpoolctl" category = "main" optional = false -python-versions = ">=3.5" +python-versions = ">=3.6" [[package]] name = "tornado" @@ -873,18 +919,28 @@ python-versions = ">= 3.5" [[package]] name = "traitlets" -version = "5.0.5" +version = "5.1.0" description = "Traitlets Python configuration system" category = "main" optional = false python-versions = ">=3.7" -[package.dependencies] -ipython-genutils = "*" - [package.extras] test = ["pytest"] +[[package]] +name = "urllib3" +version = "1.26.7" +description = "HTTP library with thread-safe connection pooling, file post, and more." +category = "main" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4" + +[package.extras] +brotli = ["brotlipy (>=0.6.0)"] +secure = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "certifi", "ipaddress"] +socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] + [[package]] name = "wcwidth" version = "0.2.5" @@ -903,53 +959,42 @@ python-versions = "*" [[package]] name = "websocket-client" -version = "1.0.1" +version = "1.2.1" description = "WebSocket client for Python with low level API options" category = "main" optional = false python-versions = ">=3.6" +[package.extras] +optional = ["python-socks", "wsaccel"] +test = ["websockets"] + [metadata] lock-version = "1.1" python-versions = "^3.8" -content-hash = "f684f47b6832846bcfe88bf58eb673f20582f94c1c2b7ff3a2d366106f5cc96c" +content-hash = "9a7eb62eec4006d13eba24a68d2ce4c743c02ad7efea06c998647c46acb57990" [metadata.files] anyio = [ - {file = "anyio-3.1.0-py3-none-any.whl", hash = "sha256:5e335cef65fbd1a422bbfbb4722e8e9a9fadbd8c06d5afe9cd614d12023f6e5a"}, - {file = "anyio-3.1.0.tar.gz", hash = "sha256:43e20711a9d003d858d694c12356dc44ab82c03ccc5290313c3392fa349dad0e"}, + {file = "anyio-3.3.2-py3-none-any.whl", hash = "sha256:c32da314c510b34a862f5afeaf8a446ffed2c2fde21583e654bd71ecfb5b744b"}, + {file = "anyio-3.3.2.tar.gz", hash = "sha256:0b993a2ef6c1dc456815c2b5ca2819f382f20af98087cc2090a4afed3a501436"}, ] appnope = [ {file = "appnope-0.1.2-py2.py3-none-any.whl", hash = "sha256:93aa393e9d6c54c5cd570ccadd8edad61ea0c4b9ea7a01409020c9aa019eb442"}, {file = "appnope-0.1.2.tar.gz", hash = "sha256:dd83cd4b5b460958838f6eb3000c660b1f9caf2a5b1de4264e941512f603258a"}, ] argon2-cffi = [ - {file = "argon2-cffi-20.1.0.tar.gz", hash = "sha256:d8029b2d3e4b4cea770e9e5a0104dd8fa185c1724a0f01528ae4826a6d25f97d"}, - {file = "argon2_cffi-20.1.0-cp27-cp27m-macosx_10_6_intel.whl", hash = "sha256:6ea92c980586931a816d61e4faf6c192b4abce89aa767ff6581e6ddc985ed003"}, - {file = "argon2_cffi-20.1.0-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:05a8ac07c7026542377e38389638a8a1e9b78f1cd8439cd7493b39f08dd75fbf"}, - {file = "argon2_cffi-20.1.0-cp27-cp27m-win32.whl", hash = "sha256:0bf066bc049332489bb2d75f69216416329d9dc65deee127152caeb16e5ce7d5"}, - {file = "argon2_cffi-20.1.0-cp27-cp27m-win_amd64.whl", hash = "sha256:57358570592c46c420300ec94f2ff3b32cbccd10d38bdc12dc6979c4a8484fbc"}, - {file = "argon2_cffi-20.1.0-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:7d455c802727710e9dfa69b74ccaab04568386ca17b0ad36350b622cd34606fe"}, - {file = "argon2_cffi-20.1.0-cp35-abi3-manylinux1_x86_64.whl", hash = "sha256:b160416adc0f012fb1f12588a5e6954889510f82f698e23ed4f4fa57f12a0647"}, - {file = "argon2_cffi-20.1.0-cp35-cp35m-win32.whl", hash = "sha256:9bee3212ba4f560af397b6d7146848c32a800652301843df06b9e8f68f0f7361"}, - {file = "argon2_cffi-20.1.0-cp35-cp35m-win_amd64.whl", hash = "sha256:392c3c2ef91d12da510cfb6f9bae52512a4552573a9e27600bdb800e05905d2b"}, - {file = "argon2_cffi-20.1.0-cp36-cp36m-win32.whl", hash = "sha256:ba7209b608945b889457f949cc04c8e762bed4fe3fec88ae9a6b7765ae82e496"}, - {file = "argon2_cffi-20.1.0-cp36-cp36m-win_amd64.whl", hash = "sha256:da7f0445b71db6d3a72462e04f36544b0de871289b0bc8a7cc87c0f5ec7079fa"}, - {file = "argon2_cffi-20.1.0-cp37-abi3-macosx_10_6_intel.whl", hash = "sha256:cc0e028b209a5483b6846053d5fd7165f460a1f14774d79e632e75e7ae64b82b"}, - {file = "argon2_cffi-20.1.0-cp37-cp37m-win32.whl", hash = "sha256:18dee20e25e4be86680b178b35ccfc5d495ebd5792cd00781548d50880fee5c5"}, - {file = "argon2_cffi-20.1.0-cp37-cp37m-win_amd64.whl", hash = "sha256:6678bb047373f52bcff02db8afab0d2a77d83bde61cfecea7c5c62e2335cb203"}, - {file = "argon2_cffi-20.1.0-cp38-cp38-win32.whl", hash = "sha256:77e909cc756ef81d6abb60524d259d959bab384832f0c651ed7dcb6e5ccdbb78"}, - {file = "argon2_cffi-20.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:9dfd5197852530294ecb5795c97a823839258dfd5eb9420233c7cfedec2058f2"}, - {file = "argon2_cffi-20.1.0-cp39-cp39-win32.whl", hash = "sha256:e2db6e85c057c16d0bd3b4d2b04f270a7467c147381e8fd73cbbe5bc719832be"}, - {file = "argon2_cffi-20.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:8a84934bd818e14a17943de8099d41160da4a336bcc699bb4c394bbb9b94bd32"}, - {file = "argon2_cffi-20.1.0-pp36-pypy36_pp73-macosx_10_7_x86_64.whl", hash = "sha256:b94042e5dcaa5d08cf104a54bfae614be502c6f44c9c89ad1535b2ebdaacbd4c"}, - {file = "argon2_cffi-20.1.0-pp36-pypy36_pp73-win32.whl", hash = "sha256:8282b84ceb46b5b75c3a882b28856b8cd7e647ac71995e71b6705ec06fc232c3"}, - {file = "argon2_cffi-20.1.0-pp37-pypy37_pp73-macosx_10_7_x86_64.whl", hash = "sha256:3aa804c0e52f208973845e8b10c70d8957c9e5a666f702793256242e9167c4e0"}, - {file = "argon2_cffi-20.1.0-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:36320372133a003374ef4275fbfce78b7ab581440dfca9f9471be3dd9a522428"}, -] -async-generator = [ - {file = "async_generator-1.10-py3-none-any.whl", hash = "sha256:01c7bf666359b4967d2cda0000cc2e4af16a0ae098cbffcb8472fb9e8ad6585b"}, - {file = "async_generator-1.10.tar.gz", hash = "sha256:6ebb3d106c12920aaae42ccb6f787ef5eefdcdd166ea3d628fa8476abe712144"}, + {file = "argon2-cffi-21.1.0.tar.gz", hash = "sha256:f710b61103d1a1f692ca3ecbd1373e28aa5e545ac625ba067ff2feca1b2bb870"}, + {file = "argon2_cffi-21.1.0-cp35-abi3-macosx_10_14_x86_64.whl", hash = "sha256:217b4f0f853ccbbb5045242946ad2e162e396064575860141b71a85eb47e475a"}, + {file = "argon2_cffi-21.1.0-cp35-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:fa7e7d1fc22514a32b1761fdfa1882b6baa5c36bb3ef557bdd69e6fc9ba14a41"}, + {file = "argon2_cffi-21.1.0-cp35-abi3-win32.whl", hash = "sha256:e4d8f0ae1524b7b0372a3e574a2561cbdddb3fdb6c28b70a72868189bda19659"}, + {file = "argon2_cffi-21.1.0-cp35-abi3-win_amd64.whl", hash = "sha256:65213a9174320a1aee03fe826596e0620783966b49eb636955958b3074e87ff9"}, + {file = "argon2_cffi-21.1.0-pp36-pypy36_pp73-macosx_10_7_x86_64.whl", hash = "sha256:245f64a203012b144b7b8c8ea6d468cb02b37caa5afee5ba4a10c80599334f6a"}, + {file = "argon2_cffi-21.1.0-pp36-pypy36_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:4ad152c418f7eb640eac41ac815534e6aa61d1624530b8e7779114ecfbf327f8"}, + {file = "argon2_cffi-21.1.0-pp36-pypy36_pp73-win32.whl", hash = "sha256:bc513db2283c385ea4da31a2cd039c33380701f376f4edd12fe56db118a3b21a"}, + {file = "argon2_cffi-21.1.0-pp37-pypy37_pp73-macosx_10_7_x86_64.whl", hash = "sha256:c7a7c8cc98ac418002090e4add5bebfff1b915ea1cb459c578cd8206fef10378"}, + {file = "argon2_cffi-21.1.0-pp37-pypy37_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:165cadae5ac1e26644f5ade3bd9c18d89963be51d9ea8817bd671006d7909057"}, + {file = "argon2_cffi-21.1.0-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:566ffb581bbd9db5562327aee71b2eda24a1c15b23a356740abe3c011bbe0dcb"}, ] attrs = [ {file = "attrs-21.2.0-py2.py3-none-any.whl", hash = "sha256:149e90d6d8ac20db7a955ad60cf0e6881a3f20d37096140088356da6c716b0b1"}, @@ -964,59 +1009,63 @@ backcall = [ {file = "backcall-0.2.0.tar.gz", hash = "sha256:5cbdbf27be5e7cfadb448baf0aa95508f91f2bbc6c6437cd9cd06e2a4c215e1e"}, ] bleach = [ - {file = "bleach-3.3.0-py2.py3-none-any.whl", hash = "sha256:6123ddc1052673e52bab52cdc955bcb57a015264a1c57d37bea2f6b817af0125"}, - {file = "bleach-3.3.0.tar.gz", hash = "sha256:98b3170739e5e83dd9dc19633f074727ad848cbedb6026708c8ac2d3b697a433"}, + {file = "bleach-4.1.0-py2.py3-none-any.whl", hash = "sha256:4d2651ab93271d1129ac9cbc679f524565cc8a1b791909c4a51eac4446a15994"}, + {file = "bleach-4.1.0.tar.gz", hash = "sha256:0900d8b37eba61a802ee40ac0061f8c2b5dee29c1927dd1d233e075ebf5a71da"}, +] +certifi = [ + {file = "certifi-2021.5.30-py2.py3-none-any.whl", hash = "sha256:50b1e4f8446b06f41be7dd6338db18e0990601dce795c2b1686458aa7e8fa7d8"}, + {file = "certifi-2021.5.30.tar.gz", hash = "sha256:2bbf76fd432960138b3ef6dda3dde0544f27cbf8546c458e60baf371917ba9ee"}, ] cffi = [ - {file = "cffi-1.14.5-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:bb89f306e5da99f4d922728ddcd6f7fcebb3241fc40edebcb7284d7514741991"}, - {file = "cffi-1.14.5-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:34eff4b97f3d982fb93e2831e6750127d1355a923ebaeeb565407b3d2f8d41a1"}, - {file = "cffi-1.14.5-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:99cd03ae7988a93dd00bcd9d0b75e1f6c426063d6f03d2f90b89e29b25b82dfa"}, - {file = "cffi-1.14.5-cp27-cp27m-win32.whl", hash = "sha256:65fa59693c62cf06e45ddbb822165394a288edce9e276647f0046e1ec26920f3"}, - {file = "cffi-1.14.5-cp27-cp27m-win_amd64.whl", hash = "sha256:51182f8927c5af975fece87b1b369f722c570fe169f9880764b1ee3bca8347b5"}, - {file = "cffi-1.14.5-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:43e0b9d9e2c9e5d152946b9c5fe062c151614b262fda2e7b201204de0b99e482"}, - {file = "cffi-1.14.5-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:cbde590d4faaa07c72bf979734738f328d239913ba3e043b1e98fe9a39f8b2b6"}, - {file = "cffi-1.14.5-cp35-cp35m-macosx_10_9_x86_64.whl", hash = "sha256:5de7970188bb46b7bf9858eb6890aad302577a5f6f75091fd7cdd3ef13ef3045"}, - {file = "cffi-1.14.5-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:a465da611f6fa124963b91bf432d960a555563efe4ed1cc403ba5077b15370aa"}, - {file = "cffi-1.14.5-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:d42b11d692e11b6634f7613ad8df5d6d5f8875f5d48939520d351007b3c13406"}, - {file = "cffi-1.14.5-cp35-cp35m-win32.whl", hash = "sha256:72d8d3ef52c208ee1c7b2e341f7d71c6fd3157138abf1a95166e6165dd5d4369"}, - {file = "cffi-1.14.5-cp35-cp35m-win_amd64.whl", hash = "sha256:29314480e958fd8aab22e4a58b355b629c59bf5f2ac2492b61e3dc06d8c7a315"}, - {file = "cffi-1.14.5-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:3d3dd4c9e559eb172ecf00a2a7517e97d1e96de2a5e610bd9b68cea3925b4892"}, - {file = "cffi-1.14.5-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:48e1c69bbacfc3d932221851b39d49e81567a4d4aac3b21258d9c24578280058"}, - {file = "cffi-1.14.5-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:69e395c24fc60aad6bb4fa7e583698ea6cc684648e1ffb7fe85e3c1ca131a7d5"}, - {file = "cffi-1.14.5-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:9e93e79c2551ff263400e1e4be085a1210e12073a31c2011dbbda14bda0c6132"}, - {file = "cffi-1.14.5-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:24ec4ff2c5c0c8f9c6b87d5bb53555bf267e1e6f70e52e5a9740d32861d36b6f"}, - {file = "cffi-1.14.5-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3c3f39fa737542161d8b0d680df2ec249334cd70a8f420f71c9304bd83c3cbed"}, - {file = "cffi-1.14.5-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:681d07b0d1e3c462dd15585ef5e33cb021321588bebd910124ef4f4fb71aef55"}, - {file = "cffi-1.14.5-cp36-cp36m-win32.whl", hash = "sha256:58e3f59d583d413809d60779492342801d6e82fefb89c86a38e040c16883be53"}, - {file = "cffi-1.14.5-cp36-cp36m-win_amd64.whl", hash = "sha256:005a36f41773e148deac64b08f233873a4d0c18b053d37da83f6af4d9087b813"}, - {file = "cffi-1.14.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:2894f2df484ff56d717bead0a5c2abb6b9d2bf26d6960c4604d5c48bbc30ee73"}, - {file = "cffi-1.14.5-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:0857f0ae312d855239a55c81ef453ee8fd24136eaba8e87a2eceba644c0d4c06"}, - {file = "cffi-1.14.5-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:cd2868886d547469123fadc46eac7ea5253ea7fcb139f12e1dfc2bbd406427d1"}, - {file = "cffi-1.14.5-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:35f27e6eb43380fa080dccf676dece30bef72e4a67617ffda586641cd4508d49"}, - {file = "cffi-1.14.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:06d7cd1abac2ffd92e65c0609661866709b4b2d82dd15f611e602b9b188b0b69"}, - {file = "cffi-1.14.5-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0f861a89e0043afec2a51fd177a567005847973be86f709bbb044d7f42fc4e05"}, - {file = "cffi-1.14.5-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cc5a8e069b9ebfa22e26d0e6b97d6f9781302fe7f4f2b8776c3e1daea35f1adc"}, - {file = "cffi-1.14.5-cp37-cp37m-win32.whl", hash = "sha256:9ff227395193126d82e60319a673a037d5de84633f11279e336f9c0f189ecc62"}, - {file = "cffi-1.14.5-cp37-cp37m-win_amd64.whl", hash = "sha256:9cf8022fb8d07a97c178b02327b284521c7708d7c71a9c9c355c178ac4bbd3d4"}, - {file = "cffi-1.14.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8b198cec6c72df5289c05b05b8b0969819783f9418e0409865dac47288d2a053"}, - {file = "cffi-1.14.5-cp38-cp38-manylinux1_i686.whl", hash = "sha256:ad17025d226ee5beec591b52800c11680fca3df50b8b29fe51d882576e039ee0"}, - {file = "cffi-1.14.5-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:6c97d7350133666fbb5cf4abdc1178c812cb205dc6f41d174a7b0f18fb93337e"}, - {file = "cffi-1.14.5-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:8ae6299f6c68de06f136f1f9e69458eae58f1dacf10af5c17353eae03aa0d827"}, - {file = "cffi-1.14.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:04c468b622ed31d408fea2346bec5bbffba2cc44226302a0de1ade9f5ea3d373"}, - {file = "cffi-1.14.5-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:06db6321b7a68b2bd6df96d08a5adadc1fa0e8f419226e25b2a5fbf6ccc7350f"}, - {file = "cffi-1.14.5-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:293e7ea41280cb28c6fcaaa0b1aa1f533b8ce060b9e701d78511e1e6c4a1de76"}, - {file = "cffi-1.14.5-cp38-cp38-win32.whl", hash = "sha256:b85eb46a81787c50650f2392b9b4ef23e1f126313b9e0e9013b35c15e4288e2e"}, - {file = "cffi-1.14.5-cp38-cp38-win_amd64.whl", hash = "sha256:1f436816fc868b098b0d63b8920de7d208c90a67212546d02f84fe78a9c26396"}, - {file = "cffi-1.14.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:1071534bbbf8cbb31b498d5d9db0f274f2f7a865adca4ae429e147ba40f73dea"}, - {file = "cffi-1.14.5-cp39-cp39-manylinux1_i686.whl", hash = "sha256:9de2e279153a443c656f2defd67769e6d1e4163952b3c622dcea5b08a6405322"}, - {file = "cffi-1.14.5-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:6e4714cc64f474e4d6e37cfff31a814b509a35cb17de4fb1999907575684479c"}, - {file = "cffi-1.14.5-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:158d0d15119b4b7ff6b926536763dc0714313aa59e320ddf787502c70c4d4bee"}, - {file = "cffi-1.14.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1bf1ac1984eaa7675ca8d5745a8cb87ef7abecb5592178406e55858d411eadc0"}, - {file = "cffi-1.14.5-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:df5052c5d867c1ea0b311fb7c3cd28b19df469c056f7fdcfe88c7473aa63e333"}, - {file = "cffi-1.14.5-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:24a570cd11895b60829e941f2613a4f79df1a27344cbbb82164ef2e0116f09c7"}, - {file = "cffi-1.14.5-cp39-cp39-win32.whl", hash = "sha256:afb29c1ba2e5a3736f1c301d9d0abe3ec8b86957d04ddfa9d7a6a42b9367e396"}, - {file = "cffi-1.14.5-cp39-cp39-win_amd64.whl", hash = "sha256:f2d45f97ab6bb54753eab54fffe75aaf3de4ff2341c9daee1987ee1837636f1d"}, - {file = "cffi-1.14.5.tar.gz", hash = "sha256:fd78e5fee591709f32ef6edb9a015b4aa1a5022598e36227500c8f4e02328d9c"}, + {file = "cffi-1.14.6-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:22b9c3c320171c108e903d61a3723b51e37aaa8c81255b5e7ce102775bd01e2c"}, + {file = "cffi-1.14.6-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:f0c5d1acbfca6ebdd6b1e3eded8d261affb6ddcf2186205518f1428b8569bb99"}, + {file = "cffi-1.14.6-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:99f27fefe34c37ba9875f224a8f36e31d744d8083e00f520f133cab79ad5e819"}, + {file = "cffi-1.14.6-cp27-cp27m-win32.whl", hash = "sha256:55af55e32ae468e9946f741a5d51f9896da6b9bf0bbdd326843fec05c730eb20"}, + {file = "cffi-1.14.6-cp27-cp27m-win_amd64.whl", hash = "sha256:7bcac9a2b4fdbed2c16fa5681356d7121ecabf041f18d97ed5b8e0dd38a80224"}, + {file = "cffi-1.14.6-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:ed38b924ce794e505647f7c331b22a693bee1538fdf46b0222c4717b42f744e7"}, + {file = "cffi-1.14.6-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:e22dcb48709fc51a7b58a927391b23ab37eb3737a98ac4338e2448bef8559b33"}, + {file = "cffi-1.14.6-cp35-cp35m-macosx_10_9_x86_64.whl", hash = "sha256:aedb15f0a5a5949ecb129a82b72b19df97bbbca024081ed2ef88bd5c0a610534"}, + {file = "cffi-1.14.6-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:48916e459c54c4a70e52745639f1db524542140433599e13911b2f329834276a"}, + {file = "cffi-1.14.6-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:f627688813d0a4140153ff532537fbe4afea5a3dffce1f9deb7f91f848a832b5"}, + {file = "cffi-1.14.6-cp35-cp35m-win32.whl", hash = "sha256:f0010c6f9d1a4011e429109fda55a225921e3206e7f62a0c22a35344bfd13cca"}, + {file = "cffi-1.14.6-cp35-cp35m-win_amd64.whl", hash = "sha256:57e555a9feb4a8460415f1aac331a2dc833b1115284f7ded7278b54afc5bd218"}, + {file = "cffi-1.14.6-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:e8c6a99be100371dbb046880e7a282152aa5d6127ae01783e37662ef73850d8f"}, + {file = "cffi-1.14.6-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:19ca0dbdeda3b2615421d54bef8985f72af6e0c47082a8d26122adac81a95872"}, + {file = "cffi-1.14.6-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:d950695ae4381ecd856bcaf2b1e866720e4ab9a1498cba61c602e56630ca7195"}, + {file = "cffi-1.14.6-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e9dc245e3ac69c92ee4c167fbdd7428ec1956d4e754223124991ef29eb57a09d"}, + {file = "cffi-1.14.6-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a8661b2ce9694ca01c529bfa204dbb144b275a31685a075ce123f12331be790b"}, + {file = "cffi-1.14.6-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b315d709717a99f4b27b59b021e6207c64620790ca3e0bde636a6c7f14618abb"}, + {file = "cffi-1.14.6-cp36-cp36m-win32.whl", hash = "sha256:80b06212075346b5546b0417b9f2bf467fea3bfe7352f781ffc05a8ab24ba14a"}, + {file = "cffi-1.14.6-cp36-cp36m-win_amd64.whl", hash = "sha256:a9da7010cec5a12193d1af9872a00888f396aba3dc79186604a09ea3ee7c029e"}, + {file = "cffi-1.14.6-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:4373612d59c404baeb7cbd788a18b2b2a8331abcc84c3ba40051fcd18b17a4d5"}, + {file = "cffi-1.14.6-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:f10afb1004f102c7868ebfe91c28f4a712227fe4cb24974350ace1f90e1febbf"}, + {file = "cffi-1.14.6-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:fd4305f86f53dfd8cd3522269ed7fc34856a8ee3709a5e28b2836b2db9d4cd69"}, + {file = "cffi-1.14.6-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6d6169cb3c6c2ad50db5b868db6491a790300ade1ed5d1da29289d73bbe40b56"}, + {file = "cffi-1.14.6-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5d4b68e216fc65e9fe4f524c177b54964af043dde734807586cf5435af84045c"}, + {file = "cffi-1.14.6-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:33791e8a2dc2953f28b8d8d300dde42dd929ac28f974c4b4c6272cb2955cb762"}, + {file = "cffi-1.14.6-cp37-cp37m-win32.whl", hash = "sha256:0c0591bee64e438883b0c92a7bed78f6290d40bf02e54c5bf0978eaf36061771"}, + {file = "cffi-1.14.6-cp37-cp37m-win_amd64.whl", hash = "sha256:8eb687582ed7cd8c4bdbff3df6c0da443eb89c3c72e6e5dcdd9c81729712791a"}, + {file = "cffi-1.14.6-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ba6f2b3f452e150945d58f4badd92310449876c4c954836cfb1803bdd7b422f0"}, + {file = "cffi-1.14.6-cp38-cp38-manylinux1_i686.whl", hash = "sha256:64fda793737bc4037521d4899be780534b9aea552eb673b9833b01f945904c2e"}, + {file = "cffi-1.14.6-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:9f3e33c28cd39d1b655ed1ba7247133b6f7fc16fa16887b120c0c670e35ce346"}, + {file = "cffi-1.14.6-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:26bb2549b72708c833f5abe62b756176022a7b9a7f689b571e74c8478ead51dc"}, + {file = "cffi-1.14.6-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:eb687a11f0a7a1839719edd80f41e459cc5366857ecbed383ff376c4e3cc6afd"}, + {file = "cffi-1.14.6-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d2ad4d668a5c0645d281dcd17aff2be3212bc109b33814bbb15c4939f44181cc"}, + {file = "cffi-1.14.6-cp38-cp38-win32.whl", hash = "sha256:487d63e1454627c8e47dd230025780e91869cfba4c753a74fda196a1f6ad6548"}, + {file = "cffi-1.14.6-cp38-cp38-win_amd64.whl", hash = "sha256:c33d18eb6e6bc36f09d793c0dc58b0211fccc6ae5149b808da4a62660678b156"}, + {file = "cffi-1.14.6-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:06c54a68935738d206570b20da5ef2b6b6d92b38ef3ec45c5422c0ebaf338d4d"}, + {file = "cffi-1.14.6-cp39-cp39-manylinux1_i686.whl", hash = "sha256:f174135f5609428cc6e1b9090f9268f5c8935fddb1b25ccb8255a2d50de6789e"}, + {file = "cffi-1.14.6-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:f3ebe6e73c319340830a9b2825d32eb6d8475c1dac020b4f0aa774ee3b898d1c"}, + {file = "cffi-1.14.6-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3c8d896becff2fa653dc4438b54a5a25a971d1f4110b32bd3068db3722c80202"}, + {file = "cffi-1.14.6-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4922cd707b25e623b902c86188aca466d3620892db76c0bdd7b99a3d5e61d35f"}, + {file = "cffi-1.14.6-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c9e005e9bd57bc987764c32a1bee4364c44fdc11a3cc20a40b93b444984f2b87"}, + {file = "cffi-1.14.6-cp39-cp39-win32.whl", hash = "sha256:eb9e2a346c5238a30a746893f23a9535e700f8192a68c07c0258e7ece6ff3728"}, + {file = "cffi-1.14.6-cp39-cp39-win_amd64.whl", hash = "sha256:818014c754cd3dba7229c0f5884396264d51ffb87ec86e927ef0be140bfdb0d2"}, + {file = "cffi-1.14.6.tar.gz", hash = "sha256:c9a875ce9d7fe32887784274dd533c57909b7b1dcadcc128a2ac21331a9765dd"}, +] +charset-normalizer = [ + {file = "charset-normalizer-2.0.6.tar.gz", hash = "sha256:5ec46d183433dcbd0ab716f2d7f29d8dee50505b3fdb40c6b985c7c4f5a3591f"}, + {file = "charset_normalizer-2.0.6-py3-none-any.whl", hash = "sha256:5d209c0a931f215cee683b6445e2d77677e7e75e159f78def0db09d68fafcaa6"}, ] colorama = [ {file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"}, @@ -1026,9 +1075,29 @@ cycler = [ {file = "cycler-0.10.0-py2.py3-none-any.whl", hash = "sha256:1d8a5ae1ff6c5cf9b93e8811e581232ad8920aeec647c37316ceac982b08cb2d"}, {file = "cycler-0.10.0.tar.gz", hash = "sha256:cd7b2d1018258d7247a71425e9f26463dfb444d411c39569972f4ce586b0c9d8"}, ] +debugpy = [ + {file = "debugpy-1.4.3-cp36-cp36m-macosx_10_15_x86_64.whl", hash = "sha256:88b17d7c2130968f75bdc706a33f46a8a6bb90f09512ea3bd984659d446ee4f4"}, + {file = "debugpy-1.4.3-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:5ded60b402f83df46dee3f25ae5851809937176afdafd3fdbaab60b633b77cad"}, + {file = "debugpy-1.4.3-cp36-cp36m-win32.whl", hash = "sha256:c0fd1a66e104752f86ca2faa6a0194dae61442a768f85369fc3d11bacff8120f"}, + {file = "debugpy-1.4.3-cp36-cp36m-win_amd64.whl", hash = "sha256:f907941ad7a460646773eb3baae4c88836e9256b390dfbfae8d92a3d3b849a7d"}, + {file = "debugpy-1.4.3-cp37-cp37m-macosx_10_15_x86_64.whl", hash = "sha256:135a77ac1a8f6ea49a69928f088967d36842bc492d89b45941c6b19222cffa42"}, + {file = "debugpy-1.4.3-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f3dcc294f3b4d79fdd7ffe1350d5d1e3cc29acaec67dd1c43143a43305bbbc91"}, + {file = "debugpy-1.4.3-cp37-cp37m-win32.whl", hash = "sha256:c3d7db37b7eb234e49f50ba22b3b1637e8daadd68985d9cd35a6152aa10faa75"}, + {file = "debugpy-1.4.3-cp37-cp37m-win_amd64.whl", hash = "sha256:dbda8f877c3dec1559c01c63a1de63969e51a4907dc308f4824238bb776026fe"}, + {file = "debugpy-1.4.3-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:7c15014290150b76f0311debf7fbba2e934680572ea60750b0f048143e873b3e"}, + {file = "debugpy-1.4.3-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:8d488356cc66172f1ea29635fd148ad131f13fad0e368ae03cc5c0a402372756"}, + {file = "debugpy-1.4.3-cp38-cp38-win32.whl", hash = "sha256:7e7210a3721fc54b52d8dc2f325e7c937ffcbba02b808e2e3215dcbf0c0b8349"}, + {file = "debugpy-1.4.3-cp38-cp38-win_amd64.whl", hash = "sha256:3e4de96c70f3398abd1777f048b47564d98a40df1f72d33b47ef5b9478e07206"}, + {file = "debugpy-1.4.3-cp39-cp39-macosx_10_15_x86_64.whl", hash = "sha256:2019ffcd08d7e643c644cd64bee0fd53c730cb8f15ff37e6a320b5afd3785bfa"}, + {file = "debugpy-1.4.3-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:847926f78c1e33f7318a743837adb6a9b360a825b558fd21f9240ba518fe1bb1"}, + {file = "debugpy-1.4.3-cp39-cp39-win32.whl", hash = "sha256:c9665e58b80d839ae1b0815341c63d00cae557c018f198c0b6b7bc5de9eca144"}, + {file = "debugpy-1.4.3-cp39-cp39-win_amd64.whl", hash = "sha256:ab3f33499c597a2ce454b81088e7f9d56127686e003c4f7a1c97ad4b38a55404"}, + {file = "debugpy-1.4.3-py2.py3-none-any.whl", hash = "sha256:0c523fcbb6fb395403ee8508853767b74949335d5cdacc9f83d350670c2c0db2"}, + {file = "debugpy-1.4.3.zip", hash = "sha256:4d53fe5aecf03ba466aa7fa7474c2b2fe28b2a6c0d36688d1e29382bfe88dd5f"}, +] decorator = [ - {file = "decorator-5.0.9-py3-none-any.whl", hash = "sha256:6e5c199c16f7a9f0e3a61a4a54b3d27e7dad0dbdde92b944426cb20914376323"}, - {file = "decorator-5.0.9.tar.gz", hash = "sha256:72ecfba4320a893c53f9706bebb2d55c270c1e51a28789361aa93e4a21319ed5"}, + {file = "decorator-5.1.0-py3-none-any.whl", hash = "sha256:7b12e7c3c6ab203a29e157335e9122cb03de9ab7264b137594103fd4a683b374"}, + {file = "decorator-5.1.0.tar.gz", hash = "sha256:e59913af105b9860aa2c8d3272d9de5a56a4e608db9a2f167a8480b323d529a7"}, ] defusedxml = [ {file = "defusedxml-0.7.1-py2.py3-none-any.whl", hash = "sha256:a352e7e428770286cc899e2542b6cdaedb2b4953ff269a210103ec58f6198a61"}, @@ -1039,16 +1108,16 @@ entrypoints = [ {file = "entrypoints-0.3.tar.gz", hash = "sha256:c70dd71abe5a8c85e55e12c19bd91ccfeec11a6e99044204511f9ed547d48451"}, ] idna = [ - {file = "idna-3.1-py3-none-any.whl", hash = "sha256:5205d03e7bcbb919cc9c19885f9920d622ca52448306f2377daede5cf3faac16"}, - {file = "idna-3.1.tar.gz", hash = "sha256:c5b02147e01ea9920e6b0a3f1f7bb833612d507592c837a6c49552768f4054e1"}, + {file = "idna-3.2-py3-none-any.whl", hash = "sha256:14475042e284991034cb48e06f6851428fb14c4dc953acd9be9a5e95c7b6dd7a"}, + {file = "idna-3.2.tar.gz", hash = "sha256:467fbad99067910785144ce333826c71fb0e63a425657295239737f7ecd125f3"}, ] ipykernel = [ - {file = "ipykernel-5.5.5-py3-none-any.whl", hash = "sha256:29eee66548ee7c2edb7941de60c0ccf0a7a8dd957341db0a49c5e8e6a0fcb712"}, - {file = "ipykernel-5.5.5.tar.gz", hash = "sha256:e976751336b51082a89fc2099fb7f96ef20f535837c398df6eab1283c2070884"}, + {file = "ipykernel-6.4.1-py3-none-any.whl", hash = "sha256:a3f6c2dda2ecf63b37446808a70ed825fea04790779ca524889c596deae0def8"}, + {file = "ipykernel-6.4.1.tar.gz", hash = "sha256:df3355e5eec23126bc89767a676c5f0abfc7f4c3497d118c592b83b316e8c0cd"}, ] ipython = [ - {file = "ipython-7.23.1-py3-none-any.whl", hash = "sha256:f78c6a3972dde1cc9e4041cbf4de583546314ba52d3c97208e5b6b2221a9cb7d"}, - {file = "ipython-7.23.1.tar.gz", hash = "sha256:714810a5c74f512b69d5f3b944c86e592cee0a5fb9c728e582f074610f6cf038"}, + {file = "ipython-7.28.0-py3-none-any.whl", hash = "sha256:f16148f9163e1e526f1008d7c8d966d9c15600ca20d1a754287cf96d00ba6f1d"}, + {file = "ipython-7.28.0.tar.gz", hash = "sha256:2097be5c814d1b974aea57673176a924c4c8c9583890e7a5f082f547b9975b11"}, ] ipython-genutils = [ {file = "ipython_genutils-0.2.0-py2.py3-none-any.whl", hash = "sha256:72dd37233799e619666c9f639a9da83c34013a73e8bbc79a7a6348d93c61fab8"}, @@ -1067,78 +1136,100 @@ joblib = [ {file = "joblib-1.0.1.tar.gz", hash = "sha256:9c17567692206d2f3fb9ecf5e991084254fe631665c450b443761c4186a613f7"}, ] json5 = [ - {file = "json5-0.9.5-py2.py3-none-any.whl", hash = "sha256:af1a1b9a2850c7f62c23fde18be4749b3599fd302f494eebf957e2ada6b9e42c"}, - {file = "json5-0.9.5.tar.gz", hash = "sha256:703cfee540790576b56a92e1c6aaa6c4b0d98971dc358ead83812aa4d06bdb96"}, + {file = "json5-0.9.6-py2.py3-none-any.whl", hash = "sha256:823e510eb355949bed817e1f3e2d682455dc6af9daf6066d5698d6a2ca4481c2"}, + {file = "json5-0.9.6.tar.gz", hash = "sha256:9175ad1bc248e22bb8d95a8e8d765958bf0008fef2fe8abab5bc04e0f1ac8302"}, ] jsonschema = [ - {file = "jsonschema-3.2.0-py2.py3-none-any.whl", hash = "sha256:4e5b3cf8216f577bee9ce139cbe72eca3ea4f292ec60928ff24758ce626cd163"}, - {file = "jsonschema-3.2.0.tar.gz", hash = "sha256:c8a85b28d377cc7737e46e2d9f2b4f44ee3c0e1deac6bf46ddefc7187d30797a"}, + {file = "jsonschema-4.0.1-py3-none-any.whl", hash = "sha256:9938802041347f2c62cad2aef59e9a0826cd34584f3609db950efacb4dbf6518"}, + {file = "jsonschema-4.0.1.tar.gz", hash = "sha256:48f4e74f8bec0c2f75e9fcfffa264e78342873e1b57e2cfeae54864cc5e9e4dd"}, ] jupyter-client = [ - {file = "jupyter_client-6.2.0-py3-none-any.whl", hash = "sha256:9715152067e3f7ea3b56f341c9a0f9715c8c7cc316ee0eb13c3c84f5ca0065f5"}, - {file = "jupyter_client-6.2.0.tar.gz", hash = "sha256:e2ab61d79fbf8b56734a4c2499f19830fbd7f6fefb3e87868ef0545cb3c17eb9"}, + {file = "jupyter_client-7.0.5-py3-none-any.whl", hash = "sha256:124a6e6979c38999d9153b1c4d1808c4c820a45066d5ed1857a5b59c04ffccb3"}, + {file = "jupyter_client-7.0.5.tar.gz", hash = "sha256:382aca66dcaf96d7eaaa6c546d57cdf8b3b1cf5bc1f2704c58a1d8d244f1163d"}, ] jupyter-core = [ - {file = "jupyter_core-4.7.1-py3-none-any.whl", hash = "sha256:8c6c0cac5c1b563622ad49321d5ec47017bd18b94facb381c6973a0486395f8e"}, - {file = "jupyter_core-4.7.1.tar.gz", hash = "sha256:79025cb3225efcd36847d0840f3fc672c0abd7afd0de83ba8a1d3837619122b4"}, + {file = "jupyter_core-4.8.1-py3-none-any.whl", hash = "sha256:8dd262ec8afae95bd512518eb003bc546b76adbf34bf99410e9accdf4be9aa3a"}, + {file = "jupyter_core-4.8.1.tar.gz", hash = "sha256:ef210dcb4fca04de07f2ead4adf408776aca94d17151d6f750ad6ded0b91ea16"}, ] jupyter-server = [ - {file = "jupyter_server-1.8.0-py3-none-any.whl", hash = "sha256:81547b97f346647fb600b9bbfd020075603dbefe25f639d3d4dc2b7c7a6013cf"}, - {file = "jupyter_server-1.8.0.tar.gz", hash = "sha256:8f0c75e0a577536125ad62a442ebb7cf02746f1a69d907e8a273c6225d281237"}, + {file = "jupyter_server-1.11.0-py3-none-any.whl", hash = "sha256:827c134da7a9e09136c2dc2fd16743350970105247f085abfc6ce0432d0c979e"}, + {file = "jupyter_server-1.11.0.tar.gz", hash = "sha256:8ab4f484a4a2698f757cff0769d27b5d991e0232a666d54f4d6ada4e6a61330b"}, ] jupyterlab = [ - {file = "jupyterlab-3.0.16-py3-none-any.whl", hash = "sha256:88f6e7580c15cf731d96495fda362e786753e18d1e3e7e735915862efb602a92"}, - {file = "jupyterlab-3.0.16.tar.gz", hash = "sha256:7ad4fbe1f6d38255869410fd151a8b15692a663ca97c0a8146b3f5c40e275c23"}, + {file = "jupyterlab-3.1.14-py3-none-any.whl", hash = "sha256:1241ff4ab8604a281eda5d8215fe59e418737edcdfe71df09a0bd5fdd4ccfd2c"}, + {file = "jupyterlab-3.1.14.tar.gz", hash = "sha256:13174cb6076dd5da6f1b85725ccfcc9518d8f98e86b8b644fc89b1dfaeda63a9"}, ] jupyterlab-pygments = [ {file = "jupyterlab_pygments-0.1.2-py2.py3-none-any.whl", hash = "sha256:abfb880fd1561987efaefcb2d2ac75145d2a5d0139b1876d5be806e32f630008"}, {file = "jupyterlab_pygments-0.1.2.tar.gz", hash = "sha256:cfcda0873626150932f438eccf0f8bf22bfa92345b814890ab360d666b254146"}, ] jupyterlab-server = [ - {file = "jupyterlab_server-2.5.2-py3-none-any.whl", hash = "sha256:7c7209e00910aff1ad8a7b8fd5826536561c6bafba9608ed5d1b04e1b9819efd"}, - {file = "jupyterlab_server-2.5.2.tar.gz", hash = "sha256:43bc96fa49196e3ace214693e0955eb73fe11d37ac1577d45b177a0588c0a1d6"}, + {file = "jupyterlab_server-2.8.2-py3-none-any.whl", hash = "sha256:9507f059ddb3d088674ed76fd3d751cedd940f8a74055e2250bf44babcc2ea1f"}, + {file = "jupyterlab_server-2.8.2.tar.gz", hash = "sha256:26d813c8162c83d466df7d155865987dabe70aa452f9187dfb79fd88afc8fa0b"}, ] kiwisolver = [ - {file = "kiwisolver-1.3.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:fd34fbbfbc40628200730bc1febe30631347103fc8d3d4fa012c21ab9c11eca9"}, - {file = "kiwisolver-1.3.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:d3155d828dec1d43283bd24d3d3e0d9c7c350cdfcc0bd06c0ad1209c1bbc36d0"}, - {file = "kiwisolver-1.3.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:5a7a7dbff17e66fac9142ae2ecafb719393aaee6a3768c9de2fd425c63b53e21"}, - {file = "kiwisolver-1.3.1-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:f8d6f8db88049a699817fd9178782867bf22283e3813064302ac59f61d95be05"}, - {file = "kiwisolver-1.3.1-cp36-cp36m-manylinux2014_ppc64le.whl", hash = "sha256:5f6ccd3dd0b9739edcf407514016108e2280769c73a85b9e59aa390046dbf08b"}, - {file = "kiwisolver-1.3.1-cp36-cp36m-win32.whl", hash = "sha256:225e2e18f271e0ed8157d7f4518ffbf99b9450fca398d561eb5c4a87d0986dd9"}, - {file = "kiwisolver-1.3.1-cp36-cp36m-win_amd64.whl", hash = "sha256:cf8b574c7b9aa060c62116d4181f3a1a4e821b2ec5cbfe3775809474113748d4"}, - {file = "kiwisolver-1.3.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:232c9e11fd7ac3a470d65cd67e4359eee155ec57e822e5220322d7b2ac84fbf0"}, - {file = "kiwisolver-1.3.1-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:b38694dcdac990a743aa654037ff1188c7a9801ac3ccc548d3341014bc5ca278"}, - {file = "kiwisolver-1.3.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:ca3820eb7f7faf7f0aa88de0e54681bddcb46e485beb844fcecbcd1c8bd01689"}, - {file = "kiwisolver-1.3.1-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:c8fd0f1ae9d92b42854b2979024d7597685ce4ada367172ed7c09edf2cef9cb8"}, - {file = "kiwisolver-1.3.1-cp37-cp37m-manylinux2014_ppc64le.whl", hash = "sha256:1e1bc12fb773a7b2ffdeb8380609f4f8064777877b2225dec3da711b421fda31"}, - {file = "kiwisolver-1.3.1-cp37-cp37m-win32.whl", hash = "sha256:72c99e39d005b793fb7d3d4e660aed6b6281b502e8c1eaf8ee8346023c8e03bc"}, - {file = "kiwisolver-1.3.1-cp37-cp37m-win_amd64.whl", hash = "sha256:8be8d84b7d4f2ba4ffff3665bcd0211318aa632395a1a41553250484a871d454"}, - {file = "kiwisolver-1.3.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:31dfd2ac56edc0ff9ac295193eeaea1c0c923c0355bf948fbd99ed6018010b72"}, - {file = "kiwisolver-1.3.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:563c649cfdef27d081c84e72a03b48ea9408c16657500c312575ae9d9f7bc1c3"}, - {file = "kiwisolver-1.3.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:78751b33595f7f9511952e7e60ce858c6d64db2e062afb325985ddbd34b5c131"}, - {file = "kiwisolver-1.3.1-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:a357fd4f15ee49b4a98b44ec23a34a95f1e00292a139d6015c11f55774ef10de"}, - {file = "kiwisolver-1.3.1-cp38-cp38-manylinux2014_ppc64le.whl", hash = "sha256:5989db3b3b34b76c09253deeaf7fbc2707616f130e166996606c284395da3f18"}, - {file = "kiwisolver-1.3.1-cp38-cp38-win32.whl", hash = "sha256:c08e95114951dc2090c4a630c2385bef681cacf12636fb0241accdc6b303fd81"}, - {file = "kiwisolver-1.3.1-cp38-cp38-win_amd64.whl", hash = "sha256:44a62e24d9b01ba94ae7a4a6c3fb215dc4af1dde817e7498d901e229aaf50e4e"}, - {file = "kiwisolver-1.3.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:50af681a36b2a1dee1d3c169ade9fdc59207d3c31e522519181e12f1b3ba7000"}, - {file = "kiwisolver-1.3.1-cp39-cp39-manylinux1_i686.whl", hash = "sha256:a53d27d0c2a0ebd07e395e56a1fbdf75ffedc4a05943daf472af163413ce9598"}, - {file = "kiwisolver-1.3.1-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:834ee27348c4aefc20b479335fd422a2c69db55f7d9ab61721ac8cd83eb78882"}, - {file = "kiwisolver-1.3.1-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:5c3e6455341008a054cccee8c5d24481bcfe1acdbc9add30aa95798e95c65621"}, - {file = "kiwisolver-1.3.1-cp39-cp39-manylinux2014_ppc64le.whl", hash = "sha256:acef3d59d47dd85ecf909c359d0fd2c81ed33bdff70216d3956b463e12c38a54"}, - {file = "kiwisolver-1.3.1-cp39-cp39-win32.whl", hash = "sha256:c5518d51a0735b1e6cee1fdce66359f8d2b59c3ca85dc2b0813a8aa86818a030"}, - {file = "kiwisolver-1.3.1-cp39-cp39-win_amd64.whl", hash = "sha256:b9edd0110a77fc321ab090aaa1cfcaba1d8499850a12848b81be2222eab648f6"}, - {file = "kiwisolver-1.3.1-pp36-pypy36_pp73-macosx_10_9_x86_64.whl", hash = "sha256:0cd53f403202159b44528498de18f9285b04482bab2a6fc3f5dd8dbb9352e30d"}, - {file = "kiwisolver-1.3.1-pp36-pypy36_pp73-manylinux2010_x86_64.whl", hash = "sha256:33449715e0101e4d34f64990352bce4095c8bf13bed1b390773fc0a7295967b3"}, - {file = "kiwisolver-1.3.1-pp36-pypy36_pp73-win32.whl", hash = "sha256:401a2e9afa8588589775fe34fc22d918ae839aaaf0c0e96441c0fdbce6d8ebe6"}, - {file = "kiwisolver-1.3.1.tar.gz", hash = "sha256:950a199911a8d94683a6b10321f9345d5a3a8433ec58b217ace979e18f16e248"}, + {file = "kiwisolver-1.3.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:1d819553730d3c2724582124aee8a03c846ec4362ded1034c16fb3ef309264e6"}, + {file = "kiwisolver-1.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:8d93a1095f83e908fc253f2fb569c2711414c0bfd451cab580466465b235b470"}, + {file = "kiwisolver-1.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c4550a359c5157aaf8507e6820d98682872b9100ce7607f8aa070b4b8af6c298"}, + {file = "kiwisolver-1.3.2-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:2210f28778c7d2ee13f3c2a20a3a22db889e75f4ec13a21072eabb5693801e84"}, + {file = "kiwisolver-1.3.2-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:82f49c5a79d3839bc8f38cb5f4bfc87e15f04cbafa5fbd12fb32c941cb529cfb"}, + {file = "kiwisolver-1.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9661a04ca3c950a8ac8c47f53cbc0b530bce1b52f516a1e87b7736fec24bfff0"}, + {file = "kiwisolver-1.3.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2ddb500a2808c100e72c075cbb00bf32e62763c82b6a882d403f01a119e3f402"}, + {file = "kiwisolver-1.3.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:72be6ebb4e92520b9726d7146bc9c9b277513a57a38efcf66db0620aec0097e0"}, + {file = "kiwisolver-1.3.2-cp310-cp310-win32.whl", hash = "sha256:83d2c9db5dfc537d0171e32de160461230eb14663299b7e6d18ca6dca21e4977"}, + {file = "kiwisolver-1.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:cba430db673c29376135e695c6e2501c44c256a81495da849e85d1793ee975ad"}, + {file = "kiwisolver-1.3.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:4116ba9a58109ed5e4cb315bdcbff9838f3159d099ba5259c7c7fb77f8537492"}, + {file = "kiwisolver-1.3.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:19554bd8d54cf41139f376753af1a644b63c9ca93f8f72009d50a2080f870f77"}, + {file = "kiwisolver-1.3.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a7a4cf5bbdc861987a7745aed7a536c6405256853c94abc9f3287c3fa401b174"}, + {file = "kiwisolver-1.3.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0007840186bacfaa0aba4466d5890334ea5938e0bb7e28078a0eb0e63b5b59d5"}, + {file = "kiwisolver-1.3.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ec2eba188c1906b05b9b49ae55aae4efd8150c61ba450e6721f64620c50b59eb"}, + {file = "kiwisolver-1.3.2-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:3dbb3cea20b4af4f49f84cffaf45dd5f88e8594d18568e0225e6ad9dec0e7967"}, + {file = "kiwisolver-1.3.2-cp37-cp37m-win32.whl", hash = "sha256:5326ddfacbe51abf9469fe668944bc2e399181a2158cb5d45e1d40856b2a0589"}, + {file = "kiwisolver-1.3.2-cp37-cp37m-win_amd64.whl", hash = "sha256:c6572c2dab23c86a14e82c245473d45b4c515314f1f859e92608dcafbd2f19b8"}, + {file = "kiwisolver-1.3.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:b5074fb09429f2b7bc82b6fb4be8645dcbac14e592128beeff5461dcde0af09f"}, + {file = "kiwisolver-1.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:22521219ca739654a296eea6d4367703558fba16f98688bd8ce65abff36eaa84"}, + {file = "kiwisolver-1.3.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:c358721aebd40c243894298f685a19eb0491a5c3e0b923b9f887ef1193ddf829"}, + {file = "kiwisolver-1.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7ba5a1041480c6e0a8b11a9544d53562abc2d19220bfa14133e0cdd9967e97af"}, + {file = "kiwisolver-1.3.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:44e6adf67577dbdfa2d9f06db9fbc5639afefdb5bf2b4dfec25c3a7fbc619536"}, + {file = "kiwisolver-1.3.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1d45d1c74f88b9f41062716c727f78f2a59a5476ecbe74956fafb423c5c87a76"}, + {file = "kiwisolver-1.3.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:70adc3658138bc77a36ce769f5f183169bc0a2906a4f61f09673f7181255ac9b"}, + {file = "kiwisolver-1.3.2-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:b6a5431940f28b6de123de42f0eb47b84a073ee3c3345dc109ad550a3307dd28"}, + {file = "kiwisolver-1.3.2-cp38-cp38-win32.whl", hash = "sha256:ee040a7de8d295dbd261ef2d6d3192f13e2b08ec4a954de34a6fb8ff6422e24c"}, + {file = "kiwisolver-1.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:8dc3d842fa41a33fe83d9f5c66c0cc1f28756530cd89944b63b072281e852031"}, + {file = "kiwisolver-1.3.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:a498bcd005e8a3fedd0022bb30ee0ad92728154a8798b703f394484452550507"}, + {file = "kiwisolver-1.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:80efd202108c3a4150e042b269f7c78643420cc232a0a771743bb96b742f838f"}, + {file = "kiwisolver-1.3.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f8eb7b6716f5b50e9c06207a14172cf2de201e41912ebe732846c02c830455b9"}, + {file = "kiwisolver-1.3.2-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:f441422bb313ab25de7b3dbfd388e790eceb76ce01a18199ec4944b369017009"}, + {file = "kiwisolver-1.3.2-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:30fa008c172355c7768159983a7270cb23838c4d7db73d6c0f6b60dde0d432c6"}, + {file = "kiwisolver-1.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2f8f6c8f4f1cff93ca5058d6ec5f0efda922ecb3f4c5fb76181f327decff98b8"}, + {file = "kiwisolver-1.3.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ba677bcaff9429fd1bf01648ad0901cea56c0d068df383d5f5856d88221fe75b"}, + {file = "kiwisolver-1.3.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7843b1624d6ccca403a610d1277f7c28ad184c5aa88a1750c1a999754e65b439"}, + {file = "kiwisolver-1.3.2-cp39-cp39-win32.whl", hash = "sha256:e6f5eb2f53fac7d408a45fbcdeda7224b1cfff64919d0f95473420a931347ae9"}, + {file = "kiwisolver-1.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:eedd3b59190885d1ebdf6c5e0ca56828beb1949b4dfe6e5d0256a461429ac386"}, + {file = "kiwisolver-1.3.2-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:dedc71c8eb9c5096037766390172c34fb86ef048b8e8958b4e484b9e505d66bc"}, + {file = "kiwisolver-1.3.2-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:bf7eb45d14fc036514c09554bf983f2a72323254912ed0c3c8e697b62c4c158f"}, + {file = "kiwisolver-1.3.2-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:2b65bd35f3e06a47b5c30ea99e0c2b88f72c6476eedaf8cfbc8e66adb5479dcf"}, + {file = "kiwisolver-1.3.2-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:25405f88a37c5f5bcba01c6e350086d65e7465fd1caaf986333d2a045045a223"}, + {file = "kiwisolver-1.3.2-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:bcadb05c3d4794eb9eee1dddf1c24215c92fb7b55a80beae7a60530a91060560"}, + {file = "kiwisolver-1.3.2.tar.gz", hash = "sha256:fc4453705b81d03568d5b808ad8f09c77c47534f6ac2e72e733f9ca4714aa75c"}, ] markupsafe = [ + {file = "MarkupSafe-2.0.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d8446c54dc28c01e5a2dbac5a25f071f6653e6e40f3a8818e8b45d790fe6ef53"}, + {file = "MarkupSafe-2.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:36bc903cbb393720fad60fc28c10de6acf10dc6cc883f3e24ee4012371399a38"}, + {file = "MarkupSafe-2.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2d7d807855b419fc2ed3e631034685db6079889a1f01d5d9dac950f764da3dad"}, + {file = "MarkupSafe-2.0.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:add36cb2dbb8b736611303cd3bfcee00afd96471b09cda130da3581cbdc56a6d"}, + {file = "MarkupSafe-2.0.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:168cd0a3642de83558a5153c8bd34f175a9a6e7f6dc6384b9655d2697312a646"}, + {file = "MarkupSafe-2.0.1-cp310-cp310-win32.whl", hash = "sha256:99df47edb6bda1249d3e80fdabb1dab8c08ef3975f69aed437cb69d0a5de1e28"}, + {file = "MarkupSafe-2.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:e0f138900af21926a02425cf736db95be9f4af72ba1bb21453432a07f6082134"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:f9081981fe268bd86831e5c75f7de206ef275defcb82bc70740ae6dc507aee51"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:0955295dd5eec6cb6cc2fe1698f4c6d84af2e92de33fbcac4111913cd100a6ff"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:0446679737af14f45767963a1a9ef7620189912317d095f2d9ffa183a4d25d2b"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:f826e31d18b516f653fe296d967d700fddad5901ae07c622bb3705955e1faa94"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:fa130dd50c57d53368c9d59395cb5526eda596d3ffe36666cd81a44d56e48872"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:905fec760bd2fa1388bb5b489ee8ee5f7291d692638ea5f67982d968366bef9f"}, + {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bf5d821ffabf0ef3533c39c518f3357b171a1651c1ff6827325e4489b0e46c3c"}, + {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:0d4b31cc67ab36e3392bbf3862cfbadac3db12bdd8b02a2731f509ed5b829724"}, + {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:baa1a4e8f868845af802979fcdbf0bb11f94f1cb7ced4c4b8a351bb60d108145"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-win32.whl", hash = "sha256:6c4ca60fa24e85fe25b912b01e62cb969d69a23a5d5867682dd3e80b5b02581d"}, {file = "MarkupSafe-2.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:b2f4bf27480f5e5e8ce285a8c8fd176c0b03e93dcc6646477d4630e83440c6a9"}, {file = "MarkupSafe-2.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0717a7390a68be14b8c793ba258e075c6f4ca819f15edfc2a3a027c823718567"}, @@ -1147,14 +1238,21 @@ markupsafe = [ {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:d7f9850398e85aba693bb640262d3611788b1f29a79f0c93c565694658f4071f"}, {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:6a7fae0dd14cf60ad5ff42baa2e95727c3d81ded453457771d02b7d2b3f9c0c2"}, {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:b7f2d075102dc8c794cbde1947378051c4e5180d52d276987b8d28a3bd58c17d"}, + {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e9936f0b261d4df76ad22f8fee3ae83b60d7c3e871292cd42f40b81b70afae85"}, + {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:2a7d351cbd8cfeb19ca00de495e224dea7e7d919659c2841bbb7f420ad03e2d6"}, + {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:60bf42e36abfaf9aff1f50f52644b336d4f0a3fd6d8a60ca0d054ac9f713a864"}, {file = "MarkupSafe-2.0.1-cp37-cp37m-win32.whl", hash = "sha256:a30e67a65b53ea0a5e62fe23682cfe22712e01f453b95233b25502f7c61cb415"}, {file = "MarkupSafe-2.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:611d1ad9a4288cf3e3c16014564df047fe08410e628f89805e475368bd304914"}, + {file = "MarkupSafe-2.0.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5bb28c636d87e840583ee3adeb78172efc47c8b26127267f54a9c0ec251d41a9"}, {file = "MarkupSafe-2.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:be98f628055368795d818ebf93da628541e10b75b41c559fdf36d104c5787066"}, {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:1d609f577dc6e1aa17d746f8bd3c31aa4d258f4070d61b2aa5c4166c1539de35"}, {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:7d91275b0245b1da4d4cfa07e0faedd5b0812efc15b702576d103293e252af1b"}, {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:01a9b8ea66f1658938f65b93a85ebe8bc016e6769611be228d797c9d998dd298"}, {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:47ab1e7b91c098ab893b828deafa1203de86d0bc6ab587b160f78fe6c4011f75"}, {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:97383d78eb34da7e1fa37dd273c20ad4320929af65d156e35a5e2d89566d9dfb"}, + {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6fcf051089389abe060c9cd7caa212c707e58153afa2c649f00346ce6d260f1b"}, + {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:5855f8438a7d1d458206a2466bf82b0f104a3724bf96a1c781ab731e4201731a"}, + {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:3dd007d54ee88b46be476e293f48c85048603f5f516008bee124ddd891398ed6"}, {file = "MarkupSafe-2.0.1-cp38-cp38-win32.whl", hash = "sha256:023cb26ec21ece8dc3907c0e8320058b2e0cb3c55cf9564da612bc325bed5e64"}, {file = "MarkupSafe-2.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:984d76483eb32f1bcb536dc27e4ad56bba4baa70be32fa87152832cdd9db0833"}, {file = "MarkupSafe-2.0.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:2ef54abee730b502252bcdf31b10dacb0a416229b72c18b19e24a4509f273d26"}, @@ -1164,50 +1262,55 @@ markupsafe = [ {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:4efca8f86c54b22348a5467704e3fec767b2db12fc39c6d963168ab1d3fc9135"}, {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:ab3ef638ace319fa26553db0624c4699e31a28bb2a835c5faca8f8acf6a5a902"}, {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:f8ba0e8349a38d3001fae7eadded3f6606f0da5d748ee53cc1dab1d6527b9509"}, + {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c47adbc92fc1bb2b3274c4b3a43ae0e4573d9fbff4f54cd484555edbf030baf1"}, + {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:37205cac2a79194e3750b0af2a5720d95f786a55ce7df90c3af697bfa100eaac"}, + {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:1f2ade76b9903f39aa442b4aadd2177decb66525062db244b35d71d0ee8599b6"}, {file = "MarkupSafe-2.0.1-cp39-cp39-win32.whl", hash = "sha256:10f82115e21dc0dfec9ab5c0223652f7197feb168c940f3ef61563fc2d6beb74"}, {file = "MarkupSafe-2.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:693ce3f9e70a6cf7d2fb9e6c9d8b204b6b39897a2c4a1aa65728d5ac97dcc1d8"}, {file = "MarkupSafe-2.0.1.tar.gz", hash = "sha256:594c67807fb16238b30c44bdf74f36c02cdf22d1c8cda91ef8a0ed8dabf5620a"}, ] matplotlib = [ - {file = "matplotlib-3.4.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c541ee5a3287efe066bbe358320853cf4916bc14c00c38f8f3d8d75275a405a9"}, - {file = "matplotlib-3.4.2-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:3a5c18dbd2c7c366da26a4ad1462fe3e03a577b39e3b503bbcf482b9cdac093c"}, - {file = "matplotlib-3.4.2-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:a9d8cb5329df13e0cdaa14b3b43f47b5e593ec637f13f14db75bb16e46178b05"}, - {file = "matplotlib-3.4.2-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:7ad19f3fb6145b9eb41c08e7cbb9f8e10b91291396bee21e9ce761bb78df63ec"}, - {file = "matplotlib-3.4.2-cp37-cp37m-win32.whl", hash = "sha256:7a58f3d8fe8fac3be522c79d921c9b86e090a59637cb88e3bc51298d7a2c862a"}, - {file = "matplotlib-3.4.2-cp37-cp37m-win_amd64.whl", hash = "sha256:6382bc6e2d7e481bcd977eb131c31dee96e0fb4f9177d15ec6fb976d3b9ace1a"}, - {file = "matplotlib-3.4.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6a6a44f27aabe720ec4fd485061e8a35784c2b9ffa6363ad546316dfc9cea04e"}, - {file = "matplotlib-3.4.2-cp38-cp38-manylinux1_i686.whl", hash = "sha256:1c1779f7ab7d8bdb7d4c605e6ffaa0614b3e80f1e3c8ccf7b9269a22dbc5986b"}, - {file = "matplotlib-3.4.2-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:5826f56055b9b1c80fef82e326097e34dc4af8c7249226b7dd63095a686177d1"}, - {file = "matplotlib-3.4.2-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:0bea5ec5c28d49020e5d7923c2725b837e60bc8be99d3164af410eb4b4c827da"}, - {file = "matplotlib-3.4.2-cp38-cp38-win32.whl", hash = "sha256:6475d0209024a77f869163ec3657c47fed35d9b6ed8bccba8aa0f0099fbbdaa8"}, - {file = "matplotlib-3.4.2-cp38-cp38-win_amd64.whl", hash = "sha256:21b31057bbc5e75b08e70a43cefc4c0b2c2f1b1a850f4a0f7af044eb4163086c"}, - {file = "matplotlib-3.4.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b26535b9de85326e6958cdef720ecd10bcf74a3f4371bf9a7e5b2e659c17e153"}, - {file = "matplotlib-3.4.2-cp39-cp39-manylinux1_i686.whl", hash = "sha256:32fa638cc10886885d1ca3d409d4473d6a22f7ceecd11322150961a70fab66dd"}, - {file = "matplotlib-3.4.2-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:956c8849b134b4a343598305a3ca1bdd3094f01f5efc8afccdebeffe6b315247"}, - {file = "matplotlib-3.4.2-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:85f191bb03cb1a7b04b5c2cca4792bef94df06ef473bc49e2818105671766fee"}, - {file = "matplotlib-3.4.2-cp39-cp39-win32.whl", hash = "sha256:b1d5a2cedf5de05567c441b3a8c2651fbde56df08b82640e7f06c8cd91e201f6"}, - {file = "matplotlib-3.4.2-cp39-cp39-win_amd64.whl", hash = "sha256:df815378a754a7edd4559f8c51fc7064f779a74013644a7f5ac7a0c31f875866"}, - {file = "matplotlib-3.4.2.tar.gz", hash = "sha256:d8d994cefdff9aaba45166eb3de4f5211adb4accac85cbf97137e98f26ea0219"}, + {file = "matplotlib-3.4.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:5c988bb43414c7c2b0a31bd5187b4d27fd625c080371b463a6d422047df78913"}, + {file = "matplotlib-3.4.3-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:f1c5efc278d996af8a251b2ce0b07bbeccb821f25c8c9846bdcb00ffc7f158aa"}, + {file = "matplotlib-3.4.3-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:eeb1859efe7754b1460e1d4991bbd4a60a56f366bc422ef3a9c5ae05f0bc70b5"}, + {file = "matplotlib-3.4.3-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:844a7b0233e4ff7fba57e90b8799edaa40b9e31e300b8d5efc350937fa8b1bea"}, + {file = "matplotlib-3.4.3-cp37-cp37m-win32.whl", hash = "sha256:85f0c9cf724715e75243a7b3087cf4a3de056b55e05d4d76cc58d610d62894f3"}, + {file = "matplotlib-3.4.3-cp37-cp37m-win_amd64.whl", hash = "sha256:c70b6311dda3e27672f1bf48851a0de816d1ca6aaf3d49365fbdd8e959b33d2b"}, + {file = "matplotlib-3.4.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b884715a59fec9ad3b6048ecf3860f3b2ce965e676ef52593d6fa29abcf7d330"}, + {file = "matplotlib-3.4.3-cp38-cp38-manylinux1_i686.whl", hash = "sha256:a78a3b51f29448c7f4d4575e561f6b0dbb8d01c13c2046ab6c5220eb25c06506"}, + {file = "matplotlib-3.4.3-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:6a724e3a48a54b8b6e7c4ae38cd3d07084508fa47c410c8757e9db9791421838"}, + {file = "matplotlib-3.4.3-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:48e1e0859b54d5f2e29bb78ca179fd59b971c6ceb29977fb52735bfd280eb0f5"}, + {file = "matplotlib-3.4.3-cp38-cp38-win32.whl", hash = "sha256:01c9de93a2ca0d128c9064f23709362e7fefb34910c7c9e0b8ab0de8258d5eda"}, + {file = "matplotlib-3.4.3-cp38-cp38-win_amd64.whl", hash = "sha256:ebfb01a65c3f5d53a8c2a8133fec2b5221281c053d944ae81ff5822a68266617"}, + {file = "matplotlib-3.4.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b8b53f336a4688cfce615887505d7e41fd79b3594bf21dd300531a4f5b4f746a"}, + {file = "matplotlib-3.4.3-cp39-cp39-manylinux1_i686.whl", hash = "sha256:fcd6f1954943c0c192bfbebbac263f839d7055409f1173f80d8b11a224d236da"}, + {file = "matplotlib-3.4.3-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:6be8df61b1626e1a142c57e065405e869e9429b4a6dab4a324757d0dc4d42235"}, + {file = "matplotlib-3.4.3-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:41b6e307458988891fcdea2d8ecf84a8c92d53f84190aa32da65f9505546e684"}, + {file = "matplotlib-3.4.3-cp39-cp39-win32.whl", hash = "sha256:f72657f1596199dc1e4e7a10f52a4784ead8a711f4e5b59bea95bdb97cf0e4fd"}, + {file = "matplotlib-3.4.3-cp39-cp39-win_amd64.whl", hash = "sha256:f15edcb0629a0801738925fe27070480f446fcaa15de65946ff946ad99a59a40"}, + {file = "matplotlib-3.4.3-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:556965514b259204637c360d213de28d43a1f4aed1eca15596ce83f768c5a56f"}, + {file = "matplotlib-3.4.3-pp37-pypy37_pp73-manylinux2010_x86_64.whl", hash = "sha256:54a026055d5f8614f184e588f6e29064019a0aa8448450214c0b60926d62d919"}, + {file = "matplotlib-3.4.3.tar.gz", hash = "sha256:fc4f526dfdb31c9bd6b8ca06bf9fab663ca12f3ec9cdf4496fb44bc680140318"}, ] matplotlib-inline = [ - {file = "matplotlib-inline-0.1.2.tar.gz", hash = "sha256:f41d5ff73c9f5385775d5c0bc13b424535c8402fe70ea8210f93e11f3683993e"}, - {file = "matplotlib_inline-0.1.2-py3-none-any.whl", hash = "sha256:5cf1176f554abb4fa98cb362aa2b55c500147e4bdbb07e3fda359143e1da0811"}, + {file = "matplotlib-inline-0.1.3.tar.gz", hash = "sha256:a04bfba22e0d1395479f866853ec1ee28eea1485c1d69a6faf00dc3e24ff34ee"}, + {file = "matplotlib_inline-0.1.3-py3-none-any.whl", hash = "sha256:aed605ba3b72462d64d475a21a9296f400a19c4f74a31b59103d2a99ffd5aa5c"}, ] mistune = [ {file = "mistune-0.8.4-py2.py3-none-any.whl", hash = "sha256:88a1051873018da288eee8538d476dffe1262495144b33ecb586c4ab266bb8d4"}, {file = "mistune-0.8.4.tar.gz", hash = "sha256:59a3429db53c50b5c6bcc8a07f8848cb00d7dc8bdb431a4ab41920d201d4756e"}, ] nbclassic = [ - {file = "nbclassic-0.3.1-py3-none-any.whl", hash = "sha256:a7437c90a0bffcce172a4540cc53e140ea5987280c87c31a0cfa6e5d315eb907"}, - {file = "nbclassic-0.3.1.tar.gz", hash = "sha256:f920f8d09849bea7950e1017ff3bd101763a8d68f565a51ce053572e65aa7947"}, + {file = "nbclassic-0.3.2-py3-none-any.whl", hash = "sha256:57936a39410a18261442ca3b298421f859c9012272b87bf55e17b5507f052f4d"}, + {file = "nbclassic-0.3.2.tar.gz", hash = "sha256:863462bf6a6e0e5e502dcc479ce2ea1edf60437c969f1850d0c0823dba0c39b7"}, ] nbclient = [ - {file = "nbclient-0.5.3-py3-none-any.whl", hash = "sha256:e79437364a2376892b3f46bedbf9b444e5396cfb1bc366a472c37b48e9551500"}, - {file = "nbclient-0.5.3.tar.gz", hash = "sha256:db17271330c68c8c88d46d72349e24c147bb6f34ec82d8481a8f025c4d26589c"}, + {file = "nbclient-0.5.4-py3-none-any.whl", hash = "sha256:95a300c6fbe73721736cf13972a46d8d666f78794b832866ed7197a504269e11"}, + {file = "nbclient-0.5.4.tar.gz", hash = "sha256:6c8ad36a28edad4562580847f9f1636fe5316a51a323ed85a24a4ad37d4aefce"}, ] nbconvert = [ - {file = "nbconvert-6.0.7-py3-none-any.whl", hash = "sha256:39e9f977920b203baea0be67eea59f7b37a761caa542abe80f5897ce3cf6311d"}, - {file = "nbconvert-6.0.7.tar.gz", hash = "sha256:cbbc13a86dfbd4d1b5dee106539de0795b4db156c894c2c5dc382062bbc29002"}, + {file = "nbconvert-6.2.0-py3-none-any.whl", hash = "sha256:b1b9dc4f1ff6cafae0e6d91f42fb9046fdc32e6beb6d7e2fa2cd7191ad535240"}, + {file = "nbconvert-6.2.0.tar.gz", hash = "sha256:16ceecd0afaa8fd26c245fa32e2c52066c02f13aa73387fffafd84750baea863"}, ] nbformat = [ {file = "nbformat-5.1.3-py3-none-any.whl", hash = "sha256:eb8447edd7127d043361bc17f2f5a807626bc8e878c7709a1c647abda28a9171"}, @@ -1218,59 +1321,69 @@ nest-asyncio = [ {file = "nest_asyncio-1.5.1.tar.gz", hash = "sha256:afc5a1c515210a23c461932765691ad39e8eba6551c055ac8d5546e69250d0aa"}, ] notebook = [ - {file = "notebook-6.4.0-py3-none-any.whl", hash = "sha256:f7f0a71a999c7967d9418272ae4c3378a220bd28330fbfb49860e46cf8a5838a"}, - {file = "notebook-6.4.0.tar.gz", hash = "sha256:9c4625e2a2aa49d6eae4ce20cbc3d8976db19267e32d2a304880e0c10bf8aef9"}, + {file = "notebook-6.4.4-py3-none-any.whl", hash = "sha256:33488bdcc5cbef23c3cfa12cd51b0b5459a211945b5053d17405980611818149"}, + {file = "notebook-6.4.4.tar.gz", hash = "sha256:26b0095c568e307a310fd78818ad8ebade4f00462dada4c0e34cbad632b9085d"}, ] numpy = [ - {file = "numpy-1.20.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:70eb5808127284c4e5c9e836208e09d685a7978b6a216db85960b1a112eeace8"}, - {file = "numpy-1.20.3-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:6ca2b85a5997dabc38301a22ee43c82adcb53ff660b89ee88dded6b33687e1d8"}, - {file = "numpy-1.20.3-cp37-cp37m-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:c5bf0e132acf7557fc9bb8ded8b53bbbbea8892f3c9a1738205878ca9434206a"}, - {file = "numpy-1.20.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:db250fd3e90117e0312b611574cd1b3f78bec046783195075cbd7ba9c3d73f16"}, - {file = "numpy-1.20.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:637d827248f447e63585ca3f4a7d2dfaa882e094df6cfa177cc9cf9cd6cdf6d2"}, - {file = "numpy-1.20.3-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:8b7bb4b9280da3b2856cb1fc425932f46fba609819ee1c62256f61799e6a51d2"}, - {file = "numpy-1.20.3-cp37-cp37m-win32.whl", hash = "sha256:67d44acb72c31a97a3d5d33d103ab06d8ac20770e1c5ad81bdb3f0c086a56cf6"}, - {file = "numpy-1.20.3-cp37-cp37m-win_amd64.whl", hash = "sha256:43909c8bb289c382170e0282158a38cf306a8ad2ff6dfadc447e90f9961bef43"}, - {file = "numpy-1.20.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:f1452578d0516283c87608a5a5548b0cdde15b99650efdfd85182102ef7a7c17"}, - {file = "numpy-1.20.3-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:6e51534e78d14b4a009a062641f465cfaba4fdcb046c3ac0b1f61dd97c861b1b"}, - {file = "numpy-1.20.3-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:e515c9a93aebe27166ec9593411c58494fa98e5fcc219e47260d9ab8a1cc7f9f"}, - {file = "numpy-1.20.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c1c09247ccea742525bdb5f4b5ceeacb34f95731647fe55774aa36557dbb5fa4"}, - {file = "numpy-1.20.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:66fbc6fed94a13b9801fb70b96ff30605ab0a123e775a5e7a26938b717c5d71a"}, - {file = "numpy-1.20.3-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:ea9cff01e75a956dbee133fa8e5b68f2f92175233de2f88de3a682dd94deda65"}, - {file = "numpy-1.20.3-cp38-cp38-win32.whl", hash = "sha256:f39a995e47cb8649673cfa0579fbdd1cdd33ea497d1728a6cb194d6252268e48"}, - {file = "numpy-1.20.3-cp38-cp38-win_amd64.whl", hash = "sha256:1676b0a292dd3c99e49305a16d7a9f42a4ab60ec522eac0d3dd20cdf362ac010"}, - {file = "numpy-1.20.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:830b044f4e64a76ba71448fce6e604c0fc47a0e54d8f6467be23749ac2cbd2fb"}, - {file = "numpy-1.20.3-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:55b745fca0a5ab738647d0e4db099bd0a23279c32b31a783ad2ccea729e632df"}, - {file = "numpy-1.20.3-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:5d050e1e4bc9ddb8656d7b4f414557720ddcca23a5b88dd7cff65e847864c400"}, - {file = "numpy-1.20.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a9c65473ebc342715cb2d7926ff1e202c26376c0dcaaee85a1fd4b8d8c1d3b2f"}, - {file = "numpy-1.20.3-cp39-cp39-win32.whl", hash = "sha256:16f221035e8bd19b9dc9a57159e38d2dd060b48e93e1d843c49cb370b0f415fd"}, - {file = "numpy-1.20.3-cp39-cp39-win_amd64.whl", hash = "sha256:6690080810f77485667bfbff4f69d717c3be25e5b11bb2073e76bb3f578d99b4"}, - {file = "numpy-1.20.3-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:4e465afc3b96dbc80cf4a5273e5e2b1e3451286361b4af70ce1adb2984d392f9"}, - {file = "numpy-1.20.3.zip", hash = "sha256:e55185e51b18d788e49fe8305fd73ef4470596b33fc2c1ceb304566b99c71a69"}, + {file = "numpy-1.21.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:38e8648f9449a549a7dfe8d8755a5979b45b3538520d1e735637ef28e8c2dc50"}, + {file = "numpy-1.21.1-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:fd7d7409fa643a91d0a05c7554dd68aa9c9bb16e186f6ccfe40d6e003156e33a"}, + {file = "numpy-1.21.1-cp37-cp37m-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:a75b4498b1e93d8b700282dc8e655b8bd559c0904b3910b144646dbbbc03e062"}, + {file = "numpy-1.21.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1412aa0aec3e00bc23fbb8664d76552b4efde98fb71f60737c83efbac24112f1"}, + {file = "numpy-1.21.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e46ceaff65609b5399163de5893d8f2a82d3c77d5e56d976c8b5fb01faa6b671"}, + {file = "numpy-1.21.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:c6a2324085dd52f96498419ba95b5777e40b6bcbc20088fddb9e8cbb58885e8e"}, + {file = "numpy-1.21.1-cp37-cp37m-win32.whl", hash = "sha256:73101b2a1fef16602696d133db402a7e7586654682244344b8329cdcbbb82172"}, + {file = "numpy-1.21.1-cp37-cp37m-win_amd64.whl", hash = "sha256:7a708a79c9a9d26904d1cca8d383bf869edf6f8e7650d85dbc77b041e8c5a0f8"}, + {file = "numpy-1.21.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:95b995d0c413f5d0428b3f880e8fe1660ff9396dcd1f9eedbc311f37b5652e16"}, + {file = "numpy-1.21.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:635e6bd31c9fb3d475c8f44a089569070d10a9ef18ed13738b03049280281267"}, + {file = "numpy-1.21.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4a3d5fb89bfe21be2ef47c0614b9c9c707b7362386c9a3ff1feae63e0267ccb6"}, + {file = "numpy-1.21.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:8a326af80e86d0e9ce92bcc1e65c8ff88297de4fa14ee936cb2293d414c9ec63"}, + {file = "numpy-1.21.1-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:791492091744b0fe390a6ce85cc1bf5149968ac7d5f0477288f78c89b385d9af"}, + {file = "numpy-1.21.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0318c465786c1f63ac05d7c4dbcecd4d2d7e13f0959b01b534ea1e92202235c5"}, + {file = "numpy-1.21.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9a513bd9c1551894ee3d31369f9b07460ef223694098cf27d399513415855b68"}, + {file = "numpy-1.21.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:91c6f5fc58df1e0a3cc0c3a717bb3308ff850abdaa6d2d802573ee2b11f674a8"}, + {file = "numpy-1.21.1-cp38-cp38-win32.whl", hash = "sha256:978010b68e17150db8765355d1ccdd450f9fc916824e8c4e35ee620590e234cd"}, + {file = "numpy-1.21.1-cp38-cp38-win_amd64.whl", hash = "sha256:9749a40a5b22333467f02fe11edc98f022133ee1bfa8ab99bda5e5437b831214"}, + {file = "numpy-1.21.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:d7a4aeac3b94af92a9373d6e77b37691b86411f9745190d2c351f410ab3a791f"}, + {file = "numpy-1.21.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:d9e7912a56108aba9b31df688a4c4f5cb0d9d3787386b87d504762b6754fbb1b"}, + {file = "numpy-1.21.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:25b40b98ebdd272bc3020935427a4530b7d60dfbe1ab9381a39147834e985eac"}, + {file = "numpy-1.21.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:8a92c5aea763d14ba9d6475803fc7904bda7decc2a0a68153f587ad82941fec1"}, + {file = "numpy-1.21.1-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:05a0f648eb28bae4bcb204e6fd14603de2908de982e761a2fc78efe0f19e96e1"}, + {file = "numpy-1.21.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f01f28075a92eede918b965e86e8f0ba7b7797a95aa8d35e1cc8821f5fc3ad6a"}, + {file = "numpy-1.21.1-cp39-cp39-win32.whl", hash = "sha256:88c0b89ad1cc24a5efbb99ff9ab5db0f9a86e9cc50240177a571fbe9c2860ac2"}, + {file = "numpy-1.21.1-cp39-cp39-win_amd64.whl", hash = "sha256:01721eefe70544d548425a07c80be8377096a54118070b8a62476866d5208e33"}, + {file = "numpy-1.21.1-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:2d4d1de6e6fb3d28781c73fbde702ac97f03d79e4ffd6598b880b2d95d62ead4"}, + {file = "numpy-1.21.1.zip", hash = "sha256:dff4af63638afcc57a3dfb9e4b26d434a7a602d225b42d746ea7fe2edf1342fd"}, ] packaging = [ - {file = "packaging-20.9-py2.py3-none-any.whl", hash = "sha256:67714da7f7bc052e064859c05c595155bd1ee9f69f76557e21f051443c20947a"}, - {file = "packaging-20.9.tar.gz", hash = "sha256:5b327ac1320dc863dca72f4514ecc086f31186744b84a230374cc1fd776feae5"}, + {file = "packaging-21.0-py3-none-any.whl", hash = "sha256:c86254f9220d55e31cc94d69bade760f0847da8000def4dfe1c6b872fd14ff14"}, + {file = "packaging-21.0.tar.gz", hash = "sha256:7dc96269f53a4ccec5c0670940a4281106dd0bb343f47b7471f779df49c2fbe7"}, ] pandas = [ - {file = "pandas-1.2.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c601c6fdebc729df4438ec1f62275d6136a0dd14d332fc0e8ce3f7d2aadb4dd6"}, - {file = "pandas-1.2.4-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:8d4c74177c26aadcfb4fd1de6c1c43c2bf822b3e0fc7a9b409eeaf84b3e92aaa"}, - {file = "pandas-1.2.4-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:b730add5267f873b3383c18cac4df2527ac4f0f0eed1c6cf37fcb437e25cf558"}, - {file = "pandas-1.2.4-cp37-cp37m-win32.whl", hash = "sha256:2cb7e8f4f152f27dc93f30b5c7a98f6c748601ea65da359af734dd0cf3fa733f"}, - {file = "pandas-1.2.4-cp37-cp37m-win_amd64.whl", hash = "sha256:2111c25e69fa9365ba80bbf4f959400054b2771ac5d041ed19415a8b488dc70a"}, - {file = "pandas-1.2.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:167693a80abc8eb28051fbd184c1b7afd13ce2c727a5af47b048f1ea3afefff4"}, - {file = "pandas-1.2.4-cp38-cp38-manylinux1_i686.whl", hash = "sha256:612add929bf3ba9d27b436cc8853f5acc337242d6b584203f207e364bb46cb12"}, - {file = "pandas-1.2.4-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:971e2a414fce20cc5331fe791153513d076814d30a60cd7348466943e6e909e4"}, - {file = "pandas-1.2.4-cp38-cp38-win32.whl", hash = "sha256:68d7baa80c74aaacbed597265ca2308f017859123231542ff8a5266d489e1858"}, - {file = "pandas-1.2.4-cp38-cp38-win_amd64.whl", hash = "sha256:bd659c11a4578af740782288cac141a322057a2e36920016e0fc7b25c5a4b686"}, - {file = "pandas-1.2.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9db70ffa8b280bb4de83f9739d514cd0735825e79eef3a61d312420b9f16b758"}, - {file = "pandas-1.2.4-cp39-cp39-manylinux1_i686.whl", hash = "sha256:298f0553fd3ba8e002c4070a723a59cdb28eda579f3e243bc2ee397773f5398b"}, - {file = "pandas-1.2.4-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:52d2472acbb8a56819a87aafdb8b5b6d2b3386e15c95bde56b281882529a7ded"}, - {file = "pandas-1.2.4-cp39-cp39-win32.whl", hash = "sha256:d0877407359811f7b853b548a614aacd7dea83b0c0c84620a9a643f180060950"}, - {file = "pandas-1.2.4-cp39-cp39-win_amd64.whl", hash = "sha256:2b063d41803b6a19703b845609c0b700913593de067b552a8b24dd8eeb8c9895"}, - {file = "pandas-1.2.4.tar.gz", hash = "sha256:649ecab692fade3cbfcf967ff936496b0cfba0af00a55dfaacd82bdda5cb2279"}, + {file = "pandas-1.3.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:68408a39a54ebadb9014ee5a4fae27b2fe524317bc80adf56c9ac59e8f8ea431"}, + {file = "pandas-1.3.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:86b16b1b920c4cb27fdd65a2c20258bcd9c794be491290660722bb0ea765054d"}, + {file = "pandas-1.3.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:37d63e78e87eb3791da7be4100a65da0383670c2b59e493d9e73098d7a879226"}, + {file = "pandas-1.3.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:53e2fb11f86f6253bb1df26e3aeab3bf2e000aaa32a953ec394571bec5dc6fd6"}, + {file = "pandas-1.3.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7326b37de08d42dd3fff5b7ef7691d0fd0bf2428f4ba5a2bdc3b3247e9a52e4c"}, + {file = "pandas-1.3.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ed2f29b4da6f6ae7c68f4b3708d9d9e59fa89b2f9e87c2b64ce055cbd39f729e"}, + {file = "pandas-1.3.3-cp37-cp37m-win32.whl", hash = "sha256:3f5020613c1d8e304840c34aeb171377dc755521bf5e69804991030c2a48aec3"}, + {file = "pandas-1.3.3-cp37-cp37m-win_amd64.whl", hash = "sha256:c399200631db9bd9335d013ec7fce4edb98651035c249d532945c78ad453f23a"}, + {file = "pandas-1.3.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:a800df4e101b721e94d04c355e611863cc31887f24c0b019572e26518cbbcab6"}, + {file = "pandas-1.3.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3334a5a9eeaca953b9db1b2b165dcdc5180b5011f3bec3a57a3580c9c22eae68"}, + {file = "pandas-1.3.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:49fd2889d8116d7acef0709e4c82b8560a8b22b0f77471391d12c27596e90267"}, + {file = "pandas-1.3.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7557b39c8e86eb0543a17a002ac1ea0f38911c3c17095bc9350d0a65b32d801c"}, + {file = "pandas-1.3.3-cp38-cp38-win32.whl", hash = "sha256:629138b7cf81a2e55aa29ce7b04c1cece20485271d1f6c469c6a0c03857db6a4"}, + {file = "pandas-1.3.3-cp38-cp38-win_amd64.whl", hash = "sha256:45649503e167d45360aa7c52f18d1591a6d5c70d2f3a26bc90a3297a30ce9a66"}, + {file = "pandas-1.3.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ebbed7312547a924df0cbe133ff1250eeb94cdff3c09a794dc991c5621c8c735"}, + {file = "pandas-1.3.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a9f1b54d7efc9df05320b14a48fb18686f781aa66cc7b47bb62fabfc67a0985c"}, + {file = "pandas-1.3.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e9bc59855598cb57f68fdabd4897d3ed2bc3a3b3bef7b868a0153c4cd03f3207"}, + {file = "pandas-1.3.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4def2ef2fb7fcd62f2aa51bacb817ee9029e5c8efe42fe527ba21f6a3ddf1a9f"}, + {file = "pandas-1.3.3-cp39-cp39-win32.whl", hash = "sha256:f7d84f321674c2f0f31887ee6d5755c54ca1ea5e144d6d54b3bbf566dd9ea0cc"}, + {file = "pandas-1.3.3-cp39-cp39-win_amd64.whl", hash = "sha256:e574c2637c9d27f322e911650b36e858c885702c5996eda8a5a60e35e6648cf2"}, + {file = "pandas-1.3.3.tar.gz", hash = "sha256:272c8cb14aa9793eada6b1ebe81994616e647b5892a370c7135efb2924b701df"}, ] pandocfilters = [ - {file = "pandocfilters-1.4.3.tar.gz", hash = "sha256:bc63fbb50534b4b1f8ebe1860889289e8af94a23bff7445259592df25a3906eb"}, + {file = "pandocfilters-1.5.0-py2.py3-none-any.whl", hash = "sha256:33aae3f25fd1a026079f5d27bdd52496f0e0803b3469282162bafdcbdf6ef14f"}, + {file = "pandocfilters-1.5.0.tar.gz", hash = "sha256:0b679503337d233b4339a817bfc8c50064e2eff681314376a47cb582305a7a38"}, ] parso = [ {file = "parso-0.8.2-py2.py3-none-any.whl", hash = "sha256:a8c4922db71e4fdb90e0d0bc6e50f9b273d3397925e5e60a717e719201778d22"}, @@ -1285,47 +1398,67 @@ pickleshare = [ {file = "pickleshare-0.7.5.tar.gz", hash = "sha256:87683d47965c1da65cdacaf31c8441d12b8044cdec9aca500cd78fc2c683afca"}, ] pillow = [ - {file = "Pillow-8.2.0-cp36-cp36m-macosx_10_10_x86_64.whl", hash = "sha256:dc38f57d8f20f06dd7c3161c59ca2c86893632623f33a42d592f097b00f720a9"}, - {file = "Pillow-8.2.0-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:a013cbe25d20c2e0c4e85a9daf438f85121a4d0344ddc76e33fd7e3965d9af4b"}, - {file = "Pillow-8.2.0-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:8bb1e155a74e1bfbacd84555ea62fa21c58e0b4e7e6b20e4447b8d07990ac78b"}, - {file = "Pillow-8.2.0-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:c5236606e8570542ed424849f7852a0ff0bce2c4c8d0ba05cc202a5a9c97dee9"}, - {file = "Pillow-8.2.0-cp36-cp36m-win32.whl", hash = "sha256:12e5e7471f9b637762453da74e390e56cc43e486a88289995c1f4c1dc0bfe727"}, - {file = "Pillow-8.2.0-cp36-cp36m-win_amd64.whl", hash = "sha256:5afe6b237a0b81bd54b53f835a153770802f164c5570bab5e005aad693dab87f"}, - {file = "Pillow-8.2.0-cp37-cp37m-macosx_10_10_x86_64.whl", hash = "sha256:cb7a09e173903541fa888ba010c345893cd9fc1b5891aaf060f6ca77b6a3722d"}, - {file = "Pillow-8.2.0-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:0d19d70ee7c2ba97631bae1e7d4725cdb2ecf238178096e8c82ee481e189168a"}, - {file = "Pillow-8.2.0-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:083781abd261bdabf090ad07bb69f8f5599943ddb539d64497ed021b2a67e5a9"}, - {file = "Pillow-8.2.0-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:c6b39294464b03457f9064e98c124e09008b35a62e3189d3513e5148611c9388"}, - {file = "Pillow-8.2.0-cp37-cp37m-win32.whl", hash = "sha256:01425106e4e8cee195a411f729cff2a7d61813b0b11737c12bd5991f5f14bcd5"}, - {file = "Pillow-8.2.0-cp37-cp37m-win_amd64.whl", hash = "sha256:3b570f84a6161cf8865c4e08adf629441f56e32f180f7aa4ccbd2e0a5a02cba2"}, - {file = "Pillow-8.2.0-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:031a6c88c77d08aab84fecc05c3cde8414cd6f8406f4d2b16fed1e97634cc8a4"}, - {file = "Pillow-8.2.0-cp38-cp38-manylinux1_i686.whl", hash = "sha256:66cc56579fd91f517290ab02c51e3a80f581aba45fd924fcdee01fa06e635812"}, - {file = "Pillow-8.2.0-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:6c32cc3145928c4305d142ebec682419a6c0a8ce9e33db900027ddca1ec39178"}, - {file = "Pillow-8.2.0-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:624b977355cde8b065f6d51b98497d6cd5fbdd4f36405f7a8790e3376125e2bb"}, - {file = "Pillow-8.2.0-cp38-cp38-win32.whl", hash = "sha256:5cbf3e3b1014dddc45496e8cf38b9f099c95a326275885199f427825c6522232"}, - {file = "Pillow-8.2.0-cp38-cp38-win_amd64.whl", hash = "sha256:463822e2f0d81459e113372a168f2ff59723e78528f91f0bd25680ac185cf797"}, - {file = "Pillow-8.2.0-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:95d5ef984eff897850f3a83883363da64aae1000e79cb3c321915468e8c6add5"}, - {file = "Pillow-8.2.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b91c36492a4bbb1ee855b7d16fe51379e5f96b85692dc8210831fbb24c43e484"}, - {file = "Pillow-8.2.0-cp39-cp39-manylinux1_i686.whl", hash = "sha256:d68cb92c408261f806b15923834203f024110a2e2872ecb0bd2a110f89d3c602"}, - {file = "Pillow-8.2.0-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:f217c3954ce5fd88303fc0c317af55d5e0204106d86dea17eb8205700d47dec2"}, - {file = "Pillow-8.2.0-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:5b70110acb39f3aff6b74cf09bb4169b167e2660dabc304c1e25b6555fa781ef"}, - {file = "Pillow-8.2.0-cp39-cp39-win32.whl", hash = "sha256:a7d5e9fad90eff8f6f6106d3b98b553a88b6f976e51fce287192a5d2d5363713"}, - {file = "Pillow-8.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:238c197fc275b475e87c1453b05b467d2d02c2915fdfdd4af126145ff2e4610c"}, - {file = "Pillow-8.2.0-pp36-pypy36_pp73-macosx_10_10_x86_64.whl", hash = "sha256:0e04d61f0064b545b989126197930807c86bcbd4534d39168f4aa5fda39bb8f9"}, - {file = "Pillow-8.2.0-pp36-pypy36_pp73-manylinux2010_i686.whl", hash = "sha256:63728564c1410d99e6d1ae8e3b810fe012bc440952168af0a2877e8ff5ab96b9"}, - {file = "Pillow-8.2.0-pp36-pypy36_pp73-manylinux2010_x86_64.whl", hash = "sha256:c03c07ed32c5324939b19e36ae5f75c660c81461e312a41aea30acdd46f93a7c"}, - {file = "Pillow-8.2.0-pp37-pypy37_pp73-macosx_10_10_x86_64.whl", hash = "sha256:4d98abdd6b1e3bf1a1cbb14c3895226816e666749ac040c4e2554231068c639b"}, - {file = "Pillow-8.2.0-pp37-pypy37_pp73-manylinux2010_i686.whl", hash = "sha256:aac00e4bc94d1b7813fe882c28990c1bc2f9d0e1aa765a5f2b516e8a6a16a9e4"}, - {file = "Pillow-8.2.0-pp37-pypy37_pp73-manylinux2010_x86_64.whl", hash = "sha256:22fd0f42ad15dfdde6c581347eaa4adb9a6fc4b865f90b23378aa7914895e120"}, - {file = "Pillow-8.2.0-pp37-pypy37_pp73-win32.whl", hash = "sha256:e98eca29a05913e82177b3ba3d198b1728e164869c613d76d0de4bde6768a50e"}, - {file = "Pillow-8.2.0.tar.gz", hash = "sha256:a787ab10d7bb5494e5f76536ac460741788f1fbce851068d73a87ca7c35fc3e1"}, + {file = "Pillow-8.3.2-cp310-cp310-macosx_10_10_universal2.whl", hash = "sha256:c691b26283c3a31594683217d746f1dad59a7ae1d4cfc24626d7a064a11197d4"}, + {file = "Pillow-8.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f514c2717012859ccb349c97862568fdc0479aad85b0270d6b5a6509dbc142e2"}, + {file = "Pillow-8.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:be25cb93442c6d2f8702c599b51184bd3ccd83adebd08886b682173e09ef0c3f"}, + {file = "Pillow-8.3.2-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d675a876b295afa114ca8bf42d7f86b5fb1298e1b6bb9a24405a3f6c8338811c"}, + {file = "Pillow-8.3.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:59697568a0455764a094585b2551fd76bfd6b959c9f92d4bdec9d0e14616303a"}, + {file = "Pillow-8.3.2-cp310-cp310-win32.whl", hash = "sha256:2d5e9dc0bf1b5d9048a94c48d0813b6c96fccfa4ccf276d9c36308840f40c228"}, + {file = "Pillow-8.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:11c27e74bab423eb3c9232d97553111cc0be81b74b47165f07ebfdd29d825875"}, + {file = "Pillow-8.3.2-cp36-cp36m-macosx_10_10_x86_64.whl", hash = "sha256:11eb7f98165d56042545c9e6db3ce394ed8b45089a67124298f0473b29cb60b2"}, + {file = "Pillow-8.3.2-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2f23b2d3079522fdf3c09de6517f625f7a964f916c956527bed805ac043799b8"}, + {file = "Pillow-8.3.2-cp36-cp36m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:19ec4cfe4b961edc249b0e04b5618666c23a83bc35842dea2bfd5dfa0157f81b"}, + {file = "Pillow-8.3.2-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e5a31c07cea5edbaeb4bdba6f2b87db7d3dc0f446f379d907e51cc70ea375629"}, + {file = "Pillow-8.3.2-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:15ccb81a6ffc57ea0137f9f3ac2737ffa1d11f786244d719639df17476d399a7"}, + {file = "Pillow-8.3.2-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:8f284dc1695caf71a74f24993b7c7473d77bc760be45f776a2c2f4e04c170550"}, + {file = "Pillow-8.3.2-cp36-cp36m-win32.whl", hash = "sha256:4abc247b31a98f29e5224f2d31ef15f86a71f79c7f4d2ac345a5d551d6393073"}, + {file = "Pillow-8.3.2-cp36-cp36m-win_amd64.whl", hash = "sha256:a048dad5ed6ad1fad338c02c609b862dfaa921fcd065d747194a6805f91f2196"}, + {file = "Pillow-8.3.2-cp37-cp37m-macosx_10_10_x86_64.whl", hash = "sha256:06d1adaa284696785375fa80a6a8eb309be722cf4ef8949518beb34487a3df71"}, + {file = "Pillow-8.3.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bd24054aaf21e70a51e2a2a5ed1183560d3a69e6f9594a4bfe360a46f94eba83"}, + {file = "Pillow-8.3.2-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:27a330bf7014ee034046db43ccbb05c766aa9e70b8d6c5260bfc38d73103b0ba"}, + {file = "Pillow-8.3.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:13654b521fb98abdecec105ea3fb5ba863d1548c9b58831dd5105bb3873569f1"}, + {file = "Pillow-8.3.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a1bd983c565f92779be456ece2479840ec39d386007cd4ae83382646293d681b"}, + {file = "Pillow-8.3.2-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:4326ea1e2722f3dc00ed77c36d3b5354b8fb7399fb59230249ea6d59cbed90da"}, + {file = "Pillow-8.3.2-cp37-cp37m-win32.whl", hash = "sha256:085a90a99404b859a4b6c3daa42afde17cb3ad3115e44a75f0d7b4a32f06a6c9"}, + {file = "Pillow-8.3.2-cp37-cp37m-win_amd64.whl", hash = "sha256:18a07a683805d32826c09acfce44a90bf474e6a66ce482b1c7fcd3757d588df3"}, + {file = "Pillow-8.3.2-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:4e59e99fd680e2b8b11bbd463f3c9450ab799305d5f2bafb74fefba6ac058616"}, + {file = "Pillow-8.3.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4d89a2e9219a526401015153c0e9dd48319ea6ab9fe3b066a20aa9aee23d9fd3"}, + {file = "Pillow-8.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:56fd98c8294f57636084f4b076b75f86c57b2a63a8410c0cd172bc93695ee979"}, + {file = "Pillow-8.3.2-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2b11c9d310a3522b0fd3c35667914271f570576a0e387701f370eb39d45f08a4"}, + {file = "Pillow-8.3.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0412516dcc9de9b0a1e0ae25a280015809de8270f134cc2c1e32c4eeb397cf30"}, + {file = "Pillow-8.3.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:bcb04ff12e79b28be6c9988f275e7ab69f01cc2ba319fb3114f87817bb7c74b6"}, + {file = "Pillow-8.3.2-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:0b9911ec70731711c3b6ebcde26caea620cbdd9dcb73c67b0730c8817f24711b"}, + {file = "Pillow-8.3.2-cp38-cp38-win32.whl", hash = "sha256:ce2e5e04bb86da6187f96d7bab3f93a7877830981b37f0287dd6479e27a10341"}, + {file = "Pillow-8.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:35d27687f027ad25a8d0ef45dd5208ef044c588003cdcedf05afb00dbc5c2deb"}, + {file = "Pillow-8.3.2-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:04835e68ef12904bc3e1fd002b33eea0779320d4346082bd5b24bec12ad9c3e9"}, + {file = "Pillow-8.3.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:10e00f7336780ca7d3653cf3ac26f068fa11b5a96894ea29a64d3dc4b810d630"}, + {file = "Pillow-8.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2cde7a4d3687f21cffdf5bb171172070bb95e02af448c4c8b2f223d783214056"}, + {file = "Pillow-8.3.2-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1c3ff00110835bdda2b1e2b07f4a2548a39744bb7de5946dc8e95517c4fb2ca6"}, + {file = "Pillow-8.3.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:35d409030bf3bd05fa66fb5fdedc39c521b397f61ad04309c90444e893d05f7d"}, + {file = "Pillow-8.3.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6bff50ba9891be0a004ef48828e012babaaf7da204d81ab9be37480b9020a82b"}, + {file = "Pillow-8.3.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:7dbfbc0020aa1d9bc1b0b8bcf255a7d73f4ad0336f8fd2533fcc54a4ccfb9441"}, + {file = "Pillow-8.3.2-cp39-cp39-win32.whl", hash = "sha256:963ebdc5365d748185fdb06daf2ac758116deecb2277ec5ae98139f93844bc09"}, + {file = "Pillow-8.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:cc9d0dec711c914ed500f1d0d3822868760954dce98dfb0b7382a854aee55d19"}, + {file = "Pillow-8.3.2-pp36-pypy36_pp73-macosx_10_10_x86_64.whl", hash = "sha256:2c661542c6f71dfd9dc82d9d29a8386287e82813b0375b3a02983feac69ef864"}, + {file = "Pillow-8.3.2-pp36-pypy36_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:548794f99ff52a73a156771a0402f5e1c35285bd981046a502d7e4793e8facaa"}, + {file = "Pillow-8.3.2-pp36-pypy36_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:8b68f565a4175e12e68ca900af8910e8fe48aaa48fd3ca853494f384e11c8bcd"}, + {file = "Pillow-8.3.2-pp36-pypy36_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:838eb85de6d9307c19c655c726f8d13b8b646f144ca6b3771fa62b711ebf7624"}, + {file = "Pillow-8.3.2-pp36-pypy36_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:feb5db446e96bfecfec078b943cc07744cc759893cef045aa8b8b6d6aaa8274e"}, + {file = "Pillow-8.3.2-pp37-pypy37_pp73-macosx_10_10_x86_64.whl", hash = "sha256:fc0db32f7223b094964e71729c0361f93db43664dd1ec86d3df217853cedda87"}, + {file = "Pillow-8.3.2-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:fd4fd83aa912d7b89b4b4a1580d30e2a4242f3936882a3f433586e5ab97ed0d5"}, + {file = "Pillow-8.3.2-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:d0c8ebbfd439c37624db98f3877d9ed12c137cadd99dde2d2eae0dab0bbfc355"}, + {file = "Pillow-8.3.2-pp37-pypy37_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6cb3dd7f23b044b0737317f892d399f9e2f0b3a02b22b2c692851fb8120d82c6"}, + {file = "Pillow-8.3.2-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a66566f8a22561fc1a88dc87606c69b84fa9ce724f99522cf922c801ec68f5c1"}, + {file = "Pillow-8.3.2-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:ce651ca46d0202c302a535d3047c55a0131a720cf554a578fc1b8a2aff0e7d96"}, + {file = "Pillow-8.3.2.tar.gz", hash = "sha256:dde3f3ed8d00c72631bc19cbfff8ad3b6215062a5eed402381ad365f82f0c18c"}, ] prometheus-client = [ - {file = "prometheus_client-0.10.1-py2.py3-none-any.whl", hash = "sha256:030e4f9df5f53db2292eec37c6255957eb76168c6f974e4176c711cf91ed34aa"}, - {file = "prometheus_client-0.10.1.tar.gz", hash = "sha256:b6c5a9643e3545bcbfd9451766cbaa5d9c67e7303c7bc32c750b6fa70ecb107d"}, + {file = "prometheus_client-0.11.0-py2.py3-none-any.whl", hash = "sha256:b014bc76815eb1399da8ce5fc84b7717a3e63652b0c0f8804092c9363acab1b2"}, + {file = "prometheus_client-0.11.0.tar.gz", hash = "sha256:3a8baade6cb80bcfe43297e33e7623f3118d660d41387593758e2fb1ea173a86"}, ] prompt-toolkit = [ - {file = "prompt_toolkit-3.0.18-py3-none-any.whl", hash = "sha256:bf00f22079f5fadc949f42ae8ff7f05702826a97059ffcc6281036ad40ac6f04"}, - {file = "prompt_toolkit-3.0.18.tar.gz", hash = "sha256:e1b4f11b9336a28fa11810bc623c357420f69dfdb6d2dac41ca2c21a55c033bc"}, + {file = "prompt_toolkit-3.0.20-py3-none-any.whl", hash = "sha256:6076e46efae19b1e0ca1ec003ed37a933dc94b4d20f486235d436e64771dcd5c"}, + {file = "prompt_toolkit-3.0.20.tar.gz", hash = "sha256:eb71d5a6b72ce6db177af4a7d4d7085b99756bf656d98ffcc4fecd36850eea6c"}, ] ptyprocess = [ {file = "ptyprocess-0.7.0-py2.py3-none-any.whl", hash = "sha256:4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35"}, @@ -1340,115 +1473,136 @@ pycparser = [ {file = "pycparser-2.20.tar.gz", hash = "sha256:2d475327684562c3a96cc71adf7dc8c4f0565175cf86b6d7a404ff4c771f15f0"}, ] pygments = [ - {file = "Pygments-2.9.0-py3-none-any.whl", hash = "sha256:d66e804411278594d764fc69ec36ec13d9ae9147193a1740cd34d272ca383b8e"}, - {file = "Pygments-2.9.0.tar.gz", hash = "sha256:a18f47b506a429f6f4b9df81bb02beab9ca21d0a5fee38ed15aef65f0545519f"}, + {file = "Pygments-2.10.0-py3-none-any.whl", hash = "sha256:b8e67fe6af78f492b3c4b3e2970c0624cbf08beb1e493b2c99b9fa1b67a20380"}, + {file = "Pygments-2.10.0.tar.gz", hash = "sha256:f398865f7eb6874156579fdf36bc840a03cab64d1cde9e93d68f46a425ec52c6"}, ] pyparsing = [ {file = "pyparsing-2.4.7-py2.py3-none-any.whl", hash = "sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b"}, {file = "pyparsing-2.4.7.tar.gz", hash = "sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1"}, ] pyrsistent = [ - {file = "pyrsistent-0.17.3.tar.gz", hash = "sha256:2e636185d9eb976a18a8a8e96efce62f2905fea90041958d8cc2a189756ebf3e"}, + {file = "pyrsistent-0.18.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:f4c8cabb46ff8e5d61f56a037974228e978f26bfefce4f61a4b1ac0ba7a2ab72"}, + {file = "pyrsistent-0.18.0-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:da6e5e818d18459fa46fac0a4a4e543507fe1110e808101277c5a2b5bab0cd2d"}, + {file = "pyrsistent-0.18.0-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:5e4395bbf841693eaebaa5bb5c8f5cdbb1d139e07c975c682ec4e4f8126e03d2"}, + {file = "pyrsistent-0.18.0-cp36-cp36m-win32.whl", hash = "sha256:527be2bfa8dc80f6f8ddd65242ba476a6c4fb4e3aedbf281dfbac1b1ed4165b1"}, + {file = "pyrsistent-0.18.0-cp36-cp36m-win_amd64.whl", hash = "sha256:2aaf19dc8ce517a8653746d98e962ef480ff34b6bc563fc067be6401ffb457c7"}, + {file = "pyrsistent-0.18.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:58a70d93fb79dc585b21f9d72487b929a6fe58da0754fa4cb9f279bb92369396"}, + {file = "pyrsistent-0.18.0-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:4916c10896721e472ee12c95cdc2891ce5890898d2f9907b1b4ae0f53588b710"}, + {file = "pyrsistent-0.18.0-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:73ff61b1411e3fb0ba144b8f08d6749749775fe89688093e1efef9839d2dcc35"}, + {file = "pyrsistent-0.18.0-cp37-cp37m-win32.whl", hash = "sha256:b29b869cf58412ca5738d23691e96d8aff535e17390128a1a52717c9a109da4f"}, + {file = "pyrsistent-0.18.0-cp37-cp37m-win_amd64.whl", hash = "sha256:097b96f129dd36a8c9e33594e7ebb151b1515eb52cceb08474c10a5479e799f2"}, + {file = "pyrsistent-0.18.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:772e94c2c6864f2cd2ffbe58bb3bdefbe2a32afa0acb1a77e472aac831f83427"}, + {file = "pyrsistent-0.18.0-cp38-cp38-manylinux1_i686.whl", hash = "sha256:c1a9ff320fa699337e05edcaae79ef8c2880b52720bc031b219e5b5008ebbdef"}, + {file = "pyrsistent-0.18.0-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:cd3caef37a415fd0dae6148a1b6957a8c5f275a62cca02e18474608cb263640c"}, + {file = "pyrsistent-0.18.0-cp38-cp38-win32.whl", hash = "sha256:e79d94ca58fcafef6395f6352383fa1a76922268fa02caa2272fff501c2fdc78"}, + {file = "pyrsistent-0.18.0-cp38-cp38-win_amd64.whl", hash = "sha256:a0c772d791c38bbc77be659af29bb14c38ced151433592e326361610250c605b"}, + {file = "pyrsistent-0.18.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:d5ec194c9c573aafaceebf05fc400656722793dac57f254cd4741f3c27ae57b4"}, + {file = "pyrsistent-0.18.0-cp39-cp39-manylinux1_i686.whl", hash = "sha256:6b5eed00e597b5b5773b4ca30bd48a5774ef1e96f2a45d105db5b4ebb4bca680"}, + {file = "pyrsistent-0.18.0-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:48578680353f41dca1ca3dc48629fb77dfc745128b56fc01096b2530c13fd426"}, + {file = "pyrsistent-0.18.0-cp39-cp39-win32.whl", hash = "sha256:f3ef98d7b76da5eb19c37fda834d50262ff9167c65658d1d8f974d2e4d90676b"}, + {file = "pyrsistent-0.18.0-cp39-cp39-win_amd64.whl", hash = "sha256:404e1f1d254d314d55adb8d87f4f465c8693d6f902f67eb6ef5b4526dc58e6ea"}, + {file = "pyrsistent-0.18.0.tar.gz", hash = "sha256:773c781216f8c2900b42a7b638d5b517bb134ae1acbebe4d1e8f1f41ea60eb4b"}, ] python-dateutil = [ - {file = "python-dateutil-2.8.1.tar.gz", hash = "sha256:73ebfe9dbf22e832286dafa60473e4cd239f8592f699aa5adaf10050e6e1823c"}, - {file = "python_dateutil-2.8.1-py2.py3-none-any.whl", hash = "sha256:75bb3f31ea686f1197762692a9ee6a7550b59fc6ca3a1f4b5d7e32fb98e2da2a"}, + {file = "python-dateutil-2.8.2.tar.gz", hash = "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86"}, + {file = "python_dateutil-2.8.2-py2.py3-none-any.whl", hash = "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"}, ] pytz = [ - {file = "pytz-2021.1-py2.py3-none-any.whl", hash = "sha256:eb10ce3e7736052ed3623d49975ce333bcd712c7bb19a58b9e2089d4057d0798"}, - {file = "pytz-2021.1.tar.gz", hash = "sha256:83a4a90894bf38e243cf052c8b58f381bfe9a7a483f6a9cab140bc7f702ac4da"}, + {file = "pytz-2021.3-py2.py3-none-any.whl", hash = "sha256:3672058bc3453457b622aab7a1c3bfd5ab0bdae451512f6cf25f64ed37f5b87c"}, + {file = "pytz-2021.3.tar.gz", hash = "sha256:acad2d8b20a1af07d4e4c9d2e9285c5ed9104354062f275f3fcd88dcef4f1326"}, ] pywin32 = [ - {file = "pywin32-300-cp35-cp35m-win32.whl", hash = "sha256:1c204a81daed2089e55d11eefa4826c05e604d27fe2be40b6bf8db7b6a39da63"}, - {file = "pywin32-300-cp35-cp35m-win_amd64.whl", hash = "sha256:350c5644775736351b77ba68da09a39c760d75d2467ecec37bd3c36a94fbed64"}, - {file = "pywin32-300-cp36-cp36m-win32.whl", hash = "sha256:a3b4c48c852d4107e8a8ec980b76c94ce596ea66d60f7a697582ea9dce7e0db7"}, - {file = "pywin32-300-cp36-cp36m-win_amd64.whl", hash = "sha256:27a30b887afbf05a9cbb05e3ffd43104a9b71ce292f64a635389dbad0ed1cd85"}, - {file = "pywin32-300-cp37-cp37m-win32.whl", hash = "sha256:d7e8c7efc221f10d6400c19c32a031add1c4a58733298c09216f57b4fde110dc"}, - {file = "pywin32-300-cp37-cp37m-win_amd64.whl", hash = "sha256:8151e4d7a19262d6694162d6da85d99a16f8b908949797fd99c83a0bfaf5807d"}, - {file = "pywin32-300-cp38-cp38-win32.whl", hash = "sha256:fbb3b1b0fbd0b4fc2a3d1d81fe0783e30062c1abed1d17c32b7879d55858cfae"}, - {file = "pywin32-300-cp38-cp38-win_amd64.whl", hash = "sha256:60a8fa361091b2eea27f15718f8eb7f9297e8d51b54dbc4f55f3d238093d5190"}, - {file = "pywin32-300-cp39-cp39-win32.whl", hash = "sha256:638b68eea5cfc8def537e43e9554747f8dee786b090e47ead94bfdafdb0f2f50"}, - {file = "pywin32-300-cp39-cp39-win_amd64.whl", hash = "sha256:b1609ce9bd5c411b81f941b246d683d6508992093203d4eb7f278f4ed1085c3f"}, + {file = "pywin32-301-cp35-cp35m-win32.whl", hash = "sha256:93367c96e3a76dfe5003d8291ae16454ca7d84bb24d721e0b74a07610b7be4a7"}, + {file = "pywin32-301-cp35-cp35m-win_amd64.whl", hash = "sha256:9635df6998a70282bd36e7ac2a5cef9ead1627b0a63b17c731312c7a0daebb72"}, + {file = "pywin32-301-cp36-cp36m-win32.whl", hash = "sha256:c866f04a182a8cb9b7855de065113bbd2e40524f570db73ef1ee99ff0a5cc2f0"}, + {file = "pywin32-301-cp36-cp36m-win_amd64.whl", hash = "sha256:dafa18e95bf2a92f298fe9c582b0e205aca45c55f989937c52c454ce65b93c78"}, + {file = "pywin32-301-cp37-cp37m-win32.whl", hash = "sha256:98f62a3f60aa64894a290fb7494bfa0bfa0a199e9e052e1ac293b2ad3cd2818b"}, + {file = "pywin32-301-cp37-cp37m-win_amd64.whl", hash = "sha256:fb3b4933e0382ba49305cc6cd3fb18525df7fd96aa434de19ce0878133bf8e4a"}, + {file = "pywin32-301-cp38-cp38-win32.whl", hash = "sha256:88981dd3cfb07432625b180f49bf4e179fb8cbb5704cd512e38dd63636af7a17"}, + {file = "pywin32-301-cp38-cp38-win_amd64.whl", hash = "sha256:8c9d33968aa7fcddf44e47750e18f3d034c3e443a707688a008a2e52bbef7e96"}, + {file = "pywin32-301-cp39-cp39-win32.whl", hash = "sha256:595d397df65f1b2e0beaca63a883ae6d8b6df1cdea85c16ae85f6d2e648133fe"}, + {file = "pywin32-301-cp39-cp39-win_amd64.whl", hash = "sha256:87604a4087434cd814ad8973bd47d6524bd1fa9e971ce428e76b62a5e0860fdf"}, ] pywinpty = [ - {file = "pywinpty-1.1.1-cp36-none-win_amd64.whl", hash = "sha256:fa2a0af28eaaacc59227c6edbc0f1525704d68b2dfa3e5b47ae21c5aa25d6d78"}, - {file = "pywinpty-1.1.1-cp37-none-win_amd64.whl", hash = "sha256:0fe3f538860c6b06e6fbe63da0ee5dab5194746b0df1be7ed65b4fce5da21d21"}, - {file = "pywinpty-1.1.1-cp38-none-win_amd64.whl", hash = "sha256:12c89765b3102d2eea3d39d191d1b0baea68fb5e3bd094c67b2575b3c9ebfa12"}, - {file = "pywinpty-1.1.1-cp39-none-win_amd64.whl", hash = "sha256:50bce6f7d9857ffe9694847af7e8bf989b198d0ebc2bf30e26d54c4622cb5c50"}, - {file = "pywinpty-1.1.1.tar.gz", hash = "sha256:4a3ffa2444daf15c5f65a76b5b2864447cc915564e41e2876816b9e4fe849070"}, + {file = "pywinpty-1.1.4-cp36-none-win_amd64.whl", hash = "sha256:fb975976ad92be44801de95fdf2b0366747767cb0528478553aff85dd63ebb09"}, + {file = "pywinpty-1.1.4-cp37-none-win_amd64.whl", hash = "sha256:5d25b30a2f87105778bc2f57cb1271f58aaa25568921ef042faf001b3b0a7307"}, + {file = "pywinpty-1.1.4-cp38-none-win_amd64.whl", hash = "sha256:c5c3550100689632f6663f39865ef8716835dab1838a9eb9b472644af92673f8"}, + {file = "pywinpty-1.1.4-cp39-none-win_amd64.whl", hash = "sha256:ad60a336d92ac38e2159320db6d5999c4c2726a141c3ed3f9694021feb6a234e"}, + {file = "pywinpty-1.1.4.tar.gz", hash = "sha256:cc700c9d5a9fcebf677ac93a4943ca9a24db6e2f11a5f0e7e8e226184c5036f7"}, ] pyzmq = [ - {file = "pyzmq-22.0.3-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:c0cde362075ee8f3d2b0353b283e203c2200243b5a15d5c5c03b78112a17e7d4"}, - {file = "pyzmq-22.0.3-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:ff1ea14075bbddd6f29bf6beb8a46d0db779bcec6b9820909584081ec119f8fd"}, - {file = "pyzmq-22.0.3-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:26380487eae4034d6c2a3fb8d0f2dff6dd0d9dd711894e8d25aa2d1938950a33"}, - {file = "pyzmq-22.0.3-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:3e29f9cf85a40d521d048b55c63f59d6c772ac1c4bf51cdfc23b62a62e377c33"}, - {file = "pyzmq-22.0.3-cp36-cp36m-win32.whl", hash = "sha256:4f34a173f813b38b83f058e267e30465ed64b22cd0cf6bad21148d3fa718f9bb"}, - {file = "pyzmq-22.0.3-cp36-cp36m-win_amd64.whl", hash = "sha256:30df70f81fe210506aa354d7fd486a39b87d9f7f24c3d3f4f698ec5d96b8c084"}, - {file = "pyzmq-22.0.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:7026f0353977431fc884abd4ac28268894bd1a780ba84bb266d470b0ec26d2ed"}, - {file = "pyzmq-22.0.3-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:6d4163704201fff0f3ab0cd5d7a0ea1514ecfffd3926d62ec7e740a04d2012c7"}, - {file = "pyzmq-22.0.3-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:763c175294d861869f18eb42901d500eda7d3fa4565f160b3b2fd2678ea0ebab"}, - {file = "pyzmq-22.0.3-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:61e4bb6cd60caf1abcd796c3f48395e22c5b486eeca6f3a8797975c57d94b03e"}, - {file = "pyzmq-22.0.3-cp37-cp37m-win32.whl", hash = "sha256:b25e5d339550a850f7e919fe8cb4c8eabe4c917613db48dab3df19bfb9a28969"}, - {file = "pyzmq-22.0.3-cp37-cp37m-win_amd64.whl", hash = "sha256:3ef50d74469b03725d781a2a03c57537d86847ccde587130fe35caafea8f75c6"}, - {file = "pyzmq-22.0.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:60e63577b85055e4cc43892fecd877b86695ee3ef12d5d10a3c5d6e77a7cc1a3"}, - {file = "pyzmq-22.0.3-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:f5831eff6b125992ec65d973f5151c48003b6754030094723ac4c6e80a97c8c4"}, - {file = "pyzmq-22.0.3-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:9221783dacb419604d5345d0e097bddef4459a9a95322de6c306bf1d9896559f"}, - {file = "pyzmq-22.0.3-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:b62ea18c0458a65ccd5be90f276f7a5a3f26a6dea0066d948ce2fa896051420f"}, - {file = "pyzmq-22.0.3-cp38-cp38-win32.whl", hash = "sha256:81e7df0da456206201e226491aa1fc449da85328bf33bbeec2c03bb3a9f18324"}, - {file = "pyzmq-22.0.3-cp38-cp38-win_amd64.whl", hash = "sha256:f52070871a0fd90a99130babf21f8af192304ec1e995bec2a9533efc21ea4452"}, - {file = "pyzmq-22.0.3-cp39-cp39-macosx_10_15_universal2.whl", hash = "sha256:c5e29fe4678f97ce429f076a2a049a3d0b2660ada8f2c621e5dc9939426056dd"}, - {file = "pyzmq-22.0.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:d18ddc6741b51f3985978f2fda57ddcdae359662d7a6b395bc8ff2292fca14bd"}, - {file = "pyzmq-22.0.3-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:4231943514812dfb74f44eadcf85e8dd8cf302b4d0bce450ce1357cac88dbfdc"}, - {file = "pyzmq-22.0.3-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:23a74de4b43c05c3044aeba0d1f3970def8f916151a712a3ac1e5cd9c0bc2902"}, - {file = "pyzmq-22.0.3-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:532af3e6dddea62d9c49062ece5add998c9823c2419da943cf95589f56737de0"}, - {file = "pyzmq-22.0.3-cp39-cp39-win32.whl", hash = "sha256:33acd2b9790818b9d00526135acf12790649d8d34b2b04d64558b469c9d86820"}, - {file = "pyzmq-22.0.3-cp39-cp39-win_amd64.whl", hash = "sha256:a558c5bc89d56d7253187dccc4e81b5bb0eac5ae9511eb4951910a1245d04622"}, - {file = "pyzmq-22.0.3-pp36-pypy36_pp73-macosx_10_9_x86_64.whl", hash = "sha256:581787c62eaa0e0db6c5413cedc393ebbadac6ddfd22e1cf9a60da23c4f1a4b2"}, - {file = "pyzmq-22.0.3-pp36-pypy36_pp73-manylinux2010_x86_64.whl", hash = "sha256:38e3dca75d81bec4f2defa14b0a65b74545812bb519a8e89c8df96bbf4639356"}, - {file = "pyzmq-22.0.3-pp36-pypy36_pp73-win32.whl", hash = "sha256:2f971431aaebe0a8b54ac018e041c2f0b949a43745444e4dadcc80d0f0ef8457"}, - {file = "pyzmq-22.0.3-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:da7d4d4c778c86b60949d17531e60c54ed3726878de8a7f8a6d6e7f8cc8c3205"}, - {file = "pyzmq-22.0.3-pp37-pypy37_pp73-manylinux2010_x86_64.whl", hash = "sha256:13465c1ff969cab328bc92f7015ce3843f6e35f8871ad79d236e4fbc85dbe4cb"}, - {file = "pyzmq-22.0.3-pp37-pypy37_pp73-win32.whl", hash = "sha256:279cc9b51db48bec2db146f38e336049ac5a59e5f12fb3a8ad864e238c1c62e3"}, - {file = "pyzmq-22.0.3.tar.gz", hash = "sha256:f7f63ce127980d40f3e6a5fdb87abf17ce1a7c2bd8bf2c7560e1bbce8ab1f92d"}, + {file = "pyzmq-22.3.0-cp310-cp310-macosx_10_15_universal2.whl", hash = "sha256:6b217b8f9dfb6628f74b94bdaf9f7408708cb02167d644edca33f38746ca12dd"}, + {file = "pyzmq-22.3.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2841997a0d85b998cbafecb4183caf51fd19c4357075dfd33eb7efea57e4c149"}, + {file = "pyzmq-22.3.0-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:f89468059ebc519a7acde1ee50b779019535db8dcf9b8c162ef669257fef7a93"}, + {file = "pyzmq-22.3.0-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:ea12133df25e3a6918718fbb9a510c6ee5d3fdd5a346320421aac3882f4feeea"}, + {file = "pyzmq-22.3.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76c532fd68b93998aab92356be280deec5de8f8fe59cd28763d2cc8a58747b7f"}, + {file = "pyzmq-22.3.0-cp310-cp310-win32.whl", hash = "sha256:67db33bea0a29d03e6eeec55a8190e033318cee3cbc732ba8fd939617cbf762d"}, + {file = "pyzmq-22.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:7661fc1d5cb73481cf710a1418a4e1e301ed7d5d924f91c67ba84b2a1b89defd"}, + {file = "pyzmq-22.3.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:79244b9e97948eaf38695f4b8e6fc63b14b78cc37f403c6642ba555517ac1268"}, + {file = "pyzmq-22.3.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ab888624ed68930442a3f3b0b921ad7439c51ba122dbc8c386e6487a658e4a4e"}, + {file = "pyzmq-22.3.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:18cd854b423fce44951c3a4d3e686bac8f1243d954f579e120a1714096637cc0"}, + {file = "pyzmq-22.3.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:de8df0684398bd74ad160afdc2a118ca28384ac6f5e234eb0508858d8d2d9364"}, + {file = "pyzmq-22.3.0-cp36-cp36m-win32.whl", hash = "sha256:3c1895c95be92600233e476fe283f042e71cf8f0b938aabf21b7aafa62a8dac9"}, + {file = "pyzmq-22.3.0-cp36-cp36m-win_amd64.whl", hash = "sha256:851977788b9caa8ed011f5f643d3ee8653af02c5fc723fa350db5125abf2be7b"}, + {file = "pyzmq-22.3.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b4ebed0977f92320f6686c96e9e8dd29eed199eb8d066936bac991afc37cbb70"}, + {file = "pyzmq-22.3.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42abddebe2c6a35180ca549fadc7228d23c1e1f76167c5ebc8a936b5804ea2df"}, + {file = "pyzmq-22.3.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c1e41b32d6f7f9c26bc731a8b529ff592f31fc8b6ef2be9fa74abd05c8a342d7"}, + {file = "pyzmq-22.3.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:be4e0f229cf3a71f9ecd633566bd6f80d9fa6afaaff5489492be63fe459ef98c"}, + {file = "pyzmq-22.3.0-cp37-cp37m-win32.whl", hash = "sha256:7c58f598d9fcc52772b89a92d72bf8829c12d09746a6d2c724c5b30076c1f11d"}, + {file = "pyzmq-22.3.0-cp37-cp37m-win_amd64.whl", hash = "sha256:2b97502c16a5ec611cd52410bdfaab264997c627a46b0f98d3f666227fd1ea2d"}, + {file = "pyzmq-22.3.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d728b08448e5ac3e4d886b165385a262883c34b84a7fe1166277fe675e1c197a"}, + {file = "pyzmq-22.3.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:480b9931bfb08bf8b094edd4836271d4d6b44150da051547d8c7113bf947a8b0"}, + {file = "pyzmq-22.3.0-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:7dc09198e4073e6015d9a8ea093fc348d4e59de49382476940c3dd9ae156fba8"}, + {file = "pyzmq-22.3.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ca6cd58f62a2751728016d40082008d3b3412a7f28ddfb4a2f0d3c130f69e74"}, + {file = "pyzmq-22.3.0-cp38-cp38-win32.whl", hash = "sha256:c0f84360dcca3481e8674393bdf931f9f10470988f87311b19d23cda869bb6b7"}, + {file = "pyzmq-22.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:f762442bab706fd874064ca218b33a1d8e40d4938e96c24dafd9b12e28017f45"}, + {file = "pyzmq-22.3.0-cp39-cp39-macosx_10_15_universal2.whl", hash = "sha256:954e73c9cd4d6ae319f1c936ad159072b6d356a92dcbbabfd6e6204b9a79d356"}, + {file = "pyzmq-22.3.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f43b4a2e6218371dd4f41e547bd919ceeb6ebf4abf31a7a0669cd11cd91ea973"}, + {file = "pyzmq-22.3.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:acebba1a23fb9d72b42471c3771b6f2f18dcd46df77482612054bd45c07dfa36"}, + {file = "pyzmq-22.3.0-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:cf98fd7a6c8aaa08dbc699ffae33fd71175696d78028281bc7b832b26f00ca57"}, + {file = "pyzmq-22.3.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d072f7dfbdb184f0786d63bda26e8a0882041b1e393fbe98940395f7fab4c5e2"}, + {file = "pyzmq-22.3.0-cp39-cp39-win32.whl", hash = "sha256:e6a02cf7271ee94674a44f4e62aa061d2d049001c844657740e156596298b70b"}, + {file = "pyzmq-22.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:d3dcb5548ead4f1123851a5ced467791f6986d68c656bc63bfff1bf9e36671e2"}, + {file = "pyzmq-22.3.0-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:3a4c9886d61d386b2b493377d980f502186cd71d501fffdba52bd2a0880cef4f"}, + {file = "pyzmq-22.3.0-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:80e043a89c6cadefd3a0712f8a1322038e819ebe9dbac7eca3bce1721bcb63bf"}, + {file = "pyzmq-22.3.0-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:1621e7a2af72cced1f6ec8ca8ca91d0f76ac236ab2e8828ac8fe909512d566cb"}, + {file = "pyzmq-22.3.0-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:d6157793719de168b199194f6b6173f0ccd3bf3499e6870fac17086072e39115"}, + {file = "pyzmq-22.3.0.tar.gz", hash = "sha256:8eddc033e716f8c91c6a2112f0a8ebc5e00532b4a6ae1eb0ccc48e027f9c671c"}, ] requests = [ - {file = "requests-2.15.1-py2.py3-none-any.whl", hash = "sha256:ff753b2196cd18b1bbeddc9dcd5c864056599f7a7d9a4fb5677e723efa2b7fb9"}, - {file = "requests-2.15.1.tar.gz", hash = "sha256:e5659b9315a0610505e050bb7190bf6fa2ccee1ac295f2b760ef9d8a03ebbb2e"}, + {file = "requests-2.26.0-py2.py3-none-any.whl", hash = "sha256:6c1246513ecd5ecd4528a0906f910e8f0f9c6b8ec72030dc9fd154dc1a6efd24"}, + {file = "requests-2.26.0.tar.gz", hash = "sha256:b8aa58f8cf793ffd8782d3d8cb19e66ef36f7aba4353eec859e74678b01b07a7"}, +] +requests-unixsocket = [ + {file = "requests-unixsocket-0.2.0.tar.gz", hash = "sha256:9e5c1a20afc3cf786197ae59c79bcdb0e7565f218f27df5f891307ee8817c1ea"}, + {file = "requests_unixsocket-0.2.0-py2.py3-none-any.whl", hash = "sha256:014d07bfb66dc805a011a8b4b306cf4ec96d2eddb589f6b2b5765e626f0dc0cc"}, ] scikit-learn = [ - {file = "scikit-learn-0.24.2.tar.gz", hash = "sha256:d14701a12417930392cd3898e9646cf5670c190b933625ebe7511b1f7d7b8736"}, - {file = "scikit_learn-0.24.2-cp36-cp36m-macosx_10_13_x86_64.whl", hash = "sha256:d5bf9c863ba4717b3917b5227463ee06860fc43931dc9026747de416c0a10fee"}, - {file = "scikit_learn-0.24.2-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:5beaeb091071625e83f5905192d8aecde65ba2f26f8b6719845bbf586f7a04a1"}, - {file = "scikit_learn-0.24.2-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:06ffdcaaf81e2a3b1b50c3ac6842cfb13df2d8b737d61f64643ed61da7389cde"}, - {file = "scikit_learn-0.24.2-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:fec42690a2eb646b384eafb021c425fab48991587edb412d4db77acc358b27ce"}, - {file = "scikit_learn-0.24.2-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:5ff3e4e4cf7592d36541edec434e09fb8ab9ba6b47608c4ffe30c9038d301897"}, - {file = "scikit_learn-0.24.2-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:3cbd734e1aefc7c5080e6b6973fe062f97c26a1cdf1a991037ca196ce1c8f427"}, - {file = "scikit_learn-0.24.2-cp36-cp36m-win32.whl", hash = "sha256:f74429a07fedb36a03c159332b914e6de757176064f9fed94b5f79ebac07d913"}, - {file = "scikit_learn-0.24.2-cp36-cp36m-win_amd64.whl", hash = "sha256:dd968a174aa82f3341a615a033fa6a8169e9320cbb46130686562db132d7f1f0"}, - {file = "scikit_learn-0.24.2-cp37-cp37m-macosx_10_13_x86_64.whl", hash = "sha256:49ec0b1361da328da9bb7f1a162836028e72556356adeb53342f8fae6b450d47"}, - {file = "scikit_learn-0.24.2-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:f18c3ed484eeeaa43a0d45dc2efb4d00fc6542ccdcfa2c45d7b635096a2ae534"}, - {file = "scikit_learn-0.24.2-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:cdf24c1b9bbeb4936456b42ac5bd32c60bb194a344951acb6bfb0cddee5439a4"}, - {file = "scikit_learn-0.24.2-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:d177fe1ff47cc235942d628d41ee5b1c6930d8f009f1a451c39b5411e8d0d4cf"}, - {file = "scikit_learn-0.24.2-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:f3ec00f023d84526381ad0c0f2cff982852d035c921bbf8ceb994f4886c00c64"}, - {file = "scikit_learn-0.24.2-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:ae19ac105cf7ce8c205a46166992fdec88081d6e783ab6e38ecfbe45729f3c39"}, - {file = "scikit_learn-0.24.2-cp37-cp37m-win32.whl", hash = "sha256:f0ed4483c258fb23150e31b91ea7d25ff8495dba108aea0b0d4206a777705350"}, - {file = "scikit_learn-0.24.2-cp37-cp37m-win_amd64.whl", hash = "sha256:39b7e3b71bcb1fe46397185d6c1a5db1c441e71c23c91a31e7ad8cc3f7305f9a"}, - {file = "scikit_learn-0.24.2-cp38-cp38-macosx_10_13_x86_64.whl", hash = "sha256:90a297330f608adeb4d2e9786c6fda395d3150739deb3d42a86d9a4c2d15bc1d"}, - {file = "scikit_learn-0.24.2-cp38-cp38-manylinux1_i686.whl", hash = "sha256:f1d2108e770907540b5248977e4cff9ffaf0f73d0d13445ee938df06ca7579c6"}, - {file = "scikit_learn-0.24.2-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:1eec963fe9ffc827442c2e9333227c4d49749a44e592f305398c1db5c1563393"}, - {file = "scikit_learn-0.24.2-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:2db429090b98045d71218a9ba913cc9b3fe78e0ba0b6b647d8748bc6d5a44080"}, - {file = "scikit_learn-0.24.2-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:62214d2954377fcf3f31ec867dd4e436df80121e7a32947a0b3244f58f45e455"}, - {file = "scikit_learn-0.24.2-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:8fac72b9688176922f9f54fda1ba5f7ffd28cbeb9aad282760186e8ceba9139a"}, - {file = "scikit_learn-0.24.2-cp38-cp38-win32.whl", hash = "sha256:ae426e3a52842c6b6d77d00f906b6031c8c2cfdfabd6af7511bb4bc9a68d720e"}, - {file = "scikit_learn-0.24.2-cp38-cp38-win_amd64.whl", hash = "sha256:038f4e9d6ef10e1f3fe82addc3a14735c299866eb10f2c77c090410904828312"}, - {file = "scikit_learn-0.24.2-cp39-cp39-macosx_10_13_x86_64.whl", hash = "sha256:48f273836e19901ba2beecd919f7b352f09310ce67c762f6e53bc6b81cacf1f0"}, - {file = "scikit_learn-0.24.2-cp39-cp39-manylinux1_i686.whl", hash = "sha256:a2a47449093dcf70babc930beba2ca0423cb7df2fa5fd76be5260703d67fa574"}, - {file = "scikit_learn-0.24.2-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:0e71ce9c7cbc20f6f8b860107ce15114da26e8675238b4b82b7e7cd37ca0c087"}, - {file = "scikit_learn-0.24.2-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:2754c85b2287333f9719db7f23fb7e357f436deed512db3417a02bf6f2830aa5"}, - {file = "scikit_learn-0.24.2-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:7be1b88c23cfac46e06404582215a917017cd2edaa2e4d40abe6aaff5458f24b"}, - {file = "scikit_learn-0.24.2-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:4e6198675a6f9d333774671bd536668680eea78e2e81c0b19e57224f58d17f37"}, - {file = "scikit_learn-0.24.2-cp39-cp39-win32.whl", hash = "sha256:cbdb0b3db99dd1d5f69d31b4234367d55475add31df4d84a3bd690ef017b55e2"}, - {file = "scikit_learn-0.24.2-cp39-cp39-win_amd64.whl", hash = "sha256:40556bea1ef26ef54bc678d00cf138a63069144a0b5f3a436eecd8f3468b903e"}, + {file = "scikit-learn-1.0.tar.gz", hash = "sha256:776800194e757cd212b47cd05907e0eb67a554ad333fe76776060dbb729e3427"}, + {file = "scikit_learn-1.0-cp37-cp37m-macosx_10_13_x86_64.whl", hash = "sha256:e8a6074f7d505bbfd30bcc1c57dc7cb150cc9c021459c2e2729854be1aefb5f7"}, + {file = "scikit_learn-1.0-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:56ab58978c7aa181856a42f8f491be953b755105040aeb070ebd6b180896f146"}, + {file = "scikit_learn-1.0-cp37-cp37m-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:b1df4d1151dd6d945324583125e6449bb74ec7cd91ffd7f850015cdb75f151b5"}, + {file = "scikit_learn-1.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b9f10b85dcd9ce80f738e33f55a32b3a538b47409dc1a59eec30b46ea96759db"}, + {file = "scikit_learn-1.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:663a6aaad92e5690b03d931f849016c9718beaa654e9a15f08bfcac750241036"}, + {file = "scikit_learn-1.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:190c178028f9073d9f61cd30a19c685993236b9b2df884f16608cbb3ff03800b"}, + {file = "scikit_learn-1.0-cp37-cp37m-win32.whl", hash = "sha256:555f4b4c10d3bef9e3cda63c3b45670a091fb50328fccd54948cd8a7cf887198"}, + {file = "scikit_learn-1.0-cp37-cp37m-win_amd64.whl", hash = "sha256:9f103cd6d7e15fa537a844c1a85c9beeeee8ec38357287c9efd3ee4bb8354e1d"}, + {file = "scikit_learn-1.0-cp38-cp38-macosx_10_13_x86_64.whl", hash = "sha256:121f78d6564000dc5e968394f45aac87981fcaaf2be40cfcd8f07b2baa1e1829"}, + {file = "scikit_learn-1.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:83ab0d0447b8de8450c554952a8399791544605caf274fc3c904e247e1584ced"}, + {file = "scikit_learn-1.0-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f8aecb3edc443e5625725ae1ef8f500fa78ce7cb0e864115864bb9f234d18290"}, + {file = "scikit_learn-1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c1f710bba72925aa96e60828df5d2a4872f5d4a4ad7bb4a4c9a6a41c9ce9a198"}, + {file = "scikit_learn-1.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4cb5ccb2b63c617ead48c6d92001273ad1b0e8e2bd4a4857edb58749a88b6d82"}, + {file = "scikit_learn-1.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:29559c207616604bbaa664bf98eed81b32d9f3d4c975065a206a5e2b268fe784"}, + {file = "scikit_learn-1.0-cp38-cp38-win32.whl", hash = "sha256:c9c329ec195cdea6a4dee3cebdb1602f4e0f69351c63bc58a4812f3c8a9f4f2d"}, + {file = "scikit_learn-1.0-cp38-cp38-win_amd64.whl", hash = "sha256:14bd46639b2149b3ed613adc095511313a0db62ba9fa31117bdcb5c23722e93b"}, + {file = "scikit_learn-1.0-cp39-cp39-macosx_10_13_x86_64.whl", hash = "sha256:efeac34d0ce6bf9404d268545867cbde9d6ecadd0e9bd7e6b468e5f4e2349875"}, + {file = "scikit_learn-1.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:af94b89a8f7759603c696b320e86e57f4b2bb4911e02bf2bae33c714ac498fb8"}, + {file = "scikit_learn-1.0-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:6d8bdacde73f5f484325179f466ce2011f79360e9a152100179c3dafb88f2a35"}, + {file = "scikit_learn-1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f7053801ceb7c51ce674c6a8e37a18fcc221c292f66ef7da84744ecf13b4a0c0"}, + {file = "scikit_learn-1.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e35135657b7103a70298cf557e4fad06af97607cb0780d8f44a2f91ca7769458"}, + {file = "scikit_learn-1.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:9d8caf7fa58791b6b26e912e44d5056818b7bb3142bfa7806f54bde47c189078"}, + {file = "scikit_learn-1.0-cp39-cp39-win32.whl", hash = "sha256:6a056637f7f9876e4c9db9b5434d340e0c97e25f00c4c04458f0ff906e82488e"}, + {file = "scikit_learn-1.0-cp39-cp39-win_amd64.whl", hash = "sha256:eed33b7ca2bf3fdd585339db42838ab0b641952e064564bff6e9a10573ea665c"}, ] scipy = [ {file = "scipy-1.6.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:a15a1f3fc0abff33e792d6049161b7795909b40b97c6cc2934ed54384017ab76"}, @@ -1472,8 +1626,8 @@ scipy = [ {file = "scipy-1.6.1.tar.gz", hash = "sha256:c4fceb864890b6168e79b0e714c585dbe2fd4222768ee90bc1aa0f8218691b11"}, ] send2trash = [ - {file = "Send2Trash-1.5.0-py3-none-any.whl", hash = "sha256:f1691922577b6fa12821234aeb57599d887c4900b9ca537948d2dac34aea888b"}, - {file = "Send2Trash-1.5.0.tar.gz", hash = "sha256:60001cc07d707fe247c94f74ca6ac0d3255aabcb930529690897ca2a39db28b2"}, + {file = "Send2Trash-1.8.0-py3-none-any.whl", hash = "sha256:f20eaadfdb517eaca5ce077640cb261c7d2698385a6a0f072a4a5447fd49fa08"}, + {file = "Send2Trash-1.8.0.tar.gz", hash = "sha256:d2c24762fd3759860a0aff155e45871447ea58d2be6bdd39b5c8f966a0c99c2d"}, ] six = [ {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, @@ -1484,16 +1638,16 @@ sniffio = [ {file = "sniffio-1.2.0.tar.gz", hash = "sha256:c4666eecec1d3f50960c6bdf61ab7bc350648da6c126e3cf6898d8cd4ddcd3de"}, ] terminado = [ - {file = "terminado-0.10.0-py3-none-any.whl", hash = "sha256:048ce7b271ad1f94c48130844af1de163e54913b919f8c268c89b36a6d468d7c"}, - {file = "terminado-0.10.0.tar.gz", hash = "sha256:46fd07c9dc7db7321922270d544a1f18eaa7a02fd6cd4438314f27a687cabbea"}, + {file = "terminado-0.12.1-py3-none-any.whl", hash = "sha256:09fdde344324a1c9c6e610ee4ca165c4bb7f5bbf982fceeeb38998a988ef8452"}, + {file = "terminado-0.12.1.tar.gz", hash = "sha256:b20fd93cc57c1678c799799d117874367cc07a3d2d55be95205b1a88fa08393f"}, ] testpath = [ {file = "testpath-0.5.0-py3-none-any.whl", hash = "sha256:8044f9a0bab6567fc644a3593164e872543bb44225b0e24846e2c89237937589"}, {file = "testpath-0.5.0.tar.gz", hash = "sha256:1acf7a0bcd3004ae8357409fc33751e16d37ccc650921da1094a86581ad1e417"}, ] threadpoolctl = [ - {file = "threadpoolctl-2.1.0-py3-none-any.whl", hash = "sha256:38b74ca20ff3bb42caca8b00055111d74159ee95c4370882bbff2b93d24da725"}, - {file = "threadpoolctl-2.1.0.tar.gz", hash = "sha256:ddc57c96a38beb63db45d6c159b5ab07b6bced12c45a1f07b2b92f272aebfa6b"}, + {file = "threadpoolctl-3.0.0-py3-none-any.whl", hash = "sha256:4fade5b3b48ae4b1c30f200b28f39180371104fccc642e039e0f2435ec8cc211"}, + {file = "threadpoolctl-3.0.0.tar.gz", hash = "sha256:d03115321233d0be715f0d3a5ad1d6c065fe425ddc2d671ca8e45e9fd5d7a52a"}, ] tornado = [ {file = "tornado-6.1-cp35-cp35m-macosx_10_9_x86_64.whl", hash = "sha256:d371e811d6b156d82aa5f9a4e08b58debf97c302a35714f6f45e35139c332e32"}, @@ -1539,8 +1693,12 @@ tornado = [ {file = "tornado-6.1.tar.gz", hash = "sha256:33c6e81d7bd55b468d2e793517c909b139960b6c790a60b7991b9b6b76fb9791"}, ] traitlets = [ - {file = "traitlets-5.0.5-py3-none-any.whl", hash = "sha256:69ff3f9d5351f31a7ad80443c2674b7099df13cc41fc5fa6e2f6d3b0330b0426"}, - {file = "traitlets-5.0.5.tar.gz", hash = "sha256:178f4ce988f69189f7e523337a3e11d91c786ded9360174a3d9ca83e79bc5396"}, + {file = "traitlets-5.1.0-py3-none-any.whl", hash = "sha256:03f172516916220b58c9f19d7f854734136dd9528103d04e9bf139a92c9f54c4"}, + {file = "traitlets-5.1.0.tar.gz", hash = "sha256:bd382d7ea181fbbcce157c133db9a829ce06edffe097bcf3ab945b435452b46d"}, +] +urllib3 = [ + {file = "urllib3-1.26.7-py2.py3-none-any.whl", hash = "sha256:c4fdf4019605b6e5423637e01bc9fe4daef873709a7973e195ceba0a62bbc844"}, + {file = "urllib3-1.26.7.tar.gz", hash = "sha256:4987c65554f7a2dbf30c18fd48778ef124af6fab771a377103da0585e2336ece"}, ] wcwidth = [ {file = "wcwidth-0.2.5-py2.py3-none-any.whl", hash = "sha256:beb4802a9cebb9144e99086eff703a642a13d6a0052920003a230f3294bbe784"}, @@ -1551,6 +1709,6 @@ webencodings = [ {file = "webencodings-0.5.1.tar.gz", hash = "sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923"}, ] websocket-client = [ - {file = "websocket-client-1.0.1.tar.gz", hash = "sha256:3e2bf58191d4619b161389a95bdce84ce9e0b24eb8107e7e590db682c2d0ca81"}, - {file = "websocket_client-1.0.1-py2.py3-none-any.whl", hash = "sha256:abf306dc6351dcef07f4d40453037e51cc5d9da2ef60d0fc5d0fe3bcda255372"}, + {file = "websocket-client-1.2.1.tar.gz", hash = "sha256:8dfb715d8a992f5712fff8c843adae94e22b22a99b2c5e6b0ec4a1a981cc4e0d"}, + {file = "websocket_client-1.2.1-py2.py3-none-any.whl", hash = "sha256:0133d2f784858e59959ce82ddac316634229da55b498aac311f1620567a710ec"}, ] diff --git a/pyproject.toml b/pyproject.toml index e8042f3..bcce65f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -27,10 +27,11 @@ repository = "https://github.com/webartifex/intro-to-data-science" [tool.poetry.dependencies] python = "^3.8" -jupyterlab = "^3.0.16" -matplotlib = "^3.4.2" -numpy = "^1.20.3" -pandas = "^1.2.4" -scikit-learn = "^0.24.2" + +jupyterlab = "^3.1" +matplotlib = "^3.4" +numpy = "^1.21" +pandas = "^1.3" +scikit-learn = "^1.0" [tool.poetry.dev-dependencies] diff --git a/static/link/to_hn.png b/static/link/to_hn.png new file mode 100644 index 0000000..b8a4a66 Binary files /dev/null and b/static/link/to_hn.png differ diff --git a/static/link/to_mb.png b/static/link/to_mb.png new file mode 100644 index 0000000..ae37d50 Binary files /dev/null and b/static/link/to_mb.png differ diff --git a/static/link/to_np.png b/static/link/to_np.png new file mode 100644 index 0000000..b2911db Binary files /dev/null and b/static/link/to_np.png differ diff --git a/static/link/to_pd.png b/static/link/to_pd.png new file mode 100644 index 0000000..85d56c6 Binary files /dev/null and b/static/link/to_pd.png differ diff --git a/static/link/to_plt.png b/static/link/to_plt.png new file mode 100644 index 0000000..a3b443c Binary files /dev/null and b/static/link/to_plt.png differ diff --git a/static/link/to_skl.png b/static/link/to_skl.png new file mode 100644 index 0000000..9c780cd Binary files /dev/null and b/static/link/to_skl.png differ