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..d000eaf --- /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": "intro-to-data-science", + "language": "python", + "name": "intro-to-data-science" + }, + "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.12.4" + }, + "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..5dbbfaf --- /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": "intro-to-data-science", + "language": "python", + "name": "intro-to-data-science" + }, + "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.12.4" + }, + "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..32ab209 --- /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&curstr=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": "intro-to-data-science", + "language": "python", + "name": "intro-to-data-science" + }, + "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.12.4" + }, + "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..46670ec --- /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": "intro-to-data-science", + "language": "python", + "name": "intro-to-data-science" + }, + "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.12.4" + }, + "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..3b5e5ab --- /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": "intro-to-data-science", + "language": "python", + "name": "intro-to-data-science" + }, + "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.12.4" + }, + "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..d3b0ff1 --- /dev/null +++ b/00_python_in_a_nutshell/05_content_functions.ipynb @@ -0,0 +1,558 @@ +{ + "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&curstr=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)", + "Cell \u001b[0;32mIn[5], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[43mresult\u001b[49m\n", + "\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 [seed() ](https://docs.python.org/3/library/random.html#random.seed) function, we use the `.` operator, formally called the attribute access operator. \n", + "\n", + "We use [random.seed() ](https://docs.python.org/3/library/random.html#random.seed) to make the random numbers *replicable* on separate runs of this notebook." + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [], + "source": [ + "random.seed(42)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "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": 17, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "0.6394267984578837" + ] + }, + "execution_count": 17, + "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": 18, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 18, + "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": 19, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "3" + ] + }, + "execution_count": 19, + "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": "intro-to-data-science", + "language": "python", + "name": "intro-to-data-science" + }, + "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.12.4" + }, + "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..e50152e --- /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": "intro-to-data-science", + "language": "python", + "name": "intro-to-data-science" + }, + "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.12.4" + }, + "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..2ac1470 --- /dev/null +++ b/00_python_in_a_nutshell/07_content_data_types.ipynb @@ -0,0 +1,707 @@ +{ + "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": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "a.is_integer() # Note: In Python versions < 3.12 this cell raises an `AttributeError`" + ] + }, + { + "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)", + "Cell \u001b[0;32mIn[21], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[43mmore_numbers\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mappend\u001b[49m(\u001b[38;5;241m10\u001b[39m)\n", + "\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)", + "Cell \u001b[0;32mIn[26], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[43mto_words\u001b[49m\u001b[43m[\u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mzero\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m]\u001b[49m\n", + "\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": "intro-to-data-science", + "language": "python", + "name": "intro-to-data-science" + }, + "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.12.4" + }, + "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..7ad92fe --- /dev/null +++ b/01_scientific_stack/00_content_numpy.ipynb @@ -0,0 +1,1366 @@ +{ + "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/instructor/Repositories/intro-to-data-science/.venv/lib/python3.12/site-packages (2.0.0)\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/instructor/Repositories/intro-to-data-science/.venv/lib/python3.12/site-packages (3.9.1)\n", + "Requirement already satisfied: contourpy>=1.0.1 in /home/instructor/Repositories/intro-to-data-science/.venv/lib/python3.12/site-packages (from matplotlib) (1.2.1)\n", + "Requirement already satisfied: cycler>=0.10 in /home/instructor/Repositories/intro-to-data-science/.venv/lib/python3.12/site-packages (from matplotlib) (0.12.1)\n", + "Requirement already satisfied: fonttools>=4.22.0 in /home/instructor/Repositories/intro-to-data-science/.venv/lib/python3.12/site-packages (from matplotlib) (4.53.1)\n", + "Requirement already satisfied: kiwisolver>=1.3.1 in /home/instructor/Repositories/intro-to-data-science/.venv/lib/python3.12/site-packages (from matplotlib) (1.4.5)\n", + "Requirement already satisfied: numpy>=1.23 in /home/instructor/Repositories/intro-to-data-science/.venv/lib/python3.12/site-packages (from matplotlib) (2.0.0)\n", + "Requirement already satisfied: packaging>=20.0 in /home/instructor/Repositories/intro-to-data-science/.venv/lib/python3.12/site-packages (from matplotlib) (24.1)\n", + "Requirement already satisfied: pillow>=8 in /home/instructor/Repositories/intro-to-data-science/.venv/lib/python3.12/site-packages (from matplotlib) (10.4.0)\n", + "Requirement already satisfied: pyparsing>=2.3.1 in /home/instructor/Repositories/intro-to-data-science/.venv/lib/python3.12/site-packages (from matplotlib) (3.1.2)\n", + "Requirement already satisfied: python-dateutil>=2.7 in /home/instructor/Repositories/intro-to-data-science/.venv/lib/python3.12/site-packages (from matplotlib) (2.9.0.post0)\n", + "Requirement already satisfied: six>=1.5 in /home/instructor/Repositories/intro-to-data-science/.venv/lib/python3.12/site-packages (from python-dateutil>=2.7->matplotlib) (1.16.0)\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", + " [\n", + " [1, 2, 3, 4, 5],\n", + " [6, 7, 8, 9, 10],\n", + " ]\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)", + "Cell \u001b[0;32mIn[12], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[43mnp\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mdot\u001b[49m\u001b[43m(\u001b[49m\u001b[43mv1\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mm1\u001b[49m\u001b[43m)\u001b[49m\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": [ + "np.int64(1)" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "v1[0]" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "np.int64(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": [ + "np.int64(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": [ + "np.int64(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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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "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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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "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": [ + "First, let's set the [np.random.seed() ](https://docs.python.org/3/library/random.html#random.seed) to make the random numbers *replicable* on separate runs of this notebook." + ] + }, + { + "cell_type": "code", + "execution_count": 44, + "metadata": {}, + "outputs": [], + "source": [ + "np.random.seed(42)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Then, 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": 45, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 45, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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q/bu3au7775bGzZsUFVVld/N8ZWTfZHJZHTdddeprq5ODz30kJkGGlRoX7z00kuxOYcW2hdxO3/a+T1x5Rzq1lhRUMycOdO64447rLvvvttKJBJWeXl575ckq6yszLryyiv9bqYx2f3x3nvvWZKsf/3Xf+3z/o033mjddNNNPrXOrOy+2L17tyXJam5uHvD+nXfe6VPrvLN27VpL0oDfhezvx8aNGy1J1scff9zn302YMMH6x3/8R38a7ZFC++IPf/iDZVmWlclkrPr6emvmzJnWJ5984nOrvVFoXyxZsiQ259BC+yJ7zojL+dPu/ij1HBr6HpD+uru71dnZqeXLl+trX/tan/cuuOACPf7442poaPCpdeZl98eZZ56pcePGadeuXX3e/+1vf6u5c+f61Dqzsvvi6NGjkjRg9np5eXnvnU6UzJw5U2+//Xaf126//Xadd955uu+++zR+/HhVVFRo06ZNmj9/viRp165d+uCDD3rnzERFoX1RXl6uTCaj2bNnq7KyUi+99FJke40K7YvRo0frzjvv7PN+VM+hhfbFWWedFavzZ6H94dY5NNQB5P7779fcuXM1YcIEHTp0SKtXr9bPf/5zvfzyy0qlUjknTU2YMEETJ070obXeG2x/JBIJfeMb39CyZct04YUX6qKLLtIzzzyjd955Rz/60Y/8brrrBtsX5513niZPnqw777xTjz32mEaNGqV169Zpw4YN+slPfuJ30103YsQITZkypc9rw4cP16hRo3pfX7hwoZYuXaqamhpVV1frrrvuUn19vS699FI/muyZQvsik8nommuu0dGjR7Vq1SplMhllMhlJ0qmnnqry8nI/mu0JO8dFXM6hdvZFnM6fhfbHsWPHXDmHhjqAfPjhh7r11lvV2tqqZDKpqVOn6uWXX9bVV1/td9N8UWh/3HPPPero6NC9996r9vZ2XXjhhdqwYYMmTZrkc8vdV2hf/PSnP9U3v/lNNTQ06PDhw5o8ebKeeeYZXXvttT633B+PP/64ysrKNH/+fHV2dmr27Nn63ve+53ezjNu+fbtee+01SRowma6lpUVnnnmmD61CEMTp/FlIRUWFK+fQhGVZloftBAAAGCAydUAAAEB4EEAAAIBxBBAAAGAcAQQAABhHAAEAAMYRQAAAgHEEEAAAYBwBBAAAGEcAAQAAxhFAAACAcQQQAABgHAEEAAAY9/8BAOZdE7QjWKkAAAAASUVORK5CYII=", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "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": "intro-to-data-science", + "language": "python", + "name": "intro-to-data-science" + }, + "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.12.4" + }, + "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..78ec38d --- /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": "intro-to-data-science", + "language": "python", + "name": "intro-to-data-science" + }, + "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.12.4" + }, + "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..2adc9dd --- /dev/null +++ b/01_scientific_stack/02_content_pandas.ipynb @@ -0,0 +1,3456 @@ +{ + "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/instructor/Repositories/intro-to-data-science/.venv/lib/python3.12/site-packages (2.2.2)\n", + "Requirement already satisfied: numpy>=1.26.0 in /home/instructor/Repositories/intro-to-data-science/.venv/lib/python3.12/site-packages (from pandas) (2.0.0)\n", + "Requirement already satisfied: python-dateutil>=2.8.2 in /home/instructor/Repositories/intro-to-data-science/.venv/lib/python3.12/site-packages (from pandas) (2.9.0.post0)\n", + "Requirement already satisfied: pytz>=2020.1 in /home/instructor/Repositories/intro-to-data-science/.venv/lib/python3.12/site-packages (from pandas) (2024.1)\n", + "Requirement already satisfied: tzdata>=2022.7 in /home/instructor/Repositories/intro-to-data-science/.venv/lib/python3.12/site-packages (from pandas) (2024.1)\n", + "Requirement already satisfied: six>=1.5 in /home/instructor/Repositories/intro-to-data-science/.venv/lib/python3.12/site-packages (from python-dateutil>=2.8.2->pandas) (1.16.0)\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", + "Index: 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[200300:200800, [\"o_street\", \"o_zip\", \"o_city\", \"o_latitude\", \"o_longitude\"]]" + ] + }, + { + "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", + "Index: 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", + " {\n", + " \"pickup_at\": \"datetime64[ns]\",\n", + " \"delivery_at\": \"datetime64[ns]\",\n", + " \"cancelled\": bool,\n", + " }\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", + "Index: 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) | (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", + " (max_a_table & df[\"customer_id\"].isin([6037, 79900, 80095])),\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", + " (max_a_table & ~df[\"customer_id\"].isin([6037, 79900, 80095])),\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[max_a_table, \"customer_id\"].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": [ + "restaurant_id\n", + "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: count, 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": [ + "customer_id\n", + "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: count, 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": [ + "np.float64(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": [ + "np.float64(885.0)" + ] + }, + "execution_count": 38, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df.loc[max_a_table, \"total\"].sum() / 100" + ] + }, + { + "cell_type": "code", + "execution_count": 39, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "np.float64(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": [ + "np.float64(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": [ + "np.float64(12.5)" + ] + }, + "execution_count": 41, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df.loc[max_a_table, \"total\"].min() / 100" + ] + }, + { + "cell_type": "code", + "execution_count": 42, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "np.float64(60.0)" + ] + }, + "execution_count": 42, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df.loc[max_a_table, \"total\"].max() / 100" + ] + }, + { + "cell_type": "code", + "execution_count": 43, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "np.float64(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": [ + "np.float64(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": [ + "np.float64(22.69)" + ] + }, + "execution_count": 45, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df.loc[max_a_table, \"total\"].mean().round() / 100" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "intro-to-data-science", + "language": "python", + "name": "intro-to-data-science" + }, + "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.12.4" + }, + "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..e2e3259 --- /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": "intro-to-data-science", + "language": "python", + "name": "intro-to-data-science" + }, + "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.12.4" + }, + "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/03_classification/00_content.ipynb b/03_classification/00_content.ipynb new file mode 100644 index 0000000..5c3d4c4 --- /dev/null +++ b/03_classification/00_content.ipynb @@ -0,0 +1,1180 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Chapter 2: A first Example - Classifying Flowers" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The purpose of this notebook is to look at a first example of a typical data science application, namely **statistical learning**, which is often referred to by its more well-known name **machine learning**. To do so, we look at a very popular example involving the classification of flowers. Albeit simplistic and almost boring in its kind, the example is a rather good one to look at from a beginner's point of view as it does not involve too many decision variables. That makes understanding technicalities and visualizing the data set a lot easier." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## What is Machine Learning" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let's at first review a couple of generic definitions to get started.\n", + "\n", + "Machine learning is the process of **extracting knowledge from data** in an automated fashion.\n", + "\n", + "Typical use cases regard making predictions on new and unseen data or simply understanding a given dataset better by finding patterns.\n", + "\n", + "Central to machine learning is the idea of **automating** the **decision making** from data **without** the user specifying **explicit rules** how these decisions should be made.\n", + "\n", + "That is in direct opposition to what we learned in the \"Expressing Logic\" section in Chapter 0, where we learned how to implement decision criterions \"by hand\" with the `if` statement." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Example Applications" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Types of Machine Learning" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Concete machine learning algorithms are commonly classified into three broad categories that may overlap as well:" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "- **Supervised** (focus of the example in this notebook): Each entry in the dataset comes with a **label**. Examples are a list of emails where spam mail is already marked as such or a sample of handwritten digits. The goal is to use the historic data to make predictions.\n", + "\n", + "- **Unsupervised**: There is no desired output associated with a data entry. In a sense, one can think of unsupervised learning as a means of discovering labels from the data itself. A popular example is the clustering of customer data.\n", + "\n", + "- **Reinforcement**: Conceptually, this can be seen as \"learning by doing\". Some kind of **reward function** tells how good a predicted outcome is. A rather recent and extremely popular example for his approach is the Alpha Go machine." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Types of Supervised Learning" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Algorithms from the supervised learning category are often broken down further into classification and regression:" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "- In **classification** tasks, the labels are *discrete*, such as \"spam\" or \"no spam\" for emails. Often, labels are nominal (e.g., colors of something), or ordinal (e.g., T-shirt sizes in S, M, or L).\n", + "- In **regression**, the labels are *continuous*. For example, given a person's age, education, and position, infer his/her salary." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Example: Iris Flower Classification" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In the example, we are given measurments regarding the size of various parts of the so-called Iris flower kind. A concrete flower always belongs to one of three distinct special Iris classes. This example application is about classifying a given flower into one of the three classes by only looking at the measurements." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Importing the Data" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The `sklearn` library provides several sample datasets, among which is also the Iris dataset.\n", + "\n", + "In a tabular visualization, the dataset could be portrayed somewhat like this:\n", + "\n", + "\n", + "\n", + "However, the data object imported from `sklearn` is organized slightly different. In particular, the so-called **features** are separated from the **labels**." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "from sklearn.datasets import load_iris" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "iris = load_iris()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Using Python's `dir()` function we can inspect the data object, i.e. find out what **attributes** it has." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "['DESCR',\n", + " 'data',\n", + " 'data_module',\n", + " 'feature_names',\n", + " 'filename',\n", + " 'frame',\n", + " 'target',\n", + " 'target_names']" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "dir(iris)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "`iris.data` provides us with a `numpy.ndarray`, where the first dimension equals the number of observed flowers (i.e., the **instances**) and the second dimension lists the various features of a flower." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[5.1, 3.5, 1.4, 0.2],\n", + " [4.9, 3. , 1.4, 0.2],\n", + " [4.7, 3.2, 1.3, 0.2],\n", + " [4.6, 3.1, 1.5, 0.2],\n", + " [5. , 3.6, 1.4, 0.2],\n", + " [5.4, 3.9, 1.7, 0.4],\n", + " [4.6, 3.4, 1.4, 0.3],\n", + " [5. , 3.4, 1.5, 0.2],\n", + " [4.4, 2.9, 1.4, 0.2],\n", + " [4.9, 3.1, 1.5, 0.1],\n", + " [5.4, 3.7, 1.5, 0.2],\n", + " [4.8, 3.4, 1.6, 0.2],\n", + " [4.8, 3. , 1.4, 0.1],\n", + " [4.3, 3. , 1.1, 0.1],\n", + " [5.8, 4. , 1.2, 0.2],\n", + " [5.7, 4.4, 1.5, 0.4],\n", + " [5.4, 3.9, 1.3, 0.4],\n", + " [5.1, 3.5, 1.4, 0.3],\n", + " [5.7, 3.8, 1.7, 0.3],\n", + " [5.1, 3.8, 1.5, 0.3],\n", + " [5.4, 3.4, 1.7, 0.2],\n", + " [5.1, 3.7, 1.5, 0.4],\n", + " [4.6, 3.6, 1. , 0.2],\n", + " [5.1, 3.3, 1.7, 0.5],\n", + " [4.8, 3.4, 1.9, 0.2],\n", + " [5. , 3. , 1.6, 0.2],\n", + " [5. , 3.4, 1.6, 0.4],\n", + " [5.2, 3.5, 1.5, 0.2],\n", + " [5.2, 3.4, 1.4, 0.2],\n", + " [4.7, 3.2, 1.6, 0.2],\n", + " [4.8, 3.1, 1.6, 0.2],\n", + " [5.4, 3.4, 1.5, 0.4],\n", + " [5.2, 4.1, 1.5, 0.1],\n", + " [5.5, 4.2, 1.4, 0.2],\n", + " [4.9, 3.1, 1.5, 0.2],\n", + " [5. , 3.2, 1.2, 0.2],\n", + " [5.5, 3.5, 1.3, 0.2],\n", + " [4.9, 3.6, 1.4, 0.1],\n", + " [4.4, 3. , 1.3, 0.2],\n", + " [5.1, 3.4, 1.5, 0.2],\n", + " [5. , 3.5, 1.3, 0.3],\n", + " [4.5, 2.3, 1.3, 0.3],\n", + " [4.4, 3.2, 1.3, 0.2],\n", + " [5. , 3.5, 1.6, 0.6],\n", + " [5.1, 3.8, 1.9, 0.4],\n", + " [4.8, 3. , 1.4, 0.3],\n", + " [5.1, 3.8, 1.6, 0.2],\n", + " [4.6, 3.2, 1.4, 0.2],\n", + " [5.3, 3.7, 1.5, 0.2],\n", + " [5. , 3.3, 1.4, 0.2],\n", + " [7. , 3.2, 4.7, 1.4],\n", + " [6.4, 3.2, 4.5, 1.5],\n", + " [6.9, 3.1, 4.9, 1.5],\n", + " [5.5, 2.3, 4. , 1.3],\n", + " [6.5, 2.8, 4.6, 1.5],\n", + " [5.7, 2.8, 4.5, 1.3],\n", + " [6.3, 3.3, 4.7, 1.6],\n", + " [4.9, 2.4, 3.3, 1. ],\n", + " [6.6, 2.9, 4.6, 1.3],\n", + " [5.2, 2.7, 3.9, 1.4],\n", + " [5. , 2. , 3.5, 1. ],\n", + " [5.9, 3. , 4.2, 1.5],\n", + " [6. , 2.2, 4. , 1. ],\n", + " [6.1, 2.9, 4.7, 1.4],\n", + " [5.6, 2.9, 3.6, 1.3],\n", + " [6.7, 3.1, 4.4, 1.4],\n", + " [5.6, 3. , 4.5, 1.5],\n", + " [5.8, 2.7, 4.1, 1. ],\n", + " [6.2, 2.2, 4.5, 1.5],\n", + " [5.6, 2.5, 3.9, 1.1],\n", + " [5.9, 3.2, 4.8, 1.8],\n", + " [6.1, 2.8, 4. , 1.3],\n", + " [6.3, 2.5, 4.9, 1.5],\n", + " [6.1, 2.8, 4.7, 1.2],\n", + " [6.4, 2.9, 4.3, 1.3],\n", + " [6.6, 3. , 4.4, 1.4],\n", + " [6.8, 2.8, 4.8, 1.4],\n", + " [6.7, 3. , 5. , 1.7],\n", + " [6. , 2.9, 4.5, 1.5],\n", + " [5.7, 2.6, 3.5, 1. ],\n", + " [5.5, 2.4, 3.8, 1.1],\n", + " [5.5, 2.4, 3.7, 1. ],\n", + " [5.8, 2.7, 3.9, 1.2],\n", + " [6. , 2.7, 5.1, 1.6],\n", + " [5.4, 3. , 4.5, 1.5],\n", + " [6. , 3.4, 4.5, 1.6],\n", + " [6.7, 3.1, 4.7, 1.5],\n", + " [6.3, 2.3, 4.4, 1.3],\n", + " [5.6, 3. , 4.1, 1.3],\n", + " [5.5, 2.5, 4. , 1.3],\n", + " [5.5, 2.6, 4.4, 1.2],\n", + " [6.1, 3. , 4.6, 1.4],\n", + " [5.8, 2.6, 4. , 1.2],\n", + " [5. , 2.3, 3.3, 1. ],\n", + " [5.6, 2.7, 4.2, 1.3],\n", + " [5.7, 3. , 4.2, 1.2],\n", + " [5.7, 2.9, 4.2, 1.3],\n", + " [6.2, 2.9, 4.3, 1.3],\n", + " [5.1, 2.5, 3. , 1.1],\n", + " [5.7, 2.8, 4.1, 1.3],\n", + " [6.3, 3.3, 6. , 2.5],\n", + " [5.8, 2.7, 5.1, 1.9],\n", + " [7.1, 3. , 5.9, 2.1],\n", + " [6.3, 2.9, 5.6, 1.8],\n", + " [6.5, 3. , 5.8, 2.2],\n", + " [7.6, 3. , 6.6, 2.1],\n", + " [4.9, 2.5, 4.5, 1.7],\n", + " [7.3, 2.9, 6.3, 1.8],\n", + " [6.7, 2.5, 5.8, 1.8],\n", + " [7.2, 3.6, 6.1, 2.5],\n", + " [6.5, 3.2, 5.1, 2. ],\n", + " [6.4, 2.7, 5.3, 1.9],\n", + " [6.8, 3. , 5.5, 2.1],\n", + " [5.7, 2.5, 5. , 2. ],\n", + " [5.8, 2.8, 5.1, 2.4],\n", + " [6.4, 3.2, 5.3, 2.3],\n", + " [6.5, 3. , 5.5, 1.8],\n", + " [7.7, 3.8, 6.7, 2.2],\n", + " [7.7, 2.6, 6.9, 2.3],\n", + " [6. , 2.2, 5. , 1.5],\n", + " [6.9, 3.2, 5.7, 2.3],\n", + " [5.6, 2.8, 4.9, 2. ],\n", + " [7.7, 2.8, 6.7, 2. ],\n", + " [6.3, 2.7, 4.9, 1.8],\n", + " [6.7, 3.3, 5.7, 2.1],\n", + " [7.2, 3.2, 6. , 1.8],\n", + " [6.2, 2.8, 4.8, 1.8],\n", + " [6.1, 3. , 4.9, 1.8],\n", + " [6.4, 2.8, 5.6, 2.1],\n", + " [7.2, 3. , 5.8, 1.6],\n", + " [7.4, 2.8, 6.1, 1.9],\n", + " [7.9, 3.8, 6.4, 2. ],\n", + " [6.4, 2.8, 5.6, 2.2],\n", + " [6.3, 2.8, 5.1, 1.5],\n", + " [6.1, 2.6, 5.6, 1.4],\n", + " [7.7, 3. , 6.1, 2.3],\n", + " [6.3, 3.4, 5.6, 2.4],\n", + " [6.4, 3.1, 5.5, 1.8],\n", + " [6. , 3. , 4.8, 1.8],\n", + " [6.9, 3.1, 5.4, 2.1],\n", + " [6.7, 3.1, 5.6, 2.4],\n", + " [6.9, 3.1, 5.1, 2.3],\n", + " [5.8, 2.7, 5.1, 1.9],\n", + " [6.8, 3.2, 5.9, 2.3],\n", + " [6.7, 3.3, 5.7, 2.5],\n", + " [6.7, 3. , 5.2, 2.3],\n", + " [6.3, 2.5, 5. , 1.9],\n", + " [6.5, 3. , 5.2, 2. ],\n", + " [6.2, 3.4, 5.4, 2.3],\n", + " [5.9, 3. , 5.1, 1.8]])" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "iris.data" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To find out what the four features are, we can list them:" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "['sepal length (cm)',\n", + " 'sepal width (cm)',\n", + " 'petal length (cm)',\n", + " 'petal width (cm)']" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "iris.feature_names" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Similarly, we can also print the flowers' labels (a.k.a. targets):" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n", + " 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n", + " 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n", + " 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n", + " 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,\n", + " 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,\n", + " 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2])" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "iris.target" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The three flower classes are encoded with integers. Let's show the corresponding names:" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array(['setosa', 'versicolor', 'virginica'], dtype='" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "feature_index = 2\n", + "colors = [\"blue\", \"red\", \"green\"]\n", + "\n", + "for label, color in zip(range(len(iris.target_names)), colors):\n", + " plt.hist(\n", + " iris.data[iris.target == label, feature_index],\n", + " label=iris.target_names[label],\n", + " color=color,\n", + " )\n", + "\n", + "plt.xlabel(iris.feature_names[feature_index])\n", + "plt.legend(loc=\"upper right\")\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Also, we can draw scatter plots of two features." + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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ba+99ho+//xz7NmzB6dOnULLli1x+PBhREREWNuEhIRgzJgxePHFF63bbr/9dnTt2hXvvPMOxo0bh6NHj+Krr75SVCcnKSkJTz/9NP73v//d+BtWiZObibTLVGJCaGIocvJzKpzno4MOBj8DMuMzubTdzXFyswblKjwSq7SdUrfddht69+6NDh06YODAgVixYgUuXryIK1euICMjA48//jgaNGhgvb322mvIyMiotL/8/Hz89ttv6NGjh832Hj16ID09HQDw2GOPIS0tDWFhYRg3bhy2bdtm0/arr75C7969ERISAl9fXzzyyCP4448/cPXqVblvnoicmt5Dj8R+iQD+XsVlYbmf0C+BSQ9Jw8RHIqXXwJR9rUy9Xo/t27fjiy++QLt27fDWW28hLCwMP/30EwBgxYoVSEtLs95++ukn7Nu374Zes1OnTsjMzMSrr76KwsJCDBo0CHFxcQDMK8Xuv/9+dOzYERs2bMDBgwfxzjvvADDPDSIiKi02PBZJg5IQ4hdis93gZ+BSdpLOoQUMXU10NGAwmCcyV3QCUaczPx4dLf+1dTodevTogR49emD69Olo0aIFdu/ejeDgYPz666+VXvHe09MTgPkCrRZ+fn4IDg7G7t270bNnT+v23bt34/bbb7dpN3jwYAwePBhxcXHo168fLly4gIMHD6KkpAQLFy60XpJk/fr18t80EbmM2PBYxITFsHIz1TomPhLp9UBionn1lk5nm/xYpsEkJJjbyfTdd99hx44duOeee9CsWTN89913+P333xEeHo6ZM2di3Lhx8Pf3R79+/VBUVIQDBw7g4sWLmDBhApo1awYfHx9s3boVBoMB3t7e8Pf3x8SJEzFjxgy0atUKERERWLlyJdLS0rB69WoA5lVbQUFBiIyMhIeHBz755BMEBgaiYcOGaN26Na5du4a33noLDzzwAHbv3o1ly5bJfdNE5HL0Hnr0Cu3l6DDI1Qk3k5eXJwCIvLy8co8VFhaKY8eOicLCwht6jQ0bhDAYhDCnPuab0WjeXhuOHTsm+vbtK5o2bSq8vLxE27ZtxVtvvWV9fPXq1SIiIkJ4enqKRo0aiTvvvFMkJydbH1+xYoUwGo3Cw8ND9OzZUwghhMlkEq+88ooICQkRdevWFbfddpv44osvrM959913RUREhKhfv77w8/MTvXv3FocOHbI+vmjRIhEU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rVvDy8sLzZs3x+zZs62PT548GW3btkW9evVw8803Y9q0abh27ZrcHUZERG7L4YlPSUkJVq5cieHDh6NOHdsDUI8++iimTp1qvT9r1ixs27YNv/76Kw4dOoT/+7//w+nTp/HEE0/YO+xKJacnI259HM7k2847ysnPQdz6uFpJfgYOHIg//vgDO3futG67cOECtm7dimHDhlX4nB07duDEiRPYvn07PvvsM+Tn5+OBBx5Ahw4dcOjQIbz66quYPHlyta999epVLFiwAP/+97/xzTffICsrCy+88EKl7adOnYq5c+di2rRpOHbsGNasWYOAgADr476+vli1ahWOHTuGxMRErFixAm+++aaKveFaTCUmpJxKwdoja5FyKgWmElP1TyIioko5/FTXV199haysLIwcObLcY1lZWfDw+Ds3u3jxIkaNGoWzZ8+iUaNG6Ny5M/bs2YN27drZM+RKmUpMiN8aX+EFHAUEdNBh/NbxiAmLkXraq1GjRujfvz/WrFmD3r17AwCSkpJw00034a677kJqamq559SvXx/vvfee9RTXsmXLoNPpsGLFCnh7e6Ndu3bIycnBqFGjqnzta9euYdmyZWjVqhUAYOzYsZg1a1aFbS9fvozExES8/fbbGD58OACgVatW+Mc//mFt8/LLL1v/HxoaihdeeAHr1q3DpEmTVOwR15Ccnoz4rfE2SbTBz4DEfom8NAQRUQ05PPG55557UNn86pSUFJv7b775pqb/+k/NSi13pKc0AYHs/GykZqWiV2gvqa89bNgwjBo1CkuWLIGXlxdWr16NIUOG2CSOpXXo0MFmXs+JEyfQsWNHm8m/t99+e7WvW69ePWvSAwBBQUE4f/58hW3T09NRVFRkTc4q8p///AeLFy9GRkYGCgoKcP369RuaxOasLEcOyybRliOHvC4WEVHNOPxUlyvJvZxbfSMV7dR44IEHIITAli1bkJ2djdTU1EpPcwHmIz4y1K1b1+a+TqerNJH18fGpsq+9e/di2LBhuPfee/HZZ5/h8OHDeOmll1BcXCwlVmdR3ZFDABi/dTxPexER1QATH4mCfJVNslbaTg1vb2/ExsZi9erVWLt2LcLCwtCpUyfFzw8LC8ORI0dsqlzv379faoxt2rSBj48PduzYUeHje/bsQYsWLfDSSy+hS5cuaNOmDU6fPi01Bmeg5sghERGpw8RH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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "first_feature_index = 1\n", + "second_feature_index = 0\n", + "\n", + "colors = [\"blue\", \"red\", \"green\"]\n", + "\n", + "for label, color in zip(range(len(iris.target_names)), colors):\n", + " plt.scatter(\n", + " iris.data[iris.target == label, first_feature_index],\n", + " iris.data[iris.target == label, second_feature_index],\n", + " label=iris.target_names[label],\n", + " c=color,\n", + " )\n", + "\n", + "plt.xlabel(iris.feature_names[first_feature_index])\n", + "plt.ylabel(iris.feature_names[second_feature_index])\n", + "plt.legend(loc=\"upper left\")\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Using the higher level library `pandas`, one can easily create a so-called **scatterplot matrix**." + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [], + "source": [ + "import pandas as pd" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "iris_df = pd.DataFrame(iris.data, columns=iris.feature_names)\n", + "\n", + "pd.plotting.scatter_matrix(iris_df, figsize=(8, 8));" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Concept of Generalization" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The goal of a supervised machine learning model is to make predictions on *new* (i.e., previously unseen) data.\n", + "\n", + "In a real-world application, we are not interested in marking an already labeled email as spam or not. Instead, we want to make the user's life easier by automatically classifying new incoming mail.\n", + "\n", + "In order to get an idea of how good a model **generalizes**, a best practice is to *split* the available data into a **training** and a **test** set. Only the former is used to train the model. Then, predictions are made on the test data and the predictions can be compared with the actual labels.\n", + "\n", + "Common splits are 75/25 or 60/40." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Train/Test Split for the Iris data" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "It is common practice to refer to the feature matrix as `X` and the vector of labels as `y`." + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [], + "source": [ + "X, y = iris.data, iris.target" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "A naive splitting approach could be to use array slicing." + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [], + "source": [ + "X_train, X_test, y_train, y_test = X[0:100, :], X[100:150, :], y[0:100], y[100:150]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "However, this would lead to unbalanced label distributions. For example, the test set would only be made up of flowers of the same type." + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,\n", + " 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,\n", + " 2, 2, 2, 2, 2, 2])" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "y_test" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([ 0, 0, 50])" + ] + }, + "execution_count": 17, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "np.bincount(y_test)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "`sklearn` provides a function that not only randomizes the split but also ensures that the resulting label distribution is proportionate to the overall distribution, a concept called **stratification**." + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [], + "source": [ + "from sklearn.model_selection import train_test_split" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([2, 1, 2, 1, 2, 2, 1, 1, 0, 2, 0, 0, 2, 2, 0, 2, 1, 0, 0, 0, 1, 0,\n", + " 1, 2, 2, 1, 1, 1, 1, 0, 2, 2, 1, 0, 2, 0, 0, 0, 0, 1, 1, 0, 2, 2,\n", + " 1])" + ] + }, + "execution_count": 19, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "X_train, X_test, y_train, y_test = train_test_split(\n", + " X, y, train_size=0.7, test_size=0.3, random_state=42, stratify=y\n", + ")\n", + "\n", + "y_test" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([15, 15, 15])" + ] + }, + "execution_count": 20, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "np.bincount(y_test)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### A simple Classification Model: k-Nearest Neighbors" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To predict the label for any observation, just determine the k \"nearest\" observations in the training set (e.g., by Euclidean distance) and use a simple majority vote." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Training and Predicting with the Iris data" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "`sklearn` provides a uniform interface for all its classification models. They all have a `.fit()` and a `.predict()` method that abstract away the actual machine learning algorithm." + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": {}, + "outputs": [], + "source": [ + "from sklearn.neighbors import KNeighborsClassifier" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": {}, + "outputs": [], + "source": [ + "knn = KNeighborsClassifier(n_neighbors=5)\n", + "\n", + "knn.fit(X_train, y_train)\n", + "\n", + "y_pred = knn.predict(X_test)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us list the labels predicted for the test set ..." + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([2, 1, 2, 1, 2, 2, 1, 1, 0, 2, 0, 0, 2, 2, 0, 2, 1, 0, 0, 0, 1, 0,\n", + " 1, 2, 2, 1, 1, 1, 1, 0, 2, 2, 1, 0, 2, 0, 0, 0, 0, 1, 1, 0, 1, 2,\n", + " 1])" + ] + }, + "execution_count": 23, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "y_pred" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "... and compare them with the actual labels." + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([2, 1, 2, 1, 2, 2, 1, 1, 0, 2, 0, 0, 2, 2, 0, 2, 1, 0, 0, 0, 1, 0,\n", + " 1, 2, 2, 1, 1, 1, 1, 0, 2, 2, 1, 0, 2, 0, 0, 0, 0, 1, 1, 0, 2, 2,\n", + " 1])" + ] + }, + "execution_count": 24, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "y_test" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "`numpy` shows us the indices where the predictions are wrong." + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(array([42]),)" + ] + }, + "execution_count": 25, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "np.where(y_pred != y_test)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Alternatively, we can calculate the fraction of correctly predicted flowers." + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "np.float64(0.9777777777777777)" + ] + }, + "execution_count": 26, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "np.sum(y_pred == y_test) / len(y_test)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "It is important to mention that we can also \"predict\" the training set. Somehow surprisingly, the model does not get the training set 100% correct." + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "np.float64(0.9714285714285714)" + ] + }, + "execution_count": 27, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "y_train_pred = knn.predict(X_train)\n", + "\n", + "np.sum(y_train_pred == y_train) / len(y_train)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "A visualization reveals that the misclassified flowers are right \"at the borderline\" between two neighboring clusters of flower classes." + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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zp8/X2n/x48fo7CwUOlFRERExk2nCVBMTAySk5OxbNkylfp7e3vjm2++wU8//YTvvvsOcrkcXbt2xfXrFdfaWrZsGWxtbRUvNzc3TYVPREREBkpnj8Ffu3YNfn5+2L9/v2LsT1BQEHx9fREREaHSOkpKSuDj44ORI0di8eLF5fZ5/PgxHj9+rHhfWFgINzc3jT8GT0RERNpTax6DP336NG7fvo327dsr2mQyGX799Vd8+eWXePz4McRicaXrMDU1Rbt27XD58uUK+5ibm8Pc3FxjcRMREZHh01kC1LNnT6Smpiq1vfHGG2jevDnmzJnzwuQHeJowpaamom/fvtoKk4iIiGohnSVANjY2aNWqlVKblZUV6tevr2gfO3YsGjZsqBgj9PHHH+Oll15C06ZNkZ+fj88++wxXr17FpEmTajx+IiIiMlx6MQ9QRXJycmBi8u847by8PEyePBk3b96Evb09OnTogGPHjqFFixY6jJKIiIgMDWuBERERkd6rNYOga5vi4idYuzYFmZn5aNLEDlOn+sLMjF8vERGRPuIZWgNmz07EqlWnIZP9ezFt1qwjmDmzAz79NEh3gREREVG5mABV0+zZifjss1Nl2mUyQdHOJIiIiEi/6LwUhiErLn6CVatOV9pn1arTKC5+UkMRERERkSqYAFXD2rUpSre9yiOTCVi7NqVmAiIiIiKVMAGqhszMfI32IyIioprBBKgamjSx02g/IiIiqhlMgKph6lRfiMWiSvuIxSJMnepbMwERERGRSpgAVYOZWR3MnNmh0j4zZ3bgfEBERER6hmfmaip9xP35eYDEYhHnASIiItJTLIWhIZwJmoiISHtYCkNPmZnVQXi4n67DICIiIhVwDBAREREZHSZAREREZHSYABEREZHRYQJERERERocJEBERERkdJkBERERkdJgAERERkdFhAkRERERGhwkQERERGR2jmwm6tPJHYWGhjiMhIiIiVZWetzVVwcvoEqB79+4BANzc3HQcCREREanr3r17sLW1rfZ6jK4Yqlwux19//QUbGxuIRCJdh2PwCgsL4ebmhmvXrmm0uCxVH4+NfuJx0V88Nvqp9Ljk5ORAJBLB1dUVJibVH8FjdFeATExMIJVKdR1GrSORSPgLQ0/x2OgnHhf9xWOjn2xtbTV6XDgImoiIiIwOEyAiIiIyOkyAqFrMzc2xYMECmJub6zoUeg6PjX7icdFfPDb6SVvHxegGQRMRERHxChAREREZHSZAREREZHSYABEREZHRYQJERERERocJEL3QmjVr4OnpCQsLC3Tu3Bl//PFHhX03bdoEkUik9LKwsKjBaI3Dr7/+igEDBsDV1RUikQg7d+584TKJiYlo3749zM3N0bRpU2zatEnrcRojdY9NYmJimf8zIpEIN2/erJmAjcSyZcvQsWNH2NjYwNHREYMHD0Z6evoLl9u+fTuaN28OCwsLtG7dGnv37q2BaI1HVY6Lps4zTICoUj/++CNmzpyJBQsWIDk5GW3btkWfPn1w+/btCpeRSCTIzc1VvK5evVqDERuH+/fvo23btlizZo1K/bOystCvXz/06NEDKSkpCA8Px6RJk/Dzzz9rOVLjo+6xKZWenq70/8bR0VFLERqnI0eOYNq0afj999+xf/9+lJSUoHfv3rh//36Fyxw7dgwjR47ExIkTcebMGQwePBiDBw/GuXPnajDy2q0qxwXQ0HlGIKpEp06dhGnTpiney2QywdXVVVi2bFm5/Tdu3CjY2trWUHQkCIIAQNixY0elfWbPni20bNlSqe21114T+vTpo8XISJVjc/jwYQGAkJeXVyMx0VO3b98WAAhHjhypsM/w4cOFfv36KbV17txZePPNN7UdntFS5bho6jzDK0BUoeLiYpw+fRq9evVStJmYmKBXr144fvx4hcsVFRXBw8MDbm5uGDRoEM6fP18T4VIljh8/rnQcAaBPnz6VHkeqWb6+vnBxccErr7yCo0eP6jqcWq+goAAAUK9evQr78P9NzVPluACaOc8wAaIK/fPPP5DJZHByclJqd3JyqnB8gre3N7755hv89NNP+O677yCXy9G1a1dcv369JkKmCty8ebPc41hYWIiHDx/qKCoCABcXF6xbtw5xcXGIi4uDm5sbgoKCkJycrOvQai25XI7w8HD4+/ujVatWFfar6P8Nx2dph6rHRVPnGaOrBk/a1aVLF3Tp0kXxvmvXrvDx8cH69euxePFiHUZGpJ+8vb3h7e2teN+1a1dkZmbi888/x7fffqvDyGqvadOm4dy5c/jtt990HQo9Q9XjoqnzDK8AUYUaNGgAsViMW7duKbXfunULzs7OKq3D1NQU7dq1w+XLl7URIqnI2dm53OMokUhgaWmpo6ioIp06deL/GS2ZPn06du/e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WZg4cSJ++eUXpKSk4I033kBxcbHK62jdujXq1auHI0eOKCVAR44cwcmTJ1FSUoKuXbuqvf+qMDU1VXovEomUbl2p4tlbaupsRxPbJiLVMQEiMiIikQj+/v5YtGgRzpw5AzMzM+zYsQNOTk5wdXXFlStX0LRpU6VXo0aNlNbxbEL05MkTnD59Gj4+PgCAo0ePomvXrpg6dSratWuHpk2blrmCpEqMAQEB+Omnn3D+/Hl069YNbdq0wePHj7F+/Xr4+fnBysqq3GV9fHzw559/4tGjR+XGCwBmZmYAng7Y1oY2bdogJSUFd+/e1cr6iUgzmAARGYkTJ05g6dKlOHXqFHJychAfH4+///5bkbwsWrQIy5Ytw+rVq3Hp0iWkpqZi48aNWLVqldJ61qxZgx07duDixYuYNm0a8vLyMGHCBACAl5cXTp06hZ9//hmXLl3CRx99hJMnT6oda1BQEH744Qf4+vrC2toaJiYm6N69O7Zu3YrAwMAKlxs1ahREIhEmT56MCxcuYO/evVixYoVSHw8PD4hEIuzevRt///234uqXpowcORLOzs4YPHgwjh49iitXriAuLg7Hjx/X6HaIqHqYABEZCYlEgl9//RV9+/ZFs2bN8OGHH2LlypWKCfwmTZqEr776Chs3bkTr1q0RGBiITZs2lbkCtHz5cixfvhxt27bFb7/9hl27dqFBgwYAgDfffBMhISF47bXX0LlzZ9y5cwdTp05VO9bAwEDIZDKlsT5BQUFl2p5nbW2N//3vf0hNTUW7du3wwQcf4JNPPlHq07BhQyxatAhz586Fk5MTpk+frnZ8lTEzM8Mvv/wCR0dH9O3bF61bt8by5cshFos1uh0iqh6RIPz/M7BERJXIzs5Go0aNcObMGfj6+uo6HL0wfvx45Ofna70MRqnExET06NEDeXl5sLOzq5FtEtVWvAJERFQNu3fvhrW1NXbv3q3V7bRs2VLr5TaIjAmvABGRSngFqKzbt2+jsLAQwNNH5isanK0JV69eRUlJCQCgcePGSo/ME5H6mAARERGR0eGfEERERGR0mAARERGR0WECREREREaHCRAREREZHSZAREREZHSYABEREZHRYQJERERERocJEBERERkdJkBERERkdP4PxvOKjUrhdLAAAAAASUVORK5CYII=", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "first_feature_index = 3\n", + "second_feature_index = 0\n", + "\n", + "correct_idx = np.where(y_pred == y_test)[0]\n", + "incorrect_idx = np.where(y_pred != y_test)[0]\n", + "\n", + "colors = [\"darkblue\", \"darkgreen\", \"gray\"]\n", + "\n", + "for n, color in enumerate(colors):\n", + " idx = np.where(y_test == n)[0]\n", + " plt.scatter(\n", + " X_test[idx, first_feature_index],\n", + " X_test[idx, second_feature_index],\n", + " color=color,\n", + " label=iris.target_names[n],\n", + " )\n", + "\n", + "plt.scatter(\n", + " X_test[incorrect_idx, first_feature_index],\n", + " X_test[incorrect_idx, second_feature_index],\n", + " color=\"darkred\",\n", + " label=\"misclassified\",\n", + ")\n", + "\n", + "plt.xlabel(\"sepal width [cm]\")\n", + "plt.ylabel(\"petal length [cm]\")\n", + "plt.legend(loc=\"best\")\n", + "plt.title(\"Iris Classification results\")\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In practice, the number of neighbors must be chosen before the model is trained. Therefore, it is possible to \"optimize\" it. This process is referred to as **hyper-parameter tuning**. For the Iris dataset this does not make much of a difference." + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1 0.9333333333333333\n", + "2 0.9111111111111111\n", + "3 0.9555555555555556\n", + "4 0.9555555555555556\n", + "5 0.9777777777777777\n", + "6 0.9333333333333333\n", + "7 0.9555555555555556\n", + "8 0.9333333333333333\n", + "9 0.9555555555555556\n", + "10 0.9555555555555556\n", + "11 0.9333333333333333\n", + "12 0.9333333333333333\n", + "13 0.9333333333333333\n", + "14 0.9333333333333333\n", + "15 0.9555555555555556\n", + "16 0.9555555555555556\n", + "17 0.9555555555555556\n", + "18 0.9555555555555556\n", + "19 0.9555555555555556\n", + "20 0.9333333333333333\n", + "21 0.9555555555555556\n", + "22 0.9333333333333333\n", + "23 0.9555555555555556\n", + "24 0.9333333333333333\n", + "25 0.9333333333333333\n", + "26 0.9555555555555556\n", + "27 0.9333333333333333\n", + "28 0.9111111111111111\n", + "29 0.9111111111111111\n", + "30 0.9111111111111111\n" + ] + } + ], + "source": [ + "for i in range(1, 31):\n", + " knn = KNeighborsClassifier(n_neighbors=i)\n", + " knn.fit(X_train, y_train)\n", + " y_pred = knn.predict(X_test)\n", + " correct = np.sum(y_pred == y_test) / len(y_test)\n", + " print(i, correct)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Further Resources on Machine Learning" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Depending on the programming language one chooses, the following books are recommended:" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "- [Python Machine Learning](https://www.amazon.de/Python-Machine-Learning-scikit-learn-TensorFlow/dp/1787125939/ref=sr_1_1?__mk_de_DE=%C3%85M%C3%85%C5%BD%C3%95%C3%91&keywords=python+machine+learning&qid=1575545025&sr=8-1) by Sebastian Raschka\n", + "\n", + "" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "- [An Introduction to Statistical Learning](http://faculty.marshall.usc.edu/gareth-james/ISL/)\n", + "\n", + "" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "intro-to-data-science", + "language": "python", + "name": "intro-to-data-science" + }, + "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.12.4" + }, + "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/raw/3_types_of_machine_learning.png b/03_classification/static/3_types_of_machine_learning.png similarity index 100% rename from raw/3_types_of_machine_learning.png rename to 03_classification/static/3_types_of_machine_learning.png diff --git a/raw/classification_vs_regression.png b/03_classification/static/classification_vs_regression.png similarity index 100% rename from raw/classification_vs_regression.png rename to 03_classification/static/classification_vs_regression.png diff --git a/raw/examples.png b/03_classification/static/examples.png similarity index 100% rename from raw/examples.png rename to 03_classification/static/examples.png diff --git a/raw/generalization.png b/03_classification/static/generalization.png similarity index 100% rename from raw/generalization.png rename to 03_classification/static/generalization.png diff --git a/raw/iris.png b/03_classification/static/iris.png similarity index 100% rename from raw/iris.png rename to 03_classification/static/iris.png diff --git a/raw/iris_data.png b/03_classification/static/iris_data.png similarity index 100% rename from raw/iris_data.png rename to 03_classification/static/iris_data.png diff --git a/raw/knn.png b/03_classification/static/knn.png similarity index 100% rename from raw/knn.png rename to 03_classification/static/knn.png diff --git a/raw/python_ml.png b/03_classification/static/python_ml_book.png similarity index 100% rename from raw/python_ml.png rename to 03_classification/static/python_ml_book.png diff --git a/raw/r.png b/03_classification/static/r_ml_book.png similarity index 100% rename from raw/r.png rename to 03_classification/static/r_ml_book.png diff --git a/raw/spam.png b/03_classification/static/spam.png similarity index 100% rename from raw/spam.png rename to 03_classification/static/spam.png diff --git a/raw/what_is_machine_learning.png b/03_classification/static/what_is_machine_learning.png similarity index 100% rename from raw/what_is_machine_learning.png rename to 03_classification/static/what_is_machine_learning.png diff --git a/LICENSE.txt b/LICENSE.txt index 0ec444a..e7802f3 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2018-2020 Alexander Hess [alexander@webartifex.biz] +Copyright (c) 2018-2021 Alexander Hess [alexander@webartifex.biz] Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 1264a22..d0e1b32 100644 --- a/README.md +++ b/README.md @@ -1,50 +1,78 @@ -# Workshop: Machine Learning for Beginners +# An Introduction to Data Science -This repository contains the code for the workshop "Machine Learning for -Beginners" as presented in various occasions at -[WHU - Otto Beisheim School of Management](https://www.whu.edu), such as the -[Campus for Supply Chain Management](https://www.campus-for-supply-chain-management-cscm.de/), -[IdeaLab](https://www.idealab.io)'s [IdeaHack](http://www.ideahack.io), or -within many [executive education](https://ee.whu.edu/) programs. +This project is an introductory workshop + in **[Data Science ](https://en.wikipedia.org/wiki/Data_science)** + in the programming language **[Python ](https://www.python.org/)**. +To learn about Python and programming in detail, + this [introductory course ](https://github.com/webartifex/intro-to-python) is recommended. -## Prerequisites +### Table of Contents -To be suitable for *total beginners*, there are *no* prerequisites. -If you are interested to learn more after this workshop, check out the -full-semester course **[Introduction to Python & Programming](https://github.com/webartifex/intro-to-python)**. +- *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) -## Installation +### Objective -To follow this workshop on your own computer, a working installation of -**Python 3.7** or higher is required. +The **main goal** is to **show** students + how **Python** can be used to solve typical **data science** tasks. -A popular and beginner friendly way is to install the [Anaconda Distribution](https://www.anaconda.com/distribution/) -that not only ships Python but comes pre-packaged with a lot of third-party -libraries from the so-called "scientific stack". -Just go to the [download](https://www.anaconda.com/distribution/#download-section) -section and install the latest version (i.e., *2020-02* with Python 3.7 at the -time of this writing) for your operating system. -Then, among others, you will find an entry "Jupyter Notebook" in your start -menu. -Click on it and a new tab in your web browser will open where you can switch -between folders as you could in your computer's default file browser. +### Prerequisites -To download the course's materials as a ZIP file, click on the green "Clone or -download" button on the top right on this website. -Then, unpack the ZIP file into a folder of your choosing (ideally somewhere -within your personal user folder so that the files show up right away). +To be suitable for *beginners*, there are *no* formal prerequisites. +It is only expected that the student has: +- a *solid* understanding of the **English** language and +- knowledge of **basic mathematics** from high school. + + +### Getting started & Installation + +To follow this workshop, an installation of **Python 3.9** or higher is expected. + +A popular and beginner friendly way is + to install the [Anaconda Distribution](https://www.anaconda.com/download) + that not only ships Python itself + but also comes pre-packaged with a lot of third-party libraries + including [Python's scientific stack](https://scipy.org/). + +Detailed instructions can be found [here ](https://github.com/webartifex/intro-to-python#installation). + +If you are *not* using the Anaconda Distribution, + you must install the third-party libraries via the command + `pip install -r requirements.txt` (or something equivalent) + before working with the notebook files. + + +## Contributing + +Feedback **is highly encouraged** and will be incorporated. +Open an issue in the [issues tracker ](https://github.com/webartifex/intro-to-data-science/issues) + or initiate a [pull request ](https://help.github.com/en/articles/about-pull-requests) + if you are familiar with the concept. +Simple issues that *anyone* can **help fix** are, for example, + **spelling mistakes** or **broken links**. +If you feel that some topic is missing entirely, you may also mention that. +The materials here are considered a **permanent work-in-progress**. ## About the Author -Alexander Hess is a PhD student at the Chair of Logistics Management at the -[WHU - Otto Beisheim School of Management](https://www.whu.edu) where he -conducts research on urban delivery platforms and teaches an introductory -course on Python (cf., [Fall Term 2019](https://vlv.whu.edu/campus/all/event.asp?objgguid=0xE57C2715B01B441AAFD3E79AA05CACCF&from=vvz&gguid=0x6A2B0ED5B2B949E69957A2099E7DE2F1&mode=own&tguid=0x3980A9BBC3BF4A638E977F2DC163F44B&lang=en), -[Spring Term 2020](https://vlv.whu.edu/campus/all/event.asp?objgguid=0x3354F4C108FF4E959CDD692A325D9AFE&from=vvz&gguid=0x262E29795DD742CFBDE72B12B69CEFD6&mode=own&lang=en&tguid=0x2E4A7D1FF3C34AD08FF07685461781C9)). - -Connect him on [LinkedIn](https://www.linkedin.com/in/webartifex). +Alexander Hess is a PhD student + at the Chair of Logistics Management at [WHU - Otto Beisheim School of Management](https://www.whu.edu) + where he conducts research on urban delivery platforms + and teaches coding courses based on Python in the BSc and MBA programs. +Connect with him on [LinkedIn](https://www.linkedin.com/in/webartifex). diff --git a/poetry.lock b/poetry.lock index f014c8d..b44ac31 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,1409 +1,2879 @@ +# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand. + +[[package]] +name = "anyio" +version = "4.4.0" +description = "High level compatibility layer for multiple asynchronous event loop implementations" +optional = false +python-versions = ">=3.8" +files = [ + {file = "anyio-4.4.0-py3-none-any.whl", hash = "sha256:c1b2d8f46a8a812513012e1107cb0e68c17159a7a594208005a57dc776e1bdc7"}, + {file = "anyio-4.4.0.tar.gz", hash = "sha256:5aadc6a1bbb7cdb0bede386cac5e2940f5e2ff3aa20277e991cf028e0585ce94"}, +] + +[package.dependencies] +exceptiongroup = {version = ">=1.0.2", markers = "python_version < \"3.11\""} +idna = ">=2.8" +sniffio = ">=1.1" +typing-extensions = {version = ">=4.1", markers = "python_version < \"3.11\""} + +[package.extras] +doc = ["Sphinx (>=7)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx-rtd-theme"] +test = ["anyio[trio]", "coverage[toml] (>=7)", "exceptiongroup (>=1.2.0)", "hypothesis (>=4.0)", "psutil (>=5.9)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "uvloop (>=0.17)"] +trio = ["trio (>=0.23)"] + [[package]] -category = "main" -description = "Disable App Nap on OS X 10.9" -marker = "sys_platform == \"darwin\" or platform_system == \"Darwin\"" name = "appnope" +version = "0.1.4" +description = "Disable App Nap on macOS >= 10.9" optional = false -python-versions = "*" -version = "0.1.0" +python-versions = ">=3.6" +files = [ + {file = "appnope-0.1.4-py2.py3-none-any.whl", hash = "sha256:502575ee11cd7a28c0205f379b525beefebab9d161b7c964670864014ed7213c"}, + {file = "appnope-0.1.4.tar.gz", hash = "sha256:1de3860566df9caf38f01f86f65e0e13e379af54f9e4bee1e66b48f2efffd1ee"}, +] [[package]] -category = "main" -description = "The secure Argon2 password hashing algorithm." name = "argon2-cffi" +version = "23.1.0" +description = "Argon2 for Python" optional = false -python-versions = "*" -version = "20.1.0" +python-versions = ">=3.7" +files = [ + {file = "argon2_cffi-23.1.0-py3-none-any.whl", hash = "sha256:c670642b78ba29641818ab2e68bd4e6a78ba53b7eff7b4c3815ae16abf91c7ea"}, + {file = "argon2_cffi-23.1.0.tar.gz", hash = "sha256:879c3e79a2729ce768ebb7d36d4609e3a78a4ca2ec3a9f12286ca057e3d0db08"}, +] [package.dependencies] -cffi = ">=1.0.0" -six = "*" +argon2-cffi-bindings = "*" [package.extras] -dev = ["coverage (>=5.0.2)", "hypothesis", "pytest", "sphinx", "wheel", "pre-commit"] -docs = ["sphinx"] -tests = ["coverage (>=5.0.2)", "hypothesis", "pytest"] +dev = ["argon2-cffi[tests,typing]", "tox (>4)"] +docs = ["furo", "myst-parser", "sphinx", "sphinx-copybutton", "sphinx-notfound-page"] +tests = ["hypothesis", "pytest"] +typing = ["mypy"] [[package]] -category = "main" -description = "Async generators and context managers for Python 3.5+" -name = "async-generator" +name = "argon2-cffi-bindings" +version = "21.2.0" +description = "Low-level CFFI bindings for Argon2" optional = false -python-versions = ">=3.5" -version = "1.10" +python-versions = ">=3.6" +files = [ + {file = "argon2-cffi-bindings-21.2.0.tar.gz", hash = "sha256:bb89ceffa6c791807d1305ceb77dbfacc5aa499891d2c55661c6459651fc39e3"}, + {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:ccb949252cb2ab3a08c02024acb77cfb179492d5701c7cbdbfd776124d4d2367"}, + {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9524464572e12979364b7d600abf96181d3541da11e23ddf565a32e70bd4dc0d"}, + {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b746dba803a79238e925d9046a63aa26bf86ab2a2fe74ce6b009a1c3f5c8f2ae"}, + {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:58ed19212051f49a523abb1dbe954337dc82d947fb6e5a0da60f7c8471a8476c"}, + {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:bd46088725ef7f58b5a1ef7ca06647ebaf0eb4baff7d1d0d177c6cc8744abd86"}, + {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-musllinux_1_1_i686.whl", hash = "sha256:8cd69c07dd875537a824deec19f978e0f2078fdda07fd5c42ac29668dda5f40f"}, + {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:f1152ac548bd5b8bcecfb0b0371f082037e47128653df2e8ba6e914d384f3c3e"}, + {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-win32.whl", hash = "sha256:603ca0aba86b1349b147cab91ae970c63118a0f30444d4bc80355937c950c082"}, + {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-win_amd64.whl", hash = "sha256:b2ef1c30440dbbcba7a5dc3e319408b59676e2e039e2ae11a8775ecf482b192f"}, + {file = "argon2_cffi_bindings-21.2.0-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:e415e3f62c8d124ee16018e491a009937f8cf7ebf5eb430ffc5de21b900dad93"}, + {file = "argon2_cffi_bindings-21.2.0-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:3e385d1c39c520c08b53d63300c3ecc28622f076f4c2b0e6d7e796e9f6502194"}, + {file = "argon2_cffi_bindings-21.2.0-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2c3e3cc67fdb7d82c4718f19b4e7a87123caf8a93fde7e23cf66ac0337d3cb3f"}, + {file = "argon2_cffi_bindings-21.2.0-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6a22ad9800121b71099d0fb0a65323810a15f2e292f2ba450810a7316e128ee5"}, + {file = "argon2_cffi_bindings-21.2.0-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f9f8b450ed0547e3d473fdc8612083fd08dd2120d6ac8f73828df9b7d45bb351"}, + {file = "argon2_cffi_bindings-21.2.0-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:93f9bf70084f97245ba10ee36575f0c3f1e7d7724d67d8e5b08e61787c320ed7"}, + {file = "argon2_cffi_bindings-21.2.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:3b9ef65804859d335dc6b31582cad2c5166f0c3e7975f324d9ffaa34ee7e6583"}, + {file = "argon2_cffi_bindings-21.2.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d4966ef5848d820776f5f562a7d45fdd70c2f330c961d0d745b784034bd9f48d"}, + {file = "argon2_cffi_bindings-21.2.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:20ef543a89dee4db46a1a6e206cd015360e5a75822f76df533845c3cbaf72670"}, + {file = "argon2_cffi_bindings-21.2.0-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ed2937d286e2ad0cc79a7087d3c272832865f779430e0cc2b4f3718d3159b0cb"}, + {file = "argon2_cffi_bindings-21.2.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:5e00316dabdaea0b2dd82d141cc66889ced0cdcbfa599e8b471cf22c620c329a"}, +] + +[package.dependencies] +cffi = ">=1.0.1" + +[package.extras] +dev = ["cogapp", "pre-commit", "pytest", "wheel"] +tests = ["pytest"] + +[[package]] +name = "arrow" +version = "1.3.0" +description = "Better dates & times for Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "arrow-1.3.0-py3-none-any.whl", hash = "sha256:c728b120ebc00eb84e01882a6f5e7927a53960aa990ce7dd2b10f39005a67f80"}, + {file = "arrow-1.3.0.tar.gz", hash = "sha256:d4540617648cb5f895730f1ad8c82a65f2dad0166f57b75f3ca54759c4d67a85"}, +] + +[package.dependencies] +python-dateutil = ">=2.7.0" +types-python-dateutil = ">=2.8.10" + +[package.extras] +doc = ["doc8", "sphinx (>=7.0.0)", "sphinx-autobuild", "sphinx-autodoc-typehints", "sphinx_rtd_theme (>=1.3.0)"] +test = ["dateparser (==1.*)", "pre-commit", "pytest", "pytest-cov", "pytest-mock", "pytz (==2021.1)", "simplejson (==3.*)"] + +[[package]] +name = "asttokens" +version = "2.4.1" +description = "Annotate AST trees with source code positions" +optional = false +python-versions = "*" +files = [ + {file = "asttokens-2.4.1-py2.py3-none-any.whl", hash = "sha256:051ed49c3dcae8913ea7cd08e46a606dba30b79993209636c4875bc1d637bc24"}, + {file = "asttokens-2.4.1.tar.gz", hash = "sha256:b03869718ba9a6eb027e134bfdf69f38a236d681c83c160d510768af11254ba0"}, +] + +[package.dependencies] +six = ">=1.12.0" + +[package.extras] +astroid = ["astroid (>=1,<2)", "astroid (>=2,<4)"] +test = ["astroid (>=1,<2)", "astroid (>=2,<4)", "pytest"] + +[[package]] +name = "async-lru" +version = "2.0.4" +description = "Simple LRU cache for asyncio" +optional = false +python-versions = ">=3.8" +files = [ + {file = "async-lru-2.0.4.tar.gz", hash = "sha256:b8a59a5df60805ff63220b2a0c5b5393da5521b113cd5465a44eb037d81a5627"}, + {file = "async_lru-2.0.4-py3-none-any.whl", hash = "sha256:ff02944ce3c288c5be660c42dbcca0742b32c3b279d6dceda655190240b99224"}, +] + +[package.dependencies] +typing-extensions = {version = ">=4.0.0", markers = "python_version < \"3.11\""} [[package]] -category = "main" -description = "Classes Without Boilerplate" name = "attrs" +version = "23.2.0" +description = "Classes Without Boilerplate" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "20.2.0" +python-versions = ">=3.7" +files = [ + {file = "attrs-23.2.0-py3-none-any.whl", hash = "sha256:99b87a485a5820b23b879f04c2305b44b951b502fd64be915879d77a7e8fc6f1"}, + {file = "attrs-23.2.0.tar.gz", hash = "sha256:935dc3b529c262f6cf76e50877d35a4bd3c1de194fd41f47a2b7ae8f19971f30"}, +] [package.extras] -dev = ["coverage (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "zope.interface", "sphinx", "sphinx-rtd-theme", "pre-commit"] -docs = ["sphinx", "sphinx-rtd-theme", "zope.interface"] -tests = ["coverage (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "zope.interface"] -tests_no_zope = ["coverage (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six"] +cov = ["attrs[tests]", "coverage[toml] (>=5.3)"] +dev = ["attrs[tests]", "pre-commit"] +docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier", "zope-interface"] +tests = ["attrs[tests-no-zope]", "zope-interface"] +tests-mypy = ["mypy (>=1.6)", "pytest-mypy-plugins"] +tests-no-zope = ["attrs[tests-mypy]", "cloudpickle", "hypothesis", "pympler", "pytest (>=4.3.0)", "pytest-xdist[psutil]"] [[package]] -category = "main" -description = "Specifications for callback functions passed in to an API" -name = "backcall" +name = "babel" +version = "2.15.0" +description = "Internationalization utilities" optional = false -python-versions = "*" -version = "0.2.0" +python-versions = ">=3.8" +files = [ + {file = "Babel-2.15.0-py3-none-any.whl", hash = "sha256:08706bdad8d0a3413266ab61bd6c34d0c28d6e1e7badf40a2cebe67644e2e1fb"}, + {file = "babel-2.15.0.tar.gz", hash = "sha256:8daf0e265d05768bc6c7a314cf1321e9a123afc328cc635c18622a2f30a04413"}, +] + +[package.extras] +dev = ["freezegun (>=1.0,<2.0)", "pytest (>=6.0)", "pytest-cov"] [[package]] -category = "main" -description = "An easy safelist-based HTML-sanitizing tool." -name = "bleach" +name = "beautifulsoup4" +version = "4.12.3" +description = "Screen-scraping library" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -version = "3.2.0" +python-versions = ">=3.6.0" +files = [ + {file = "beautifulsoup4-4.12.3-py3-none-any.whl", hash = "sha256:b80878c9f40111313e55da8ba20bdba06d8fa3969fc68304167741bbf9e082ed"}, + {file = "beautifulsoup4-4.12.3.tar.gz", hash = "sha256:74e3d1928edc070d21748185c46e3fb33490f22f52a3addee9aee0f4f7781051"}, +] + +[package.dependencies] +soupsieve = ">1.2" + +[package.extras] +cchardet = ["cchardet"] +chardet = ["chardet"] +charset-normalizer = ["charset-normalizer"] +html5lib = ["html5lib"] +lxml = ["lxml"] + +[[package]] +name = "black" +version = "24.4.2" +description = "The uncompromising code formatter." +optional = false +python-versions = ">=3.8" +files = [ + {file = "black-24.4.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:dd1b5a14e417189db4c7b64a6540f31730713d173f0b63e55fabd52d61d8fdce"}, + {file = "black-24.4.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8e537d281831ad0e71007dcdcbe50a71470b978c453fa41ce77186bbe0ed6021"}, + {file = "black-24.4.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eaea3008c281f1038edb473c1aa8ed8143a5535ff18f978a318f10302b254063"}, + {file = "black-24.4.2-cp310-cp310-win_amd64.whl", hash = "sha256:7768a0dbf16a39aa5e9a3ded568bb545c8c2727396d063bbaf847df05b08cd96"}, + {file = "black-24.4.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:257d724c2c9b1660f353b36c802ccece186a30accc7742c176d29c146df6e474"}, + {file = "black-24.4.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:bdde6f877a18f24844e381d45e9947a49e97933573ac9d4345399be37621e26c"}, + {file = "black-24.4.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e151054aa00bad1f4e1f04919542885f89f5f7d086b8a59e5000e6c616896ffb"}, + {file = "black-24.4.2-cp311-cp311-win_amd64.whl", hash = "sha256:7e122b1c4fb252fd85df3ca93578732b4749d9be076593076ef4d07a0233c3e1"}, + {file = "black-24.4.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:accf49e151c8ed2c0cdc528691838afd217c50412534e876a19270fea1e28e2d"}, + {file = "black-24.4.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:88c57dc656038f1ab9f92b3eb5335ee9b021412feaa46330d5eba4e51fe49b04"}, + {file = "black-24.4.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:be8bef99eb46d5021bf053114442914baeb3649a89dc5f3a555c88737e5e98fc"}, + {file = "black-24.4.2-cp312-cp312-win_amd64.whl", hash = "sha256:415e686e87dbbe6f4cd5ef0fbf764af7b89f9057b97c908742b6008cc554b9c0"}, + {file = "black-24.4.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:bf10f7310db693bb62692609b397e8d67257c55f949abde4c67f9cc574492cc7"}, + {file = "black-24.4.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:98e123f1d5cfd42f886624d84464f7756f60ff6eab89ae845210631714f6db94"}, + {file = "black-24.4.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:48a85f2cb5e6799a9ef05347b476cce6c182d6c71ee36925a6c194d074336ef8"}, + {file = "black-24.4.2-cp38-cp38-win_amd64.whl", hash = "sha256:b1530ae42e9d6d5b670a34db49a94115a64596bc77710b1d05e9801e62ca0a7c"}, + {file = "black-24.4.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:37aae07b029fa0174d39daf02748b379399b909652a806e5708199bd93899da1"}, + {file = "black-24.4.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:da33a1a5e49c4122ccdfd56cd021ff1ebc4a1ec4e2d01594fef9b6f267a9e741"}, + {file = "black-24.4.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ef703f83fc32e131e9bcc0a5094cfe85599e7109f896fe8bc96cc402f3eb4b6e"}, + {file = "black-24.4.2-cp39-cp39-win_amd64.whl", hash = "sha256:b9176b9832e84308818a99a561e90aa479e73c523b3f77afd07913380ae2eab7"}, + {file = "black-24.4.2-py3-none-any.whl", hash = "sha256:d36ed1124bb81b32f8614555b34cc4259c3fbc7eec17870e8ff8ded335b58d8c"}, + {file = "black-24.4.2.tar.gz", hash = "sha256:c872b53057f000085da66a19c55d68f6f8ddcac2642392ad3a355878406fbd4d"}, +] + +[package.dependencies] +click = ">=8.0.0" +ipython = {version = ">=7.8.0", optional = true, markers = "extra == \"jupyter\""} +mypy-extensions = ">=0.4.3" +packaging = ">=22.0" +pathspec = ">=0.9.0" +platformdirs = ">=2" +tokenize-rt = {version = ">=3.2.0", optional = true, markers = "extra == \"jupyter\""} +tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} +typing-extensions = {version = ">=4.0.1", markers = "python_version < \"3.11\""} + +[package.extras] +colorama = ["colorama (>=0.4.3)"] +d = ["aiohttp (>=3.7.4)", "aiohttp (>=3.7.4,!=3.9.0)"] +jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] +uvloop = ["uvloop (>=0.15.2)"] + +[[package]] +name = "bleach" +version = "6.1.0" +description = "An easy safelist-based HTML-sanitizing tool." +optional = false +python-versions = ">=3.8" +files = [ + {file = "bleach-6.1.0-py3-none-any.whl", hash = "sha256:3225f354cfc436b9789c66c4ee030194bee0568fbf9cbdad3bc8b5c26c5f12b6"}, + {file = "bleach-6.1.0.tar.gz", hash = "sha256:0a31f1837963c41d46bbf1331b8778e1308ea0791db03cc4e7357b97cf42a8fe"}, +] [package.dependencies] -packaging = "*" six = ">=1.9.0" webencodings = "*" -[[package]] -category = "main" -description = "Python package for providing Mozilla's CA Bundle." -name = "certifi" -optional = false -python-versions = "*" -version = "2020.6.20" +[package.extras] +css = ["tinycss2 (>=1.1.0,<1.3)"] [[package]] -category = "main" -description = "Foreign Function Interface for Python calling C code." -name = "cffi" +name = "certifi" +version = "2024.7.4" +description = "Python package for providing Mozilla's CA Bundle." optional = false -python-versions = "*" -version = "1.14.3" +python-versions = ">=3.6" +files = [ + {file = "certifi-2024.7.4-py3-none-any.whl", hash = "sha256:c198e21b1289c2ab85ee4e67bb4b4ef3ead0892059901a8d5b622f24a1101e90"}, + {file = "certifi-2024.7.4.tar.gz", hash = "sha256:5a1e7645bc0ec61a09e26c36f6106dd4cf40c6db3a1fb6352b0244e7fb057c7b"}, +] + +[[package]] +name = "cffi" +version = "1.16.0" +description = "Foreign Function Interface for Python calling C code." +optional = false +python-versions = ">=3.8" +files = [ + {file = "cffi-1.16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6b3d6606d369fc1da4fd8c357d026317fbb9c9b75d36dc16e90e84c26854b088"}, + {file = "cffi-1.16.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ac0f5edd2360eea2f1daa9e26a41db02dd4b0451b48f7c318e217ee092a213e9"}, + {file = "cffi-1.16.0-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7e61e3e4fa664a8588aa25c883eab612a188c725755afff6289454d6362b9673"}, + {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a72e8961a86d19bdb45851d8f1f08b041ea37d2bd8d4fd19903bc3083d80c896"}, + {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5b50bf3f55561dac5438f8e70bfcdfd74543fd60df5fa5f62d94e5867deca684"}, + {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7651c50c8c5ef7bdb41108b7b8c5a83013bfaa8a935590c5d74627c047a583c7"}, + {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e4108df7fe9b707191e55f33efbcb2d81928e10cea45527879a4749cbe472614"}, + {file = "cffi-1.16.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:32c68ef735dbe5857c810328cb2481e24722a59a2003018885514d4c09af9743"}, + {file = "cffi-1.16.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:673739cb539f8cdaa07d92d02efa93c9ccf87e345b9a0b556e3ecc666718468d"}, + {file = "cffi-1.16.0-cp310-cp310-win32.whl", hash = "sha256:9f90389693731ff1f659e55c7d1640e2ec43ff725cc61b04b2f9c6d8d017df6a"}, + {file = "cffi-1.16.0-cp310-cp310-win_amd64.whl", hash = "sha256:e6024675e67af929088fda399b2094574609396b1decb609c55fa58b028a32a1"}, + {file = "cffi-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b84834d0cf97e7d27dd5b7f3aca7b6e9263c56308ab9dc8aae9784abb774d404"}, + {file = "cffi-1.16.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1b8ebc27c014c59692bb2664c7d13ce7a6e9a629be20e54e7271fa696ff2b417"}, + {file = "cffi-1.16.0-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ee07e47c12890ef248766a6e55bd38ebfb2bb8edd4142d56db91b21ea68b7627"}, + {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8a9d3ebe49f084ad71f9269834ceccbf398253c9fac910c4fd7053ff1386936"}, + {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e70f54f1796669ef691ca07d046cd81a29cb4deb1e5f942003f401c0c4a2695d"}, + {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5bf44d66cdf9e893637896c7faa22298baebcd18d1ddb6d2626a6e39793a1d56"}, + {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7b78010e7b97fef4bee1e896df8a4bbb6712b7f05b7ef630f9d1da00f6444d2e"}, + {file = "cffi-1.16.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c6a164aa47843fb1b01e941d385aab7215563bb8816d80ff3a363a9f8448a8dc"}, + {file = "cffi-1.16.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e09f3ff613345df5e8c3667da1d918f9149bd623cd9070c983c013792a9a62eb"}, + {file = "cffi-1.16.0-cp311-cp311-win32.whl", hash = "sha256:2c56b361916f390cd758a57f2e16233eb4f64bcbeee88a4881ea90fca14dc6ab"}, + {file = "cffi-1.16.0-cp311-cp311-win_amd64.whl", hash = "sha256:db8e577c19c0fda0beb7e0d4e09e0ba74b1e4c092e0e40bfa12fe05b6f6d75ba"}, + {file = "cffi-1.16.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:fa3a0128b152627161ce47201262d3140edb5a5c3da88d73a1b790a959126956"}, + {file = "cffi-1.16.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:68e7c44931cc171c54ccb702482e9fc723192e88d25a0e133edd7aff8fcd1f6e"}, + {file = "cffi-1.16.0-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:abd808f9c129ba2beda4cfc53bde801e5bcf9d6e0f22f095e45327c038bfe68e"}, + {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:88e2b3c14bdb32e440be531ade29d3c50a1a59cd4e51b1dd8b0865c54ea5d2e2"}, + {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fcc8eb6d5902bb1cf6dc4f187ee3ea80a1eba0a89aba40a5cb20a5087d961357"}, + {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b7be2d771cdba2942e13215c4e340bfd76398e9227ad10402a8767ab1865d2e6"}, + {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e715596e683d2ce000574bae5d07bd522c781a822866c20495e52520564f0969"}, + {file = "cffi-1.16.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:2d92b25dbf6cae33f65005baf472d2c245c050b1ce709cc4588cdcdd5495b520"}, + {file = "cffi-1.16.0-cp312-cp312-win32.whl", hash = "sha256:b2ca4e77f9f47c55c194982e10f058db063937845bb2b7a86c84a6cfe0aefa8b"}, + {file = "cffi-1.16.0-cp312-cp312-win_amd64.whl", hash = "sha256:68678abf380b42ce21a5f2abde8efee05c114c2fdb2e9eef2efdb0257fba1235"}, + {file = "cffi-1.16.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0c9ef6ff37e974b73c25eecc13952c55bceed9112be2d9d938ded8e856138bcc"}, + {file = "cffi-1.16.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a09582f178759ee8128d9270cd1344154fd473bb77d94ce0aeb2a93ebf0feaf0"}, + {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e760191dd42581e023a68b758769e2da259b5d52e3103c6060ddc02c9edb8d7b"}, + {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:80876338e19c951fdfed6198e70bc88f1c9758b94578d5a7c4c91a87af3cf31c"}, + {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a6a14b17d7e17fa0d207ac08642c8820f84f25ce17a442fd15e27ea18d67c59b"}, + {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6602bc8dc6f3a9e02b6c22c4fc1e47aa50f8f8e6d3f78a5e16ac33ef5fefa324"}, + {file = "cffi-1.16.0-cp38-cp38-win32.whl", hash = "sha256:131fd094d1065b19540c3d72594260f118b231090295d8c34e19a7bbcf2e860a"}, + {file = "cffi-1.16.0-cp38-cp38-win_amd64.whl", hash = "sha256:31d13b0f99e0836b7ff893d37af07366ebc90b678b6664c955b54561fc36ef36"}, + {file = "cffi-1.16.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:582215a0e9adbe0e379761260553ba11c58943e4bbe9c36430c4ca6ac74b15ed"}, + {file = "cffi-1.16.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b29ebffcf550f9da55bec9e02ad430c992a87e5f512cd63388abb76f1036d8d2"}, + {file = "cffi-1.16.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dc9b18bf40cc75f66f40a7379f6a9513244fe33c0e8aa72e2d56b0196a7ef872"}, + {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9cb4a35b3642fc5c005a6755a5d17c6c8b6bcb6981baf81cea8bfbc8903e8ba8"}, + {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b86851a328eedc692acf81fb05444bdf1891747c25af7529e39ddafaf68a4f3f"}, + {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c0f31130ebc2d37cdd8e44605fb5fa7ad59049298b3f745c74fa74c62fbfcfc4"}, + {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f8e709127c6c77446a8c0a8c8bf3c8ee706a06cd44b1e827c3e6a2ee6b8c098"}, + {file = "cffi-1.16.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:748dcd1e3d3d7cd5443ef03ce8685043294ad6bd7c02a38d1bd367cfd968e000"}, + {file = "cffi-1.16.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8895613bcc094d4a1b2dbe179d88d7fb4a15cee43c052e8885783fac397d91fe"}, + {file = "cffi-1.16.0-cp39-cp39-win32.whl", hash = "sha256:ed86a35631f7bfbb28e108dd96773b9d5a6ce4811cf6ea468bb6a359b256b1e4"}, + {file = "cffi-1.16.0-cp39-cp39-win_amd64.whl", hash = "sha256:3686dffb02459559c74dd3d81748269ffb0eb027c39a6fc99502de37d501faa8"}, + {file = "cffi-1.16.0.tar.gz", hash = "sha256:bcb3ef43e58665bbda2fb198698fcae6776483e0c4a631aa5647806c25e02cc0"}, +] [package.dependencies] pycparser = "*" [[package]] -category = "main" -description = "Universal encoding detector for Python 2 and 3" -name = "chardet" -optional = false -python-versions = "*" -version = "3.0.4" - -[[package]] -category = "main" -description = "Cross-platform colored terminal text." -marker = "sys_platform == \"win32\"" -name = "colorama" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -version = "0.4.3" - -[[package]] -category = "main" -description = "Composable style cycles" -name = "cycler" -optional = false -python-versions = "*" -version = "0.10.0" - -[package.dependencies] -six = "*" - -[[package]] -category = "main" -description = "Decorators for Humans" -name = "decorator" -optional = false -python-versions = ">=2.6, !=3.0.*, !=3.1.*" -version = "4.4.2" - -[[package]] -category = "main" -description = "XML bomb protection for Python stdlib modules" -name = "defusedxml" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -version = "0.6.0" - -[[package]] -category = "main" -description = "Discover and load entry points from installed packages." -name = "entrypoints" -optional = false -python-versions = ">=2.7" -version = "0.3" - -[[package]] -category = "main" -description = "Internationalized Domain Names in Applications (IDNA)" -name = "idna" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "2.10" - -[[package]] -category = "main" -description = "Read metadata from Python packages" -marker = "python_version < \"3.8\"" -name = "importlib-metadata" -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" -version = "1.7.0" - -[package.dependencies] -zipp = ">=0.5" - -[package.extras] -docs = ["sphinx", "rst.linker"] -testing = ["packaging", "pep517", "importlib-resources (>=1.3)"] - -[[package]] -category = "main" -description = "IPython Kernel for Jupyter" -name = "ipykernel" -optional = false -python-versions = ">=3.5" -version = "5.3.4" - -[package.dependencies] -appnope = "*" -ipython = ">=5.0.0" -jupyter-client = "*" -tornado = ">=4.2" -traitlets = ">=4.1.0" - -[package.extras] -test = ["pytest (!=5.3.4)", "pytest-cov", "flaky", "nose"] - -[[package]] -category = "main" -description = "IPython: Productive Interactive Computing" -name = "ipython" -optional = false -python-versions = ">=3.7" -version = "7.18.1" - -[package.dependencies] -appnope = "*" -backcall = "*" -colorama = "*" -decorator = "*" -jedi = ">=0.10" -pexpect = ">4.3" -pickleshare = "*" -prompt-toolkit = ">=2.0.0,<3.0.0 || >3.0.0,<3.0.1 || >3.0.1,<3.1.0" -pygments = "*" -setuptools = ">=18.5" -traitlets = ">=4.2" - -[package.extras] -all = ["Sphinx (>=1.3)", "ipykernel", "ipyparallel", "ipywidgets", "nbconvert", "nbformat", "nose (>=0.10.1)", "notebook", "numpy (>=1.14)", "pygments", "qtconsole", "requests", "testpath"] -doc = ["Sphinx (>=1.3)"] -kernel = ["ipykernel"] -nbconvert = ["nbconvert"] -nbformat = ["nbformat"] -notebook = ["notebook", "ipywidgets"] -parallel = ["ipyparallel"] -qtconsole = ["qtconsole"] -test = ["nose (>=0.10.1)", "requests", "testpath", "pygments", "nbformat", "ipykernel", "numpy (>=1.14)"] - -[[package]] -category = "main" -description = "Vestigial utilities from IPython" -name = "ipython-genutils" -optional = false -python-versions = "*" -version = "0.2.0" - -[[package]] -category = "main" -description = "An autocompletion tool for Python that can be used for text editors." -name = "jedi" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -version = "0.17.2" - -[package.dependencies] -parso = ">=0.7.0,<0.8.0" - -[package.extras] -qa = ["flake8 (3.7.9)"] -testing = ["Django (<3.1)", "colorama", "docopt", "pytest (>=3.9.0,<5.0.0)"] - -[[package]] -category = "main" -description = "A very fast and expressive template engine." -name = "jinja2" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -version = "2.11.2" - -[package.dependencies] -MarkupSafe = ">=0.23" - -[package.extras] -i18n = ["Babel (>=0.8)"] - -[[package]] -category = "main" -description = "Lightweight pipelining: using Python functions as pipeline jobs." -name = "joblib" -optional = false -python-versions = ">=3.6" -version = "0.16.0" - -[[package]] -category = "main" -description = "A Python implementation of the JSON5 data format." -name = "json5" -optional = false -python-versions = "*" -version = "0.9.5" - -[package.extras] -dev = ["hypothesis"] - -[[package]] -category = "main" -description = "An implementation of JSON Schema validation for Python" -name = "jsonschema" -optional = false -python-versions = "*" -version = "3.2.0" - -[package.dependencies] -attrs = ">=17.4.0" -pyrsistent = ">=0.14.0" -setuptools = "*" -six = ">=1.11.0" - -[package.dependencies.importlib-metadata] -python = "<3.8" -version = "*" - -[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"] - -[[package]] -category = "main" -description = "Jupyter protocol implementation and client libraries" -name = "jupyter-client" -optional = false -python-versions = ">=3.5" -version = "6.1.7" - -[package.dependencies] -jupyter-core = ">=4.6.0" -python-dateutil = ">=2.1" -pyzmq = ">=13" -tornado = ">=4.1" -traitlets = "*" - -[package.extras] -test = ["ipykernel", "ipython", "mock", "pytest", "pytest-asyncio", "async-generator", "pytest-timeout"] - -[[package]] -category = "main" -description = "Jupyter core package. A base package on which Jupyter projects rely." -name = "jupyter-core" -optional = false -python-versions = "!=3.0,!=3.1,!=3.2,!=3.3,!=3.4,>=2.7" -version = "4.6.3" - -[package.dependencies] -pywin32 = ">=1.0" -traitlets = "*" - -[[package]] -category = "main" -description = "The JupyterLab notebook server extension." -name = "jupyterlab" -optional = false -python-versions = ">=3.5" -version = "2.2.8" - -[package.dependencies] -jinja2 = ">=2.10" -jupyterlab-server = ">=1.1.5,<2.0" -notebook = ">=4.3.1" -tornado = "<6.0.0 || >6.0.0,<6.0.1 || >6.0.1,<6.0.2 || >6.0.2" - -[package.extras] -docs = ["jsx-lexer", "recommonmark", "sphinx", "sphinx-rtd-theme", "sphinx-copybutton"] -test = ["pytest", "pytest-check-links", "requests", "wheel", "virtualenv"] - -[[package]] -category = "main" -description = "Pygments theme using JupyterLab CSS variables" -name = "jupyterlab-pygments" -optional = false -python-versions = "*" -version = "0.1.1" - -[package.dependencies] -pygments = ">=2.4.1,<3" - -[[package]] -category = "main" -description = "JupyterLab Server" -name = "jupyterlab-server" -optional = false -python-versions = ">=3.5" -version = "1.2.0" - -[package.dependencies] -jinja2 = ">=2.10" -json5 = "*" -jsonschema = ">=3.0.1" -notebook = ">=4.2.0" -requests = "*" - -[package.extras] -test = ["pytest", "requests"] - -[[package]] -category = "main" -description = "A fast implementation of the Cassowary constraint solver" -name = "kiwisolver" -optional = false -python-versions = ">=3.6" -version = "1.2.0" - -[[package]] -category = "main" -description = "Safely add untrusted strings to HTML/XML markup." -name = "markupsafe" -optional = false -python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*" -version = "1.1.1" - -[[package]] -category = "main" -description = "Python plotting package" -name = "matplotlib" -optional = false -python-versions = ">=3.6" +name = "charset-normalizer" version = "3.3.2" - -[package.dependencies] -certifi = ">=2020.06.20" -cycler = ">=0.10" -kiwisolver = ">=1.0.1" -numpy = ">=1.15" -pillow = ">=6.2.0" -pyparsing = ">=2.0.3,<2.0.4 || >2.0.4,<2.1.2 || >2.1.2,<2.1.6 || >2.1.6" -python-dateutil = ">=2.1" - -[[package]] -category = "main" -description = "The fastest markdown parser in pure Python" -name = "mistune" +description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." optional = false -python-versions = "*" -version = "0.8.4" +python-versions = ">=3.7.0" +files = [ + {file = "charset-normalizer-3.3.2.tar.gz", hash = "sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9063e24fdb1e498ab71cb7419e24622516c4a04476b17a2dab57e8baa30d6e03"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6897af51655e3691ff853668779c7bad41579facacf5fd7253b0133308cf000d"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1d3193f4a680c64b4b6a9115943538edb896edc190f0b222e73761716519268e"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd70574b12bb8a4d2aaa0094515df2463cb429d8536cfb6c7ce983246983e5a6"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8465322196c8b4d7ab6d1e049e4c5cb460d0394da4a27d23cc242fbf0034b6b5"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a9a8e9031d613fd2009c182b69c7b2c1ef8239a0efb1df3f7c8da66d5dd3d537"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:beb58fe5cdb101e3a055192ac291b7a21e3b7ef4f67fa1d74e331a7f2124341c"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e06ed3eb3218bc64786f7db41917d4e686cc4856944f53d5bdf83a6884432e12"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:2e81c7b9c8979ce92ed306c249d46894776a909505d8f5a4ba55b14206e3222f"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:572c3763a264ba47b3cf708a44ce965d98555f618ca42c926a9c1616d8f34269"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-win32.whl", hash = "sha256:3d47fa203a7bd9c5b6cee4736ee84ca03b8ef23193c0d1ca99b5089f72645c73"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:10955842570876604d404661fbccbc9c7e684caf432c09c715ec38fbae45ae09"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:802fe99cca7457642125a8a88a084cef28ff0cf9407060f7b93dca5aa25480db"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ceae2f17a9c33cb48e3263960dc5fc8005351ee19db217e9b1bb15d28c02574"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:65f6f63034100ead094b8744b3b97965785388f308a64cf8d7c34f2f2e5be0c4"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4a78b2b446bd7c934f5dcedc588903fb2f5eec172f3d29e52a9096a43722adfc"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e537484df0d8f426ce2afb2d0f8e1c3d0b114b83f8850e5f2fbea0e797bd82ae"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:eb6904c354526e758fda7167b33005998fb68c46fbc10e013ca97f21ca5c8887"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:deb6be0ac38ece9ba87dea880e438f25ca3eddfac8b002a2ec3d9183a454e8ae"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:4ab2fe47fae9e0f9dee8c04187ce5d09f48eabe611be8259444906793ab7cbce"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:80402cd6ee291dcb72644d6eac93785fe2c8b9cb30893c1af5b8fdd753b9d40f"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-win32.whl", hash = "sha256:7cd13a2e3ddeed6913a65e66e94b51d80a041145a026c27e6bb76c31a853c6ab"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-win32.whl", hash = "sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:95f2a5796329323b8f0512e09dbb7a1860c46a39da62ecb2324f116fa8fdc85c"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c002b4ffc0be611f0d9da932eb0f704fe2602a9a949d1f738e4c34c75b0863d5"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a981a536974bbc7a512cf44ed14938cf01030a99e9b3a06dd59578882f06f985"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3287761bc4ee9e33561a7e058c72ac0938c4f57fe49a09eae428fd88aafe7bb6"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:42cb296636fcc8b0644486d15c12376cb9fa75443e00fb25de0b8602e64c1714"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0a55554a2fa0d408816b3b5cedf0045f4b8e1a6065aec45849de2d6f3f8e9786"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:c083af607d2515612056a31f0a8d9e0fcb5876b7bfc0abad3ecd275bc4ebc2d5"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:87d1351268731db79e0f8e745d92493ee2841c974128ef629dc518b937d9194c"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:bd8f7df7d12c2db9fab40bdd87a7c09b1530128315d047a086fa3ae3435cb3a8"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:c180f51afb394e165eafe4ac2936a14bee3eb10debc9d9e4db8958fe36afe711"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:8c622a5fe39a48f78944a87d4fb8a53ee07344641b0562c540d840748571b811"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-win32.whl", hash = "sha256:db364eca23f876da6f9e16c9da0df51aa4f104a972735574842618b8c6d999d4"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-win_amd64.whl", hash = "sha256:86216b5cee4b06df986d214f664305142d9c76df9b6512be2738aa72a2048f99"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:6463effa3186ea09411d50efc7d85360b38d5f09b870c48e4600f63af490e56a"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6c4caeef8fa63d06bd437cd4bdcf3ffefe6738fb1b25951440d80dc7df8c03ac"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:37e55c8e51c236f95b033f6fb391d7d7970ba5fe7ff453dad675e88cf303377a"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb69256e180cb6c8a894fee62b3afebae785babc1ee98b81cdf68bbca1987f33"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ae5f4161f18c61806f411a13b0310bea87f987c7d2ecdbdaad0e94eb2e404238"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b2b0a0c0517616b6869869f8c581d4eb2dd83a4d79e0ebcb7d373ef9956aeb0a"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:45485e01ff4d3630ec0d9617310448a8702f70e9c01906b0d0118bdf9d124cf2"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eb00ed941194665c332bf8e078baf037d6c35d7c4f3102ea2d4f16ca94a26dc8"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:2127566c664442652f024c837091890cb1942c30937add288223dc895793f898"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a50aebfa173e157099939b17f18600f72f84eed3049e743b68ad15bd69b6bf99"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:4d0d1650369165a14e14e1e47b372cfcb31d6ab44e6e33cb2d4e57265290044d"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:923c0c831b7cfcb071580d3f46c4baf50f174be571576556269530f4bbd79d04"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:06a81e93cd441c56a9b65d8e1d043daeb97a3d0856d177d5c90ba85acb3db087"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-win32.whl", hash = "sha256:6ef1d82a3af9d3eecdba2321dc1b3c238245d890843e040e41e470ffa64c3e25"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:eb8821e09e916165e160797a6c17edda0679379a4be5c716c260e836e122f54b"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c235ebd9baae02f1b77bcea61bce332cb4331dc3617d254df3323aa01ab47bd4"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5b4c145409bef602a690e7cfad0a15a55c13320ff7a3ad7ca59c13bb8ba4d45d"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:68d1f8a9e9e37c1223b656399be5d6b448dea850bed7d0f87a8311f1ff3dabb0"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22afcb9f253dac0696b5a4be4a1c0f8762f8239e21b99680099abd9b2b1b2269"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e27ad930a842b4c5eb8ac0016b0a54f5aebbe679340c26101df33424142c143c"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1f79682fbe303db92bc2b1136016a38a42e835d932bab5b3b1bfcfbf0640e519"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b261ccdec7821281dade748d088bb6e9b69e6d15b30652b74cbbac25e280b796"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:122c7fa62b130ed55f8f285bfd56d5f4b4a5b503609d181f9ad85e55c89f4185"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d0eccceffcb53201b5bfebb52600a5fb483a20b61da9dbc885f8b103cbe7598c"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9f96df6923e21816da7e0ad3fd47dd8f94b2a5ce594e00677c0013018b813458"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:7f04c839ed0b6b98b1a7501a002144b76c18fb1c1850c8b98d458ac269e26ed2"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:34d1c8da1e78d2e001f363791c98a272bb734000fcef47a491c1e3b0505657a8"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-win32.whl", hash = "sha256:aed38f6e4fb3f5d6bf81bfa990a07806be9d83cf7bacef998ab1a9bd660a581f"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:b01b88d45a6fcb69667cd6d2f7a9aeb4bf53760d7fc536bf679ec94fe9f3ff3d"}, + {file = "charset_normalizer-3.3.2-py3-none-any.whl", hash = "sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc"}, +] [[package]] -category = "main" -description = "A client library for executing notebooks. Formally nbconvert's ExecutePreprocessor." -name = "nbclient" -optional = false -python-versions = ">=3.6" -version = "0.5.0" - -[package.dependencies] -async-generator = "*" -jupyter-client = ">=6.1.5" -nbformat = ">=5.0" -nest-asyncio = "*" -traitlets = ">=4.2" - -[package.extras] -dev = ["codecov", "coverage", "ipython", "ipykernel", "ipywidgets", "pytest (>=4.1)", "pytest-cov (>=2.6.1)", "check-manifest", "flake8", "mypy", "tox", "bumpversion", "xmltodict", "pip (>=18.1)", "wheel (>=0.31.0)", "setuptools (>=38.6.0)", "twine (>=1.11.0)", "black"] -sphinx = ["Sphinx (>=1.7)", "sphinx-book-theme", "mock", "moto", "myst-parser"] -test = ["codecov", "coverage", "ipython", "ipykernel", "ipywidgets", "pytest (>=4.1)", "pytest-cov (>=2.6.1)", "check-manifest", "flake8", "mypy", "tox", "bumpversion", "xmltodict", "pip (>=18.1)", "wheel (>=0.31.0)", "setuptools (>=38.6.0)", "twine (>=1.11.0)", "black"] - -[[package]] -category = "main" -description = "Converting Jupyter Notebooks" -name = "nbconvert" -optional = false -python-versions = ">=3.6" -version = "6.0.3" - -[package.dependencies] -bleach = "*" -defusedxml = "*" -entrypoints = ">=0.2.2" -jinja2 = ">=2.4" -jupyter-core = "*" -jupyterlab-pygments = "*" -mistune = ">=0.8.1,<2" -nbclient = ">=0.5.0,<0.6.0" -nbformat = ">=4.4" -pandocfilters = ">=1.4.1" -pygments = ">=2.4.1" -testpath = "*" -traitlets = ">=4.2" - -[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"] -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)"] - -[[package]] -category = "main" -description = "The Jupyter Notebook format" -name = "nbformat" -optional = false -python-versions = ">=3.5" -version = "5.0.7" - -[package.dependencies] -ipython-genutils = "*" -jsonschema = ">=2.4,<2.5.0 || >2.5.0" -jupyter-core = "*" -traitlets = ">=4.1" - -[package.extras] -test = ["pytest", "pytest-cov", "testpath"] - -[[package]] -category = "main" -description = "Patch asyncio to allow nested event loops" -name = "nest-asyncio" -optional = false -python-versions = ">=3.5" -version = "1.4.0" - -[[package]] -category = "main" -description = "A web-based notebook environment for interactive computing" -name = "notebook" -optional = false -python-versions = ">=3.5" -version = "6.1.4" - -[package.dependencies] -Send2Trash = "*" -argon2-cffi = "*" -ipykernel = "*" -ipython-genutils = "*" -jinja2 = "*" -jupyter-client = ">=5.3.4" -jupyter-core = ">=4.6.1" -nbconvert = "*" -nbformat = "*" -prometheus-client = "*" -pyzmq = ">=17" -terminado = ">=0.8.3" -tornado = ">=5.0" -traitlets = ">=4.2.1" - -[package.extras] -docs = ["sphinx", "nbsphinx", "sphinxcontrib-github-alt"] -test = ["nose", "coverage", "requests", "nose-warnings-filters", "nbval", "nose-exclude", "selenium", "pytest", "pytest-cov", "requests-unixsocket"] - -[[package]] -category = "main" -description = "NumPy is the fundamental package for array computing with Python." -name = "numpy" -optional = false -python-versions = ">=3.6" -version = "1.19.2" - -[[package]] -category = "main" -description = "Core utilities for Python packages" -name = "packaging" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "20.4" - -[package.dependencies] -pyparsing = ">=2.0.2" -six = "*" - -[[package]] -category = "main" -description = "Powerful data structures for data analysis, time series, and statistics" -name = "pandas" -optional = false -python-versions = ">=3.6.1" -version = "1.1.2" - -[package.dependencies] -numpy = ">=1.15.4" -python-dateutil = ">=2.7.3" -pytz = ">=2017.2" - -[package.extras] -test = ["pytest (>=4.0.2)", "pytest-xdist", "hypothesis (>=3.58)"] - -[[package]] -category = "main" -description = "Utilities for writing pandoc filters in python" -name = "pandocfilters" -optional = false -python-versions = "*" -version = "1.4.2" - -[[package]] -category = "main" -description = "A Python Parser" -name = "parso" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "0.7.1" - -[package.extras] -testing = ["docopt", "pytest (>=3.0.7)"] - -[[package]] -category = "main" -description = "Pexpect allows easy control of interactive console applications." -marker = "sys_platform != \"win32\"" -name = "pexpect" -optional = false -python-versions = "*" -version = "4.8.0" - -[package.dependencies] -ptyprocess = ">=0.5" - -[[package]] -category = "main" -description = "Tiny 'shelve'-like database with concurrency support" -name = "pickleshare" -optional = false -python-versions = "*" -version = "0.7.5" - -[[package]] -category = "main" -description = "Python Imaging Library (Fork)" -name = "pillow" -optional = false -python-versions = ">=3.5" -version = "7.2.0" - -[[package]] -category = "main" -description = "Python client for the Prometheus monitoring system." -name = "prometheus-client" -optional = false -python-versions = "*" -version = "0.8.0" - -[package.extras] -twisted = ["twisted"] - -[[package]] -category = "main" -description = "Library for building powerful interactive command lines in Python" -name = "prompt-toolkit" -optional = false -python-versions = ">=3.6.1" -version = "3.0.7" - -[package.dependencies] -wcwidth = "*" - -[[package]] -category = "main" -description = "Run a subprocess in a pseudo terminal" -marker = "sys_platform != \"win32\" or os_name != \"nt\"" -name = "ptyprocess" -optional = false -python-versions = "*" -version = "0.6.0" - -[[package]] -category = "main" -description = "C parser in Python" -name = "pycparser" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "2.20" - -[[package]] -category = "main" -description = "Pygments is a syntax highlighting package written in Python." -name = "pygments" -optional = false -python-versions = ">=3.5" -version = "2.7.0" - -[[package]] -category = "main" -description = "Python parsing module" -name = "pyparsing" -optional = false -python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" -version = "2.4.7" - -[[package]] -category = "main" -description = "Persistent/Functional/Immutable data structures" -name = "pyrsistent" -optional = false -python-versions = ">=3.5" -version = "0.17.3" - -[[package]] -category = "main" -description = "Extensions to the standard Python datetime module" -name = "python-dateutil" -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" -version = "2.8.1" - -[package.dependencies] -six = ">=1.5" - -[[package]] -category = "main" -description = "World timezone definitions, modern and historical" -name = "pytz" -optional = false -python-versions = "*" -version = "2020.1" - -[[package]] -category = "main" -description = "Python for Window Extensions" -marker = "sys_platform == \"win32\"" -name = "pywin32" -optional = false -python-versions = "*" -version = "228" - -[[package]] -category = "main" -description = "Python bindings for the winpty library" -marker = "os_name == \"nt\"" -name = "pywinpty" -optional = false -python-versions = "*" -version = "0.5.7" - -[[package]] -category = "main" -description = "Python bindings for 0MQ" -name = "pyzmq" -optional = false -python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*" -version = "19.0.2" - -[[package]] -category = "main" -description = "Python HTTP for Humans." -name = "requests" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -version = "2.24.0" - -[package.dependencies] -certifi = ">=2017.4.17" -chardet = ">=3.0.2,<4" -idna = ">=2.5,<3" -urllib3 = ">=1.21.1,<1.25.0 || >1.25.0,<1.25.1 || >1.25.1,<1.26" - -[package.extras] -security = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)"] -socks = ["PySocks (>=1.5.6,<1.5.7 || >1.5.7)", "win-inet-pton"] - -[[package]] -category = "main" -description = "A set of python modules for machine learning and data mining" -name = "scikit-learn" -optional = false -python-versions = ">=3.6" -version = "0.23.2" - -[package.dependencies] -joblib = ">=0.11" -numpy = ">=1.13.3" -scipy = ">=0.19.1" -threadpoolctl = ">=2.0.0" - -[package.extras] -alldeps = ["numpy (>=1.13.3)", "scipy (>=0.19.1)"] - -[[package]] -category = "main" -description = "SciPy: Scientific Library for Python" -name = "scipy" -optional = false -python-versions = ">=3.6" -version = "1.5.2" - -[package.dependencies] -numpy = ">=1.14.5" - -[[package]] -category = "main" -description = "Send file to trash natively under Mac OS X, Windows and Linux." -name = "send2trash" -optional = false -python-versions = "*" -version = "1.5.0" - -[[package]] -category = "main" -description = "Python 2 and 3 compatibility utilities" -name = "six" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" -version = "1.15.0" - -[[package]] -category = "main" -description = "Terminals served to xterm.js using Tornado websockets" -name = "terminado" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "0.8.3" - -[package.dependencies] -ptyprocess = "*" -pywinpty = ">=0.5" -tornado = ">=4" - -[[package]] -category = "main" -description = "Test utilities for code working with files and commands" -name = "testpath" -optional = false -python-versions = "*" -version = "0.4.4" - -[package.extras] -test = ["pathlib2"] - -[[package]] -category = "main" -description = "threadpoolctl" -name = "threadpoolctl" -optional = false -python-versions = ">=3.5" -version = "2.1.0" - -[[package]] -category = "main" -description = "Tornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed." -name = "tornado" -optional = false -python-versions = ">= 3.5" -version = "6.0.4" - -[[package]] -category = "main" -description = "Traitlets Python configuration system" -name = "traitlets" +name = "click" +version = "8.1.7" +description = "Composable command line interface toolkit" optional = false python-versions = ">=3.7" -version = "5.0.4" +files = [ + {file = "click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28"}, + {file = "click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"}, +] [package.dependencies] -ipython-genutils = "*" +colorama = {version = "*", markers = "platform_system == \"Windows\""} + +[[package]] +name = "colorama" +version = "0.4.6" +description = "Cross-platform colored terminal text." +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" +files = [ + {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, + {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, +] + +[[package]] +name = "comm" +version = "0.2.2" +description = "Jupyter Python Comm implementation, for usage in ipykernel, xeus-python etc." +optional = false +python-versions = ">=3.8" +files = [ + {file = "comm-0.2.2-py3-none-any.whl", hash = "sha256:e6fb86cb70ff661ee8c9c14e7d36d6de3b4066f1441be4063df9c5009f0a64d3"}, + {file = "comm-0.2.2.tar.gz", hash = "sha256:3fd7a84065306e07bea1773df6eb8282de51ba82f77c72f9c85716ab11fe980e"}, +] + +[package.dependencies] +traitlets = ">=4" [package.extras] test = ["pytest"] [[package]] -category = "main" -description = "HTTP library with thread-safe connection pooling, file post, and more." -name = "urllib3" +name = "contourpy" +version = "1.2.1" +description = "Python library for calculating contours of 2D quadrilateral grids" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4" -version = "1.25.10" +python-versions = ">=3.9" +files = [ + {file = "contourpy-1.2.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bd7c23df857d488f418439686d3b10ae2fbf9bc256cd045b37a8c16575ea1040"}, + {file = "contourpy-1.2.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5b9eb0ca724a241683c9685a484da9d35c872fd42756574a7cfbf58af26677fd"}, + {file = "contourpy-1.2.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4c75507d0a55378240f781599c30e7776674dbaf883a46d1c90f37e563453480"}, + {file = "contourpy-1.2.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:11959f0ce4a6f7b76ec578576a0b61a28bdc0696194b6347ba3f1c53827178b9"}, + {file = "contourpy-1.2.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:eb3315a8a236ee19b6df481fc5f997436e8ade24a9f03dfdc6bd490fea20c6da"}, + {file = "contourpy-1.2.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:39f3ecaf76cd98e802f094e0d4fbc6dc9c45a8d0c4d185f0f6c2234e14e5f75b"}, + {file = "contourpy-1.2.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:94b34f32646ca0414237168d68a9157cb3889f06b096612afdd296003fdd32fd"}, + {file = "contourpy-1.2.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:457499c79fa84593f22454bbd27670227874cd2ff5d6c84e60575c8b50a69619"}, + {file = "contourpy-1.2.1-cp310-cp310-win32.whl", hash = "sha256:ac58bdee53cbeba2ecad824fa8159493f0bf3b8ea4e93feb06c9a465d6c87da8"}, + {file = "contourpy-1.2.1-cp310-cp310-win_amd64.whl", hash = "sha256:9cffe0f850e89d7c0012a1fb8730f75edd4320a0a731ed0c183904fe6ecfc3a9"}, + {file = "contourpy-1.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6022cecf8f44e36af10bd9118ca71f371078b4c168b6e0fab43d4a889985dbb5"}, + {file = "contourpy-1.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ef5adb9a3b1d0c645ff694f9bca7702ec2c70f4d734f9922ea34de02294fdf72"}, + {file = "contourpy-1.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6150ffa5c767bc6332df27157d95442c379b7dce3a38dff89c0f39b63275696f"}, + {file = "contourpy-1.2.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4c863140fafc615c14a4bf4efd0f4425c02230eb8ef02784c9a156461e62c965"}, + {file = "contourpy-1.2.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:00e5388f71c1a0610e6fe56b5c44ab7ba14165cdd6d695429c5cd94021e390b2"}, + {file = "contourpy-1.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d4492d82b3bc7fbb7e3610747b159869468079fe149ec5c4d771fa1f614a14df"}, + {file = "contourpy-1.2.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:49e70d111fee47284d9dd867c9bb9a7058a3c617274900780c43e38d90fe1205"}, + {file = "contourpy-1.2.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:b59c0ffceff8d4d3996a45f2bb6f4c207f94684a96bf3d9728dbb77428dd8cb8"}, + {file = "contourpy-1.2.1-cp311-cp311-win32.whl", hash = "sha256:7b4182299f251060996af5249c286bae9361fa8c6a9cda5efc29fe8bfd6062ec"}, + {file = "contourpy-1.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:2855c8b0b55958265e8b5888d6a615ba02883b225f2227461aa9127c578a4922"}, + {file = "contourpy-1.2.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:62828cada4a2b850dbef89c81f5a33741898b305db244904de418cc957ff05dc"}, + {file = "contourpy-1.2.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:309be79c0a354afff9ff7da4aaed7c3257e77edf6c1b448a779329431ee79d7e"}, + {file = "contourpy-1.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2e785e0f2ef0d567099b9ff92cbfb958d71c2d5b9259981cd9bee81bd194c9a4"}, + {file = "contourpy-1.2.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1cac0a8f71a041aa587410424ad46dfa6a11f6149ceb219ce7dd48f6b02b87a7"}, + {file = "contourpy-1.2.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:af3f4485884750dddd9c25cb7e3915d83c2db92488b38ccb77dd594eac84c4a0"}, + {file = "contourpy-1.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9ce6889abac9a42afd07a562c2d6d4b2b7134f83f18571d859b25624a331c90b"}, + {file = "contourpy-1.2.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:a1eea9aecf761c661d096d39ed9026574de8adb2ae1c5bd7b33558af884fb2ce"}, + {file = "contourpy-1.2.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:187fa1d4c6acc06adb0fae5544c59898ad781409e61a926ac7e84b8f276dcef4"}, + {file = "contourpy-1.2.1-cp312-cp312-win32.whl", hash = "sha256:c2528d60e398c7c4c799d56f907664673a807635b857df18f7ae64d3e6ce2d9f"}, + {file = "contourpy-1.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:1a07fc092a4088ee952ddae19a2b2a85757b923217b7eed584fdf25f53a6e7ce"}, + {file = "contourpy-1.2.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:bb6834cbd983b19f06908b45bfc2dad6ac9479ae04abe923a275b5f48f1a186b"}, + {file = "contourpy-1.2.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1d59e739ab0e3520e62a26c60707cc3ab0365d2f8fecea74bfe4de72dc56388f"}, + {file = "contourpy-1.2.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bd3db01f59fdcbce5b22afad19e390260d6d0222f35a1023d9adc5690a889364"}, + {file = "contourpy-1.2.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a12a813949e5066148712a0626895c26b2578874e4cc63160bb007e6df3436fe"}, + {file = "contourpy-1.2.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fe0ccca550bb8e5abc22f530ec0466136379c01321fd94f30a22231e8a48d985"}, + {file = "contourpy-1.2.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e1d59258c3c67c865435d8fbeb35f8c59b8bef3d6f46c1f29f6123556af28445"}, + {file = "contourpy-1.2.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:f32c38afb74bd98ce26de7cc74a67b40afb7b05aae7b42924ea990d51e4dac02"}, + {file = "contourpy-1.2.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:d31a63bc6e6d87f77d71e1abbd7387ab817a66733734883d1fc0021ed9bfa083"}, + {file = "contourpy-1.2.1-cp39-cp39-win32.whl", hash = "sha256:ddcb8581510311e13421b1f544403c16e901c4e8f09083c881fab2be80ee31ba"}, + {file = "contourpy-1.2.1-cp39-cp39-win_amd64.whl", hash = "sha256:10a37ae557aabf2509c79715cd20b62e4c7c28b8cd62dd7d99e5ed3ce28c3fd9"}, + {file = "contourpy-1.2.1-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:a31f94983fecbac95e58388210427d68cd30fe8a36927980fab9c20062645609"}, + {file = "contourpy-1.2.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ef2b055471c0eb466033760a521efb9d8a32b99ab907fc8358481a1dd29e3bd3"}, + {file = "contourpy-1.2.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:b33d2bc4f69caedcd0a275329eb2198f560b325605810895627be5d4b876bf7f"}, + {file = "contourpy-1.2.1.tar.gz", hash = "sha256:4d8908b3bee1c889e547867ca4cdc54e5ab6be6d3e078556814a22457f49423c"}, +] + +[package.dependencies] +numpy = ">=1.20" [package.extras] -brotli = ["brotlipy (>=0.6.0)"] -secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "pyOpenSSL (>=0.14)", "ipaddress"] -socks = ["PySocks (>=1.5.6,<1.5.7 || >1.5.7,<2.0)"] +bokeh = ["bokeh", "selenium"] +docs = ["furo", "sphinx (>=7.2)", "sphinx-copybutton"] +mypy = ["contourpy[bokeh,docs]", "docutils-stubs", "mypy (==1.8.0)", "types-Pillow"] +test = ["Pillow", "contourpy[test-no-images]", "matplotlib"] +test-no-images = ["pytest", "pytest-cov", "pytest-xdist", "wurlitzer"] [[package]] -category = "main" -description = "Measures the displayed width of unicode strings in a terminal" -name = "wcwidth" +name = "cycler" +version = "0.12.1" +description = "Composable style cycles" +optional = false +python-versions = ">=3.8" +files = [ + {file = "cycler-0.12.1-py3-none-any.whl", hash = "sha256:85cef7cff222d8644161529808465972e51340599459b8ac3ccbac5a854e0d30"}, + {file = "cycler-0.12.1.tar.gz", hash = "sha256:88bb128f02ba341da8ef447245a9e138fae777f6a23943da4540077d3601eb1c"}, +] + +[package.extras] +docs = ["ipython", "matplotlib", "numpydoc", "sphinx"] +tests = ["pytest", "pytest-cov", "pytest-xdist"] + +[[package]] +name = "debugpy" +version = "1.8.2" +description = "An implementation of the Debug Adapter Protocol for Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "debugpy-1.8.2-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:7ee2e1afbf44b138c005e4380097d92532e1001580853a7cb40ed84e0ef1c3d2"}, + {file = "debugpy-1.8.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3f8c3f7c53130a070f0fc845a0f2cee8ed88d220d6b04595897b66605df1edd6"}, + {file = "debugpy-1.8.2-cp310-cp310-win32.whl", hash = "sha256:f179af1e1bd4c88b0b9f0fa153569b24f6b6f3de33f94703336363ae62f4bf47"}, + {file = "debugpy-1.8.2-cp310-cp310-win_amd64.whl", hash = "sha256:0600faef1d0b8d0e85c816b8bb0cb90ed94fc611f308d5fde28cb8b3d2ff0fe3"}, + {file = "debugpy-1.8.2-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:8a13417ccd5978a642e91fb79b871baded925d4fadd4dfafec1928196292aa0a"}, + {file = "debugpy-1.8.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:acdf39855f65c48ac9667b2801234fc64d46778021efac2de7e50907ab90c634"}, + {file = "debugpy-1.8.2-cp311-cp311-win32.whl", hash = "sha256:2cbd4d9a2fc5e7f583ff9bf11f3b7d78dfda8401e8bb6856ad1ed190be4281ad"}, + {file = "debugpy-1.8.2-cp311-cp311-win_amd64.whl", hash = "sha256:d3408fddd76414034c02880e891ea434e9a9cf3a69842098ef92f6e809d09afa"}, + {file = "debugpy-1.8.2-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:5d3ccd39e4021f2eb86b8d748a96c766058b39443c1f18b2dc52c10ac2757835"}, + {file = "debugpy-1.8.2-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:62658aefe289598680193ff655ff3940e2a601765259b123dc7f89c0239b8cd3"}, + {file = "debugpy-1.8.2-cp312-cp312-win32.whl", hash = "sha256:bd11fe35d6fd3431f1546d94121322c0ac572e1bfb1f6be0e9b8655fb4ea941e"}, + {file = "debugpy-1.8.2-cp312-cp312-win_amd64.whl", hash = "sha256:15bc2f4b0f5e99bf86c162c91a74c0631dbd9cef3c6a1d1329c946586255e859"}, + {file = "debugpy-1.8.2-cp38-cp38-macosx_11_0_x86_64.whl", hash = "sha256:5a019d4574afedc6ead1daa22736c530712465c0c4cd44f820d803d937531b2d"}, + {file = "debugpy-1.8.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:40f062d6877d2e45b112c0bbade9a17aac507445fd638922b1a5434df34aed02"}, + {file = "debugpy-1.8.2-cp38-cp38-win32.whl", hash = "sha256:c78ba1680f1015c0ca7115671fe347b28b446081dada3fedf54138f44e4ba031"}, + {file = "debugpy-1.8.2-cp38-cp38-win_amd64.whl", hash = "sha256:cf327316ae0c0e7dd81eb92d24ba8b5e88bb4d1b585b5c0d32929274a66a5210"}, + {file = "debugpy-1.8.2-cp39-cp39-macosx_11_0_x86_64.whl", hash = "sha256:1523bc551e28e15147815d1397afc150ac99dbd3a8e64641d53425dba57b0ff9"}, + {file = "debugpy-1.8.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e24ccb0cd6f8bfaec68d577cb49e9c680621c336f347479b3fce060ba7c09ec1"}, + {file = "debugpy-1.8.2-cp39-cp39-win32.whl", hash = "sha256:7f8d57a98c5a486c5c7824bc0b9f2f11189d08d73635c326abef268f83950326"}, + {file = "debugpy-1.8.2-cp39-cp39-win_amd64.whl", hash = "sha256:16c8dcab02617b75697a0a925a62943e26a0330da076e2a10437edd9f0bf3755"}, + {file = "debugpy-1.8.2-py2.py3-none-any.whl", hash = "sha256:16e16df3a98a35c63c3ab1e4d19be4cbc7fdda92d9ddc059294f18910928e0ca"}, + {file = "debugpy-1.8.2.zip", hash = "sha256:95378ed08ed2089221896b9b3a8d021e642c24edc8fef20e5d4342ca8be65c00"}, +] + +[[package]] +name = "decorator" +version = "5.1.1" +description = "Decorators for Humans" +optional = false +python-versions = ">=3.5" +files = [ + {file = "decorator-5.1.1-py3-none-any.whl", hash = "sha256:b8c3f85900b9dc423225913c5aace94729fe1fa9763b38939a95226f02d37186"}, + {file = "decorator-5.1.1.tar.gz", hash = "sha256:637996211036b6385ef91435e4fae22989472f9d571faba8927ba8253acbc330"}, +] + +[[package]] +name = "defusedxml" +version = "0.7.1" +description = "XML bomb protection for Python stdlib modules" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +files = [ + {file = "defusedxml-0.7.1-py2.py3-none-any.whl", hash = "sha256:a352e7e428770286cc899e2542b6cdaedb2b4953ff269a210103ec58f6198a61"}, + {file = "defusedxml-0.7.1.tar.gz", hash = "sha256:1bb3032db185915b62d7c6209c5a8792be6a32ab2fedacc84e01b52c51aa3e69"}, +] + +[[package]] +name = "exceptiongroup" +version = "1.2.2" +description = "Backport of PEP 654 (exception groups)" +optional = false +python-versions = ">=3.7" +files = [ + {file = "exceptiongroup-1.2.2-py3-none-any.whl", hash = "sha256:3111b9d131c238bec2f8f516e123e14ba243563fb135d3fe885990585aa7795b"}, + {file = "exceptiongroup-1.2.2.tar.gz", hash = "sha256:47c2edf7c6738fafb49fd34290706d1a1a2f4d1c6df275526b62cbb4aa5393cc"}, +] + +[package.extras] +test = ["pytest (>=6)"] + +[[package]] +name = "executing" +version = "2.0.1" +description = "Get the currently executing AST node of a frame, and other information" +optional = false +python-versions = ">=3.5" +files = [ + {file = "executing-2.0.1-py2.py3-none-any.whl", hash = "sha256:eac49ca94516ccc753f9fb5ce82603156e590b27525a8bc32cce8ae302eb61bc"}, + {file = "executing-2.0.1.tar.gz", hash = "sha256:35afe2ce3affba8ee97f2d69927fa823b08b472b7b994e36a52a964b93d16147"}, +] + +[package.extras] +tests = ["asttokens (>=2.1.0)", "coverage", "coverage-enable-subprocess", "ipython", "littleutils", "pytest", "rich"] + +[[package]] +name = "fastjsonschema" +version = "2.20.0" +description = "Fastest Python implementation of JSON schema" optional = false python-versions = "*" -version = "0.2.5" +files = [ + {file = "fastjsonschema-2.20.0-py3-none-any.whl", hash = "sha256:5875f0b0fa7a0043a91e93a9b8f793bcbbba9691e7fd83dca95c28ba26d21f0a"}, + {file = "fastjsonschema-2.20.0.tar.gz", hash = "sha256:3d48fc5300ee96f5d116f10fe6f28d938e6008f59a6a025c2649475b87f76a23"}, +] + +[package.extras] +devel = ["colorama", "json-spec", "jsonschema", "pylint", "pytest", "pytest-benchmark", "pytest-cache", "validictory"] [[package]] -category = "main" -description = "Character encoding aliases for legacy web content" -name = "webencodings" +name = "fonttools" +version = "4.53.1" +description = "Tools to manipulate font files" optional = false -python-versions = "*" -version = "0.5.1" +python-versions = ">=3.8" +files = [ + {file = "fonttools-4.53.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:0679a30b59d74b6242909945429dbddb08496935b82f91ea9bf6ad240ec23397"}, + {file = "fonttools-4.53.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e8bf06b94694251861ba7fdeea15c8ec0967f84c3d4143ae9daf42bbc7717fe3"}, + {file = "fonttools-4.53.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b96cd370a61f4d083c9c0053bf634279b094308d52fdc2dd9a22d8372fdd590d"}, + {file = "fonttools-4.53.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a1c7c5aa18dd3b17995898b4a9b5929d69ef6ae2af5b96d585ff4005033d82f0"}, + {file = "fonttools-4.53.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:e013aae589c1c12505da64a7d8d023e584987e51e62006e1bb30d72f26522c41"}, + {file = "fonttools-4.53.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:9efd176f874cb6402e607e4cc9b4a9cd584d82fc34a4b0c811970b32ba62501f"}, + {file = "fonttools-4.53.1-cp310-cp310-win32.whl", hash = "sha256:c8696544c964500aa9439efb6761947393b70b17ef4e82d73277413f291260a4"}, + {file = "fonttools-4.53.1-cp310-cp310-win_amd64.whl", hash = "sha256:8959a59de5af6d2bec27489e98ef25a397cfa1774b375d5787509c06659b3671"}, + {file = "fonttools-4.53.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:da33440b1413bad53a8674393c5d29ce64d8c1a15ef8a77c642ffd900d07bfe1"}, + {file = "fonttools-4.53.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5ff7e5e9bad94e3a70c5cd2fa27f20b9bb9385e10cddab567b85ce5d306ea923"}, + {file = "fonttools-4.53.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c6e7170d675d12eac12ad1a981d90f118c06cf680b42a2d74c6c931e54b50719"}, + {file = "fonttools-4.53.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bee32ea8765e859670c4447b0817514ca79054463b6b79784b08a8df3a4d78e3"}, + {file = "fonttools-4.53.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:6e08f572625a1ee682115223eabebc4c6a2035a6917eac6f60350aba297ccadb"}, + {file = "fonttools-4.53.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b21952c092ffd827504de7e66b62aba26fdb5f9d1e435c52477e6486e9d128b2"}, + {file = "fonttools-4.53.1-cp311-cp311-win32.whl", hash = "sha256:9dfdae43b7996af46ff9da520998a32b105c7f098aeea06b2226b30e74fbba88"}, + {file = "fonttools-4.53.1-cp311-cp311-win_amd64.whl", hash = "sha256:d4d0096cb1ac7a77b3b41cd78c9b6bc4a400550e21dc7a92f2b5ab53ed74eb02"}, + {file = "fonttools-4.53.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:d92d3c2a1b39631a6131c2fa25b5406855f97969b068e7e08413325bc0afba58"}, + {file = "fonttools-4.53.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:3b3c8ebafbee8d9002bd8f1195d09ed2bd9ff134ddec37ee8f6a6375e6a4f0e8"}, + {file = "fonttools-4.53.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:32f029c095ad66c425b0ee85553d0dc326d45d7059dbc227330fc29b43e8ba60"}, + {file = "fonttools-4.53.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10f5e6c3510b79ea27bb1ebfcc67048cde9ec67afa87c7dd7efa5c700491ac7f"}, + {file = "fonttools-4.53.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:f677ce218976496a587ab17140da141557beb91d2a5c1a14212c994093f2eae2"}, + {file = "fonttools-4.53.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:9e6ceba2a01b448e36754983d376064730690401da1dd104ddb543519470a15f"}, + {file = "fonttools-4.53.1-cp312-cp312-win32.whl", hash = "sha256:791b31ebbc05197d7aa096bbc7bd76d591f05905d2fd908bf103af4488e60670"}, + {file = "fonttools-4.53.1-cp312-cp312-win_amd64.whl", hash = "sha256:6ed170b5e17da0264b9f6fae86073be3db15fa1bd74061c8331022bca6d09bab"}, + {file = "fonttools-4.53.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:c818c058404eb2bba05e728d38049438afd649e3c409796723dfc17cd3f08749"}, + {file = "fonttools-4.53.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:651390c3b26b0c7d1f4407cad281ee7a5a85a31a110cbac5269de72a51551ba2"}, + {file = "fonttools-4.53.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e54f1bba2f655924c1138bbc7fa91abd61f45c68bd65ab5ed985942712864bbb"}, + {file = "fonttools-4.53.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c9cd19cf4fe0595ebdd1d4915882b9440c3a6d30b008f3cc7587c1da7b95be5f"}, + {file = "fonttools-4.53.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:2af40ae9cdcb204fc1d8f26b190aa16534fcd4f0df756268df674a270eab575d"}, + {file = "fonttools-4.53.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:35250099b0cfb32d799fb5d6c651220a642fe2e3c7d2560490e6f1d3f9ae9169"}, + {file = "fonttools-4.53.1-cp38-cp38-win32.whl", hash = "sha256:f08df60fbd8d289152079a65da4e66a447efc1d5d5a4d3f299cdd39e3b2e4a7d"}, + {file = "fonttools-4.53.1-cp38-cp38-win_amd64.whl", hash = "sha256:7b6b35e52ddc8fb0db562133894e6ef5b4e54e1283dff606fda3eed938c36fc8"}, + {file = "fonttools-4.53.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:75a157d8d26c06e64ace9df037ee93a4938a4606a38cb7ffaf6635e60e253b7a"}, + {file = "fonttools-4.53.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4824c198f714ab5559c5be10fd1adf876712aa7989882a4ec887bf1ef3e00e31"}, + {file = "fonttools-4.53.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:becc5d7cb89c7b7afa8321b6bb3dbee0eec2b57855c90b3e9bf5fb816671fa7c"}, + {file = "fonttools-4.53.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:84ec3fb43befb54be490147b4a922b5314e16372a643004f182babee9f9c3407"}, + {file = "fonttools-4.53.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:73379d3ffdeecb376640cd8ed03e9d2d0e568c9d1a4e9b16504a834ebadc2dfb"}, + {file = "fonttools-4.53.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:02569e9a810f9d11f4ae82c391ebc6fb5730d95a0657d24d754ed7763fb2d122"}, + {file = "fonttools-4.53.1-cp39-cp39-win32.whl", hash = "sha256:aae7bd54187e8bf7fd69f8ab87b2885253d3575163ad4d669a262fe97f0136cb"}, + {file = "fonttools-4.53.1-cp39-cp39-win_amd64.whl", hash = "sha256:e5b708073ea3d684235648786f5f6153a48dc8762cdfe5563c57e80787c29fbb"}, + {file = "fonttools-4.53.1-py3-none-any.whl", hash = "sha256:f1f8758a2ad110bd6432203a344269f445a2907dc24ef6bccfd0ac4e14e0d71d"}, + {file = "fonttools-4.53.1.tar.gz", hash = "sha256:e128778a8e9bc11159ce5447f76766cefbd876f44bd79aff030287254e4752c4"}, +] + +[package.extras] +all = ["brotli (>=1.0.1)", "brotlicffi (>=0.8.0)", "fs (>=2.2.0,<3)", "lxml (>=4.0)", "lz4 (>=1.7.4.2)", "matplotlib", "munkres", "pycairo", "scipy", "skia-pathops (>=0.5.0)", "sympy", "uharfbuzz (>=0.23.0)", "unicodedata2 (>=15.1.0)", "xattr", "zopfli (>=0.1.4)"] +graphite = ["lz4 (>=1.7.4.2)"] +interpolatable = ["munkres", "pycairo", "scipy"] +lxml = ["lxml (>=4.0)"] +pathops = ["skia-pathops (>=0.5.0)"] +plot = ["matplotlib"] +repacker = ["uharfbuzz (>=0.23.0)"] +symfont = ["sympy"] +type1 = ["xattr"] +ufo = ["fs (>=2.2.0,<3)"] +unicode = ["unicodedata2 (>=15.1.0)"] +woff = ["brotli (>=1.0.1)", "brotlicffi (>=0.8.0)", "zopfli (>=0.1.4)"] [[package]] -category = "main" -description = "Backport of pathlib-compatible object wrapper for zip files" -marker = "python_version < \"3.8\"" -name = "zipp" +name = "fqdn" +version = "1.5.1" +description = "Validates fully-qualified domain names against RFC 1123, so that they are acceptable to modern bowsers" +optional = false +python-versions = ">=2.7, !=3.0, !=3.1, !=3.2, !=3.3, !=3.4, <4" +files = [ + {file = "fqdn-1.5.1-py3-none-any.whl", hash = "sha256:3a179af3761e4df6eb2e026ff9e1a3033d3587bf980a0b1b2e1e5d08d7358014"}, + {file = "fqdn-1.5.1.tar.gz", hash = "sha256:105ed3677e767fb5ca086a0c1f4bb66ebc3c100be518f0e0d755d9eae164d89f"}, +] + +[[package]] +name = "h11" +version = "0.14.0" +description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" +optional = false +python-versions = ">=3.7" +files = [ + {file = "h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761"}, + {file = "h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d"}, +] + +[[package]] +name = "httpcore" +version = "1.0.5" +description = "A minimal low-level HTTP client." +optional = false +python-versions = ">=3.8" +files = [ + {file = "httpcore-1.0.5-py3-none-any.whl", hash = "sha256:421f18bac248b25d310f3cacd198d55b8e6125c107797b609ff9b7a6ba7991b5"}, + {file = "httpcore-1.0.5.tar.gz", hash = "sha256:34a38e2f9291467ee3b44e89dd52615370e152954ba21721378a87b2960f7a61"}, +] + +[package.dependencies] +certifi = "*" +h11 = ">=0.13,<0.15" + +[package.extras] +asyncio = ["anyio (>=4.0,<5.0)"] +http2 = ["h2 (>=3,<5)"] +socks = ["socksio (==1.*)"] +trio = ["trio (>=0.22.0,<0.26.0)"] + +[[package]] +name = "httpx" +version = "0.27.0" +description = "The next generation HTTP client." +optional = false +python-versions = ">=3.8" +files = [ + {file = "httpx-0.27.0-py3-none-any.whl", hash = "sha256:71d5465162c13681bff01ad59b2cc68dd838ea1f10e51574bac27103f00c91a5"}, + {file = "httpx-0.27.0.tar.gz", hash = "sha256:a0cb88a46f32dc874e04ee956e4c2764aba2aa228f650b06788ba6bda2962ab5"}, +] + +[package.dependencies] +anyio = "*" +certifi = "*" +httpcore = "==1.*" +idna = "*" +sniffio = "*" + +[package.extras] +brotli = ["brotli", "brotlicffi"] +cli = ["click (==8.*)", "pygments (==2.*)", "rich (>=10,<14)"] +http2 = ["h2 (>=3,<5)"] +socks = ["socksio (==1.*)"] + +[[package]] +name = "idna" +version = "3.7" +description = "Internationalized Domain Names in Applications (IDNA)" +optional = false +python-versions = ">=3.5" +files = [ + {file = "idna-3.7-py3-none-any.whl", hash = "sha256:82fee1fc78add43492d3a1898bfa6d8a904cc97d8427f683ed8e798d07761aa0"}, + {file = "idna-3.7.tar.gz", hash = "sha256:028ff3aadf0609c1fd278d8ea3089299412a7a8b9bd005dd08b9f8285bcb5cfc"}, +] + +[[package]] +name = "importlib-metadata" +version = "8.0.0" +description = "Read metadata from Python packages" +optional = false +python-versions = ">=3.8" +files = [ + {file = "importlib_metadata-8.0.0-py3-none-any.whl", hash = "sha256:15584cf2b1bf449d98ff8a6ff1abef57bf20f3ac6454f431736cd3e660921b2f"}, + {file = "importlib_metadata-8.0.0.tar.gz", hash = "sha256:188bd24e4c346d3f0a933f275c2fec67050326a856b9a359881d7c2a697e8812"}, +] + +[package.dependencies] +zipp = ">=0.5" + +[package.extras] +doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] +perf = ["ipython"] +test = ["flufl.flake8", "importlib-resources (>=1.3)", "jaraco.test (>=5.4)", "packaging", "pyfakefs", "pytest (>=6,!=8.1.*)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy", "pytest-perf (>=0.9.2)", "pytest-ruff (>=0.2.1)"] + +[[package]] +name = "importlib-resources" +version = "6.4.0" +description = "Read resources from Python packages" +optional = false +python-versions = ">=3.8" +files = [ + {file = "importlib_resources-6.4.0-py3-none-any.whl", hash = "sha256:50d10f043df931902d4194ea07ec57960f66a80449ff867bfe782b4c486ba78c"}, + {file = "importlib_resources-6.4.0.tar.gz", hash = "sha256:cdb2b453b8046ca4e3798eb1d84f3cce1446a0e8e7b5ef4efb600f19fc398145"}, +] + +[package.dependencies] +zipp = {version = ">=3.1.0", markers = "python_version < \"3.10\""} + +[package.extras] +docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-lint"] +testing = ["jaraco.test (>=5.4)", "pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy", "pytest-ruff (>=0.2.1)", "zipp (>=3.17)"] + +[[package]] +name = "invoke" +version = "2.2.0" +description = "Pythonic task execution" optional = false python-versions = ">=3.6" -version = "3.1.0" +files = [ + {file = "invoke-2.2.0-py3-none-any.whl", hash = "sha256:6ea924cc53d4f78e3d98bc436b08069a03077e6f85ad1ddaa8a116d7dad15820"}, + {file = "invoke-2.2.0.tar.gz", hash = "sha256:ee6cbb101af1a859c7fe84f2a264c059020b0cb7fe3535f9424300ab568f6bd5"}, +] + +[[package]] +name = "ipykernel" +version = "6.29.5" +description = "IPython Kernel for Jupyter" +optional = false +python-versions = ">=3.8" +files = [ + {file = "ipykernel-6.29.5-py3-none-any.whl", hash = "sha256:afdb66ba5aa354b09b91379bac28ae4afebbb30e8b39510c9690afb7a10421b5"}, + {file = "ipykernel-6.29.5.tar.gz", hash = "sha256:f093a22c4a40f8828f8e330a9c297cb93dcab13bd9678ded6de8e5cf81c56215"}, +] + +[package.dependencies] +appnope = {version = "*", markers = "platform_system == \"Darwin\""} +comm = ">=0.1.1" +debugpy = ">=1.6.5" +ipython = ">=7.23.1" +jupyter-client = ">=6.1.12" +jupyter-core = ">=4.12,<5.0.dev0 || >=5.1.dev0" +matplotlib-inline = ">=0.1" +nest-asyncio = "*" +packaging = "*" +psutil = "*" +pyzmq = ">=24" +tornado = ">=6.1" +traitlets = ">=5.4.0" [package.extras] -docs = ["sphinx", "jaraco.packaging (>=3.2)", "rst.linker (>=1.9)"] -testing = ["jaraco.itertools", "func-timeout"] +cov = ["coverage[toml]", "curio", "matplotlib", "pytest-cov", "trio"] +docs = ["myst-parser", "pydata-sphinx-theme", "sphinx", "sphinx-autodoc-typehints", "sphinxcontrib-github-alt", "sphinxcontrib-spelling", "trio"] +pyqt5 = ["pyqt5"] +pyside6 = ["pyside6"] +test = ["flaky", "ipyparallel", "pre-commit", "pytest (>=7.0)", "pytest-asyncio (>=0.23.5)", "pytest-cov", "pytest-timeout"] -[metadata] -content-hash = "7e24cd65e092682db86f62c26adeff3da77639fdc814d54f2319f259cc2e1aa2" -lock-version = "1.0" -python-versions = "^3.7" +[[package]] +name = "ipython" +version = "8.18.1" +description = "IPython: Productive Interactive Computing" +optional = false +python-versions = ">=3.9" +files = [ + {file = "ipython-8.18.1-py3-none-any.whl", hash = "sha256:e8267419d72d81955ec1177f8a29aaa90ac80ad647499201119e2f05e99aa397"}, + {file = "ipython-8.18.1.tar.gz", hash = "sha256:ca6f079bb33457c66e233e4580ebfc4128855b4cf6370dddd73842a9563e8a27"}, +] -[metadata.files] -appnope = [ - {file = "appnope-0.1.0-py2.py3-none-any.whl", hash = "sha256:5b26757dc6f79a3b7dc9fab95359328d5747fcb2409d331ea66d0272b90ab2a0"}, - {file = "appnope-0.1.0.tar.gz", hash = "sha256:8b995ffe925347a2138d7ac0fe77155e4311a0ea6d6da4f5128fe4b3cbe5ed71"}, +[package.dependencies] +colorama = {version = "*", markers = "sys_platform == \"win32\""} +decorator = "*" +exceptiongroup = {version = "*", markers = "python_version < \"3.11\""} +jedi = ">=0.16" +matplotlib-inline = "*" +pexpect = {version = ">4.3", markers = "sys_platform != \"win32\""} +prompt-toolkit = ">=3.0.41,<3.1.0" +pygments = ">=2.4.0" +stack-data = "*" +traitlets = ">=5" +typing-extensions = {version = "*", markers = "python_version < \"3.10\""} + +[package.extras] +all = ["black", "curio", "docrepr", "exceptiongroup", "ipykernel", "ipyparallel", "ipywidgets", "matplotlib", "matplotlib (!=3.2.0)", "nbconvert", "nbformat", "notebook", "numpy (>=1.22)", "pandas", "pickleshare", "pytest (<7)", "pytest (<7.1)", "pytest-asyncio (<0.22)", "qtconsole", "setuptools (>=18.5)", "sphinx (>=1.3)", "sphinx-rtd-theme", "stack-data", "testpath", "trio", "typing-extensions"] +black = ["black"] +doc = ["docrepr", "exceptiongroup", "ipykernel", "matplotlib", "pickleshare", "pytest (<7)", "pytest (<7.1)", "pytest-asyncio (<0.22)", "setuptools (>=18.5)", "sphinx (>=1.3)", "sphinx-rtd-theme", "stack-data", "testpath", "typing-extensions"] +kernel = ["ipykernel"] +nbconvert = ["nbconvert"] +nbformat = ["nbformat"] +notebook = ["ipywidgets", "notebook"] +parallel = ["ipyparallel"] +qtconsole = ["qtconsole"] +test = ["pickleshare", "pytest (<7.1)", "pytest-asyncio (<0.22)", "testpath"] +test-extra = ["curio", "matplotlib (!=3.2.0)", "nbformat", "numpy (>=1.22)", "pandas", "pickleshare", "pytest (<7.1)", "pytest-asyncio (<0.22)", "testpath", "trio"] + +[[package]] +name = "isoduration" +version = "20.11.0" +description = "Operations with ISO 8601 durations" +optional = false +python-versions = ">=3.7" +files = [ + {file = "isoduration-20.11.0-py3-none-any.whl", hash = "sha256:b2904c2a4228c3d44f409c8ae8e2370eb21a26f7ac2ec5446df141dde3452042"}, + {file = "isoduration-20.11.0.tar.gz", hash = "sha256:ac2f9015137935279eac671f94f89eb00584f940f5dc49462a0c4ee692ba1bd9"}, ] -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"}, + +[package.dependencies] +arrow = ">=0.15.0" + +[[package]] +name = "jedi" +version = "0.19.1" +description = "An autocompletion tool for Python that can be used for text editors." +optional = false +python-versions = ">=3.6" +files = [ + {file = "jedi-0.19.1-py2.py3-none-any.whl", hash = "sha256:e983c654fe5c02867aef4cdfce5a2fbb4a50adc0af145f70504238f18ef5e7e0"}, + {file = "jedi-0.19.1.tar.gz", hash = "sha256:cf0496f3651bc65d7174ac1b7d043eff454892c708a87d1b683e57b569927ffd"}, ] -async-generator = [ - {file = "async_generator-1.10-py3-none-any.whl", hash = "sha256:01c7bf666359b4967d2cda0000cc2e4af16a0ae098cbffcb8472fb9e8ad6585b"}, - {file = "async_generator-1.10.tar.gz", hash = "sha256:6ebb3d106c12920aaae42ccb6f787ef5eefdcdd166ea3d628fa8476abe712144"}, + +[package.dependencies] +parso = ">=0.8.3,<0.9.0" + +[package.extras] +docs = ["Jinja2 (==2.11.3)", "MarkupSafe (==1.1.1)", "Pygments (==2.8.1)", "alabaster (==0.7.12)", "babel (==2.9.1)", "chardet (==4.0.0)", "commonmark (==0.8.1)", "docutils (==0.17.1)", "future (==0.18.2)", "idna (==2.10)", "imagesize (==1.2.0)", "mock (==1.0.1)", "packaging (==20.9)", "pyparsing (==2.4.7)", "pytz (==2021.1)", "readthedocs-sphinx-ext (==2.1.4)", "recommonmark (==0.5.0)", "requests (==2.25.1)", "six (==1.15.0)", "snowballstemmer (==2.1.0)", "sphinx (==1.8.5)", "sphinx-rtd-theme (==0.4.3)", "sphinxcontrib-serializinghtml (==1.1.4)", "sphinxcontrib-websupport (==1.2.4)", "urllib3 (==1.26.4)"] +qa = ["flake8 (==5.0.4)", "mypy (==0.971)", "types-setuptools (==67.2.0.1)"] +testing = ["Django", "attrs", "colorama", "docopt", "pytest (<7.0.0)"] + +[[package]] +name = "jinja2" +version = "3.1.4" +description = "A very fast and expressive template engine." +optional = false +python-versions = ">=3.7" +files = [ + {file = "jinja2-3.1.4-py3-none-any.whl", hash = "sha256:bc5dd2abb727a5319567b7a813e6a2e7318c39f4f487cfe6c89c6f9c7d25197d"}, + {file = "jinja2-3.1.4.tar.gz", hash = "sha256:4a3aee7acbbe7303aede8e9648d13b8bf88a429282aa6122a993f0ac800cb369"}, ] -attrs = [ - {file = "attrs-20.2.0-py2.py3-none-any.whl", hash = "sha256:fce7fc47dfc976152e82d53ff92fa0407700c21acd20886a13777a0d20e655dc"}, - {file = "attrs-20.2.0.tar.gz", hash = "sha256:26b54ddbbb9ee1d34d5d3668dd37d6cf74990ab23c828c2888dccdceee395594"}, + +[package.dependencies] +MarkupSafe = ">=2.0" + +[package.extras] +i18n = ["Babel (>=2.7)"] + +[[package]] +name = "joblib" +version = "1.4.2" +description = "Lightweight pipelining with Python functions" +optional = false +python-versions = ">=3.8" +files = [ + {file = "joblib-1.4.2-py3-none-any.whl", hash = "sha256:06d478d5674cbc267e7496a410ee875abd68e4340feff4490bcb7afb88060ae6"}, + {file = "joblib-1.4.2.tar.gz", hash = "sha256:2382c5816b2636fbd20a09e0f4e9dad4736765fdfb7dca582943b9c1366b3f0e"}, ] -backcall = [ - {file = "backcall-0.2.0-py2.py3-none-any.whl", hash = "sha256:fbbce6a29f263178a1f7915c1940bde0ec2b2a967566fe1c65c1dfb7422bd255"}, - {file = "backcall-0.2.0.tar.gz", hash = "sha256:5cbdbf27be5e7cfadb448baf0aa95508f91f2bbc6c6437cd9cd06e2a4c215e1e"}, + +[[package]] +name = "json5" +version = "0.9.25" +description = "A Python implementation of the JSON5 data format." +optional = false +python-versions = ">=3.8" +files = [ + {file = "json5-0.9.25-py3-none-any.whl", hash = "sha256:34ed7d834b1341a86987ed52f3f76cd8ee184394906b6e22a1e0deb9ab294e8f"}, + {file = "json5-0.9.25.tar.gz", hash = "sha256:548e41b9be043f9426776f05df8635a00fe06104ea51ed24b67f908856e151ae"}, ] -bleach = [ - {file = "bleach-3.2.0-py2.py3-none-any.whl", hash = "sha256:769483204d247465c0b001ead257fb86bba6944bce6fe1b6759c812cceb54e3d"}, - {file = "bleach-3.2.0.tar.gz", hash = "sha256:f9e0205cc57b558c21bdfc11034f9d96b14c4052c25be60885d94f4277c792e0"}, + +[[package]] +name = "jsonpointer" +version = "3.0.0" +description = "Identify specific nodes in a JSON document (RFC 6901)" +optional = false +python-versions = ">=3.7" +files = [ + {file = "jsonpointer-3.0.0-py2.py3-none-any.whl", hash = "sha256:13e088adc14fca8b6aa8177c044e12701e6ad4b28ff10e65f2267a90109c9942"}, + {file = "jsonpointer-3.0.0.tar.gz", hash = "sha256:2b2d729f2091522d61c3b31f82e11870f60b68f43fbc705cb76bf4b832af59ef"}, ] -certifi = [ - {file = "certifi-2020.6.20-py2.py3-none-any.whl", hash = "sha256:8fc0819f1f30ba15bdb34cceffb9ef04d99f420f68eb75d901e9560b8749fc41"}, - {file = "certifi-2020.6.20.tar.gz", hash = "sha256:5930595817496dd21bb8dc35dad090f1c2cd0adfaf21204bf6732ca5d8ee34d3"}, + +[[package]] +name = "jsonschema" +version = "4.23.0" +description = "An implementation of JSON Schema validation for Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "jsonschema-4.23.0-py3-none-any.whl", hash = "sha256:fbadb6f8b144a8f8cf9f0b89ba94501d143e50411a1278633f56a7acf7fd5566"}, + {file = "jsonschema-4.23.0.tar.gz", hash = "sha256:d71497fef26351a33265337fa77ffeb82423f3ea21283cd9467bb03999266bc4"}, ] -cffi = [ - {file = "cffi-1.14.3-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:485d029815771b9fe4fa7e1c304352fe57df6939afe835dfd0182c7c13d5e92e"}, - {file = "cffi-1.14.3-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:3cb3e1b9ec43256c4e0f8d2837267a70b0e1ca8c4f456685508ae6106b1f504c"}, - {file = "cffi-1.14.3-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:f0620511387790860b249b9241c2f13c3a80e21a73e0b861a2df24e9d6f56730"}, - {file = "cffi-1.14.3-cp27-cp27m-win32.whl", hash = "sha256:005f2bfe11b6745d726dbb07ace4d53f057de66e336ff92d61b8c7e9c8f4777d"}, - {file = "cffi-1.14.3-cp27-cp27m-win_amd64.whl", hash = "sha256:2f9674623ca39c9ebe38afa3da402e9326c245f0f5ceff0623dccdac15023e05"}, - {file = "cffi-1.14.3-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:09e96138280241bd355cd585148dec04dbbedb4f46128f340d696eaafc82dd7b"}, - {file = "cffi-1.14.3-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:3363e77a6176afb8823b6e06db78c46dbc4c7813b00a41300a4873b6ba63b171"}, - {file = "cffi-1.14.3-cp35-cp35m-macosx_10_9_x86_64.whl", hash = "sha256:52bf29af05344c95136df71716bb60508bbd217691697b4307dcae681612db9f"}, - {file = "cffi-1.14.3-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:0ef488305fdce2580c8b2708f22d7785ae222d9825d3094ab073e22e93dfe51f"}, - {file = "cffi-1.14.3-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:0b1ad452cc824665ddc682400b62c9e4f5b64736a2ba99110712fdee5f2505c4"}, - {file = "cffi-1.14.3-cp35-cp35m-win32.whl", hash = "sha256:85ba797e1de5b48aa5a8427b6ba62cf69607c18c5d4eb747604b7302f1ec382d"}, - {file = "cffi-1.14.3-cp35-cp35m-win_amd64.whl", hash = "sha256:e66399cf0fc07de4dce4f588fc25bfe84a6d1285cc544e67987d22663393926d"}, - {file = "cffi-1.14.3-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:c687778dda01832555e0af205375d649fa47afeaeeb50a201711f9a9573323b8"}, - {file = "cffi-1.14.3-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:15f351bed09897fbda218e4db5a3d5c06328862f6198d4fb385f3e14e19decb3"}, - {file = "cffi-1.14.3-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:4d7c26bfc1ea9f92084a1d75e11999e97b62d63128bcc90c3624d07813c52808"}, - {file = "cffi-1.14.3-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:23e5d2040367322824605bc29ae8ee9175200b92cb5483ac7d466927a9b3d537"}, - {file = "cffi-1.14.3-cp36-cp36m-win32.whl", hash = "sha256:a624fae282e81ad2e4871bdb767e2c914d0539708c0f078b5b355258293c98b0"}, - {file = "cffi-1.14.3-cp36-cp36m-win_amd64.whl", hash = "sha256:de31b5164d44ef4943db155b3e8e17929707cac1e5bd2f363e67a56e3af4af6e"}, - {file = "cffi-1.14.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:03d3d238cc6c636a01cf55b9b2e1b6531a7f2f4103fabb5a744231582e68ecc7"}, - {file = "cffi-1.14.3-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:f92cdecb618e5fa4658aeb97d5eb3d2f47aa94ac6477c6daf0f306c5a3b9e6b1"}, - {file = "cffi-1.14.3-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:22399ff4870fb4c7ef19fff6eeb20a8bbf15571913c181c78cb361024d574579"}, - {file = "cffi-1.14.3-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:f4eae045e6ab2bb54ca279733fe4eb85f1effda392666308250714e01907f394"}, - {file = "cffi-1.14.3-cp37-cp37m-win32.whl", hash = "sha256:b0358e6fefc74a16f745afa366acc89f979040e0cbc4eec55ab26ad1f6a9bfbc"}, - {file = "cffi-1.14.3-cp37-cp37m-win_amd64.whl", hash = "sha256:6642f15ad963b5092d65aed022d033c77763515fdc07095208f15d3563003869"}, - {file = "cffi-1.14.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:c2a33558fdbee3df370399fe1712d72464ce39c66436270f3664c03f94971aff"}, - {file = "cffi-1.14.3-cp38-cp38-manylinux1_i686.whl", hash = "sha256:2791f68edc5749024b4722500e86303a10d342527e1e3bcac47f35fbd25b764e"}, - {file = "cffi-1.14.3-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:529c4ed2e10437c205f38f3691a68be66c39197d01062618c55f74294a4a4828"}, - {file = "cffi-1.14.3-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:8f0f1e499e4000c4c347a124fa6a27d37608ced4fe9f7d45070563b7c4c370c9"}, - {file = "cffi-1.14.3-cp38-cp38-win32.whl", hash = "sha256:3b8eaf915ddc0709779889c472e553f0d3e8b7bdf62dab764c8921b09bf94522"}, - {file = "cffi-1.14.3-cp38-cp38-win_amd64.whl", hash = "sha256:bbd2f4dfee1079f76943767fce837ade3087b578aeb9f69aec7857d5bf25db15"}, - {file = "cffi-1.14.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5d9a7dc7cf8b1101af2602fe238911bcc1ac36d239e0a577831f5dac993856e9"}, - {file = "cffi-1.14.3-cp39-cp39-manylinux1_i686.whl", hash = "sha256:cc75f58cdaf043fe6a7a6c04b3b5a0e694c6a9e24050967747251fb80d7bce0d"}, - {file = "cffi-1.14.3-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:bf39a9e19ce7298f1bd6a9758fa99707e9e5b1ebe5e90f2c3913a47bc548747c"}, - {file = "cffi-1.14.3-cp39-cp39-win32.whl", hash = "sha256:d80998ed59176e8cba74028762fbd9b9153b9afc71ea118e63bbf5d4d0f9552b"}, - {file = "cffi-1.14.3-cp39-cp39-win_amd64.whl", hash = "sha256:c150eaa3dadbb2b5339675b88d4573c1be3cb6f2c33a6c83387e10cc0bf05bd3"}, - {file = "cffi-1.14.3.tar.gz", hash = "sha256:f92f789e4f9241cd262ad7a555ca2c648a98178a953af117ef7fad46aa1d5591"}, + +[package.dependencies] +attrs = ">=22.2.0" +fqdn = {version = "*", optional = true, markers = "extra == \"format-nongpl\""} +idna = {version = "*", optional = true, markers = "extra == \"format-nongpl\""} +isoduration = {version = "*", optional = true, markers = "extra == \"format-nongpl\""} +jsonpointer = {version = ">1.13", optional = true, markers = "extra == \"format-nongpl\""} +jsonschema-specifications = ">=2023.03.6" +referencing = ">=0.28.4" +rfc3339-validator = {version = "*", optional = true, markers = "extra == \"format-nongpl\""} +rfc3986-validator = {version = ">0.1.0", optional = true, markers = "extra == \"format-nongpl\""} +rpds-py = ">=0.7.1" +uri-template = {version = "*", optional = true, markers = "extra == \"format-nongpl\""} +webcolors = {version = ">=24.6.0", optional = true, markers = "extra == \"format-nongpl\""} + +[package.extras] +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 (>=24.6.0)"] + +[[package]] +name = "jsonschema-specifications" +version = "2023.12.1" +description = "The JSON Schema meta-schemas and vocabularies, exposed as a Registry" +optional = false +python-versions = ">=3.8" +files = [ + {file = "jsonschema_specifications-2023.12.1-py3-none-any.whl", hash = "sha256:87e4fdf3a94858b8a2ba2778d9ba57d8a9cafca7c7489c46ba0d30a8bc6a9c3c"}, + {file = "jsonschema_specifications-2023.12.1.tar.gz", hash = "sha256:48a76787b3e70f5ed53f1160d2b81f586e4ca6d1548c5de7085d1682674764cc"}, ] -chardet = [ - {file = "chardet-3.0.4-py2.py3-none-any.whl", hash = "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"}, - {file = "chardet-3.0.4.tar.gz", hash = "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae"}, + +[package.dependencies] +referencing = ">=0.31.0" + +[[package]] +name = "jupyter-client" +version = "8.6.2" +description = "Jupyter protocol implementation and client libraries" +optional = false +python-versions = ">=3.8" +files = [ + {file = "jupyter_client-8.6.2-py3-none-any.whl", hash = "sha256:50cbc5c66fd1b8f65ecb66bc490ab73217993632809b6e505687de18e9dea39f"}, + {file = "jupyter_client-8.6.2.tar.gz", hash = "sha256:2bda14d55ee5ba58552a8c53ae43d215ad9868853489213f37da060ced54d8df"}, ] -colorama = [ - {file = "colorama-0.4.3-py2.py3-none-any.whl", hash = "sha256:7d73d2a99753107a36ac6b455ee49046802e59d9d076ef8e47b61499fa29afff"}, - {file = "colorama-0.4.3.tar.gz", hash = "sha256:e96da0d330793e2cb9485e9ddfd918d456036c7149416295932478192f4436a1"}, + +[package.dependencies] +importlib-metadata = {version = ">=4.8.3", markers = "python_version < \"3.10\""} +jupyter-core = ">=4.12,<5.0.dev0 || >=5.1.dev0" +python-dateutil = ">=2.8.2" +pyzmq = ">=23.0" +tornado = ">=6.2" +traitlets = ">=5.3" + +[package.extras] +docs = ["ipykernel", "myst-parser", "pydata-sphinx-theme", "sphinx (>=4)", "sphinx-autodoc-typehints", "sphinxcontrib-github-alt", "sphinxcontrib-spelling"] +test = ["coverage", "ipykernel (>=6.14)", "mypy", "paramiko", "pre-commit", "pytest (<8.2.0)", "pytest-cov", "pytest-jupyter[client] (>=0.4.1)", "pytest-timeout"] + +[[package]] +name = "jupyter-core" +version = "5.7.2" +description = "Jupyter core package. A base package on which Jupyter projects rely." +optional = false +python-versions = ">=3.8" +files = [ + {file = "jupyter_core-5.7.2-py3-none-any.whl", hash = "sha256:4f7315d2f6b4bcf2e3e7cb6e46772eba760ae459cd1f59d29eb57b0a01bd7409"}, + {file = "jupyter_core-5.7.2.tar.gz", hash = "sha256:aa5f8d32bbf6b431ac830496da7392035d6f61b4f54872f15c4bd2a9c3f536d9"}, ] -cycler = [ - {file = "cycler-0.10.0-py2.py3-none-any.whl", hash = "sha256:1d8a5ae1ff6c5cf9b93e8811e581232ad8920aeec647c37316ceac982b08cb2d"}, - {file = "cycler-0.10.0.tar.gz", hash = "sha256:cd7b2d1018258d7247a71425e9f26463dfb444d411c39569972f4ce586b0c9d8"}, + +[package.dependencies] +platformdirs = ">=2.5" +pywin32 = {version = ">=300", markers = "sys_platform == \"win32\" and platform_python_implementation != \"PyPy\""} +traitlets = ">=5.3" + +[package.extras] +docs = ["myst-parser", "pydata-sphinx-theme", "sphinx-autodoc-typehints", "sphinxcontrib-github-alt", "sphinxcontrib-spelling", "traitlets"] +test = ["ipykernel", "pre-commit", "pytest (<8)", "pytest-cov", "pytest-timeout"] + +[[package]] +name = "jupyter-events" +version = "0.10.0" +description = "Jupyter Event System library" +optional = false +python-versions = ">=3.8" +files = [ + {file = "jupyter_events-0.10.0-py3-none-any.whl", hash = "sha256:4b72130875e59d57716d327ea70d3ebc3af1944d3717e5a498b8a06c6c159960"}, + {file = "jupyter_events-0.10.0.tar.gz", hash = "sha256:670b8229d3cc882ec782144ed22e0d29e1c2d639263f92ca8383e66682845e22"}, ] -decorator = [ - {file = "decorator-4.4.2-py2.py3-none-any.whl", hash = "sha256:41fa54c2a0cc4ba648be4fd43cff00aedf5b9465c9bf18d64325bc225f08f760"}, - {file = "decorator-4.4.2.tar.gz", hash = "sha256:e3a62f0520172440ca0dcc823749319382e377f37f140a0b99ef45fecb84bfe7"}, + +[package.dependencies] +jsonschema = {version = ">=4.18.0", extras = ["format-nongpl"]} +python-json-logger = ">=2.0.4" +pyyaml = ">=5.3" +referencing = "*" +rfc3339-validator = "*" +rfc3986-validator = ">=0.1.1" +traitlets = ">=5.3" + +[package.extras] +cli = ["click", "rich"] +docs = ["jupyterlite-sphinx", "myst-parser", "pydata-sphinx-theme", "sphinxcontrib-spelling"] +test = ["click", "pre-commit", "pytest (>=7.0)", "pytest-asyncio (>=0.19.0)", "pytest-console-scripts", "rich"] + +[[package]] +name = "jupyter-lsp" +version = "2.2.5" +description = "Multi-Language Server WebSocket proxy for Jupyter Notebook/Lab server" +optional = false +python-versions = ">=3.8" +files = [ + {file = "jupyter-lsp-2.2.5.tar.gz", hash = "sha256:793147a05ad446f809fd53ef1cd19a9f5256fd0a2d6b7ce943a982cb4f545001"}, + {file = "jupyter_lsp-2.2.5-py3-none-any.whl", hash = "sha256:45fbddbd505f3fbfb0b6cb2f1bc5e15e83ab7c79cd6e89416b248cb3c00c11da"}, ] -defusedxml = [ - {file = "defusedxml-0.6.0-py2.py3-none-any.whl", hash = "sha256:6687150770438374ab581bb7a1b327a847dd9c5749e396102de3fad4e8a3ef93"}, - {file = "defusedxml-0.6.0.tar.gz", hash = "sha256:f684034d135af4c6cbb949b8a4d2ed61634515257a67299e5f940fbaa34377f5"}, + +[package.dependencies] +importlib-metadata = {version = ">=4.8.3", markers = "python_version < \"3.10\""} +jupyter-server = ">=1.1.2" + +[[package]] +name = "jupyter-server" +version = "2.14.2" +description = "The backend—i.e. core services, APIs, and REST endpoints—to Jupyter web applications." +optional = false +python-versions = ">=3.8" +files = [ + {file = "jupyter_server-2.14.2-py3-none-any.whl", hash = "sha256:47ff506127c2f7851a17bf4713434208fc490955d0e8632e95014a9a9afbeefd"}, + {file = "jupyter_server-2.14.2.tar.gz", hash = "sha256:66095021aa9638ced276c248b1d81862e4c50f292d575920bbe960de1c56b12b"}, ] -entrypoints = [ - {file = "entrypoints-0.3-py2.py3-none-any.whl", hash = "sha256:589f874b313739ad35be6e0cd7efde2a4e9b6fea91edcc34e58ecbb8dbe56d19"}, - {file = "entrypoints-0.3.tar.gz", hash = "sha256:c70dd71abe5a8c85e55e12c19bd91ccfeec11a6e99044204511f9ed547d48451"}, + +[package.dependencies] +anyio = ">=3.1.0" +argon2-cffi = ">=21.1" +jinja2 = ">=3.0.3" +jupyter-client = ">=7.4.4" +jupyter-core = ">=4.12,<5.0.dev0 || >=5.1.dev0" +jupyter-events = ">=0.9.0" +jupyter-server-terminals = ">=0.4.4" +nbconvert = ">=6.4.4" +nbformat = ">=5.3.0" +overrides = ">=5.0" +packaging = ">=22.0" +prometheus-client = ">=0.9" +pywinpty = {version = ">=2.0.1", markers = "os_name == \"nt\""} +pyzmq = ">=24" +send2trash = ">=1.8.2" +terminado = ">=0.8.3" +tornado = ">=6.2.0" +traitlets = ">=5.6.0" +websocket-client = ">=1.7" + +[package.extras] +docs = ["ipykernel", "jinja2", "jupyter-client", "myst-parser", "nbformat", "prometheus-client", "pydata-sphinx-theme", "send2trash", "sphinx-autodoc-typehints", "sphinxcontrib-github-alt", "sphinxcontrib-openapi (>=0.8.0)", "sphinxcontrib-spelling", "sphinxemoji", "tornado", "typing-extensions"] +test = ["flaky", "ipykernel", "pre-commit", "pytest (>=7.0,<9)", "pytest-console-scripts", "pytest-jupyter[server] (>=0.7)", "pytest-timeout", "requests"] + +[[package]] +name = "jupyter-server-terminals" +version = "0.5.3" +description = "A Jupyter Server Extension Providing Terminals." +optional = false +python-versions = ">=3.8" +files = [ + {file = "jupyter_server_terminals-0.5.3-py3-none-any.whl", hash = "sha256:41ee0d7dc0ebf2809c668e0fc726dfaf258fcd3e769568996ca731b6194ae9aa"}, + {file = "jupyter_server_terminals-0.5.3.tar.gz", hash = "sha256:5ae0295167220e9ace0edcfdb212afd2b01ee8d179fe6f23c899590e9b8a5269"}, ] -idna = [ - {file = "idna-2.10-py2.py3-none-any.whl", hash = "sha256:b97d804b1e9b523befed77c48dacec60e6dcb0b5391d57af6a65a312a90648c0"}, - {file = "idna-2.10.tar.gz", hash = "sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6"}, + +[package.dependencies] +pywinpty = {version = ">=2.0.3", markers = "os_name == \"nt\""} +terminado = ">=0.8.3" + +[package.extras] +docs = ["jinja2", "jupyter-server", "mistune (<4.0)", "myst-parser", "nbformat", "packaging", "pydata-sphinx-theme", "sphinxcontrib-github-alt", "sphinxcontrib-openapi", "sphinxcontrib-spelling", "sphinxemoji", "tornado"] +test = ["jupyter-server (>=2.0.0)", "pytest (>=7.0)", "pytest-jupyter[server] (>=0.5.3)", "pytest-timeout"] + +[[package]] +name = "jupyterlab" +version = "4.2.3" +description = "JupyterLab computational environment" +optional = false +python-versions = ">=3.8" +files = [ + {file = "jupyterlab-4.2.3-py3-none-any.whl", hash = "sha256:0b59d11808e84bb84105c73364edfa867dd475492429ab34ea388a52f2e2e596"}, + {file = "jupyterlab-4.2.3.tar.gz", hash = "sha256:df6e46969ea51d66815167f23d92f105423b7f1f06fa604d4f44aeb018c82c7b"}, ] -importlib-metadata = [ - {file = "importlib_metadata-1.7.0-py2.py3-none-any.whl", hash = "sha256:dc15b2969b4ce36305c51eebe62d418ac7791e9a157911d58bfb1f9ccd8e2070"}, - {file = "importlib_metadata-1.7.0.tar.gz", hash = "sha256:90bb658cdbbf6d1735b6341ce708fc7024a3e14e99ffdc5783edea9f9b077f83"}, + +[package.dependencies] +async-lru = ">=1.0.0" +httpx = ">=0.25.0" +importlib-metadata = {version = ">=4.8.3", markers = "python_version < \"3.10\""} +ipykernel = ">=6.5.0" +jinja2 = ">=3.0.3" +jupyter-core = "*" +jupyter-lsp = ">=2.0.0" +jupyter-server = ">=2.4.0,<3" +jupyterlab-server = ">=2.27.1,<3" +notebook-shim = ">=0.2" +packaging = "*" +setuptools = ">=40.1.0" +tomli = {version = ">=1.2.2", markers = "python_version < \"3.11\""} +tornado = ">=6.2.0" +traitlets = "*" + +[package.extras] +dev = ["build", "bump2version", "coverage", "hatch", "pre-commit", "pytest-cov", "ruff (==0.3.5)"] +docs = ["jsx-lexer", "myst-parser", "pydata-sphinx-theme (>=0.13.0)", "pytest", "pytest-check-links", "pytest-jupyter", "sphinx (>=1.8,<7.3.0)", "sphinx-copybutton"] +docs-screenshots = ["altair (==5.3.0)", "ipython (==8.16.1)", "ipywidgets (==8.1.2)", "jupyterlab-geojson (==3.4.0)", "jupyterlab-language-pack-zh-cn (==4.1.post2)", "matplotlib (==3.8.3)", "nbconvert (>=7.0.0)", "pandas (==2.2.1)", "scipy (==1.12.0)", "vega-datasets (==0.9.0)"] +test = ["coverage", "pytest (>=7.0)", "pytest-check-links (>=0.7)", "pytest-console-scripts", "pytest-cov", "pytest-jupyter (>=0.5.3)", "pytest-timeout", "pytest-tornasync", "requests", "requests-cache", "virtualenv"] +upgrade-extension = ["copier (>=8,<10)", "jinja2-time (<0.3)", "pydantic (<2.0)", "pyyaml-include (<2.0)", "tomli-w (<2.0)"] + +[[package]] +name = "jupyterlab-pygments" +version = "0.3.0" +description = "Pygments theme using JupyterLab CSS variables" +optional = false +python-versions = ">=3.8" +files = [ + {file = "jupyterlab_pygments-0.3.0-py3-none-any.whl", hash = "sha256:841a89020971da1d8693f1a99997aefc5dc424bb1b251fd6322462a1b8842780"}, + {file = "jupyterlab_pygments-0.3.0.tar.gz", hash = "sha256:721aca4d9029252b11cfa9d185e5b5af4d54772bb8072f9b7036f4170054d35d"}, ] -ipykernel = [ - {file = "ipykernel-5.3.4-py3-none-any.whl", hash = "sha256:d6fbba26dba3cebd411382bc484f7bc2caa98427ae0ddb4ab37fe8bfeb5c7dd3"}, - {file = "ipykernel-5.3.4.tar.gz", hash = "sha256:9b2652af1607986a1b231c62302d070bc0534f564c393a5d9d130db9abbbe89d"}, + +[[package]] +name = "jupyterlab-server" +version = "2.27.2" +description = "A set of server components for JupyterLab and JupyterLab like applications." +optional = false +python-versions = ">=3.8" +files = [ + {file = "jupyterlab_server-2.27.2-py3-none-any.whl", hash = "sha256:54aa2d64fd86383b5438d9f0c032f043c4d8c0264b8af9f60bd061157466ea43"}, + {file = "jupyterlab_server-2.27.2.tar.gz", hash = "sha256:15cbb349dc45e954e09bacf81b9f9bcb10815ff660fb2034ecd7417db3a7ea27"}, ] -ipython = [ - {file = "ipython-7.18.1-py3-none-any.whl", hash = "sha256:2e22c1f74477b5106a6fb301c342ab8c64bb75d702e350f05a649e8cb40a0fb8"}, - {file = "ipython-7.18.1.tar.gz", hash = "sha256:a331e78086001931de9424940699691ad49dfb457cea31f5471eae7b78222d5e"}, + +[package.dependencies] +babel = ">=2.10" +importlib-metadata = {version = ">=4.8.3", markers = "python_version < \"3.10\""} +jinja2 = ">=3.0.3" +json5 = ">=0.9.0" +jsonschema = ">=4.18.0" +jupyter-server = ">=1.21,<3" +packaging = ">=21.3" +requests = ">=2.31" + +[package.extras] +docs = ["autodoc-traits", "jinja2 (<3.2.0)", "mistune (<4)", "myst-parser", "pydata-sphinx-theme", "sphinx", "sphinx-copybutton", "sphinxcontrib-openapi (>0.8)"] +openapi = ["openapi-core (>=0.18.0,<0.19.0)", "ruamel-yaml"] +test = ["hatch", "ipykernel", "openapi-core (>=0.18.0,<0.19.0)", "openapi-spec-validator (>=0.6.0,<0.8.0)", "pytest (>=7.0,<8)", "pytest-console-scripts", "pytest-cov", "pytest-jupyter[server] (>=0.6.2)", "pytest-timeout", "requests-mock", "ruamel-yaml", "sphinxcontrib-spelling", "strict-rfc3339", "werkzeug"] + +[[package]] +name = "kiwisolver" +version = "1.4.5" +description = "A fast implementation of the Cassowary constraint solver" +optional = false +python-versions = ">=3.7" +files = [ + {file = "kiwisolver-1.4.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:05703cf211d585109fcd72207a31bb170a0f22144d68298dc5e61b3c946518af"}, + {file = "kiwisolver-1.4.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:146d14bebb7f1dc4d5fbf74f8a6cb15ac42baadee8912eb84ac0b3b2a3dc6ac3"}, + {file = "kiwisolver-1.4.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6ef7afcd2d281494c0a9101d5c571970708ad911d028137cd558f02b851c08b4"}, + {file = "kiwisolver-1.4.5-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:9eaa8b117dc8337728e834b9c6e2611f10c79e38f65157c4c38e9400286f5cb1"}, + {file = "kiwisolver-1.4.5-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:ec20916e7b4cbfb1f12380e46486ec4bcbaa91a9c448b97023fde0d5bbf9e4ff"}, + {file = "kiwisolver-1.4.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:39b42c68602539407884cf70d6a480a469b93b81b7701378ba5e2328660c847a"}, + {file = "kiwisolver-1.4.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:aa12042de0171fad672b6c59df69106d20d5596e4f87b5e8f76df757a7c399aa"}, + {file = "kiwisolver-1.4.5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2a40773c71d7ccdd3798f6489aaac9eee213d566850a9533f8d26332d626b82c"}, + {file = "kiwisolver-1.4.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:19df6e621f6d8b4b9c4d45f40a66839294ff2bb235e64d2178f7522d9170ac5b"}, + {file = "kiwisolver-1.4.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:83d78376d0d4fd884e2c114d0621624b73d2aba4e2788182d286309ebdeed770"}, + {file = "kiwisolver-1.4.5-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:e391b1f0a8a5a10ab3b9bb6afcfd74f2175f24f8975fb87ecae700d1503cdee0"}, + {file = "kiwisolver-1.4.5-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:852542f9481f4a62dbb5dd99e8ab7aedfeb8fb6342349a181d4036877410f525"}, + {file = "kiwisolver-1.4.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:59edc41b24031bc25108e210c0def6f6c2191210492a972d585a06ff246bb79b"}, + {file = "kiwisolver-1.4.5-cp310-cp310-win32.whl", hash = "sha256:a6aa6315319a052b4ee378aa171959c898a6183f15c1e541821c5c59beaa0238"}, + {file = "kiwisolver-1.4.5-cp310-cp310-win_amd64.whl", hash = "sha256:d0ef46024e6a3d79c01ff13801cb19d0cad7fd859b15037aec74315540acc276"}, + {file = "kiwisolver-1.4.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:11863aa14a51fd6ec28688d76f1735f8f69ab1fabf388851a595d0721af042f5"}, + {file = "kiwisolver-1.4.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:8ab3919a9997ab7ef2fbbed0cc99bb28d3c13e6d4b1ad36e97e482558a91be90"}, + {file = "kiwisolver-1.4.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:fcc700eadbbccbf6bc1bcb9dbe0786b4b1cb91ca0dcda336eef5c2beed37b797"}, + {file = "kiwisolver-1.4.5-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dfdd7c0b105af050eb3d64997809dc21da247cf44e63dc73ff0fd20b96be55a9"}, + {file = "kiwisolver-1.4.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76c6a5964640638cdeaa0c359382e5703e9293030fe730018ca06bc2010c4437"}, + {file = "kiwisolver-1.4.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bbea0db94288e29afcc4c28afbf3a7ccaf2d7e027489c449cf7e8f83c6346eb9"}, + {file = "kiwisolver-1.4.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ceec1a6bc6cab1d6ff5d06592a91a692f90ec7505d6463a88a52cc0eb58545da"}, + {file = "kiwisolver-1.4.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:040c1aebeda72197ef477a906782b5ab0d387642e93bda547336b8957c61022e"}, + {file = "kiwisolver-1.4.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:f91de7223d4c7b793867797bacd1ee53bfe7359bd70d27b7b58a04efbb9436c8"}, + {file = "kiwisolver-1.4.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:faae4860798c31530dd184046a900e652c95513796ef51a12bc086710c2eec4d"}, + {file = "kiwisolver-1.4.5-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:b0157420efcb803e71d1b28e2c287518b8808b7cf1ab8af36718fd0a2c453eb0"}, + {file = "kiwisolver-1.4.5-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:06f54715b7737c2fecdbf140d1afb11a33d59508a47bf11bb38ecf21dc9ab79f"}, + {file = "kiwisolver-1.4.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:fdb7adb641a0d13bdcd4ef48e062363d8a9ad4a182ac7647ec88f695e719ae9f"}, + {file = "kiwisolver-1.4.5-cp311-cp311-win32.whl", hash = "sha256:bb86433b1cfe686da83ce32a9d3a8dd308e85c76b60896d58f082136f10bffac"}, + {file = "kiwisolver-1.4.5-cp311-cp311-win_amd64.whl", hash = "sha256:6c08e1312a9cf1074d17b17728d3dfce2a5125b2d791527f33ffbe805200a355"}, + {file = "kiwisolver-1.4.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:32d5cf40c4f7c7b3ca500f8985eb3fb3a7dfc023215e876f207956b5ea26632a"}, + {file = "kiwisolver-1.4.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:f846c260f483d1fd217fe5ed7c173fb109efa6b1fc8381c8b7552c5781756192"}, + {file = "kiwisolver-1.4.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5ff5cf3571589b6d13bfbfd6bcd7a3f659e42f96b5fd1c4830c4cf21d4f5ef45"}, + {file = "kiwisolver-1.4.5-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7269d9e5f1084a653d575c7ec012ff57f0c042258bf5db0954bf551c158466e7"}, + {file = "kiwisolver-1.4.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da802a19d6e15dffe4b0c24b38b3af68e6c1a68e6e1d8f30148c83864f3881db"}, + {file = "kiwisolver-1.4.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3aba7311af82e335dd1e36ffff68aaca609ca6290c2cb6d821a39aa075d8e3ff"}, + {file = "kiwisolver-1.4.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:763773d53f07244148ccac5b084da5adb90bfaee39c197554f01b286cf869228"}, + {file = "kiwisolver-1.4.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2270953c0d8cdab5d422bee7d2007f043473f9d2999631c86a223c9db56cbd16"}, + {file = "kiwisolver-1.4.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d099e745a512f7e3bbe7249ca835f4d357c586d78d79ae8f1dcd4d8adeb9bda9"}, + {file = "kiwisolver-1.4.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:74db36e14a7d1ce0986fa104f7d5637aea5c82ca6326ed0ec5694280942d1162"}, + {file = "kiwisolver-1.4.5-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:7e5bab140c309cb3a6ce373a9e71eb7e4873c70c2dda01df6820474f9889d6d4"}, + {file = "kiwisolver-1.4.5-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:0f114aa76dc1b8f636d077979c0ac22e7cd8f3493abbab152f20eb8d3cda71f3"}, + {file = "kiwisolver-1.4.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:88a2df29d4724b9237fc0c6eaf2a1adae0cdc0b3e9f4d8e7dc54b16812d2d81a"}, + {file = "kiwisolver-1.4.5-cp312-cp312-win32.whl", hash = "sha256:72d40b33e834371fd330fb1472ca19d9b8327acb79a5821d4008391db8e29f20"}, + {file = "kiwisolver-1.4.5-cp312-cp312-win_amd64.whl", hash = "sha256:2c5674c4e74d939b9d91dda0fae10597ac7521768fec9e399c70a1f27e2ea2d9"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:3a2b053a0ab7a3960c98725cfb0bf5b48ba82f64ec95fe06f1d06c99b552e130"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3cd32d6c13807e5c66a7cbb79f90b553642f296ae4518a60d8d76243b0ad2898"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:59ec7b7c7e1a61061850d53aaf8e93db63dce0c936db1fda2658b70e4a1be709"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:da4cfb373035def307905d05041c1d06d8936452fe89d464743ae7fb8371078b"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2400873bccc260b6ae184b2b8a4fec0e4082d30648eadb7c3d9a13405d861e89"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:1b04139c4236a0f3aff534479b58f6f849a8b351e1314826c2d230849ed48985"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:4e66e81a5779b65ac21764c295087de82235597a2293d18d943f8e9e32746265"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:7931d8f1f67c4be9ba1dd9c451fb0eeca1a25b89e4d3f89e828fe12a519b782a"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:b3f7e75f3015df442238cca659f8baa5f42ce2a8582727981cbfa15fee0ee205"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:bbf1d63eef84b2e8c89011b7f2235b1e0bf7dacc11cac9431fc6468e99ac77fb"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:4c380469bd3f970ef677bf2bcba2b6b0b4d5c75e7a020fb863ef75084efad66f"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-win32.whl", hash = "sha256:9408acf3270c4b6baad483865191e3e582b638b1654a007c62e3efe96f09a9a3"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-win_amd64.whl", hash = "sha256:5b94529f9b2591b7af5f3e0e730a4e0a41ea174af35a4fd067775f9bdfeee01a"}, + {file = "kiwisolver-1.4.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:11c7de8f692fc99816e8ac50d1d1aef4f75126eefc33ac79aac02c099fd3db71"}, + {file = "kiwisolver-1.4.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:53abb58632235cd154176ced1ae8f0d29a6657aa1aa9decf50b899b755bc2b93"}, + {file = "kiwisolver-1.4.5-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:88b9f257ca61b838b6f8094a62418421f87ac2a1069f7e896c36a7d86b5d4c29"}, + {file = "kiwisolver-1.4.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3195782b26fc03aa9c6913d5bad5aeb864bdc372924c093b0f1cebad603dd712"}, + {file = "kiwisolver-1.4.5-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fc579bf0f502e54926519451b920e875f433aceb4624a3646b3252b5caa9e0b6"}, + {file = "kiwisolver-1.4.5-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5a580c91d686376f0f7c295357595c5a026e6cbc3d77b7c36e290201e7c11ecb"}, + {file = "kiwisolver-1.4.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:cfe6ab8da05c01ba6fbea630377b5da2cd9bcbc6338510116b01c1bc939a2c18"}, + {file = "kiwisolver-1.4.5-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:d2e5a98f0ec99beb3c10e13b387f8db39106d53993f498b295f0c914328b1333"}, + {file = "kiwisolver-1.4.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:a51a263952b1429e429ff236d2f5a21c5125437861baeed77f5e1cc2d2c7c6da"}, + {file = "kiwisolver-1.4.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:3edd2fa14e68c9be82c5b16689e8d63d89fe927e56debd6e1dbce7a26a17f81b"}, + {file = "kiwisolver-1.4.5-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:74d1b44c6cfc897df648cc9fdaa09bc3e7679926e6f96df05775d4fb3946571c"}, + {file = "kiwisolver-1.4.5-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:76d9289ed3f7501012e05abb8358bbb129149dbd173f1f57a1bf1c22d19ab7cc"}, + {file = "kiwisolver-1.4.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:92dea1ffe3714fa8eb6a314d2b3c773208d865a0e0d35e713ec54eea08a66250"}, + {file = "kiwisolver-1.4.5-cp38-cp38-win32.whl", hash = "sha256:5c90ae8c8d32e472be041e76f9d2f2dbff4d0b0be8bd4041770eddb18cf49a4e"}, + {file = "kiwisolver-1.4.5-cp38-cp38-win_amd64.whl", hash = "sha256:c7940c1dc63eb37a67721b10d703247552416f719c4188c54e04334321351ced"}, + {file = "kiwisolver-1.4.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:9407b6a5f0d675e8a827ad8742e1d6b49d9c1a1da5d952a67d50ef5f4170b18d"}, + {file = "kiwisolver-1.4.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:15568384086b6df3c65353820a4473575dbad192e35010f622c6ce3eebd57af9"}, + {file = "kiwisolver-1.4.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0dc9db8e79f0036e8173c466d21ef18e1befc02de8bf8aa8dc0813a6dc8a7046"}, + {file = "kiwisolver-1.4.5-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:cdc8a402aaee9a798b50d8b827d7ecf75edc5fb35ea0f91f213ff927c15f4ff0"}, + {file = "kiwisolver-1.4.5-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:6c3bd3cde54cafb87d74d8db50b909705c62b17c2099b8f2e25b461882e544ff"}, + {file = "kiwisolver-1.4.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:955e8513d07a283056b1396e9a57ceddbd272d9252c14f154d450d227606eb54"}, + {file = "kiwisolver-1.4.5-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:346f5343b9e3f00b8db8ba359350eb124b98c99efd0b408728ac6ebf38173958"}, + {file = "kiwisolver-1.4.5-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b9098e0049e88c6a24ff64545cdfc50807818ba6c1b739cae221bbbcbc58aad3"}, + {file = "kiwisolver-1.4.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:00bd361b903dc4bbf4eb165f24d1acbee754fce22ded24c3d56eec268658a5cf"}, + {file = "kiwisolver-1.4.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:7b8b454bac16428b22560d0a1cf0a09875339cab69df61d7805bf48919415901"}, + {file = "kiwisolver-1.4.5-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:f1d072c2eb0ad60d4c183f3fb44ac6f73fb7a8f16a2694a91f988275cbf352f9"}, + {file = "kiwisolver-1.4.5-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:31a82d498054cac9f6d0b53d02bb85811185bcb477d4b60144f915f3b3126342"}, + {file = "kiwisolver-1.4.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:6512cb89e334e4700febbffaaa52761b65b4f5a3cf33f960213d5656cea36a77"}, + {file = "kiwisolver-1.4.5-cp39-cp39-win32.whl", hash = "sha256:9db8ea4c388fdb0f780fe91346fd438657ea602d58348753d9fb265ce1bca67f"}, + {file = "kiwisolver-1.4.5-cp39-cp39-win_amd64.whl", hash = "sha256:59415f46a37f7f2efeec758353dd2eae1b07640d8ca0f0c42548ec4125492635"}, + {file = "kiwisolver-1.4.5-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:5c7b3b3a728dc6faf3fc372ef24f21d1e3cee2ac3e9596691d746e5a536de920"}, + {file = "kiwisolver-1.4.5-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:620ced262a86244e2be10a676b646f29c34537d0d9cc8eb26c08f53d98013390"}, + {file = "kiwisolver-1.4.5-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:378a214a1e3bbf5ac4a8708304318b4f890da88c9e6a07699c4ae7174c09a68d"}, + {file = "kiwisolver-1.4.5-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aaf7be1207676ac608a50cd08f102f6742dbfc70e8d60c4db1c6897f62f71523"}, + {file = "kiwisolver-1.4.5-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:ba55dce0a9b8ff59495ddd050a0225d58bd0983d09f87cfe2b6aec4f2c1234e4"}, + {file = "kiwisolver-1.4.5-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:fd32ea360bcbb92d28933fc05ed09bffcb1704ba3fc7942e81db0fd4f81a7892"}, + {file = "kiwisolver-1.4.5-pp38-pypy38_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:5e7139af55d1688f8b960ee9ad5adafc4ac17c1c473fe07133ac092310d76544"}, + {file = "kiwisolver-1.4.5-pp38-pypy38_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:dced8146011d2bc2e883f9bd68618b8247387f4bbec46d7392b3c3b032640126"}, + {file = "kiwisolver-1.4.5-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c9bf3325c47b11b2e51bca0824ea217c7cd84491d8ac4eefd1e409705ef092bd"}, + {file = "kiwisolver-1.4.5-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:5794cf59533bc3f1b1c821f7206a3617999db9fbefc345360aafe2e067514929"}, + {file = "kiwisolver-1.4.5-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:e368f200bbc2e4f905b8e71eb38b3c04333bddaa6a2464a6355487b02bb7fb09"}, + {file = "kiwisolver-1.4.5-pp39-pypy39_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e5d706eba36b4c4d5bc6c6377bb6568098765e990cfc21ee16d13963fab7b3e7"}, + {file = "kiwisolver-1.4.5-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:85267bd1aa8880a9c88a8cb71e18d3d64d2751a790e6ca6c27b8ccc724bcd5ad"}, + {file = "kiwisolver-1.4.5-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:210ef2c3a1f03272649aff1ef992df2e724748918c4bc2d5a90352849eb40bea"}, + {file = "kiwisolver-1.4.5-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:11d011a7574eb3b82bcc9c1a1d35c1d7075677fdd15de527d91b46bd35e935ee"}, + {file = "kiwisolver-1.4.5.tar.gz", hash = "sha256:e57e563a57fb22a142da34f38acc2fc1a5c864bc29ca1517a88abc963e60d6ec"}, ] -ipython-genutils = [ - {file = "ipython_genutils-0.2.0-py2.py3-none-any.whl", hash = "sha256:72dd37233799e619666c9f639a9da83c34013a73e8bbc79a7a6348d93c61fab8"}, - {file = "ipython_genutils-0.2.0.tar.gz", hash = "sha256:eb2e116e75ecef9d4d228fdc66af54269afa26ab4463042e33785b887c628ba8"}, + +[[package]] +name = "markupsafe" +version = "2.1.5" +description = "Safely add untrusted strings to HTML/XML markup." +optional = false +python-versions = ">=3.7" +files = [ + {file = "MarkupSafe-2.1.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a17a92de5231666cfbe003f0e4b9b3a7ae3afb1ec2845aadc2bacc93ff85febc"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:72b6be590cc35924b02c78ef34b467da4ba07e4e0f0454a2c5907f473fc50ce5"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e61659ba32cf2cf1481e575d0462554625196a1f2fc06a1c777d3f48e8865d46"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2174c595a0d73a3080ca3257b40096db99799265e1c27cc5a610743acd86d62f"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ae2ad8ae6ebee9d2d94b17fb62763125f3f374c25618198f40cbb8b525411900"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:075202fa5b72c86ad32dc7d0b56024ebdbcf2048c0ba09f1cde31bfdd57bcfff"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:598e3276b64aff0e7b3451b72e94fa3c238d452e7ddcd893c3ab324717456bad"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fce659a462a1be54d2ffcacea5e3ba2d74daa74f30f5f143fe0c58636e355fdd"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-win32.whl", hash = "sha256:d9fad5155d72433c921b782e58892377c44bd6252b5af2f67f16b194987338a4"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-win_amd64.whl", hash = "sha256:bf50cd79a75d181c9181df03572cdce0fbb75cc353bc350712073108cba98de5"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:629ddd2ca402ae6dbedfceeba9c46d5f7b2a61d9749597d4307f943ef198fc1f"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5b7b716f97b52c5a14bffdf688f971b2d5ef4029127f1ad7a513973cfd818df2"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6ec585f69cec0aa07d945b20805be741395e28ac1627333b1c5b0105962ffced"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b91c037585eba9095565a3556f611e3cbfaa42ca1e865f7b8015fe5c7336d5a5"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7502934a33b54030eaf1194c21c692a534196063db72176b0c4028e140f8f32c"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0e397ac966fdf721b2c528cf028494e86172b4feba51d65f81ffd65c63798f3f"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c061bb86a71b42465156a3ee7bd58c8c2ceacdbeb95d05a99893e08b8467359a"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:3a57fdd7ce31c7ff06cdfbf31dafa96cc533c21e443d57f5b1ecc6cdc668ec7f"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-win32.whl", hash = "sha256:397081c1a0bfb5124355710fe79478cdbeb39626492b15d399526ae53422b906"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-win_amd64.whl", hash = "sha256:2b7c57a4dfc4f16f7142221afe5ba4e093e09e728ca65c51f5620c9aaeb9a617"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:8dec4936e9c3100156f8a2dc89c4b88d5c435175ff03413b443469c7c8c5f4d1"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:3c6b973f22eb18a789b1460b4b91bf04ae3f0c4234a0a6aa6b0a92f6f7b951d4"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ac07bad82163452a6884fe8fa0963fb98c2346ba78d779ec06bd7a6262132aee"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f5dfb42c4604dddc8e4305050aa6deb084540643ed5804d7455b5df8fe16f5e5"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ea3d8a3d18833cf4304cd2fc9cbb1efe188ca9b5efef2bdac7adc20594a0e46b"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d050b3361367a06d752db6ead6e7edeb0009be66bc3bae0ee9d97fb326badc2a"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:bec0a414d016ac1a18862a519e54b2fd0fc8bbfd6890376898a6c0891dd82e9f"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:58c98fee265677f63a4385256a6d7683ab1832f3ddd1e66fe948d5880c21a169"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-win32.whl", hash = "sha256:8590b4ae07a35970728874632fed7bd57b26b0102df2d2b233b6d9d82f6c62ad"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-win_amd64.whl", hash = "sha256:823b65d8706e32ad2df51ed89496147a42a2a6e01c13cfb6ffb8b1e92bc910bb"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c8b29db45f8fe46ad280a7294f5c3ec36dbac9491f2d1c17345be8e69cc5928f"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ec6a563cff360b50eed26f13adc43e61bc0c04d94b8be985e6fb24b81f6dcfdf"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a549b9c31bec33820e885335b451286e2969a2d9e24879f83fe904a5ce59d70a"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4f11aa001c540f62c6166c7726f71f7573b52c68c31f014c25cc7901deea0b52"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:7b2e5a267c855eea6b4283940daa6e88a285f5f2a67f2220203786dfa59b37e9"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:2d2d793e36e230fd32babe143b04cec8a8b3eb8a3122d2aceb4a371e6b09b8df"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:ce409136744f6521e39fd8e2a24c53fa18ad67aa5bc7c2cf83645cce5b5c4e50"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-win32.whl", hash = "sha256:4096e9de5c6fdf43fb4f04c26fb114f61ef0bf2e5604b6ee3019d51b69e8c371"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-win_amd64.whl", hash = "sha256:4275d846e41ecefa46e2015117a9f491e57a71ddd59bbead77e904dc02b1bed2"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:656f7526c69fac7f600bd1f400991cc282b417d17539a1b228617081106feb4a"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:97cafb1f3cbcd3fd2b6fbfb99ae11cdb14deea0736fc2b0952ee177f2b813a46"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f3fbcb7ef1f16e48246f704ab79d79da8a46891e2da03f8783a5b6fa41a9532"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fa9db3f79de01457b03d4f01b34cf91bc0048eb2c3846ff26f66687c2f6d16ab"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffee1f21e5ef0d712f9033568f8344d5da8cc2869dbd08d87c84656e6a2d2f68"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:5dedb4db619ba5a2787a94d877bc8ffc0566f92a01c0ef214865e54ecc9ee5e0"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:30b600cf0a7ac9234b2638fbc0fb6158ba5bdcdf46aeb631ead21248b9affbc4"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8dd717634f5a044f860435c1d8c16a270ddf0ef8588d4887037c5028b859b0c3"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-win32.whl", hash = "sha256:daa4ee5a243f0f20d528d939d06670a298dd39b1ad5f8a72a4275124a7819eff"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-win_amd64.whl", hash = "sha256:619bc166c4f2de5caa5a633b8b7326fbe98e0ccbfacabd87268a2b15ff73a029"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:7a68b554d356a91cce1236aa7682dc01df0edba8d043fd1ce607c49dd3c1edcf"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:db0b55e0f3cc0be60c1f19efdde9a637c32740486004f20d1cff53c3c0ece4d2"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3e53af139f8579a6d5f7b76549125f0d94d7e630761a2111bc431fd820e163b8"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:17b950fccb810b3293638215058e432159d2b71005c74371d784862b7e4683f3"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4c31f53cdae6ecfa91a77820e8b151dba54ab528ba65dfd235c80b086d68a465"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:bff1b4290a66b490a2f4719358c0cdcd9bafb6b8f061e45c7a2460866bf50c2e"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:bc1667f8b83f48511b94671e0e441401371dfd0f0a795c7daa4a3cd1dde55bea"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5049256f536511ee3f7e1b3f87d1d1209d327e818e6ae1365e8653d7e3abb6a6"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-win32.whl", hash = "sha256:00e046b6dd71aa03a41079792f8473dc494d564611a8f89bbbd7cb93295ebdcf"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-win_amd64.whl", hash = "sha256:fa173ec60341d6bb97a89f5ea19c85c5643c1e7dedebc22f5181eb73573142c5"}, + {file = "MarkupSafe-2.1.5.tar.gz", hash = "sha256:d283d37a890ba4c1ae73ffadf8046435c76e7bc2247bbb63c00bd1a709c6544b"}, ] -jedi = [ - {file = "jedi-0.17.2-py2.py3-none-any.whl", hash = "sha256:98cc583fa0f2f8304968199b01b6b4b94f469a1f4a74c1560506ca2a211378b5"}, - {file = "jedi-0.17.2.tar.gz", hash = "sha256:86ed7d9b750603e4ba582ea8edc678657fb4007894a12bcf6f4bb97892f31d20"}, + +[[package]] +name = "matplotlib" +version = "3.9.1" +description = "Python plotting package" +optional = false +python-versions = ">=3.9" +files = [ + {file = "matplotlib-3.9.1-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:7ccd6270066feb9a9d8e0705aa027f1ff39f354c72a87efe8fa07632f30fc6bb"}, + {file = "matplotlib-3.9.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:591d3a88903a30a6d23b040c1e44d1afdd0d778758d07110eb7596f811f31842"}, + {file = "matplotlib-3.9.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dd2a59ff4b83d33bca3b5ec58203cc65985367812cb8c257f3e101632be86d92"}, + {file = "matplotlib-3.9.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0fc001516ffcf1a221beb51198b194d9230199d6842c540108e4ce109ac05cc0"}, + {file = "matplotlib-3.9.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:83c6a792f1465d174c86d06f3ae85a8fe36e6f5964633ae8106312ec0921fdf5"}, + {file = "matplotlib-3.9.1-cp310-cp310-win_amd64.whl", hash = "sha256:421851f4f57350bcf0811edd754a708d2275533e84f52f6760b740766c6747a7"}, + {file = "matplotlib-3.9.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:b3fce58971b465e01b5c538f9d44915640c20ec5ff31346e963c9e1cd66fa812"}, + {file = "matplotlib-3.9.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a973c53ad0668c53e0ed76b27d2eeeae8799836fd0d0caaa4ecc66bf4e6676c0"}, + {file = "matplotlib-3.9.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:82cd5acf8f3ef43f7532c2f230249720f5dc5dd40ecafaf1c60ac8200d46d7eb"}, + {file = "matplotlib-3.9.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ab38a4f3772523179b2f772103d8030215b318fef6360cb40558f585bf3d017f"}, + {file = "matplotlib-3.9.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:2315837485ca6188a4b632c5199900e28d33b481eb083663f6a44cfc8987ded3"}, + {file = "matplotlib-3.9.1-cp311-cp311-win_amd64.whl", hash = "sha256:a0c977c5c382f6696caf0bd277ef4f936da7e2aa202ff66cad5f0ac1428ee15b"}, + {file = "matplotlib-3.9.1-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:565d572efea2b94f264dd86ef27919515aa6d629252a169b42ce5f570db7f37b"}, + {file = "matplotlib-3.9.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6d397fd8ccc64af2ec0af1f0efc3bacd745ebfb9d507f3f552e8adb689ed730a"}, + {file = "matplotlib-3.9.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:26040c8f5121cd1ad712abffcd4b5222a8aec3a0fe40bc8542c94331deb8780d"}, + {file = "matplotlib-3.9.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d12cb1837cffaac087ad6b44399d5e22b78c729de3cdae4629e252067b705e2b"}, + {file = "matplotlib-3.9.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:0e835c6988edc3d2d08794f73c323cc62483e13df0194719ecb0723b564e0b5c"}, + {file = "matplotlib-3.9.1-cp312-cp312-win_amd64.whl", hash = "sha256:44a21d922f78ce40435cb35b43dd7d573cf2a30138d5c4b709d19f00e3907fd7"}, + {file = "matplotlib-3.9.1-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:0c584210c755ae921283d21d01f03a49ef46d1afa184134dd0f95b0202ee6f03"}, + {file = "matplotlib-3.9.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:11fed08f34fa682c2b792942f8902e7aefeed400da71f9e5816bea40a7ce28fe"}, + {file = "matplotlib-3.9.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0000354e32efcfd86bda75729716b92f5c2edd5b947200be9881f0a671565c33"}, + {file = "matplotlib-3.9.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4db17fea0ae3aceb8e9ac69c7e3051bae0b3d083bfec932240f9bf5d0197a049"}, + {file = "matplotlib-3.9.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:208cbce658b72bf6a8e675058fbbf59f67814057ae78165d8a2f87c45b48d0ff"}, + {file = "matplotlib-3.9.1-cp39-cp39-win_amd64.whl", hash = "sha256:dc23f48ab630474264276be156d0d7710ac6c5a09648ccdf49fef9200d8cbe80"}, + {file = "matplotlib-3.9.1-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:3fda72d4d472e2ccd1be0e9ccb6bf0d2eaf635e7f8f51d737ed7e465ac020cb3"}, + {file = "matplotlib-3.9.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:84b3ba8429935a444f1fdc80ed930babbe06725bcf09fbeb5c8757a2cd74af04"}, + {file = "matplotlib-3.9.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b918770bf3e07845408716e5bbda17eadfc3fcbd9307dc67f37d6cf834bb3d98"}, + {file = "matplotlib-3.9.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:f1f2e5d29e9435c97ad4c36fb6668e89aee13d48c75893e25cef064675038ac9"}, + {file = "matplotlib-3.9.1.tar.gz", hash = "sha256:de06b19b8db95dd33d0dc17c926c7c9ebed9f572074b6fac4f65068a6814d010"}, ] -jinja2 = [ - {file = "Jinja2-2.11.2-py2.py3-none-any.whl", hash = "sha256:f0a4641d3cf955324a89c04f3d94663aa4d638abe8f733ecd3582848e1c37035"}, - {file = "Jinja2-2.11.2.tar.gz", hash = "sha256:89aab215427ef59c34ad58735269eb58b1a5808103067f7bb9d5836c651b3bb0"}, + +[package.dependencies] +contourpy = ">=1.0.1" +cycler = ">=0.10" +fonttools = ">=4.22.0" +importlib-resources = {version = ">=3.2.0", markers = "python_version < \"3.10\""} +kiwisolver = ">=1.3.1" +numpy = ">=1.23" +packaging = ">=20.0" +pillow = ">=8" +pyparsing = ">=2.3.1" +python-dateutil = ">=2.7" + +[package.extras] +dev = ["meson-python (>=0.13.1)", "numpy (>=1.25)", "pybind11 (>=2.6)", "setuptools (>=64)", "setuptools_scm (>=7)"] + +[[package]] +name = "matplotlib-inline" +version = "0.1.7" +description = "Inline Matplotlib backend for Jupyter" +optional = false +python-versions = ">=3.8" +files = [ + {file = "matplotlib_inline-0.1.7-py3-none-any.whl", hash = "sha256:df192d39a4ff8f21b1895d72e6a13f5fcc5099f00fa84384e0ea28c2cc0653ca"}, + {file = "matplotlib_inline-0.1.7.tar.gz", hash = "sha256:8423b23ec666be3d16e16b60bdd8ac4e86e840ebd1dd11a30b9f117f2fa0ab90"}, ] -joblib = [ - {file = "joblib-0.16.0-py3-none-any.whl", hash = "sha256:d348c5d4ae31496b2aa060d6d9b787864dd204f9480baaa52d18850cb43e9f49"}, - {file = "joblib-0.16.0.tar.gz", hash = "sha256:8f52bf24c64b608bf0b2563e0e47d6fcf516abc8cfafe10cfd98ad66d94f92d6"}, + +[package.dependencies] +traitlets = "*" + +[[package]] +name = "mistune" +version = "3.0.2" +description = "A sane and fast Markdown parser with useful plugins and renderers" +optional = false +python-versions = ">=3.7" +files = [ + {file = "mistune-3.0.2-py3-none-any.whl", hash = "sha256:71481854c30fdbc938963d3605b72501f5c10a9320ecd412c121c163a1c7d205"}, + {file = "mistune-3.0.2.tar.gz", hash = "sha256:fc7f93ded930c92394ef2cb6f04a8aabab4117a91449e72dcc8dfa646a508be8"}, ] -json5 = [ - {file = "json5-0.9.5-py2.py3-none-any.whl", hash = "sha256:af1a1b9a2850c7f62c23fde18be4749b3599fd302f494eebf957e2ada6b9e42c"}, - {file = "json5-0.9.5.tar.gz", hash = "sha256:703cfee540790576b56a92e1c6aaa6c4b0d98971dc358ead83812aa4d06bdb96"}, + +[[package]] +name = "mypy-extensions" +version = "1.0.0" +description = "Type system extensions for programs checked with the mypy type checker." +optional = false +python-versions = ">=3.5" +files = [ + {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"}, + {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, ] -jsonschema = [ - {file = "jsonschema-3.2.0-py2.py3-none-any.whl", hash = "sha256:4e5b3cf8216f577bee9ce139cbe72eca3ea4f292ec60928ff24758ce626cd163"}, - {file = "jsonschema-3.2.0.tar.gz", hash = "sha256:c8a85b28d377cc7737e46e2d9f2b4f44ee3c0e1deac6bf46ddefc7187d30797a"}, + +[[package]] +name = "nbclient" +version = "0.10.0" +description = "A client library for executing notebooks. Formerly nbconvert's ExecutePreprocessor." +optional = false +python-versions = ">=3.8.0" +files = [ + {file = "nbclient-0.10.0-py3-none-any.whl", hash = "sha256:f13e3529332a1f1f81d82a53210322476a168bb7090a0289c795fe9cc11c9d3f"}, + {file = "nbclient-0.10.0.tar.gz", hash = "sha256:4b3f1b7dba531e498449c4db4f53da339c91d449dc11e9af3a43b4eb5c5abb09"}, ] -jupyter-client = [ - {file = "jupyter_client-6.1.7-py3-none-any.whl", hash = "sha256:c958d24d6eacb975c1acebb68ac9077da61b5f5c040f22f6849928ad7393b950"}, - {file = "jupyter_client-6.1.7.tar.gz", hash = "sha256:49e390b36fe4b4226724704ea28d9fb903f1a3601b6882ce3105221cd09377a1"}, + +[package.dependencies] +jupyter-client = ">=6.1.12" +jupyter-core = ">=4.12,<5.0.dev0 || >=5.1.dev0" +nbformat = ">=5.1" +traitlets = ">=5.4" + +[package.extras] +dev = ["pre-commit"] +docs = ["autodoc-traits", "mock", "moto", "myst-parser", "nbclient[test]", "sphinx (>=1.7)", "sphinx-book-theme", "sphinxcontrib-spelling"] +test = ["flaky", "ipykernel (>=6.19.3)", "ipython", "ipywidgets", "nbconvert (>=7.0.0)", "pytest (>=7.0,<8)", "pytest-asyncio", "pytest-cov (>=4.0)", "testpath", "xmltodict"] + +[[package]] +name = "nbconvert" +version = "7.16.4" +description = "Converting Jupyter Notebooks (.ipynb files) to other formats. Output formats include asciidoc, html, latex, markdown, pdf, py, rst, script. nbconvert can be used both as a Python library (`import nbconvert`) or as a command line tool (invoked as `jupyter nbconvert ...`)." +optional = false +python-versions = ">=3.8" +files = [ + {file = "nbconvert-7.16.4-py3-none-any.whl", hash = "sha256:05873c620fe520b6322bf8a5ad562692343fe3452abda5765c7a34b7d1aa3eb3"}, + {file = "nbconvert-7.16.4.tar.gz", hash = "sha256:86ca91ba266b0a448dc96fa6c5b9d98affabde2867b363258703536807f9f7f4"}, ] -jupyter-core = [ - {file = "jupyter_core-4.6.3-py2.py3-none-any.whl", hash = "sha256:a4ee613c060fe5697d913416fc9d553599c05e4492d58fac1192c9a6844abb21"}, - {file = "jupyter_core-4.6.3.tar.gz", hash = "sha256:394fd5dd787e7c8861741880bdf8a00ce39f95de5d18e579c74b882522219e7e"}, + +[package.dependencies] +beautifulsoup4 = "*" +bleach = "!=5.0.0" +defusedxml = "*" +importlib-metadata = {version = ">=3.6", markers = "python_version < \"3.10\""} +jinja2 = ">=3.0" +jupyter-core = ">=4.7" +jupyterlab-pygments = "*" +markupsafe = ">=2.0" +mistune = ">=2.0.3,<4" +nbclient = ">=0.5.0" +nbformat = ">=5.7" +packaging = "*" +pandocfilters = ">=1.4.1" +pygments = ">=2.4.1" +tinycss2 = "*" +traitlets = ">=5.1" + +[package.extras] +all = ["flaky", "ipykernel", "ipython", "ipywidgets (>=7.5)", "myst-parser", "nbsphinx (>=0.2.12)", "playwright", "pydata-sphinx-theme", "pyqtwebengine (>=5.15)", "pytest (>=7)", "sphinx (==5.0.2)", "sphinxcontrib-spelling", "tornado (>=6.1)"] +docs = ["ipykernel", "ipython", "myst-parser", "nbsphinx (>=0.2.12)", "pydata-sphinx-theme", "sphinx (==5.0.2)", "sphinxcontrib-spelling"] +qtpdf = ["pyqtwebengine (>=5.15)"] +qtpng = ["pyqtwebengine (>=5.15)"] +serve = ["tornado (>=6.1)"] +test = ["flaky", "ipykernel", "ipywidgets (>=7.5)", "pytest (>=7)"] +webpdf = ["playwright"] + +[[package]] +name = "nbformat" +version = "5.10.4" +description = "The Jupyter Notebook format" +optional = false +python-versions = ">=3.8" +files = [ + {file = "nbformat-5.10.4-py3-none-any.whl", hash = "sha256:3b48d6c8fbca4b299bf3982ea7db1af21580e4fec269ad087b9e81588891200b"}, + {file = "nbformat-5.10.4.tar.gz", hash = "sha256:322168b14f937a5d11362988ecac2a4952d3d8e3a2cbeb2319584631226d5b3a"}, ] -jupyterlab = [ - {file = "jupyterlab-2.2.8-py3-none-any.whl", hash = "sha256:95d0509557881cfa8a5fcdf225f2fca46faf1bc52fc56a28e0b72fcc594c90ab"}, - {file = "jupyterlab-2.2.8.tar.gz", hash = "sha256:c8377bee30504919c1e79949f9fe35443ab7f5c4be622c95307e8108410c8b8c"}, + +[package.dependencies] +fastjsonschema = ">=2.15" +jsonschema = ">=2.6" +jupyter-core = ">=4.12,<5.0.dev0 || >=5.1.dev0" +traitlets = ">=5.1" + +[package.extras] +docs = ["myst-parser", "pydata-sphinx-theme", "sphinx", "sphinxcontrib-github-alt", "sphinxcontrib-spelling"] +test = ["pep440", "pre-commit", "pytest", "testpath"] + +[[package]] +name = "nest-asyncio" +version = "1.6.0" +description = "Patch asyncio to allow nested event loops" +optional = false +python-versions = ">=3.5" +files = [ + {file = "nest_asyncio-1.6.0-py3-none-any.whl", hash = "sha256:87af6efd6b5e897c81050477ef65c62e2b2f35d51703cae01aff2905b1852e1c"}, + {file = "nest_asyncio-1.6.0.tar.gz", hash = "sha256:6f172d5449aca15afd6c646851f4e31e02c598d553a667e38cafa997cfec55fe"}, ] -jupyterlab-pygments = [ - {file = "jupyterlab_pygments-0.1.1-py2.py3-none-any.whl", hash = "sha256:c9535e5999f29bff90bd0fa423717dcaf247b71fad505d66b17d3217e9021fc5"}, - {file = "jupyterlab_pygments-0.1.1.tar.gz", hash = "sha256:19a0ccde7daddec638363cd3d60b63a4f6544c9181d65253317b2fb492a797b9"}, + +[[package]] +name = "notebook-shim" +version = "0.2.4" +description = "A shim layer for notebook traits and config" +optional = false +python-versions = ">=3.7" +files = [ + {file = "notebook_shim-0.2.4-py3-none-any.whl", hash = "sha256:411a5be4e9dc882a074ccbcae671eda64cceb068767e9a3419096986560e1cef"}, + {file = "notebook_shim-0.2.4.tar.gz", hash = "sha256:b4b2cfa1b65d98307ca24361f5b30fe785b53c3fd07b7a47e89acb5e6ac638cb"}, ] -jupyterlab-server = [ - {file = "jupyterlab_server-1.2.0-py3-none-any.whl", hash = "sha256:55d256077bf13e5bc9e8fbd5aac51bef82f6315111cec6b712b9a5ededbba924"}, - {file = "jupyterlab_server-1.2.0.tar.gz", hash = "sha256:5431d9dde96659364b7cc877693d5d21e7b80cea7ae3959ecc2b87518e5f5d8c"}, + +[package.dependencies] +jupyter-server = ">=1.8,<3" + +[package.extras] +test = ["pytest", "pytest-console-scripts", "pytest-jupyter", "pytest-tornasync"] + +[[package]] +name = "numpy" +version = "2.0.0" +description = "Fundamental package for array computing in Python" +optional = false +python-versions = ">=3.9" +files = [ + {file = "numpy-2.0.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:04494f6ec467ccb5369d1808570ae55f6ed9b5809d7f035059000a37b8d7e86f"}, + {file = "numpy-2.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2635dbd200c2d6faf2ef9a0d04f0ecc6b13b3cad54f7c67c61155138835515d2"}, + {file = "numpy-2.0.0-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:0a43f0974d501842866cc83471bdb0116ba0dffdbaac33ec05e6afed5b615238"}, + {file = "numpy-2.0.0-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:8d83bb187fb647643bd56e1ae43f273c7f4dbcdf94550d7938cfc32566756514"}, + {file = "numpy-2.0.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:79e843d186c8fb1b102bef3e2bc35ef81160ffef3194646a7fdd6a73c6b97196"}, + {file = "numpy-2.0.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6d7696c615765091cc5093f76fd1fa069870304beaccfd58b5dcc69e55ef49c1"}, + {file = "numpy-2.0.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:b4c76e3d4c56f145d41b7b6751255feefae92edbc9a61e1758a98204200f30fc"}, + {file = "numpy-2.0.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:acd3a644e4807e73b4e1867b769fbf1ce8c5d80e7caaef0d90dcdc640dfc9787"}, + {file = "numpy-2.0.0-cp310-cp310-win32.whl", hash = "sha256:cee6cc0584f71adefe2c908856ccc98702baf95ff80092e4ca46061538a2ba98"}, + {file = "numpy-2.0.0-cp310-cp310-win_amd64.whl", hash = "sha256:ed08d2703b5972ec736451b818c2eb9da80d66c3e84aed1deeb0c345fefe461b"}, + {file = "numpy-2.0.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ad0c86f3455fbd0de6c31a3056eb822fc939f81b1618f10ff3406971893b62a5"}, + {file = "numpy-2.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e7f387600d424f91576af20518334df3d97bc76a300a755f9a8d6e4f5cadd289"}, + {file = "numpy-2.0.0-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:34f003cb88b1ba38cb9a9a4a3161c1604973d7f9d5552c38bc2f04f829536609"}, + {file = "numpy-2.0.0-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:b6f6a8f45d0313db07d6d1d37bd0b112f887e1369758a5419c0370ba915b3871"}, + {file = "numpy-2.0.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5f64641b42b2429f56ee08b4f427a4d2daf916ec59686061de751a55aafa22e4"}, + {file = "numpy-2.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a7039a136017eaa92c1848152827e1424701532ca8e8967fe480fe1569dae581"}, + {file = "numpy-2.0.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:46e161722e0f619749d1cd892167039015b2c2817296104487cd03ed4a955995"}, + {file = "numpy-2.0.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:0e50842b2295ba8414c8c1d9d957083d5dfe9e16828b37de883f51fc53c4016f"}, + {file = "numpy-2.0.0-cp311-cp311-win32.whl", hash = "sha256:2ce46fd0b8a0c947ae047d222f7136fc4d55538741373107574271bc00e20e8f"}, + {file = "numpy-2.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:fbd6acc766814ea6443628f4e6751d0da6593dae29c08c0b2606164db026970c"}, + {file = "numpy-2.0.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:354f373279768fa5a584bac997de6a6c9bc535c482592d7a813bb0c09be6c76f"}, + {file = "numpy-2.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4d2f62e55a4cd9c58c1d9a1c9edaedcd857a73cb6fda875bf79093f9d9086f85"}, + {file = "numpy-2.0.0-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:1e72728e7501a450288fc8e1f9ebc73d90cfd4671ebbd631f3e7857c39bd16f2"}, + {file = "numpy-2.0.0-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:84554fc53daa8f6abf8e8a66e076aff6ece62de68523d9f665f32d2fc50fd66e"}, + {file = "numpy-2.0.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c73aafd1afca80afecb22718f8700b40ac7cab927b8abab3c3e337d70e10e5a2"}, + {file = "numpy-2.0.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:49d9f7d256fbc804391a7f72d4a617302b1afac1112fac19b6c6cec63fe7fe8a"}, + {file = "numpy-2.0.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:0ec84b9ba0654f3b962802edc91424331f423dcf5d5f926676e0150789cb3d95"}, + {file = "numpy-2.0.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:feff59f27338135776f6d4e2ec7aeeac5d5f7a08a83e80869121ef8164b74af9"}, + {file = "numpy-2.0.0-cp312-cp312-win32.whl", hash = "sha256:c5a59996dc61835133b56a32ebe4ef3740ea5bc19b3983ac60cc32be5a665d54"}, + {file = "numpy-2.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:a356364941fb0593bb899a1076b92dfa2029f6f5b8ba88a14fd0984aaf76d0df"}, + {file = "numpy-2.0.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:e61155fae27570692ad1d327e81c6cf27d535a5d7ef97648a17d922224b216de"}, + {file = "numpy-2.0.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4554eb96f0fd263041baf16cf0881b3f5dafae7a59b1049acb9540c4d57bc8cb"}, + {file = "numpy-2.0.0-cp39-cp39-macosx_14_0_arm64.whl", hash = "sha256:903703372d46bce88b6920a0cd86c3ad82dae2dbef157b5fc01b70ea1cfc430f"}, + {file = "numpy-2.0.0-cp39-cp39-macosx_14_0_x86_64.whl", hash = "sha256:3e8e01233d57639b2e30966c63d36fcea099d17c53bf424d77f088b0f4babd86"}, + {file = "numpy-2.0.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1cde1753efe513705a0c6d28f5884e22bdc30438bf0085c5c486cdaff40cd67a"}, + {file = "numpy-2.0.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:821eedb7165ead9eebdb569986968b541f9908979c2da8a4967ecac4439bae3d"}, + {file = "numpy-2.0.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:9a1712c015831da583b21c5bfe15e8684137097969c6d22e8316ba66b5baabe4"}, + {file = "numpy-2.0.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:9c27f0946a3536403efb0e1c28def1ae6730a72cd0d5878db38824855e3afc44"}, + {file = "numpy-2.0.0-cp39-cp39-win32.whl", hash = "sha256:63b92c512d9dbcc37f9d81b123dec99fdb318ba38c8059afc78086fe73820275"}, + {file = "numpy-2.0.0-cp39-cp39-win_amd64.whl", hash = "sha256:3f6bed7f840d44c08ebdb73b1825282b801799e325bcbdfa6bc5c370e5aecc65"}, + {file = "numpy-2.0.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:9416a5c2e92ace094e9f0082c5fd473502c91651fb896bc17690d6fc475128d6"}, + {file = "numpy-2.0.0-pp39-pypy39_pp73-macosx_14_0_x86_64.whl", hash = "sha256:17067d097ed036636fa79f6a869ac26df7db1ba22039d962422506640314933a"}, + {file = "numpy-2.0.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:38ecb5b0582cd125f67a629072fed6f83562d9dd04d7e03256c9829bdec027ad"}, + {file = "numpy-2.0.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:cef04d068f5fb0518a77857953193b6bb94809a806bd0a14983a8f12ada060c9"}, + {file = "numpy-2.0.0.tar.gz", hash = "sha256:cf5d1c9e6837f8af9f92b6bd3e86d513cdc11f60fd62185cc49ec7d1aba34864"}, ] -kiwisolver = [ - {file = "kiwisolver-1.2.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:443c2320520eda0a5b930b2725b26f6175ca4453c61f739fef7a5847bd262f74"}, - {file = "kiwisolver-1.2.0-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:efcf3397ae1e3c3a4a0a0636542bcad5adad3b1dd3e8e629d0b6e201347176c8"}, - {file = "kiwisolver-1.2.0-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:fccefc0d36a38c57b7bd233a9b485e2f1eb71903ca7ad7adacad6c28a56d62d2"}, - {file = "kiwisolver-1.2.0-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:be046da49fbc3aa9491cc7296db7e8d27bcf0c3d5d1a40259c10471b014e4e0c"}, - {file = "kiwisolver-1.2.0-cp36-none-win32.whl", hash = "sha256:60a78858580761fe611d22127868f3dc9f98871e6fdf0a15cc4203ed9ba6179b"}, - {file = "kiwisolver-1.2.0-cp36-none-win_amd64.whl", hash = "sha256:556da0a5f60f6486ec4969abbc1dd83cf9b5c2deadc8288508e55c0f5f87d29c"}, - {file = "kiwisolver-1.2.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:7cc095a4661bdd8a5742aaf7c10ea9fac142d76ff1770a0f84394038126d8fc7"}, - {file = "kiwisolver-1.2.0-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:c955791d80e464da3b471ab41eb65cf5a40c15ce9b001fdc5bbc241170de58ec"}, - {file = "kiwisolver-1.2.0-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:603162139684ee56bcd57acc74035fceed7dd8d732f38c0959c8bd157f913fec"}, - {file = "kiwisolver-1.2.0-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:63f55f490b958b6299e4e5bdac66ac988c3d11b7fafa522800359075d4fa56d1"}, - {file = "kiwisolver-1.2.0-cp37-none-win32.whl", hash = "sha256:03662cbd3e6729f341a97dd2690b271e51a67a68322affab12a5b011344b973c"}, - {file = "kiwisolver-1.2.0-cp37-none-win_amd64.whl", hash = "sha256:4eadb361baf3069f278b055e3bb53fa189cea2fd02cb2c353b7a99ebb4477ef1"}, - {file = "kiwisolver-1.2.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:c31bc3c8e903d60a1ea31a754c72559398d91b5929fcb329b1c3a3d3f6e72113"}, - {file = "kiwisolver-1.2.0-cp38-cp38-manylinux1_i686.whl", hash = "sha256:d52b989dc23cdaa92582ceb4af8d5bcc94d74b2c3e64cd6785558ec6a879793e"}, - {file = "kiwisolver-1.2.0-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:e586b28354d7b6584d8973656a7954b1c69c93f708c0c07b77884f91640b7657"}, - {file = "kiwisolver-1.2.0-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:38d05c9ecb24eee1246391820ed7137ac42a50209c203c908154782fced90e44"}, - {file = "kiwisolver-1.2.0-cp38-none-win32.whl", hash = "sha256:d069ef4b20b1e6b19f790d00097a5d5d2c50871b66d10075dab78938dc2ee2cf"}, - {file = "kiwisolver-1.2.0-cp38-none-win_amd64.whl", hash = "sha256:18d749f3e56c0480dccd1714230da0f328e6e4accf188dd4e6884bdd06bf02dd"}, - {file = "kiwisolver-1.2.0.tar.gz", hash = "sha256:247800260cd38160c362d211dcaf4ed0f7816afb5efe56544748b21d6ad6d17f"}, + +[[package]] +name = "overrides" +version = "7.7.0" +description = "A decorator to automatically detect mismatch when overriding a method." +optional = false +python-versions = ">=3.6" +files = [ + {file = "overrides-7.7.0-py3-none-any.whl", hash = "sha256:c7ed9d062f78b8e4c1a7b70bd8796b35ead4d9f510227ef9c5dc7626c60d7e49"}, + {file = "overrides-7.7.0.tar.gz", hash = "sha256:55158fa3d93b98cc75299b1e67078ad9003ca27945c76162c1c0766d6f91820a"}, ] -markupsafe = [ - {file = "MarkupSafe-1.1.1-cp27-cp27m-macosx_10_6_intel.whl", hash = "sha256:09027a7803a62ca78792ad89403b1b7a73a01c8cb65909cd876f7fcebd79b161"}, - {file = "MarkupSafe-1.1.1-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7"}, - {file = "MarkupSafe-1.1.1-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:500d4957e52ddc3351cabf489e79c91c17f6e0899158447047588650b5e69183"}, - {file = "MarkupSafe-1.1.1-cp27-cp27m-win32.whl", hash = "sha256:b2051432115498d3562c084a49bba65d97cf251f5a331c64a12ee7e04dacc51b"}, - {file = "MarkupSafe-1.1.1-cp27-cp27m-win_amd64.whl", hash = "sha256:98c7086708b163d425c67c7a91bad6e466bb99d797aa64f965e9d25c12111a5e"}, - {file = "MarkupSafe-1.1.1-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:cd5df75523866410809ca100dc9681e301e3c27567cf498077e8551b6d20e42f"}, - {file = "MarkupSafe-1.1.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:43a55c2930bbc139570ac2452adf3d70cdbb3cfe5912c71cdce1c2c6bbd9c5d1"}, - {file = "MarkupSafe-1.1.1-cp34-cp34m-macosx_10_6_intel.whl", hash = "sha256:1027c282dad077d0bae18be6794e6b6b8c91d58ed8a8d89a89d59693b9131db5"}, - {file = "MarkupSafe-1.1.1-cp34-cp34m-manylinux1_i686.whl", hash = "sha256:62fe6c95e3ec8a7fad637b7f3d372c15ec1caa01ab47926cfdf7a75b40e0eac1"}, - {file = "MarkupSafe-1.1.1-cp34-cp34m-manylinux1_x86_64.whl", hash = "sha256:88e5fcfb52ee7b911e8bb6d6aa2fd21fbecc674eadd44118a9cc3863f938e735"}, - {file = "MarkupSafe-1.1.1-cp34-cp34m-win32.whl", hash = "sha256:ade5e387d2ad0d7ebf59146cc00c8044acbd863725f887353a10df825fc8ae21"}, - {file = "MarkupSafe-1.1.1-cp34-cp34m-win_amd64.whl", hash = "sha256:09c4b7f37d6c648cb13f9230d847adf22f8171b1ccc4d5682398e77f40309235"}, - {file = "MarkupSafe-1.1.1-cp35-cp35m-macosx_10_6_intel.whl", hash = "sha256:79855e1c5b8da654cf486b830bd42c06e8780cea587384cf6545b7d9ac013a0b"}, - {file = "MarkupSafe-1.1.1-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:c8716a48d94b06bb3b2524c2b77e055fb313aeb4ea620c8dd03a105574ba704f"}, - {file = "MarkupSafe-1.1.1-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:7c1699dfe0cf8ff607dbdcc1e9b9af1755371f92a68f706051cc8c37d447c905"}, - {file = "MarkupSafe-1.1.1-cp35-cp35m-win32.whl", hash = "sha256:6dd73240d2af64df90aa7c4e7481e23825ea70af4b4922f8ede5b9e35f78a3b1"}, - {file = "MarkupSafe-1.1.1-cp35-cp35m-win_amd64.whl", hash = "sha256:9add70b36c5666a2ed02b43b335fe19002ee5235efd4b8a89bfcf9005bebac0d"}, - {file = "MarkupSafe-1.1.1-cp36-cp36m-macosx_10_6_intel.whl", hash = "sha256:24982cc2533820871eba85ba648cd53d8623687ff11cbb805be4ff7b4c971aff"}, - {file = "MarkupSafe-1.1.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:00bc623926325b26bb9605ae9eae8a215691f33cae5df11ca5424f06f2d1f473"}, - {file = "MarkupSafe-1.1.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:717ba8fe3ae9cc0006d7c451f0bb265ee07739daf76355d06366154ee68d221e"}, - {file = "MarkupSafe-1.1.1-cp36-cp36m-win32.whl", hash = "sha256:535f6fc4d397c1563d08b88e485c3496cf5784e927af890fb3c3aac7f933ec66"}, - {file = "MarkupSafe-1.1.1-cp36-cp36m-win_amd64.whl", hash = "sha256:b1282f8c00509d99fef04d8ba936b156d419be841854fe901d8ae224c59f0be5"}, - {file = "MarkupSafe-1.1.1-cp37-cp37m-macosx_10_6_intel.whl", hash = "sha256:8defac2f2ccd6805ebf65f5eeb132adcf2ab57aa11fdf4c0dd5169a004710e7d"}, - {file = "MarkupSafe-1.1.1-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:46c99d2de99945ec5cb54f23c8cd5689f6d7177305ebff350a58ce5f8de1669e"}, - {file = "MarkupSafe-1.1.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:ba59edeaa2fc6114428f1637ffff42da1e311e29382d81b339c1817d37ec93c6"}, - {file = "MarkupSafe-1.1.1-cp37-cp37m-win32.whl", hash = "sha256:b00c1de48212e4cc9603895652c5c410df699856a2853135b3967591e4beebc2"}, - {file = "MarkupSafe-1.1.1-cp37-cp37m-win_amd64.whl", hash = "sha256:9bf40443012702a1d2070043cb6291650a0841ece432556f784f004937f0f32c"}, - {file = "MarkupSafe-1.1.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6788b695d50a51edb699cb55e35487e430fa21f1ed838122d722e0ff0ac5ba15"}, - {file = "MarkupSafe-1.1.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:cdb132fc825c38e1aeec2c8aa9338310d29d337bebbd7baa06889d09a60a1fa2"}, - {file = "MarkupSafe-1.1.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:13d3144e1e340870b25e7b10b98d779608c02016d5184cfb9927a9f10c689f42"}, - {file = "MarkupSafe-1.1.1-cp38-cp38-win32.whl", hash = "sha256:596510de112c685489095da617b5bcbbac7dd6384aeebeda4df6025d0256a81b"}, - {file = "MarkupSafe-1.1.1-cp38-cp38-win_amd64.whl", hash = "sha256:e8313f01ba26fbbe36c7be1966a7b7424942f670f38e666995b88d012765b9be"}, - {file = "MarkupSafe-1.1.1.tar.gz", hash = "sha256:29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b"}, + +[[package]] +name = "packaging" +version = "24.1" +description = "Core utilities for Python packages" +optional = false +python-versions = ">=3.8" +files = [ + {file = "packaging-24.1-py3-none-any.whl", hash = "sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124"}, + {file = "packaging-24.1.tar.gz", hash = "sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002"}, ] -matplotlib = [ - {file = "matplotlib-3.3.2-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:27f9de4784ae6fb97679556c5542cf36c0751dccb4d6407f7c62517fa2078868"}, - {file = "matplotlib-3.3.2-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:06866c138d81a593b535d037b2727bec9b0818cadfe6a81f6ec5715b8dd38a89"}, - {file = "matplotlib-3.3.2-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:5ccecb5f78b51b885f0028b646786889f49c54883e554fca41a2a05998063f23"}, - {file = "matplotlib-3.3.2-cp36-cp36m-win32.whl", hash = "sha256:69cf76d673682140f46c6cb5e073332c1f1b2853c748dc1cb04f7d00023567f7"}, - {file = "matplotlib-3.3.2-cp36-cp36m-win_amd64.whl", hash = "sha256:371518c769d84af8ec9b7dcb871ac44f7a67ef126dd3a15c88c25458e6b6d205"}, - {file = "matplotlib-3.3.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:793e061054662aa27acaff9201cdd510a698541c6e8659eeceb31d66c16facc6"}, - {file = "matplotlib-3.3.2-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:16b241c3d17be786966495229714de37de04472da472277869b8d5b456a8df00"}, - {file = "matplotlib-3.3.2-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:3fb0409754b26f48045bacd6818e44e38ca9338089f8ba689e2f9344ff2847c7"}, - {file = "matplotlib-3.3.2-cp37-cp37m-win32.whl", hash = "sha256:548cfe81476dbac44db96e9c0b074b6fb333b4d1f12b1ae68dbed47e45166384"}, - {file = "matplotlib-3.3.2-cp37-cp37m-win_amd64.whl", hash = "sha256:f0268613073df055bcc6a490de733012f2cf4fe191c1adb74e41cec8add1a165"}, - {file = "matplotlib-3.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:57be9e21073fc367237b03ecac0d9e4b8ddbe38e86ec4a316857d8d93ac9286c"}, - {file = "matplotlib-3.3.2-cp38-cp38-manylinux1_i686.whl", hash = "sha256:be2f0ec62e0939a9dcfd3638c140c5a74fc929ee3fd1f31408ab8633db6e1523"}, - {file = "matplotlib-3.3.2-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:c5d0c2ae3e3ed4e9f46b7c03b40d443601012ffe8eb8dfbb2bd6b2d00509f797"}, - {file = "matplotlib-3.3.2-cp38-cp38-win32.whl", hash = "sha256:a522de31e07ed7d6f954cda3fbd5ca4b8edbfc592a821a7b00291be6f843292e"}, - {file = "matplotlib-3.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:8bc1d3284dee001f41ec98f59675f4d723683e1cc082830b440b5f081d8e0ade"}, - {file = "matplotlib-3.3.2-pp36-pypy36_pp73-macosx_10_9_x86_64.whl", hash = "sha256:799c421bc245a0749c1515b6dea6dc02db0a8c1f42446a0f03b3b82a60a900dc"}, - {file = "matplotlib-3.3.2-pp36-pypy36_pp73-manylinux2010_x86_64.whl", hash = "sha256:2f5eefc17dc2a71318d5a3496313be5c351c0731e8c4c6182c9ac3782cfc4076"}, - {file = "matplotlib-3.3.2.tar.gz", hash = "sha256:3d2edbf59367f03cd9daf42939ca06383a7d7803e3993eb5ff1bee8e8a3fbb6b"}, -] -mistune = [ - {file = "mistune-0.8.4-py2.py3-none-any.whl", hash = "sha256:88a1051873018da288eee8538d476dffe1262495144b33ecb586c4ab266bb8d4"}, - {file = "mistune-0.8.4.tar.gz", hash = "sha256:59a3429db53c50b5c6bcc8a07f8848cb00d7dc8bdb431a4ab41920d201d4756e"}, -] -nbclient = [ - {file = "nbclient-0.5.0-py3-none-any.whl", hash = "sha256:8a6e27ff581cee50895f44c41936ce02369674e85e2ad58643d8d4a6c36771b0"}, - {file = "nbclient-0.5.0.tar.gz", hash = "sha256:8ad52d27ba144fca1402db014857e53c5a864a2f407be66ca9d74c3a56d6591d"}, -] -nbconvert = [ - {file = "nbconvert-6.0.3-py3-none-any.whl", hash = "sha256:06c64fd45d4b6424e88eb3bf7e5eb205a0fc8a4c0a69666f0b9a2262c76f59e1"}, - {file = "nbconvert-6.0.3.tar.gz", hash = "sha256:d8490f40368a1324521f8e740a0e341dc40bcd6e6926da64fa64b3a8801f16a3"}, -] -nbformat = [ - {file = "nbformat-5.0.7-py3-none-any.whl", hash = "sha256:ea55c9b817855e2dfcd3f66d74857342612a60b1f09653440f4a5845e6e3523f"}, - {file = "nbformat-5.0.7.tar.gz", hash = "sha256:54d4d6354835a936bad7e8182dcd003ca3dc0cedfee5a306090e04854343b340"}, -] -nest-asyncio = [ - {file = "nest_asyncio-1.4.0-py3-none-any.whl", hash = "sha256:ea51120725212ef02e5870dd77fc67ba7343fc945e3b9a7ff93384436e043b6a"}, - {file = "nest_asyncio-1.4.0.tar.gz", hash = "sha256:5773054bbc14579b000236f85bc01ecced7ffd045ec8ca4a9809371ec65a59c8"}, -] -notebook = [ - {file = "notebook-6.1.4-py3-none-any.whl", hash = "sha256:07b6e8b8a61aa2f780fe9a97430470485bc71262bc5cae8521f1441b910d2c88"}, - {file = "notebook-6.1.4.tar.gz", hash = "sha256:687d01f963ea20360c0b904ee7a37c3d8cda553858c8d6e33fd0afd13e89de32"}, + +[[package]] +name = "pandas" +version = "2.2.2" +description = "Powerful data structures for data analysis, time series, and statistics" +optional = false +python-versions = ">=3.9" +files = [ + {file = "pandas-2.2.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:90c6fca2acf139569e74e8781709dccb6fe25940488755716d1d354d6bc58bce"}, + {file = "pandas-2.2.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c7adfc142dac335d8c1e0dcbd37eb8617eac386596eb9e1a1b77791cf2498238"}, + {file = "pandas-2.2.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4abfe0be0d7221be4f12552995e58723c7422c80a659da13ca382697de830c08"}, + {file = "pandas-2.2.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8635c16bf3d99040fdf3ca3db669a7250ddf49c55dc4aa8fe0ae0fa8d6dcc1f0"}, + {file = "pandas-2.2.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:40ae1dffb3967a52203105a077415a86044a2bea011b5f321c6aa64b379a3f51"}, + {file = "pandas-2.2.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8e5a0b00e1e56a842f922e7fae8ae4077aee4af0acb5ae3622bd4b4c30aedf99"}, + {file = "pandas-2.2.2-cp310-cp310-win_amd64.whl", hash = "sha256:ddf818e4e6c7c6f4f7c8a12709696d193976b591cc7dc50588d3d1a6b5dc8772"}, + {file = "pandas-2.2.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:696039430f7a562b74fa45f540aca068ea85fa34c244d0deee539cb6d70aa288"}, + {file = "pandas-2.2.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8e90497254aacacbc4ea6ae5e7a8cd75629d6ad2b30025a4a8b09aa4faf55151"}, + {file = "pandas-2.2.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:58b84b91b0b9f4bafac2a0ac55002280c094dfc6402402332c0913a59654ab2b"}, + {file = "pandas-2.2.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6d2123dc9ad6a814bcdea0f099885276b31b24f7edf40f6cdbc0912672e22eee"}, + {file = "pandas-2.2.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:2925720037f06e89af896c70bca73459d7e6a4be96f9de79e2d440bd499fe0db"}, + {file = "pandas-2.2.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:0cace394b6ea70c01ca1595f839cf193df35d1575986e484ad35c4aeae7266c1"}, + {file = "pandas-2.2.2-cp311-cp311-win_amd64.whl", hash = "sha256:873d13d177501a28b2756375d59816c365e42ed8417b41665f346289adc68d24"}, + {file = "pandas-2.2.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:9dfde2a0ddef507a631dc9dc4af6a9489d5e2e740e226ad426a05cabfbd7c8ef"}, + {file = "pandas-2.2.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:e9b79011ff7a0f4b1d6da6a61aa1aa604fb312d6647de5bad20013682d1429ce"}, + {file = "pandas-2.2.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1cb51fe389360f3b5a4d57dbd2848a5f033350336ca3b340d1c53a1fad33bcad"}, + {file = "pandas-2.2.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eee3a87076c0756de40b05c5e9a6069c035ba43e8dd71c379e68cab2c20f16ad"}, + {file = "pandas-2.2.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:3e374f59e440d4ab45ca2fffde54b81ac3834cf5ae2cdfa69c90bc03bde04d76"}, + {file = "pandas-2.2.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:43498c0bdb43d55cb162cdc8c06fac328ccb5d2eabe3cadeb3529ae6f0517c32"}, + {file = "pandas-2.2.2-cp312-cp312-win_amd64.whl", hash = "sha256:d187d355ecec3629624fccb01d104da7d7f391db0311145817525281e2804d23"}, + {file = "pandas-2.2.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:0ca6377b8fca51815f382bd0b697a0814c8bda55115678cbc94c30aacbb6eff2"}, + {file = "pandas-2.2.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9057e6aa78a584bc93a13f0a9bf7e753a5e9770a30b4d758b8d5f2a62a9433cd"}, + {file = "pandas-2.2.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:001910ad31abc7bf06f49dcc903755d2f7f3a9186c0c040b827e522e9cef0863"}, + {file = "pandas-2.2.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:66b479b0bd07204e37583c191535505410daa8df638fd8e75ae1b383851fe921"}, + {file = "pandas-2.2.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:a77e9d1c386196879aa5eb712e77461aaee433e54c68cf253053a73b7e49c33a"}, + {file = "pandas-2.2.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:92fd6b027924a7e178ac202cfbe25e53368db90d56872d20ffae94b96c7acc57"}, + {file = "pandas-2.2.2-cp39-cp39-win_amd64.whl", hash = "sha256:640cef9aa381b60e296db324337a554aeeb883ead99dc8f6c18e81a93942f5f4"}, + {file = "pandas-2.2.2.tar.gz", hash = "sha256:9e79019aba43cb4fda9e4d983f8e88ca0373adbb697ae9c6c43093218de28b54"}, ] + +[package.dependencies] numpy = [ - {file = "numpy-1.19.2-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:b594f76771bc7fc8a044c5ba303427ee67c17a09b36e1fa32bde82f5c419d17a"}, - {file = "numpy-1.19.2-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:e6ddbdc5113628f15de7e4911c02aed74a4ccff531842c583e5032f6e5a179bd"}, - {file = "numpy-1.19.2-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:3733640466733441295b0d6d3dcbf8e1ffa7e897d4d82903169529fd3386919a"}, - {file = "numpy-1.19.2-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:4339741994c775396e1a274dba3609c69ab0f16056c1077f18979bec2a2c2e6e"}, - {file = "numpy-1.19.2-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:7c6646314291d8f5ea900a7ea9c4261f834b5b62159ba2abe3836f4fa6705526"}, - {file = "numpy-1.19.2-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:7118f0a9f2f617f921ec7d278d981244ba83c85eea197be7c5a4f84af80a9c3c"}, - {file = "numpy-1.19.2-cp36-cp36m-win32.whl", hash = "sha256:9a3001248b9231ed73894c773142658bab914645261275f675d86c290c37f66d"}, - {file = "numpy-1.19.2-cp36-cp36m-win_amd64.whl", hash = "sha256:967c92435f0b3ba37a4257c48b8715b76741410467e2bdb1097e8391fccfae15"}, - {file = "numpy-1.19.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:d526fa58ae4aead839161535d59ea9565863bb0b0bdb3cc63214613fb16aced4"}, - {file = "numpy-1.19.2-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:eb25c381d168daf351147713f49c626030dcff7a393d5caa62515d415a6071d8"}, - {file = "numpy-1.19.2-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:62139af94728d22350a571b7c82795b9d59be77fc162414ada6c8b6a10ef5d02"}, - {file = "numpy-1.19.2-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:0c66da1d202c52051625e55a249da35b31f65a81cb56e4c69af0dfb8fb0125bf"}, - {file = "numpy-1.19.2-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:2117536e968abb7357d34d754e3733b0d7113d4c9f1d921f21a3d96dec5ff716"}, - {file = "numpy-1.19.2-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:54045b198aebf41bf6bf4088012777c1d11703bf74461d70cd350c0af2182e45"}, - {file = "numpy-1.19.2-cp37-cp37m-win32.whl", hash = "sha256:aba1d5daf1144b956bc87ffb87966791f5e9f3e1f6fab3d7f581db1f5b598f7a"}, - {file = "numpy-1.19.2-cp37-cp37m-win_amd64.whl", hash = "sha256:addaa551b298052c16885fc70408d3848d4e2e7352de4e7a1e13e691abc734c1"}, - {file = "numpy-1.19.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:58d66a6b3b55178a1f8a5fe98df26ace76260a70de694d99577ddeab7eaa9a9d"}, - {file = "numpy-1.19.2-cp38-cp38-manylinux1_i686.whl", hash = "sha256:59f3d687faea7a4f7f93bd9665e5b102f32f3fa28514f15b126f099b7997203d"}, - {file = "numpy-1.19.2-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:cebd4f4e64cfe87f2039e4725781f6326a61f095bc77b3716502bed812b385a9"}, - {file = "numpy-1.19.2-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:c35a01777f81e7333bcf276b605f39c872e28295441c265cd0c860f4b40148c1"}, - {file = "numpy-1.19.2-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:d7ac33585e1f09e7345aa902c281bd777fdb792432d27fca857f39b70e5dd31c"}, - {file = "numpy-1.19.2-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:04c7d4ebc5ff93d9822075ddb1751ff392a4375e5885299445fcebf877f179d5"}, - {file = "numpy-1.19.2-cp38-cp38-win32.whl", hash = "sha256:51ee93e1fac3fe08ef54ff1c7f329db64d8a9c5557e6c8e908be9497ac76374b"}, - {file = "numpy-1.19.2-cp38-cp38-win_amd64.whl", hash = "sha256:1669ec8e42f169ff715a904c9b2105b6640f3f2a4c4c2cb4920ae8b2785dac65"}, - {file = "numpy-1.19.2-pp36-pypy36_pp73-manylinux2010_x86_64.whl", hash = "sha256:0bfd85053d1e9f60234f28f63d4a5147ada7f432943c113a11afcf3e65d9d4c8"}, - {file = "numpy-1.19.2.zip", hash = "sha256:0d310730e1e793527065ad7dde736197b705d0e4c9999775f212b03c44a8484c"}, + {version = ">=1.22.4", markers = "python_version < \"3.11\""}, + {version = ">=1.23.2", markers = "python_version == \"3.11\""}, + {version = ">=1.26.0", markers = "python_version >= \"3.12\""}, ] -packaging = [ - {file = "packaging-20.4-py2.py3-none-any.whl", hash = "sha256:998416ba6962ae7fbd6596850b80e17859a5753ba17c32284f67bfff33784181"}, - {file = "packaging-20.4.tar.gz", hash = "sha256:4357f74f47b9c12db93624a82154e9b120fa8293699949152b22065d556079f8"}, +python-dateutil = ">=2.8.2" +pytz = ">=2020.1" +tzdata = ">=2022.7" + +[package.extras] +all = ["PyQt5 (>=5.15.9)", "SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "adbc-driver-sqlite (>=0.8.0)", "beautifulsoup4 (>=4.11.2)", "bottleneck (>=1.3.6)", "dataframe-api-compat (>=0.1.7)", "fastparquet (>=2022.12.0)", "fsspec (>=2022.11.0)", "gcsfs (>=2022.11.0)", "html5lib (>=1.1)", "hypothesis (>=6.46.1)", "jinja2 (>=3.1.2)", "lxml (>=4.9.2)", "matplotlib (>=3.6.3)", "numba (>=0.56.4)", "numexpr (>=2.8.4)", "odfpy (>=1.4.1)", "openpyxl (>=3.1.0)", "pandas-gbq (>=0.19.0)", "psycopg2 (>=2.9.6)", "pyarrow (>=10.0.1)", "pymysql (>=1.0.2)", "pyreadstat (>=1.2.0)", "pytest (>=7.3.2)", "pytest-xdist (>=2.2.0)", "python-calamine (>=0.1.7)", "pyxlsb (>=1.0.10)", "qtpy (>=2.3.0)", "s3fs (>=2022.11.0)", "scipy (>=1.10.0)", "tables (>=3.8.0)", "tabulate (>=0.9.0)", "xarray (>=2022.12.0)", "xlrd (>=2.0.1)", "xlsxwriter (>=3.0.5)", "zstandard (>=0.19.0)"] +aws = ["s3fs (>=2022.11.0)"] +clipboard = ["PyQt5 (>=5.15.9)", "qtpy (>=2.3.0)"] +compression = ["zstandard (>=0.19.0)"] +computation = ["scipy (>=1.10.0)", "xarray (>=2022.12.0)"] +consortium-standard = ["dataframe-api-compat (>=0.1.7)"] +excel = ["odfpy (>=1.4.1)", "openpyxl (>=3.1.0)", "python-calamine (>=0.1.7)", "pyxlsb (>=1.0.10)", "xlrd (>=2.0.1)", "xlsxwriter (>=3.0.5)"] +feather = ["pyarrow (>=10.0.1)"] +fss = ["fsspec (>=2022.11.0)"] +gcp = ["gcsfs (>=2022.11.0)", "pandas-gbq (>=0.19.0)"] +hdf5 = ["tables (>=3.8.0)"] +html = ["beautifulsoup4 (>=4.11.2)", "html5lib (>=1.1)", "lxml (>=4.9.2)"] +mysql = ["SQLAlchemy (>=2.0.0)", "pymysql (>=1.0.2)"] +output-formatting = ["jinja2 (>=3.1.2)", "tabulate (>=0.9.0)"] +parquet = ["pyarrow (>=10.0.1)"] +performance = ["bottleneck (>=1.3.6)", "numba (>=0.56.4)", "numexpr (>=2.8.4)"] +plot = ["matplotlib (>=3.6.3)"] +postgresql = ["SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "psycopg2 (>=2.9.6)"] +pyarrow = ["pyarrow (>=10.0.1)"] +spss = ["pyreadstat (>=1.2.0)"] +sql-other = ["SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "adbc-driver-sqlite (>=0.8.0)"] +test = ["hypothesis (>=6.46.1)", "pytest (>=7.3.2)", "pytest-xdist (>=2.2.0)"] +xml = ["lxml (>=4.9.2)"] + +[[package]] +name = "pandocfilters" +version = "1.5.1" +description = "Utilities for writing pandoc filters in python" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +files = [ + {file = "pandocfilters-1.5.1-py2.py3-none-any.whl", hash = "sha256:93be382804a9cdb0a7267585f157e5d1731bbe5545a85b268d6f5fe6232de2bc"}, + {file = "pandocfilters-1.5.1.tar.gz", hash = "sha256:002b4a555ee4ebc03f8b66307e287fa492e4a77b4ea14d3f934328297bb4939e"}, ] -pandas = [ - {file = "pandas-1.1.2-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:eb0ac2fd04428f18b547716f70c699a7cc9c65a6947ed8c7e688d96eb91e3db8"}, - {file = "pandas-1.1.2-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:02ec9f5f0b7df7227931a884569ef0b6d32d76789c84bcac1a719dafd1f912e8"}, - {file = "pandas-1.1.2-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:1edf6c254d2d138188e9987159978ee70e23362fe9197f3f100844a197f7e1e4"}, - {file = "pandas-1.1.2-cp36-cp36m-win32.whl", hash = "sha256:b821f239514a9ce46dd1cd6c9298a03ed58d0235d414ea264aacc1b14916bbe4"}, - {file = "pandas-1.1.2-cp36-cp36m-win_amd64.whl", hash = "sha256:ab6ea0f3116f408a8a59cd50158bfd19d2a024f4e221f14ab1bcd2da4f0c6fdf"}, - {file = "pandas-1.1.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:474fa53e3b2f3a543cbca81f7457bd1f44e7eb1be7171067636307e21b624e9c"}, - {file = "pandas-1.1.2-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:9e135ce9929cd0f0ba24f0545936af17ba935f844d4c3a2b979354a73c9440e0"}, - {file = "pandas-1.1.2-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:188cdfbf8399bc144fa95040536b5ce3429d2eda6c9c8b238c987af7df9f128c"}, - {file = "pandas-1.1.2-cp37-cp37m-win32.whl", hash = "sha256:08783a33989a6747317766b75be30a594a9764b9f145bb4bcc06e337930d9807"}, - {file = "pandas-1.1.2-cp37-cp37m-win_amd64.whl", hash = "sha256:f7008ec22b92d771b145150978d930a28fab8da3a10131b01bbf39574acdad0b"}, - {file = "pandas-1.1.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:59df9f0276aa4854d8bff28c5e5aeb74d9c6bb4d9f55d272b7124a7df40e47d0"}, - {file = "pandas-1.1.2-cp38-cp38-manylinux1_i686.whl", hash = "sha256:eeb64c5b3d4f2ea072ca8afdeb2b946cd681a863382ca79734f1b520b8d2fa26"}, - {file = "pandas-1.1.2-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:c9235b37489168ed6b173551c816b50aa89f03c24a8549a8b4d47d8dc79bfb1e"}, - {file = "pandas-1.1.2-cp38-cp38-win32.whl", hash = "sha256:0936991228241db937e87f82ec552a33888dd04a2e0d5a2fa3c689f92fab09e0"}, - {file = "pandas-1.1.2-cp38-cp38-win_amd64.whl", hash = "sha256:026d764d0b86ee53183aa4c0b90774b6146123eeada4e24946d7d24290777be1"}, - {file = "pandas-1.1.2.tar.gz", hash = "sha256:b64ffd87a2cfd31b40acd4b92cb72ea9a52a48165aec4c140e78fd69c45d1444"}, + +[[package]] +name = "parso" +version = "0.8.4" +description = "A Python Parser" +optional = false +python-versions = ">=3.6" +files = [ + {file = "parso-0.8.4-py2.py3-none-any.whl", hash = "sha256:a418670a20291dacd2dddc80c377c5c3791378ee1e8d12bffc35420643d43f18"}, + {file = "parso-0.8.4.tar.gz", hash = "sha256:eb3a7b58240fb99099a345571deecc0f9540ea5f4dd2fe14c2a99d6b281ab92d"}, ] -pandocfilters = [ - {file = "pandocfilters-1.4.2.tar.gz", hash = "sha256:b3dd70e169bb5449e6bc6ff96aea89c5eea8c5f6ab5e207fc2f521a2cf4a0da9"}, + +[package.extras] +qa = ["flake8 (==5.0.4)", "mypy (==0.971)", "types-setuptools (==67.2.0.1)"] +testing = ["docopt", "pytest"] + +[[package]] +name = "pathspec" +version = "0.12.1" +description = "Utility library for gitignore style pattern matching of file paths." +optional = false +python-versions = ">=3.8" +files = [ + {file = "pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08"}, + {file = "pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712"}, ] -parso = [ - {file = "parso-0.7.1-py2.py3-none-any.whl", hash = "sha256:97218d9159b2520ff45eb78028ba8b50d2bc61dcc062a9682666f2dc4bd331ea"}, - {file = "parso-0.7.1.tar.gz", hash = "sha256:caba44724b994a8a5e086460bb212abc5a8bc46951bf4a9a1210745953622eb9"}, + +[[package]] +name = "pexpect" +version = "4.9.0" +description = "Pexpect allows easy control of interactive console applications." +optional = false +python-versions = "*" +files = [ + {file = "pexpect-4.9.0-py2.py3-none-any.whl", hash = "sha256:7236d1e080e4936be2dc3e326cec0af72acf9212a7e1d060210e70a47e253523"}, + {file = "pexpect-4.9.0.tar.gz", hash = "sha256:ee7d41123f3c9911050ea2c2dac107568dc43b2d3b0c7557a33212c398ead30f"}, ] -pexpect = [ - {file = "pexpect-4.8.0-py2.py3-none-any.whl", hash = "sha256:0b48a55dcb3c05f3329815901ea4fc1537514d6ba867a152b581d69ae3710937"}, - {file = "pexpect-4.8.0.tar.gz", hash = "sha256:fc65a43959d153d0114afe13997d439c22823a27cefceb5ff35c2178c6784c0c"}, + +[package.dependencies] +ptyprocess = ">=0.5" + +[[package]] +name = "pillow" +version = "10.4.0" +description = "Python Imaging Library (Fork)" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pillow-10.4.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:4d9667937cfa347525b319ae34375c37b9ee6b525440f3ef48542fcf66f2731e"}, + {file = "pillow-10.4.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:543f3dc61c18dafb755773efc89aae60d06b6596a63914107f75459cf984164d"}, + {file = "pillow-10.4.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7928ecbf1ece13956b95d9cbcfc77137652b02763ba384d9ab508099a2eca856"}, + {file = "pillow-10.4.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e4d49b85c4348ea0b31ea63bc75a9f3857869174e2bf17e7aba02945cd218e6f"}, + {file = "pillow-10.4.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:6c762a5b0997f5659a5ef2266abc1d8851ad7749ad9a6a5506eb23d314e4f46b"}, + {file = "pillow-10.4.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:a985e028fc183bf12a77a8bbf36318db4238a3ded7fa9df1b9a133f1cb79f8fc"}, + {file = "pillow-10.4.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:812f7342b0eee081eaec84d91423d1b4650bb9828eb53d8511bcef8ce5aecf1e"}, + {file = "pillow-10.4.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:ac1452d2fbe4978c2eec89fb5a23b8387aba707ac72810d9490118817d9c0b46"}, + {file = "pillow-10.4.0-cp310-cp310-win32.whl", hash = "sha256:bcd5e41a859bf2e84fdc42f4edb7d9aba0a13d29a2abadccafad99de3feff984"}, + {file = "pillow-10.4.0-cp310-cp310-win_amd64.whl", hash = "sha256:ecd85a8d3e79cd7158dec1c9e5808e821feea088e2f69a974db5edf84dc53141"}, + {file = "pillow-10.4.0-cp310-cp310-win_arm64.whl", hash = "sha256:ff337c552345e95702c5fde3158acb0625111017d0e5f24bf3acdb9cc16b90d1"}, + {file = "pillow-10.4.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:0a9ec697746f268507404647e531e92889890a087e03681a3606d9b920fbee3c"}, + {file = "pillow-10.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:dfe91cb65544a1321e631e696759491ae04a2ea11d36715eca01ce07284738be"}, + {file = "pillow-10.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5dc6761a6efc781e6a1544206f22c80c3af4c8cf461206d46a1e6006e4429ff3"}, + {file = "pillow-10.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5e84b6cc6a4a3d76c153a6b19270b3526a5a8ed6b09501d3af891daa2a9de7d6"}, + {file = "pillow-10.4.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:bbc527b519bd3aa9d7f429d152fea69f9ad37c95f0b02aebddff592688998abe"}, + {file = "pillow-10.4.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:76a911dfe51a36041f2e756b00f96ed84677cdeb75d25c767f296c1c1eda1319"}, + {file = "pillow-10.4.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:59291fb29317122398786c2d44427bbd1a6d7ff54017075b22be9d21aa59bd8d"}, + {file = "pillow-10.4.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:416d3a5d0e8cfe4f27f574362435bc9bae57f679a7158e0096ad2beb427b8696"}, + {file = "pillow-10.4.0-cp311-cp311-win32.whl", hash = "sha256:7086cc1d5eebb91ad24ded9f58bec6c688e9f0ed7eb3dbbf1e4800280a896496"}, + {file = "pillow-10.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:cbed61494057c0f83b83eb3a310f0bf774b09513307c434d4366ed64f4128a91"}, + {file = "pillow-10.4.0-cp311-cp311-win_arm64.whl", hash = "sha256:f5f0c3e969c8f12dd2bb7e0b15d5c468b51e5017e01e2e867335c81903046a22"}, + {file = "pillow-10.4.0-cp312-cp312-macosx_10_10_x86_64.whl", hash = "sha256:673655af3eadf4df6b5457033f086e90299fdd7a47983a13827acf7459c15d94"}, + {file = "pillow-10.4.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:866b6942a92f56300012f5fbac71f2d610312ee65e22f1aa2609e491284e5597"}, + {file = "pillow-10.4.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:29dbdc4207642ea6aad70fbde1a9338753d33fb23ed6956e706936706f52dd80"}, + {file = "pillow-10.4.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf2342ac639c4cf38799a44950bbc2dfcb685f052b9e262f446482afaf4bffca"}, + {file = "pillow-10.4.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:f5b92f4d70791b4a67157321c4e8225d60b119c5cc9aee8ecf153aace4aad4ef"}, + {file = "pillow-10.4.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:86dcb5a1eb778d8b25659d5e4341269e8590ad6b4e8b44d9f4b07f8d136c414a"}, + {file = "pillow-10.4.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:780c072c2e11c9b2c7ca37f9a2ee8ba66f44367ac3e5c7832afcfe5104fd6d1b"}, + {file = "pillow-10.4.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:37fb69d905be665f68f28a8bba3c6d3223c8efe1edf14cc4cfa06c241f8c81d9"}, + {file = "pillow-10.4.0-cp312-cp312-win32.whl", hash = "sha256:7dfecdbad5c301d7b5bde160150b4db4c659cee2b69589705b6f8a0c509d9f42"}, + {file = "pillow-10.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:1d846aea995ad352d4bdcc847535bd56e0fd88d36829d2c90be880ef1ee4668a"}, + {file = "pillow-10.4.0-cp312-cp312-win_arm64.whl", hash = "sha256:e553cad5179a66ba15bb18b353a19020e73a7921296a7979c4a2b7f6a5cd57f9"}, + {file = "pillow-10.4.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8bc1a764ed8c957a2e9cacf97c8b2b053b70307cf2996aafd70e91a082e70df3"}, + {file = "pillow-10.4.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:6209bb41dc692ddfee4942517c19ee81b86c864b626dbfca272ec0f7cff5d9fb"}, + {file = "pillow-10.4.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bee197b30783295d2eb680b311af15a20a8b24024a19c3a26431ff83eb8d1f70"}, + {file = "pillow-10.4.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1ef61f5dd14c300786318482456481463b9d6b91ebe5ef12f405afbba77ed0be"}, + {file = "pillow-10.4.0-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:297e388da6e248c98bc4a02e018966af0c5f92dfacf5a5ca22fa01cb3179bca0"}, + {file = "pillow-10.4.0-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:e4db64794ccdf6cb83a59d73405f63adbe2a1887012e308828596100a0b2f6cc"}, + {file = "pillow-10.4.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:bd2880a07482090a3bcb01f4265f1936a903d70bc740bfcb1fd4e8a2ffe5cf5a"}, + {file = "pillow-10.4.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4b35b21b819ac1dbd1233317adeecd63495f6babf21b7b2512d244ff6c6ce309"}, + {file = "pillow-10.4.0-cp313-cp313-win32.whl", hash = "sha256:551d3fd6e9dc15e4c1eb6fc4ba2b39c0c7933fa113b220057a34f4bb3268a060"}, + {file = "pillow-10.4.0-cp313-cp313-win_amd64.whl", hash = "sha256:030abdbe43ee02e0de642aee345efa443740aa4d828bfe8e2eb11922ea6a21ea"}, + {file = "pillow-10.4.0-cp313-cp313-win_arm64.whl", hash = "sha256:5b001114dd152cfd6b23befeb28d7aee43553e2402c9f159807bf55f33af8a8d"}, + {file = "pillow-10.4.0-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:8d4d5063501b6dd4024b8ac2f04962d661222d120381272deea52e3fc52d3736"}, + {file = "pillow-10.4.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7c1ee6f42250df403c5f103cbd2768a28fe1a0ea1f0f03fe151c8741e1469c8b"}, + {file = "pillow-10.4.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b15e02e9bb4c21e39876698abf233c8c579127986f8207200bc8a8f6bb27acf2"}, + {file = "pillow-10.4.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7a8d4bade9952ea9a77d0c3e49cbd8b2890a399422258a77f357b9cc9be8d680"}, + {file = "pillow-10.4.0-cp38-cp38-manylinux_2_28_aarch64.whl", hash = "sha256:43efea75eb06b95d1631cb784aa40156177bf9dd5b4b03ff38979e048258bc6b"}, + {file = "pillow-10.4.0-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:950be4d8ba92aca4b2bb0741285a46bfae3ca699ef913ec8416c1b78eadd64cd"}, + {file = "pillow-10.4.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:d7480af14364494365e89d6fddc510a13e5a2c3584cb19ef65415ca57252fb84"}, + {file = "pillow-10.4.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:73664fe514b34c8f02452ffb73b7a92c6774e39a647087f83d67f010eb9a0cf0"}, + {file = "pillow-10.4.0-cp38-cp38-win32.whl", hash = "sha256:e88d5e6ad0d026fba7bdab8c3f225a69f063f116462c49892b0149e21b6c0a0e"}, + {file = "pillow-10.4.0-cp38-cp38-win_amd64.whl", hash = "sha256:5161eef006d335e46895297f642341111945e2c1c899eb406882a6c61a4357ab"}, + {file = "pillow-10.4.0-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:0ae24a547e8b711ccaaf99c9ae3cd975470e1a30caa80a6aaee9a2f19c05701d"}, + {file = "pillow-10.4.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:298478fe4f77a4408895605f3482b6cc6222c018b2ce565c2b6b9c354ac3229b"}, + {file = "pillow-10.4.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:134ace6dc392116566980ee7436477d844520a26a4b1bd4053f6f47d096997fd"}, + {file = "pillow-10.4.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:930044bb7679ab003b14023138b50181899da3f25de50e9dbee23b61b4de2126"}, + {file = "pillow-10.4.0-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:c76e5786951e72ed3686e122d14c5d7012f16c8303a674d18cdcd6d89557fc5b"}, + {file = "pillow-10.4.0-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:b2724fdb354a868ddf9a880cb84d102da914e99119211ef7ecbdc613b8c96b3c"}, + {file = "pillow-10.4.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:dbc6ae66518ab3c5847659e9988c3b60dc94ffb48ef9168656e0019a93dbf8a1"}, + {file = "pillow-10.4.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:06b2f7898047ae93fad74467ec3d28fe84f7831370e3c258afa533f81ef7f3df"}, + {file = "pillow-10.4.0-cp39-cp39-win32.whl", hash = "sha256:7970285ab628a3779aecc35823296a7869f889b8329c16ad5a71e4901a3dc4ef"}, + {file = "pillow-10.4.0-cp39-cp39-win_amd64.whl", hash = "sha256:961a7293b2457b405967af9c77dcaa43cc1a8cd50d23c532e62d48ab6cdd56f5"}, + {file = "pillow-10.4.0-cp39-cp39-win_arm64.whl", hash = "sha256:32cda9e3d601a52baccb2856b8ea1fc213c90b340c542dcef77140dfa3278a9e"}, + {file = "pillow-10.4.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:5b4815f2e65b30f5fbae9dfffa8636d992d49705723fe86a3661806e069352d4"}, + {file = "pillow-10.4.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:8f0aef4ef59694b12cadee839e2ba6afeab89c0f39a3adc02ed51d109117b8da"}, + {file = "pillow-10.4.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9f4727572e2918acaa9077c919cbbeb73bd2b3ebcfe033b72f858fc9fbef0026"}, + {file = "pillow-10.4.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ff25afb18123cea58a591ea0244b92eb1e61a1fd497bf6d6384f09bc3262ec3e"}, + {file = "pillow-10.4.0-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:dc3e2db6ba09ffd7d02ae9141cfa0ae23393ee7687248d46a7507b75d610f4f5"}, + {file = "pillow-10.4.0-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:02a2be69f9c9b8c1e97cf2713e789d4e398c751ecfd9967c18d0ce304efbf885"}, + {file = "pillow-10.4.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:0755ffd4a0c6f267cccbae2e9903d95477ca2f77c4fcf3a3a09570001856c8a5"}, + {file = "pillow-10.4.0-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:a02364621fe369e06200d4a16558e056fe2805d3468350df3aef21e00d26214b"}, + {file = "pillow-10.4.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:1b5dea9831a90e9d0721ec417a80d4cbd7022093ac38a568db2dd78363b00908"}, + {file = "pillow-10.4.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9b885f89040bb8c4a1573566bbb2f44f5c505ef6e74cec7ab9068c900047f04b"}, + {file = "pillow-10.4.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:87dd88ded2e6d74d31e1e0a99a726a6765cda32d00ba72dc37f0651f306daaa8"}, + {file = "pillow-10.4.0-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:2db98790afc70118bd0255c2eeb465e9767ecf1f3c25f9a1abb8ffc8cfd1fe0a"}, + {file = "pillow-10.4.0-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:f7baece4ce06bade126fb84b8af1c33439a76d8a6fd818970215e0560ca28c27"}, + {file = "pillow-10.4.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:cfdd747216947628af7b259d274771d84db2268ca062dd5faf373639d00113a3"}, + {file = "pillow-10.4.0.tar.gz", hash = "sha256:166c1cd4d24309b30d61f79f4a9114b7b2313d7450912277855ff5dfd7cd4a06"}, ] -pickleshare = [ - {file = "pickleshare-0.7.5-py2.py3-none-any.whl", hash = "sha256:9649af414d74d4df115d5d718f82acb59c9d418196b7b4290ed47a12ce62df56"}, - {file = "pickleshare-0.7.5.tar.gz", hash = "sha256:87683d47965c1da65cdacaf31c8441d12b8044cdec9aca500cd78fc2c683afca"}, + +[package.extras] +docs = ["furo", "olefile", "sphinx (>=7.3)", "sphinx-copybutton", "sphinx-inline-tabs", "sphinxext-opengraph"] +fpx = ["olefile"] +mic = ["olefile"] +tests = ["check-manifest", "coverage", "defusedxml", "markdown2", "olefile", "packaging", "pyroma", "pytest", "pytest-cov", "pytest-timeout"] +typing = ["typing-extensions"] +xmp = ["defusedxml"] + +[[package]] +name = "platformdirs" +version = "4.2.2" +description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." +optional = false +python-versions = ">=3.8" +files = [ + {file = "platformdirs-4.2.2-py3-none-any.whl", hash = "sha256:2d7a1657e36a80ea911db832a8a6ece5ee53d8de21edd5cc5879af6530b1bfee"}, + {file = "platformdirs-4.2.2.tar.gz", hash = "sha256:38b7b51f512eed9e84a22788b4bce1de17c0adb134d6becb09836e37d8654cd3"}, ] -pillow = [ - {file = "Pillow-7.2.0-cp35-cp35m-macosx_10_10_intel.whl", hash = "sha256:1ca594126d3c4def54babee699c055a913efb01e106c309fa6b04405d474d5ae"}, - {file = "Pillow-7.2.0-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:c92302a33138409e8f1ad16731568c55c9053eee71bb05b6b744067e1b62380f"}, - {file = "Pillow-7.2.0-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:8dad18b69f710bf3a001d2bf3afab7c432785d94fcf819c16b5207b1cfd17d38"}, - {file = "Pillow-7.2.0-cp35-cp35m-manylinux2014_aarch64.whl", hash = "sha256:431b15cffbf949e89df2f7b48528be18b78bfa5177cb3036284a5508159492b5"}, - {file = "Pillow-7.2.0-cp35-cp35m-win32.whl", hash = "sha256:09d7f9e64289cb40c2c8d7ad674b2ed6105f55dc3b09aa8e4918e20a0311e7ad"}, - {file = "Pillow-7.2.0-cp35-cp35m-win_amd64.whl", hash = "sha256:0295442429645fa16d05bd567ef5cff178482439c9aad0411d3f0ce9b88b3a6f"}, - {file = "Pillow-7.2.0-cp36-cp36m-macosx_10_10_x86_64.whl", hash = "sha256:ec29604081f10f16a7aea809ad42e27764188fc258b02259a03a8ff7ded3808d"}, - {file = "Pillow-7.2.0-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:612cfda94e9c8346f239bf1a4b082fdd5c8143cf82d685ba2dba76e7adeeb233"}, - {file = "Pillow-7.2.0-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:0a80dd307a5d8440b0a08bd7b81617e04d870e40a3e46a32d9c246e54705e86f"}, - {file = "Pillow-7.2.0-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:06aba4169e78c439d528fdeb34762c3b61a70813527a2c57f0540541e9f433a8"}, - {file = "Pillow-7.2.0-cp36-cp36m-win32.whl", hash = "sha256:f7e30c27477dffc3e85c2463b3e649f751789e0f6c8456099eea7ddd53be4a8a"}, - {file = "Pillow-7.2.0-cp36-cp36m-win_amd64.whl", hash = "sha256:ffe538682dc19cc542ae7c3e504fdf54ca7f86fb8a135e59dd6bc8627eae6cce"}, - {file = "Pillow-7.2.0-cp37-cp37m-macosx_10_10_x86_64.whl", hash = "sha256:94cf49723928eb6070a892cb39d6c156f7b5a2db4e8971cb958f7b6b104fb4c4"}, - {file = "Pillow-7.2.0-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:6edb5446f44d901e8683ffb25ebdfc26988ee813da3bf91e12252b57ac163727"}, - {file = "Pillow-7.2.0-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:52125833b070791fcb5710fabc640fc1df07d087fc0c0f02d3661f76c23c5b8b"}, - {file = "Pillow-7.2.0-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:9ad7f865eebde135d526bb3163d0b23ffff365cf87e767c649550964ad72785d"}, - {file = "Pillow-7.2.0-cp37-cp37m-win32.whl", hash = "sha256:c79f9c5fb846285f943aafeafda3358992d64f0ef58566e23484132ecd8d7d63"}, - {file = "Pillow-7.2.0-cp37-cp37m-win_amd64.whl", hash = "sha256:d350f0f2c2421e65fbc62690f26b59b0bcda1b614beb318c81e38647e0f673a1"}, - {file = "Pillow-7.2.0-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:6d7741e65835716ceea0fd13a7d0192961212fd59e741a46bbed7a473c634ed6"}, - {file = "Pillow-7.2.0-cp38-cp38-manylinux1_i686.whl", hash = "sha256:edf31f1150778abd4322444c393ab9c7bd2af271dd4dafb4208fb613b1f3cdc9"}, - {file = "Pillow-7.2.0-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:d08b23fdb388c0715990cbc06866db554e1822c4bdcf6d4166cf30ac82df8c41"}, - {file = "Pillow-7.2.0-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:5e51ee2b8114def244384eda1c82b10e307ad9778dac5c83fb0943775a653cd8"}, - {file = "Pillow-7.2.0-cp38-cp38-win32.whl", hash = "sha256:725aa6cfc66ce2857d585f06e9519a1cc0ef6d13f186ff3447ab6dff0a09bc7f"}, - {file = "Pillow-7.2.0-cp38-cp38-win_amd64.whl", hash = "sha256:a060cf8aa332052df2158e5a119303965be92c3da6f2d93b6878f0ebca80b2f6"}, - {file = "Pillow-7.2.0-pp36-pypy36_pp73-macosx_10_10_x86_64.whl", hash = "sha256:9c87ef410a58dd54b92424ffd7e28fd2ec65d2f7fc02b76f5e9b2067e355ebf6"}, - {file = "Pillow-7.2.0-pp36-pypy36_pp73-manylinux2010_x86_64.whl", hash = "sha256:e901964262a56d9ea3c2693df68bc9860b8bdda2b04768821e4c44ae797de117"}, - {file = "Pillow-7.2.0-pp36-pypy36_pp73-win32.whl", hash = "sha256:25930fadde8019f374400f7986e8404c8b781ce519da27792cbe46eabec00c4d"}, - {file = "Pillow-7.2.0.tar.gz", hash = "sha256:97f9e7953a77d5a70f49b9a48da7776dc51e9b738151b22dacf101641594a626"}, + +[package.extras] +docs = ["furo (>=2023.9.10)", "proselint (>=0.13)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1.25.2)"] +test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4.3)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)"] +type = ["mypy (>=1.8)"] + +[[package]] +name = "prometheus-client" +version = "0.20.0" +description = "Python client for the Prometheus monitoring system." +optional = false +python-versions = ">=3.8" +files = [ + {file = "prometheus_client-0.20.0-py3-none-any.whl", hash = "sha256:cde524a85bce83ca359cc837f28b8c0db5cac7aa653a588fd7e84ba061c329e7"}, + {file = "prometheus_client-0.20.0.tar.gz", hash = "sha256:287629d00b147a32dcb2be0b9df905da599b2d82f80377083ec8463309a4bb89"}, ] -prometheus-client = [ - {file = "prometheus_client-0.8.0-py2.py3-none-any.whl", hash = "sha256:983c7ac4b47478720db338f1491ef67a100b474e3bc7dafcbaefb7d0b8f9b01c"}, - {file = "prometheus_client-0.8.0.tar.gz", hash = "sha256:c6e6b706833a6bd1fd51711299edee907857be10ece535126a158f911ee80915"}, + +[package.extras] +twisted = ["twisted"] + +[[package]] +name = "prompt-toolkit" +version = "3.0.47" +description = "Library for building powerful interactive command lines in Python" +optional = false +python-versions = ">=3.7.0" +files = [ + {file = "prompt_toolkit-3.0.47-py3-none-any.whl", hash = "sha256:0d7bfa67001d5e39d02c224b663abc33687405033a8c422d0d675a5a13361d10"}, + {file = "prompt_toolkit-3.0.47.tar.gz", hash = "sha256:1e1b29cb58080b1e69f207c893a1a7bf16d127a5c30c9d17a25a5d77792e5360"}, ] -prompt-toolkit = [ - {file = "prompt_toolkit-3.0.7-py3-none-any.whl", hash = "sha256:83074ee28ad4ba6af190593d4d4c607ff525272a504eb159199b6dd9f950c950"}, - {file = "prompt_toolkit-3.0.7.tar.gz", hash = "sha256:822f4605f28f7d2ba6b0b09a31e25e140871e96364d1d377667b547bb3bf4489"}, + +[package.dependencies] +wcwidth = "*" + +[[package]] +name = "psutil" +version = "6.0.0" +description = "Cross-platform lib for process and system monitoring in Python." +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" +files = [ + {file = "psutil-6.0.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:a021da3e881cd935e64a3d0a20983bda0bb4cf80e4f74fa9bfcb1bc5785360c6"}, + {file = "psutil-6.0.0-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:1287c2b95f1c0a364d23bc6f2ea2365a8d4d9b726a3be7294296ff7ba97c17f0"}, + {file = "psutil-6.0.0-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:a9a3dbfb4de4f18174528d87cc352d1f788b7496991cca33c6996f40c9e3c92c"}, + {file = "psutil-6.0.0-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:6ec7588fb3ddaec7344a825afe298db83fe01bfaaab39155fa84cf1c0d6b13c3"}, + {file = "psutil-6.0.0-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:1e7c870afcb7d91fdea2b37c24aeb08f98b6d67257a5cb0a8bc3ac68d0f1a68c"}, + {file = "psutil-6.0.0-cp27-none-win32.whl", hash = "sha256:02b69001f44cc73c1c5279d02b30a817e339ceb258ad75997325e0e6169d8b35"}, + {file = "psutil-6.0.0-cp27-none-win_amd64.whl", hash = "sha256:21f1fb635deccd510f69f485b87433460a603919b45e2a324ad65b0cc74f8fb1"}, + {file = "psutil-6.0.0-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:c588a7e9b1173b6e866756dde596fd4cad94f9399daf99ad8c3258b3cb2b47a0"}, + {file = "psutil-6.0.0-cp36-abi3-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ed2440ada7ef7d0d608f20ad89a04ec47d2d3ab7190896cd62ca5fc4fe08bf0"}, + {file = "psutil-6.0.0-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5fd9a97c8e94059b0ef54a7d4baf13b405011176c3b6ff257c247cae0d560ecd"}, + {file = "psutil-6.0.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e2e8d0054fc88153ca0544f5c4d554d42e33df2e009c4ff42284ac9ebdef4132"}, + {file = "psutil-6.0.0-cp36-cp36m-win32.whl", hash = "sha256:fc8c9510cde0146432bbdb433322861ee8c3efbf8589865c8bf8d21cb30c4d14"}, + {file = "psutil-6.0.0-cp36-cp36m-win_amd64.whl", hash = "sha256:34859b8d8f423b86e4385ff3665d3f4d94be3cdf48221fbe476e883514fdb71c"}, + {file = "psutil-6.0.0-cp37-abi3-win32.whl", hash = "sha256:a495580d6bae27291324fe60cea0b5a7c23fa36a7cd35035a16d93bdcf076b9d"}, + {file = "psutil-6.0.0-cp37-abi3-win_amd64.whl", hash = "sha256:33ea5e1c975250a720b3a6609c490db40dae5d83a4eb315170c4fe0d8b1f34b3"}, + {file = "psutil-6.0.0-cp38-abi3-macosx_11_0_arm64.whl", hash = "sha256:ffe7fc9b6b36beadc8c322f84e1caff51e8703b88eee1da46d1e3a6ae11b4fd0"}, + {file = "psutil-6.0.0.tar.gz", hash = "sha256:8faae4f310b6d969fa26ca0545338b21f73c6b15db7c4a8d934a5482faa818f2"}, ] -ptyprocess = [ - {file = "ptyprocess-0.6.0-py2.py3-none-any.whl", hash = "sha256:d7cc528d76e76342423ca640335bd3633420dc1366f258cb31d05e865ef5ca1f"}, - {file = "ptyprocess-0.6.0.tar.gz", hash = "sha256:923f299cc5ad920c68f2bc0bc98b75b9f838b93b599941a6b63ddbc2476394c0"}, + +[package.extras] +test = ["enum34", "ipaddress", "mock", "pywin32", "wmi"] + +[[package]] +name = "ptyprocess" +version = "0.7.0" +description = "Run a subprocess in a pseudo terminal" +optional = false +python-versions = "*" +files = [ + {file = "ptyprocess-0.7.0-py2.py3-none-any.whl", hash = "sha256:4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35"}, + {file = "ptyprocess-0.7.0.tar.gz", hash = "sha256:5c5d0a3b48ceee0b48485e0c26037c0acd7d29765ca3fbb5cb3831d347423220"}, ] -pycparser = [ - {file = "pycparser-2.20-py2.py3-none-any.whl", hash = "sha256:7582ad22678f0fcd81102833f60ef8d0e57288b6b5fb00323d101be910e35705"}, - {file = "pycparser-2.20.tar.gz", hash = "sha256:2d475327684562c3a96cc71adf7dc8c4f0565175cf86b6d7a404ff4c771f15f0"}, + +[[package]] +name = "pure-eval" +version = "0.2.2" +description = "Safely evaluate AST nodes without side effects" +optional = false +python-versions = "*" +files = [ + {file = "pure_eval-0.2.2-py3-none-any.whl", hash = "sha256:01eaab343580944bc56080ebe0a674b39ec44a945e6d09ba7db3cb8cec289350"}, + {file = "pure_eval-0.2.2.tar.gz", hash = "sha256:2b45320af6dfaa1750f543d714b6d1c520a1688dec6fd24d339063ce0aaa9ac3"}, ] -pygments = [ - {file = "Pygments-2.7.0-py3-none-any.whl", hash = "sha256:2df50d16b45b977217e02cba6c8422aaddb859f3d0570a88e09b00eafae89c6e"}, - {file = "Pygments-2.7.0.tar.gz", hash = "sha256:2594e8fdb06fef91552f86f4fd3a244d148ab24b66042036e64f29a291515048"}, + +[package.extras] +tests = ["pytest"] + +[[package]] +name = "pycparser" +version = "2.22" +description = "C parser in Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pycparser-2.22-py3-none-any.whl", hash = "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc"}, + {file = "pycparser-2.22.tar.gz", hash = "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6"}, ] -pyparsing = [ - {file = "pyparsing-2.4.7-py2.py3-none-any.whl", hash = "sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b"}, - {file = "pyparsing-2.4.7.tar.gz", hash = "sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1"}, + +[[package]] +name = "pygments" +version = "2.18.0" +description = "Pygments is a syntax highlighting package written in Python." +optional = false +python-versions = ">=3.8" +files = [ + {file = "pygments-2.18.0-py3-none-any.whl", hash = "sha256:b8e6aca0523f3ab76fee51799c488e38782ac06eafcf95e7ba832985c8e7b13a"}, + {file = "pygments-2.18.0.tar.gz", hash = "sha256:786ff802f32e91311bff3889f6e9a86e81505fe99f2735bb6d60ae0c5004f199"}, ] -pyrsistent = [ - {file = "pyrsistent-0.17.3.tar.gz", hash = "sha256:2e636185d9eb976a18a8a8e96efce62f2905fea90041958d8cc2a189756ebf3e"}, + +[package.extras] +windows-terminal = ["colorama (>=0.4.6)"] + +[[package]] +name = "pyparsing" +version = "3.1.2" +description = "pyparsing module - Classes and methods to define and execute parsing grammars" +optional = false +python-versions = ">=3.6.8" +files = [ + {file = "pyparsing-3.1.2-py3-none-any.whl", hash = "sha256:f9db75911801ed778fe61bb643079ff86601aca99fcae6345aa67292038fb742"}, + {file = "pyparsing-3.1.2.tar.gz", hash = "sha256:a1bac0ce561155ecc3ed78ca94d3c9378656ad4c94c1270de543f621420f94ad"}, ] -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"}, + +[package.extras] +diagrams = ["jinja2", "railroad-diagrams"] + +[[package]] +name = "python-dateutil" +version = "2.9.0.post0" +description = "Extensions to the standard Python datetime module" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" +files = [ + {file = "python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3"}, + {file = "python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427"}, ] -pytz = [ - {file = "pytz-2020.1-py2.py3-none-any.whl", hash = "sha256:a494d53b6d39c3c6e44c3bec237336e14305e4f29bbf800b599253057fbb79ed"}, - {file = "pytz-2020.1.tar.gz", hash = "sha256:c35965d010ce31b23eeb663ed3cc8c906275d6be1a34393a1d73a41febf4a048"}, + +[package.dependencies] +six = ">=1.5" + +[[package]] +name = "python-json-logger" +version = "2.0.7" +description = "A python library adding a json log formatter" +optional = false +python-versions = ">=3.6" +files = [ + {file = "python-json-logger-2.0.7.tar.gz", hash = "sha256:23e7ec02d34237c5aa1e29a070193a4ea87583bb4e7f8fd06d3de8264c4b2e1c"}, + {file = "python_json_logger-2.0.7-py3-none-any.whl", hash = "sha256:f380b826a991ebbe3de4d897aeec42760035ac760345e57b812938dc8b35e2bd"}, ] -pywin32 = [ - {file = "pywin32-228-cp27-cp27m-win32.whl", hash = "sha256:37dc9935f6a383cc744315ae0c2882ba1768d9b06700a70f35dc1ce73cd4ba9c"}, - {file = "pywin32-228-cp27-cp27m-win_amd64.whl", hash = "sha256:11cb6610efc2f078c9e6d8f5d0f957620c333f4b23466931a247fb945ed35e89"}, - {file = "pywin32-228-cp35-cp35m-win32.whl", hash = "sha256:1f45db18af5d36195447b2cffacd182fe2d296849ba0aecdab24d3852fbf3f80"}, - {file = "pywin32-228-cp35-cp35m-win_amd64.whl", hash = "sha256:6e38c44097a834a4707c1b63efa9c2435f5a42afabff634a17f563bc478dfcc8"}, - {file = "pywin32-228-cp36-cp36m-win32.whl", hash = "sha256:ec16d44b49b5f34e99eb97cf270806fdc560dff6f84d281eb2fcb89a014a56a9"}, - {file = "pywin32-228-cp36-cp36m-win_amd64.whl", hash = "sha256:a60d795c6590a5b6baeacd16c583d91cce8038f959bd80c53bd9a68f40130f2d"}, - {file = "pywin32-228-cp37-cp37m-win32.whl", hash = "sha256:af40887b6fc200eafe4d7742c48417529a8702dcc1a60bf89eee152d1d11209f"}, - {file = "pywin32-228-cp37-cp37m-win_amd64.whl", hash = "sha256:00eaf43dbd05ba6a9b0080c77e161e0b7a601f9a3f660727a952e40140537de7"}, - {file = "pywin32-228-cp38-cp38-win32.whl", hash = "sha256:fa6ba028909cfc64ce9e24bcf22f588b14871980d9787f1e2002c99af8f1850c"}, - {file = "pywin32-228-cp38-cp38-win_amd64.whl", hash = "sha256:9b3466083f8271e1a5eb0329f4e0d61925d46b40b195a33413e0905dccb285e8"}, - {file = "pywin32-228-cp39-cp39-win32.whl", hash = "sha256:ed74b72d8059a6606f64842e7917aeee99159ebd6b8d6261c518d002837be298"}, - {file = "pywin32-228-cp39-cp39-win_amd64.whl", hash = "sha256:8319bafdcd90b7202c50d6014efdfe4fde9311b3ff15fd6f893a45c0868de203"}, + +[[package]] +name = "pytz" +version = "2024.1" +description = "World timezone definitions, modern and historical" +optional = false +python-versions = "*" +files = [ + {file = "pytz-2024.1-py2.py3-none-any.whl", hash = "sha256:328171f4e3623139da4983451950b28e95ac706e13f3f2630a879749e7a8b319"}, + {file = "pytz-2024.1.tar.gz", hash = "sha256:2a29735ea9c18baf14b448846bde5a48030ed267578472d8955cd0e7443a9812"}, ] -pywinpty = [ - {file = "pywinpty-0.5.7-cp27-cp27m-win32.whl", hash = "sha256:b358cb552c0f6baf790de375fab96524a0498c9df83489b8c23f7f08795e966b"}, - {file = "pywinpty-0.5.7-cp27-cp27m-win_amd64.whl", hash = "sha256:1e525a4de05e72016a7af27836d512db67d06a015aeaf2fa0180f8e6a039b3c2"}, - {file = "pywinpty-0.5.7-cp35-cp35m-win32.whl", hash = "sha256:2740eeeb59297593a0d3f762269b01d0285c1b829d6827445fcd348fb47f7e70"}, - {file = "pywinpty-0.5.7-cp35-cp35m-win_amd64.whl", hash = "sha256:33df97f79843b2b8b8bc5c7aaf54adec08cc1bae94ee99dfb1a93c7a67704d95"}, - {file = "pywinpty-0.5.7-cp36-cp36m-win32.whl", hash = "sha256:e854211df55d107f0edfda8a80b39dfc87015bef52a8fe6594eb379240d81df2"}, - {file = "pywinpty-0.5.7-cp36-cp36m-win_amd64.whl", hash = "sha256:dbd838de92de1d4ebf0dce9d4d5e4fc38d0b7b1de837947a18b57a882f219139"}, - {file = "pywinpty-0.5.7-cp37-cp37m-win32.whl", hash = "sha256:5fb2c6c6819491b216f78acc2c521b9df21e0f53b9a399d58a5c151a3c4e2a2d"}, - {file = "pywinpty-0.5.7-cp37-cp37m-win_amd64.whl", hash = "sha256:dd22c8efacf600730abe4a46c1388355ce0d4ab75dc79b15d23a7bd87bf05b48"}, - {file = "pywinpty-0.5.7-cp38-cp38-win_amd64.whl", hash = "sha256:8fc5019ff3efb4f13708bd3b5ad327589c1a554cb516d792527361525a7cb78c"}, - {file = "pywinpty-0.5.7.tar.gz", hash = "sha256:2d7e9c881638a72ffdca3f5417dd1563b60f603e1b43e5895674c2a1b01f95a0"}, + +[[package]] +name = "pywin32" +version = "306" +description = "Python for Window Extensions" +optional = false +python-versions = "*" +files = [ + {file = "pywin32-306-cp310-cp310-win32.whl", hash = "sha256:06d3420a5155ba65f0b72f2699b5bacf3109f36acbe8923765c22938a69dfc8d"}, + {file = "pywin32-306-cp310-cp310-win_amd64.whl", hash = "sha256:84f4471dbca1887ea3803d8848a1616429ac94a4a8d05f4bc9c5dcfd42ca99c8"}, + {file = "pywin32-306-cp311-cp311-win32.whl", hash = "sha256:e65028133d15b64d2ed8f06dd9fbc268352478d4f9289e69c190ecd6818b6407"}, + {file = "pywin32-306-cp311-cp311-win_amd64.whl", hash = "sha256:a7639f51c184c0272e93f244eb24dafca9b1855707d94c192d4a0b4c01e1100e"}, + {file = "pywin32-306-cp311-cp311-win_arm64.whl", hash = "sha256:70dba0c913d19f942a2db25217d9a1b726c278f483a919f1abfed79c9cf64d3a"}, + {file = "pywin32-306-cp312-cp312-win32.whl", hash = "sha256:383229d515657f4e3ed1343da8be101000562bf514591ff383ae940cad65458b"}, + {file = "pywin32-306-cp312-cp312-win_amd64.whl", hash = "sha256:37257794c1ad39ee9be652da0462dc2e394c8159dfd913a8a4e8eb6fd346da0e"}, + {file = "pywin32-306-cp312-cp312-win_arm64.whl", hash = "sha256:5821ec52f6d321aa59e2db7e0a35b997de60c201943557d108af9d4ae1ec7040"}, + {file = "pywin32-306-cp37-cp37m-win32.whl", hash = "sha256:1c73ea9a0d2283d889001998059f5eaaba3b6238f767c9cf2833b13e6a685f65"}, + {file = "pywin32-306-cp37-cp37m-win_amd64.whl", hash = "sha256:72c5f621542d7bdd4fdb716227be0dd3f8565c11b280be6315b06ace35487d36"}, + {file = "pywin32-306-cp38-cp38-win32.whl", hash = "sha256:e4c092e2589b5cf0d365849e73e02c391c1349958c5ac3e9d5ccb9a28e017b3a"}, + {file = "pywin32-306-cp38-cp38-win_amd64.whl", hash = "sha256:e8ac1ae3601bee6ca9f7cb4b5363bf1c0badb935ef243c4733ff9a393b1690c0"}, + {file = "pywin32-306-cp39-cp39-win32.whl", hash = "sha256:e25fd5b485b55ac9c057f67d94bc203f3f6595078d1fb3b458c9c28b7153a802"}, + {file = "pywin32-306-cp39-cp39-win_amd64.whl", hash = "sha256:39b61c15272833b5c329a2989999dcae836b1eed650252ab1b7bfbe1d59f30f4"}, ] -pyzmq = [ - {file = "pyzmq-19.0.2-cp27-cp27m-macosx_10_9_intel.whl", hash = "sha256:59f1e54627483dcf61c663941d94c4af9bf4163aec334171686cdaee67974fe5"}, - {file = "pyzmq-19.0.2-cp27-cp27m-win32.whl", hash = "sha256:c36ffe1e5aa35a1af6a96640d723d0d211c5f48841735c2aa8d034204e87eb87"}, - {file = "pyzmq-19.0.2-cp27-cp27m-win_amd64.whl", hash = "sha256:0a422fc290d03958899743db091f8154958410fc76ce7ee0ceb66150f72c2c97"}, - {file = "pyzmq-19.0.2-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:c20dd60b9428f532bc59f2ef6d3b1029a28fc790d408af82f871a7db03e722ff"}, - {file = "pyzmq-19.0.2-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:d46fb17f5693244de83e434648b3dbb4f4b0fec88415d6cbab1c1452b6f2ae17"}, - {file = "pyzmq-19.0.2-cp35-cp35m-macosx_10_9_intel.whl", hash = "sha256:f1a25a61495b6f7bb986accc5b597a3541d9bd3ef0016f50be16dbb32025b302"}, - {file = "pyzmq-19.0.2-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:ab0d01148d13854de716786ca73701012e07dff4dfbbd68c4e06d8888743526e"}, - {file = "pyzmq-19.0.2-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:720d2b6083498a9281eaee3f2927486e9fe02cd16d13a844f2e95217f243efea"}, - {file = "pyzmq-19.0.2-cp35-cp35m-win32.whl", hash = "sha256:29d51279060d0a70f551663bc592418bcad7f4be4eea7b324f6dd81de05cb4c1"}, - {file = "pyzmq-19.0.2-cp35-cp35m-win_amd64.whl", hash = "sha256:5120c64646e75f6db20cc16b9a94203926ead5d633de9feba4f137004241221d"}, - {file = "pyzmq-19.0.2-cp36-cp36m-macosx_10_9_intel.whl", hash = "sha256:8a6ada5a3f719bf46a04ba38595073df8d6b067316c011180102ba2a1925f5b5"}, - {file = "pyzmq-19.0.2-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:fa411b1d8f371d3a49d31b0789eb6da2537dadbb2aef74a43aa99a78195c3f76"}, - {file = "pyzmq-19.0.2-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:00dca814469436455399660247d74045172955459c0bd49b54a540ce4d652185"}, - {file = "pyzmq-19.0.2-cp36-cp36m-win32.whl", hash = "sha256:046b92e860914e39612e84fa760fc3f16054d268c11e0e25dcb011fb1bc6a075"}, - {file = "pyzmq-19.0.2-cp36-cp36m-win_amd64.whl", hash = "sha256:99cc0e339a731c6a34109e5c4072aaa06d8e32c0b93dc2c2d90345dd45fa196c"}, - {file = "pyzmq-19.0.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:e36f12f503511d72d9bdfae11cadbadca22ff632ff67c1b5459f69756a029c19"}, - {file = "pyzmq-19.0.2-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:c40fbb2b9933369e994b837ee72193d6a4c35dfb9a7c573257ef7ff28961272c"}, - {file = "pyzmq-19.0.2-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:5d9fc809aa8d636e757e4ced2302569d6e60e9b9c26114a83f0d9d6519c40493"}, - {file = "pyzmq-19.0.2-cp37-cp37m-win32.whl", hash = "sha256:3fa6debf4bf9412e59353defad1f8035a1e68b66095a94ead8f7a61ae90b2675"}, - {file = "pyzmq-19.0.2-cp37-cp37m-win_amd64.whl", hash = "sha256:73483a2caaa0264ac717af33d6fb3f143d8379e60a422730ee8d010526ce1913"}, - {file = "pyzmq-19.0.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:36ab114021c0cab1a423fe6689355e8f813979f2c750968833b318c1fa10a0fd"}, - {file = "pyzmq-19.0.2-cp38-cp38-manylinux1_i686.whl", hash = "sha256:8b66b94fe6243d2d1d89bca336b2424399aac57932858b9a30309803ffc28112"}, - {file = "pyzmq-19.0.2-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:654d3e06a4edc566b416c10293064732516cf8871a4522e0a2ba00cc2a2e600c"}, - {file = "pyzmq-19.0.2-cp38-cp38-win32.whl", hash = "sha256:276ad604bffd70992a386a84bea34883e696a6b22e7378053e5d3227321d9702"}, - {file = "pyzmq-19.0.2-cp38-cp38-win_amd64.whl", hash = "sha256:09d24a80ccb8cbda1af6ed8eb26b005b6743e58e9290566d2a6841f4e31fa8e0"}, - {file = "pyzmq-19.0.2-pp27-pypy_73-macosx_10_9_x86_64.whl", hash = "sha256:c1a31cd42905b405530e92bdb70a8a56f048c8a371728b8acf9d746ecd4482c0"}, - {file = "pyzmq-19.0.2-pp36-pypy36_pp73-macosx_10_9_x86_64.whl", hash = "sha256:a7e7f930039ee0c4c26e4dfee015f20bd6919cd8b97c9cd7afbde2923a5167b6"}, - {file = "pyzmq-19.0.2.tar.gz", hash = "sha256:296540a065c8c21b26d63e3cea2d1d57902373b16e4256afe46422691903a438"}, + +[[package]] +name = "pywinpty" +version = "2.0.13" +description = "Pseudo terminal support for Windows from Python." +optional = false +python-versions = ">=3.8" +files = [ + {file = "pywinpty-2.0.13-cp310-none-win_amd64.whl", hash = "sha256:697bff211fb5a6508fee2dc6ff174ce03f34a9a233df9d8b5fe9c8ce4d5eaf56"}, + {file = "pywinpty-2.0.13-cp311-none-win_amd64.whl", hash = "sha256:b96fb14698db1284db84ca38c79f15b4cfdc3172065b5137383910567591fa99"}, + {file = "pywinpty-2.0.13-cp312-none-win_amd64.whl", hash = "sha256:2fd876b82ca750bb1333236ce98488c1be96b08f4f7647cfdf4129dfad83c2d4"}, + {file = "pywinpty-2.0.13-cp38-none-win_amd64.whl", hash = "sha256:61d420c2116c0212808d31625611b51caf621fe67f8a6377e2e8b617ea1c1f7d"}, + {file = "pywinpty-2.0.13-cp39-none-win_amd64.whl", hash = "sha256:71cb613a9ee24174730ac7ae439fd179ca34ccb8c5349e8d7b72ab5dea2c6f4b"}, + {file = "pywinpty-2.0.13.tar.gz", hash = "sha256:c34e32351a3313ddd0d7da23d27f835c860d32fe4ac814d372a3ea9594f41dde"}, ] -requests = [ - {file = "requests-2.24.0-py2.py3-none-any.whl", hash = "sha256:fe75cc94a9443b9246fc7049224f75604b113c36acb93f87b80ed42c44cbb898"}, - {file = "requests-2.24.0.tar.gz", hash = "sha256:b3559a131db72c33ee969480840fff4bb6dd111de7dd27c8ee1f820f4f00231b"}, + +[[package]] +name = "pyyaml" +version = "6.0.1" +description = "YAML parser and emitter for Python" +optional = false +python-versions = ">=3.6" +files = [ + {file = "PyYAML-6.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a"}, + {file = "PyYAML-6.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f"}, + {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"}, + {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"}, + {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"}, + {file = "PyYAML-6.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290"}, + {file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"}, + {file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"}, + {file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"}, + {file = "PyYAML-6.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab"}, + {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"}, + {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"}, + {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"}, + {file = "PyYAML-6.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b"}, + {file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"}, + {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, + {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, + {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, + {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"}, + {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, + {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, + {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, + {file = "PyYAML-6.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df"}, + {file = "PyYAML-6.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47"}, + {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98"}, + {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c"}, + {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd"}, + {file = "PyYAML-6.0.1-cp36-cp36m-win32.whl", hash = "sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585"}, + {file = "PyYAML-6.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa"}, + {file = "PyYAML-6.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3"}, + {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27"}, + {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3"}, + {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:baa90d3f661d43131ca170712d903e6295d1f7a0f595074f151c0aed377c9b9c"}, + {file = "PyYAML-6.0.1-cp37-cp37m-win32.whl", hash = "sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba"}, + {file = "PyYAML-6.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867"}, + {file = "PyYAML-6.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595"}, + {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5"}, + {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696"}, + {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735"}, + {file = "PyYAML-6.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6"}, + {file = "PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"}, + {file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"}, + {file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"}, + {file = "PyYAML-6.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859"}, + {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"}, + {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"}, + {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"}, + {file = "PyYAML-6.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5"}, + {file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"}, + {file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"}, + {file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"}, ] -scikit-learn = [ - {file = "scikit-learn-0.23.2.tar.gz", hash = "sha256:20766f515e6cd6f954554387dfae705d93c7b544ec0e6c6a5d8e006f6f7ef480"}, - {file = "scikit_learn-0.23.2-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:98508723f44c61896a4e15894b2016762a55555fbf09365a0bb1870ecbd442de"}, - {file = "scikit_learn-0.23.2-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:a64817b050efd50f9abcfd311870073e500ae11b299683a519fbb52d85e08d25"}, - {file = "scikit_learn-0.23.2-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:daf276c465c38ef736a79bd79fc80a249f746bcbcae50c40945428f7ece074f8"}, - {file = "scikit_learn-0.23.2-cp36-cp36m-win32.whl", hash = "sha256:cb3e76380312e1f86abd20340ab1d5b3cc46a26f6593d3c33c9ea3e4c7134028"}, - {file = "scikit_learn-0.23.2-cp36-cp36m-win_amd64.whl", hash = "sha256:0a127cc70990d4c15b1019680bfedc7fec6c23d14d3719fdf9b64b22d37cdeca"}, - {file = "scikit_learn-0.23.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:2aa95c2f17d2f80534156215c87bee72b6aa314a7f8b8fe92a2d71f47280570d"}, - {file = "scikit_learn-0.23.2-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:6c28a1d00aae7c3c9568f61aafeaad813f0f01c729bee4fd9479e2132b215c1d"}, - {file = "scikit_learn-0.23.2-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:da8e7c302003dd765d92a5616678e591f347460ac7b53e53d667be7dfe6d1b10"}, - {file = "scikit_learn-0.23.2-cp37-cp37m-win32.whl", hash = "sha256:d9a1ce5f099f29c7c33181cc4386660e0ba891b21a60dc036bf369e3a3ee3aec"}, - {file = "scikit_learn-0.23.2-cp37-cp37m-win_amd64.whl", hash = "sha256:914ac2b45a058d3f1338d7736200f7f3b094857758895f8667be8a81ff443b5b"}, - {file = "scikit_learn-0.23.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:7671bbeddd7f4f9a6968f3b5442dac5f22bf1ba06709ef888cc9132ad354a9ab"}, - {file = "scikit_learn-0.23.2-cp38-cp38-manylinux1_i686.whl", hash = "sha256:d0dcaa54263307075cb93d0bee3ceb02821093b1b3d25f66021987d305d01dce"}, - {file = "scikit_learn-0.23.2-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:5ce7a8021c9defc2b75620571b350acc4a7d9763c25b7593621ef50f3bd019a2"}, - {file = "scikit_learn-0.23.2-cp38-cp38-win32.whl", hash = "sha256:0d39748e7c9669ba648acf40fb3ce96b8a07b240db6888563a7cb76e05e0d9cc"}, - {file = "scikit_learn-0.23.2-cp38-cp38-win_amd64.whl", hash = "sha256:1b8a391de95f6285a2f9adffb7db0892718950954b7149a70c783dc848f104ea"}, + +[[package]] +name = "pyzmq" +version = "26.0.3" +description = "Python bindings for 0MQ" +optional = false +python-versions = ">=3.7" +files = [ + {file = "pyzmq-26.0.3-cp310-cp310-macosx_10_15_universal2.whl", hash = "sha256:44dd6fc3034f1eaa72ece33588867df9e006a7303725a12d64c3dff92330f625"}, + {file = "pyzmq-26.0.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:acb704195a71ac5ea5ecf2811c9ee19ecdc62b91878528302dd0be1b9451cc90"}, + {file = "pyzmq-26.0.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5dbb9c997932473a27afa93954bb77a9f9b786b4ccf718d903f35da3232317de"}, + {file = "pyzmq-26.0.3-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6bcb34f869d431799c3ee7d516554797f7760cb2198ecaa89c3f176f72d062be"}, + {file = "pyzmq-26.0.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:38ece17ec5f20d7d9b442e5174ae9f020365d01ba7c112205a4d59cf19dc38ee"}, + {file = "pyzmq-26.0.3-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:ba6e5e6588e49139a0979d03a7deb9c734bde647b9a8808f26acf9c547cab1bf"}, + {file = "pyzmq-26.0.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:3bf8b000a4e2967e6dfdd8656cd0757d18c7e5ce3d16339e550bd462f4857e59"}, + {file = "pyzmq-26.0.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:2136f64fbb86451dbbf70223635a468272dd20075f988a102bf8a3f194a411dc"}, + {file = "pyzmq-26.0.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:e8918973fbd34e7814f59143c5f600ecd38b8038161239fd1a3d33d5817a38b8"}, + {file = "pyzmq-26.0.3-cp310-cp310-win32.whl", hash = "sha256:0aaf982e68a7ac284377d051c742610220fd06d330dcd4c4dbb4cdd77c22a537"}, + {file = "pyzmq-26.0.3-cp310-cp310-win_amd64.whl", hash = "sha256:f1a9b7d00fdf60b4039f4455afd031fe85ee8305b019334b72dcf73c567edc47"}, + {file = "pyzmq-26.0.3-cp310-cp310-win_arm64.whl", hash = "sha256:80b12f25d805a919d53efc0a5ad7c0c0326f13b4eae981a5d7b7cc343318ebb7"}, + {file = "pyzmq-26.0.3-cp311-cp311-macosx_10_15_universal2.whl", hash = "sha256:a72a84570f84c374b4c287183debc776dc319d3e8ce6b6a0041ce2e400de3f32"}, + {file = "pyzmq-26.0.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:7ca684ee649b55fd8f378127ac8462fb6c85f251c2fb027eb3c887e8ee347bcd"}, + {file = "pyzmq-26.0.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e222562dc0f38571c8b1ffdae9d7adb866363134299264a1958d077800b193b7"}, + {file = "pyzmq-26.0.3-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f17cde1db0754c35a91ac00b22b25c11da6eec5746431d6e5092f0cd31a3fea9"}, + {file = "pyzmq-26.0.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4b7c0c0b3244bb2275abe255d4a30c050d541c6cb18b870975553f1fb6f37527"}, + {file = "pyzmq-26.0.3-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:ac97a21de3712afe6a6c071abfad40a6224fd14fa6ff0ff8d0c6e6cd4e2f807a"}, + {file = "pyzmq-26.0.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:88b88282e55fa39dd556d7fc04160bcf39dea015f78e0cecec8ff4f06c1fc2b5"}, + {file = "pyzmq-26.0.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:72b67f966b57dbd18dcc7efbc1c7fc9f5f983e572db1877081f075004614fcdd"}, + {file = "pyzmq-26.0.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:f4b6cecbbf3b7380f3b61de3a7b93cb721125dc125c854c14ddc91225ba52f83"}, + {file = "pyzmq-26.0.3-cp311-cp311-win32.whl", hash = "sha256:eed56b6a39216d31ff8cd2f1d048b5bf1700e4b32a01b14379c3b6dde9ce3aa3"}, + {file = "pyzmq-26.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:3191d312c73e3cfd0f0afdf51df8405aafeb0bad71e7ed8f68b24b63c4f36500"}, + {file = "pyzmq-26.0.3-cp311-cp311-win_arm64.whl", hash = "sha256:b6907da3017ef55139cf0e417c5123a84c7332520e73a6902ff1f79046cd3b94"}, + {file = "pyzmq-26.0.3-cp312-cp312-macosx_10_15_universal2.whl", hash = "sha256:068ca17214038ae986d68f4a7021f97e187ed278ab6dccb79f837d765a54d753"}, + {file = "pyzmq-26.0.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:7821d44fe07335bea256b9f1f41474a642ca55fa671dfd9f00af8d68a920c2d4"}, + {file = "pyzmq-26.0.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eeb438a26d87c123bb318e5f2b3d86a36060b01f22fbdffd8cf247d52f7c9a2b"}, + {file = "pyzmq-26.0.3-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:69ea9d6d9baa25a4dc9cef5e2b77b8537827b122214f210dd925132e34ae9b12"}, + {file = "pyzmq-26.0.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7daa3e1369355766dea11f1d8ef829905c3b9da886ea3152788dc25ee6079e02"}, + {file = "pyzmq-26.0.3-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:6ca7a9a06b52d0e38ccf6bca1aeff7be178917893f3883f37b75589d42c4ac20"}, + {file = "pyzmq-26.0.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:1b7d0e124948daa4d9686d421ef5087c0516bc6179fdcf8828b8444f8e461a77"}, + {file = "pyzmq-26.0.3-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:e746524418b70f38550f2190eeee834db8850088c834d4c8406fbb9bc1ae10b2"}, + {file = "pyzmq-26.0.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:6b3146f9ae6af82c47a5282ac8803523d381b3b21caeae0327ed2f7ecb718798"}, + {file = "pyzmq-26.0.3-cp312-cp312-win32.whl", hash = "sha256:2b291d1230845871c00c8462c50565a9cd6026fe1228e77ca934470bb7d70ea0"}, + {file = "pyzmq-26.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:926838a535c2c1ea21c903f909a9a54e675c2126728c21381a94ddf37c3cbddf"}, + {file = "pyzmq-26.0.3-cp312-cp312-win_arm64.whl", hash = "sha256:5bf6c237f8c681dfb91b17f8435b2735951f0d1fad10cc5dfd96db110243370b"}, + {file = "pyzmq-26.0.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0c0991f5a96a8e620f7691e61178cd8f457b49e17b7d9cfa2067e2a0a89fc1d5"}, + {file = "pyzmq-26.0.3-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:dbf012d8fcb9f2cf0643b65df3b355fdd74fc0035d70bb5c845e9e30a3a4654b"}, + {file = "pyzmq-26.0.3-cp37-cp37m-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:01fbfbeb8249a68d257f601deb50c70c929dc2dfe683b754659569e502fbd3aa"}, + {file = "pyzmq-26.0.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1c8eb19abe87029c18f226d42b8a2c9efdd139d08f8bf6e085dd9075446db450"}, + {file = "pyzmq-26.0.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:5344b896e79800af86ad643408ca9aa303a017f6ebff8cee5a3163c1e9aec987"}, + {file = "pyzmq-26.0.3-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:204e0f176fd1d067671157d049466869b3ae1fc51e354708b0dc41cf94e23a3a"}, + {file = "pyzmq-26.0.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:a42db008d58530efa3b881eeee4991146de0b790e095f7ae43ba5cc612decbc5"}, + {file = "pyzmq-26.0.3-cp37-cp37m-win32.whl", hash = "sha256:8d7a498671ca87e32b54cb47c82a92b40130a26c5197d392720a1bce1b3c77cf"}, + {file = "pyzmq-26.0.3-cp37-cp37m-win_amd64.whl", hash = "sha256:3b4032a96410bdc760061b14ed6a33613ffb7f702181ba999df5d16fb96ba16a"}, + {file = "pyzmq-26.0.3-cp38-cp38-macosx_10_15_universal2.whl", hash = "sha256:2cc4e280098c1b192c42a849de8de2c8e0f3a84086a76ec5b07bfee29bda7d18"}, + {file = "pyzmq-26.0.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:5bde86a2ed3ce587fa2b207424ce15b9a83a9fa14422dcc1c5356a13aed3df9d"}, + {file = "pyzmq-26.0.3-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:34106f68e20e6ff253c9f596ea50397dbd8699828d55e8fa18bd4323d8d966e6"}, + {file = "pyzmq-26.0.3-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:ebbbd0e728af5db9b04e56389e2299a57ea8b9dd15c9759153ee2455b32be6ad"}, + {file = "pyzmq-26.0.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f6b1d1c631e5940cac5a0b22c5379c86e8df6a4ec277c7a856b714021ab6cfad"}, + {file = "pyzmq-26.0.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:e891ce81edd463b3b4c3b885c5603c00141151dd9c6936d98a680c8c72fe5c67"}, + {file = "pyzmq-26.0.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:9b273ecfbc590a1b98f014ae41e5cf723932f3b53ba9367cfb676f838038b32c"}, + {file = "pyzmq-26.0.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:b32bff85fb02a75ea0b68f21e2412255b5731f3f389ed9aecc13a6752f58ac97"}, + {file = "pyzmq-26.0.3-cp38-cp38-win32.whl", hash = "sha256:f6c21c00478a7bea93caaaef9e7629145d4153b15a8653e8bb4609d4bc70dbfc"}, + {file = "pyzmq-26.0.3-cp38-cp38-win_amd64.whl", hash = "sha256:3401613148d93ef0fd9aabdbddb212de3db7a4475367f49f590c837355343972"}, + {file = "pyzmq-26.0.3-cp39-cp39-macosx_10_15_universal2.whl", hash = "sha256:2ed8357f4c6e0daa4f3baf31832df8a33334e0fe5b020a61bc8b345a3db7a606"}, + {file = "pyzmq-26.0.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c1c8f2a2ca45292084c75bb6d3a25545cff0ed931ed228d3a1810ae3758f975f"}, + {file = "pyzmq-26.0.3-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:b63731993cdddcc8e087c64e9cf003f909262b359110070183d7f3025d1c56b5"}, + {file = "pyzmq-26.0.3-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:b3cd31f859b662ac5d7f4226ec7d8bd60384fa037fc02aee6ff0b53ba29a3ba8"}, + {file = "pyzmq-26.0.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:115f8359402fa527cf47708d6f8a0f8234f0e9ca0cab7c18c9c189c194dbf620"}, + {file = "pyzmq-26.0.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:715bdf952b9533ba13dfcf1f431a8f49e63cecc31d91d007bc1deb914f47d0e4"}, + {file = "pyzmq-26.0.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:e1258c639e00bf5e8a522fec6c3eaa3e30cf1c23a2f21a586be7e04d50c9acab"}, + {file = "pyzmq-26.0.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:15c59e780be8f30a60816a9adab900c12a58d79c1ac742b4a8df044ab2a6d920"}, + {file = "pyzmq-26.0.3-cp39-cp39-win32.whl", hash = "sha256:d0cdde3c78d8ab5b46595054e5def32a755fc028685add5ddc7403e9f6de9879"}, + {file = "pyzmq-26.0.3-cp39-cp39-win_amd64.whl", hash = "sha256:ce828058d482ef860746bf532822842e0ff484e27f540ef5c813d516dd8896d2"}, + {file = "pyzmq-26.0.3-cp39-cp39-win_arm64.whl", hash = "sha256:788f15721c64109cf720791714dc14afd0f449d63f3a5487724f024345067381"}, + {file = "pyzmq-26.0.3-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:2c18645ef6294d99b256806e34653e86236eb266278c8ec8112622b61db255de"}, + {file = "pyzmq-26.0.3-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7e6bc96ebe49604df3ec2c6389cc3876cabe475e6bfc84ced1bf4e630662cb35"}, + {file = "pyzmq-26.0.3-pp310-pypy310_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:971e8990c5cc4ddcff26e149398fc7b0f6a042306e82500f5e8db3b10ce69f84"}, + {file = "pyzmq-26.0.3-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d8416c23161abd94cc7da80c734ad7c9f5dbebdadfdaa77dad78244457448223"}, + {file = "pyzmq-26.0.3-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:082a2988364b60bb5de809373098361cf1dbb239623e39e46cb18bc035ed9c0c"}, + {file = "pyzmq-26.0.3-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:d57dfbf9737763b3a60d26e6800e02e04284926329aee8fb01049635e957fe81"}, + {file = "pyzmq-26.0.3-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:77a85dca4c2430ac04dc2a2185c2deb3858a34fe7f403d0a946fa56970cf60a1"}, + {file = "pyzmq-26.0.3-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:4c82a6d952a1d555bf4be42b6532927d2a5686dd3c3e280e5f63225ab47ac1f5"}, + {file = "pyzmq-26.0.3-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4496b1282c70c442809fc1b151977c3d967bfb33e4e17cedbf226d97de18f709"}, + {file = "pyzmq-26.0.3-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:e4946d6bdb7ba972dfda282f9127e5756d4f299028b1566d1245fa0d438847e6"}, + {file = "pyzmq-26.0.3-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:03c0ae165e700364b266876d712acb1ac02693acd920afa67da2ebb91a0b3c09"}, + {file = "pyzmq-26.0.3-pp38-pypy38_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:3e3070e680f79887d60feeda051a58d0ac36622e1759f305a41059eff62c6da7"}, + {file = "pyzmq-26.0.3-pp38-pypy38_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:6ca08b840fe95d1c2bd9ab92dac5685f949fc6f9ae820ec16193e5ddf603c3b2"}, + {file = "pyzmq-26.0.3-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e76654e9dbfb835b3518f9938e565c7806976c07b37c33526b574cc1a1050480"}, + {file = "pyzmq-26.0.3-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:871587bdadd1075b112e697173e946a07d722459d20716ceb3d1bd6c64bd08ce"}, + {file = "pyzmq-26.0.3-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:d0a2d1bd63a4ad79483049b26514e70fa618ce6115220da9efdff63688808b17"}, + {file = "pyzmq-26.0.3-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0270b49b6847f0d106d64b5086e9ad5dc8a902413b5dbbb15d12b60f9c1747a4"}, + {file = "pyzmq-26.0.3-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:703c60b9910488d3d0954ca585c34f541e506a091a41930e663a098d3b794c67"}, + {file = "pyzmq-26.0.3-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:74423631b6be371edfbf7eabb02ab995c2563fee60a80a30829176842e71722a"}, + {file = "pyzmq-26.0.3-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:4adfbb5451196842a88fda3612e2c0414134874bffb1c2ce83ab4242ec9e027d"}, + {file = "pyzmq-26.0.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:3516119f4f9b8671083a70b6afaa0a070f5683e431ab3dc26e9215620d7ca1ad"}, + {file = "pyzmq-26.0.3.tar.gz", hash = "sha256:dba7d9f2e047dfa2bca3b01f4f84aa5246725203d6284e3790f2ca15fba6b40a"}, ] -scipy = [ - {file = "scipy-1.5.2-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:cca9fce15109a36a0a9f9cfc64f870f1c140cb235ddf27fe0328e6afb44dfed0"}, - {file = "scipy-1.5.2-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:1c7564a4810c1cd77fcdee7fa726d7d39d4e2695ad252d7c86c3ea9d85b7fb8f"}, - {file = "scipy-1.5.2-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:07e52b316b40a4f001667d1ad4eb5f2318738de34597bd91537851365b6c61f1"}, - {file = "scipy-1.5.2-cp36-cp36m-win32.whl", hash = "sha256:d56b10d8ed72ec1be76bf10508446df60954f08a41c2d40778bc29a3a9ad9bce"}, - {file = "scipy-1.5.2-cp36-cp36m-win_amd64.whl", hash = "sha256:8e28e74b97fc8d6aa0454989db3b5d36fc27e69cef39a7ee5eaf8174ca1123cb"}, - {file = "scipy-1.5.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:6e86c873fe1335d88b7a4bfa09d021f27a9e753758fd75f3f92d714aa4093768"}, - {file = "scipy-1.5.2-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:a0afbb967fd2c98efad5f4c24439a640d39463282040a88e8e928db647d8ac3d"}, - {file = "scipy-1.5.2-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:eecf40fa87eeda53e8e11d265ff2254729d04000cd40bae648e76ff268885d66"}, - {file = "scipy-1.5.2-cp37-cp37m-win32.whl", hash = "sha256:315aa2165aca31375f4e26c230188db192ed901761390be908c9b21d8b07df62"}, - {file = "scipy-1.5.2-cp37-cp37m-win_amd64.whl", hash = "sha256:ec5fe57e46828d034775b00cd625c4a7b5c7d2e354c3b258d820c6c72212a6ec"}, - {file = "scipy-1.5.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:fc98f3eac993b9bfdd392e675dfe19850cc8c7246a8fd2b42443e506344be7d9"}, - {file = "scipy-1.5.2-cp38-cp38-manylinux1_i686.whl", hash = "sha256:a785409c0fa51764766840185a34f96a0a93527a0ff0230484d33a8ed085c8f8"}, - {file = "scipy-1.5.2-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:0a0e9a4e58a4734c2eba917f834b25b7e3b6dc333901ce7784fd31aefbd37b2f"}, - {file = "scipy-1.5.2-cp38-cp38-win32.whl", hash = "sha256:dac09281a0eacd59974e24525a3bc90fa39b4e95177e638a31b14db60d3fa806"}, - {file = "scipy-1.5.2-cp38-cp38-win_amd64.whl", hash = "sha256:92eb04041d371fea828858e4fff182453c25ae3eaa8782d9b6c32b25857d23bc"}, - {file = "scipy-1.5.2.tar.gz", hash = "sha256:066c513d90eb3fd7567a9e150828d39111ebd88d3e924cdfc9f8ce19ab6f90c9"}, + +[package.dependencies] +cffi = {version = "*", markers = "implementation_name == \"pypy\""} + +[[package]] +name = "referencing" +version = "0.35.1" +description = "JSON Referencing + Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "referencing-0.35.1-py3-none-any.whl", hash = "sha256:eda6d3234d62814d1c64e305c1331c9a3a6132da475ab6382eaa997b21ee75de"}, + {file = "referencing-0.35.1.tar.gz", hash = "sha256:25b42124a6c8b632a425174f24087783efb348a6f1e0008e63cd4466fedf703c"}, ] -send2trash = [ - {file = "Send2Trash-1.5.0-py3-none-any.whl", hash = "sha256:f1691922577b6fa12821234aeb57599d887c4900b9ca537948d2dac34aea888b"}, - {file = "Send2Trash-1.5.0.tar.gz", hash = "sha256:60001cc07d707fe247c94f74ca6ac0d3255aabcb930529690897ca2a39db28b2"}, + +[package.dependencies] +attrs = ">=22.2.0" +rpds-py = ">=0.7.0" + +[[package]] +name = "requests" +version = "2.32.3" +description = "Python HTTP for Humans." +optional = false +python-versions = ">=3.8" +files = [ + {file = "requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6"}, + {file = "requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760"}, ] -six = [ - {file = "six-1.15.0-py2.py3-none-any.whl", hash = "sha256:8b74bedcbbbaca38ff6d7491d76f2b06b3592611af620f8426e82dddb04a5ced"}, - {file = "six-1.15.0.tar.gz", hash = "sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259"}, + +[package.dependencies] +certifi = ">=2017.4.17" +charset-normalizer = ">=2,<4" +idna = ">=2.5,<4" +urllib3 = ">=1.21.1,<3" + +[package.extras] +socks = ["PySocks (>=1.5.6,!=1.5.7)"] +use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] + +[[package]] +name = "rfc3339-validator" +version = "0.1.4" +description = "A pure python RFC3339 validator" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +files = [ + {file = "rfc3339_validator-0.1.4-py2.py3-none-any.whl", hash = "sha256:24f6ec1eda14ef823da9e36ec7113124b39c04d50a4d3d3a3c2859577e7791fa"}, + {file = "rfc3339_validator-0.1.4.tar.gz", hash = "sha256:138a2abdf93304ad60530167e51d2dfb9549521a836871b88d7f4695d0022f6b"}, ] -terminado = [ - {file = "terminado-0.8.3-py2.py3-none-any.whl", hash = "sha256:a43dcb3e353bc680dd0783b1d9c3fc28d529f190bc54ba9a229f72fe6e7a54d7"}, - {file = "terminado-0.8.3.tar.gz", hash = "sha256:4804a774f802306a7d9af7322193c5390f1da0abb429e082a10ef1d46e6fb2c2"}, + +[package.dependencies] +six = "*" + +[[package]] +name = "rfc3986-validator" +version = "0.1.1" +description = "Pure python rfc3986 validator" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +files = [ + {file = "rfc3986_validator-0.1.1-py2.py3-none-any.whl", hash = "sha256:2f235c432ef459970b4306369336b9d5dbdda31b510ca1e327636e01f528bfa9"}, + {file = "rfc3986_validator-0.1.1.tar.gz", hash = "sha256:3d44bde7921b3b9ec3ae4e3adca370438eccebc676456449b145d533b240d055"}, ] -testpath = [ - {file = "testpath-0.4.4-py2.py3-none-any.whl", hash = "sha256:bfcf9411ef4bf3db7579063e0546938b1edda3d69f4e1fb8756991f5951f85d4"}, - {file = "testpath-0.4.4.tar.gz", hash = "sha256:60e0a3261c149755f4399a1fff7d37523179a70fdc3abdf78de9fc2604aeec7e"}, + +[[package]] +name = "rpds-py" +version = "0.19.0" +description = "Python bindings to Rust's persistent data structures (rpds)" +optional = false +python-versions = ">=3.8" +files = [ + {file = "rpds_py-0.19.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:fb37bd599f031f1a6fb9e58ec62864ccf3ad549cf14bac527dbfa97123edcca4"}, + {file = "rpds_py-0.19.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:3384d278df99ec2c6acf701d067147320b864ef6727405d6470838476e44d9e8"}, + {file = "rpds_py-0.19.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e54548e0be3ac117595408fd4ca0ac9278fde89829b0b518be92863b17ff67a2"}, + {file = "rpds_py-0.19.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8eb488ef928cdbc05a27245e52de73c0d7c72a34240ef4d9893fdf65a8c1a955"}, + {file = "rpds_py-0.19.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a5da93debdfe27b2bfc69eefb592e1831d957b9535e0943a0ee8b97996de21b5"}, + {file = "rpds_py-0.19.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:79e205c70afddd41f6ee79a8656aec738492a550247a7af697d5bd1aee14f766"}, + {file = "rpds_py-0.19.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:959179efb3e4a27610e8d54d667c02a9feaa86bbabaf63efa7faa4dfa780d4f1"}, + {file = "rpds_py-0.19.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a6e605bb9edcf010f54f8b6a590dd23a4b40a8cb141255eec2a03db249bc915b"}, + {file = "rpds_py-0.19.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:9133d75dc119a61d1a0ded38fb9ba40a00ef41697cc07adb6ae098c875195a3f"}, + {file = "rpds_py-0.19.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:dd36b712d35e757e28bf2f40a71e8f8a2d43c8b026d881aa0c617b450d6865c9"}, + {file = "rpds_py-0.19.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:354f3a91718489912f2e0fc331c24eaaf6a4565c080e00fbedb6015857c00582"}, + {file = "rpds_py-0.19.0-cp310-none-win32.whl", hash = "sha256:ebcbf356bf5c51afc3290e491d3722b26aaf5b6af3c1c7f6a1b757828a46e336"}, + {file = "rpds_py-0.19.0-cp310-none-win_amd64.whl", hash = "sha256:75a6076289b2df6c8ecb9d13ff79ae0cad1d5fb40af377a5021016d58cd691ec"}, + {file = "rpds_py-0.19.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:6d45080095e585f8c5097897313def60caa2046da202cdb17a01f147fb263b81"}, + {file = "rpds_py-0.19.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c5c9581019c96f865483d031691a5ff1cc455feb4d84fc6920a5ffc48a794d8a"}, + {file = "rpds_py-0.19.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1540d807364c84516417115c38f0119dfec5ea5c0dd9a25332dea60b1d26fc4d"}, + {file = "rpds_py-0.19.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9e65489222b410f79711dc3d2d5003d2757e30874096b2008d50329ea4d0f88c"}, + {file = "rpds_py-0.19.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9da6f400eeb8c36f72ef6646ea530d6d175a4f77ff2ed8dfd6352842274c1d8b"}, + {file = "rpds_py-0.19.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:37f46bb11858717e0efa7893c0f7055c43b44c103e40e69442db5061cb26ed34"}, + {file = "rpds_py-0.19.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:071d4adc734de562bd11d43bd134330fb6249769b2f66b9310dab7460f4bf714"}, + {file = "rpds_py-0.19.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9625367c8955e4319049113ea4f8fee0c6c1145192d57946c6ffcd8fe8bf48dd"}, + {file = "rpds_py-0.19.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:e19509145275d46bc4d1e16af0b57a12d227c8253655a46bbd5ec317e941279d"}, + {file = "rpds_py-0.19.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:4d438e4c020d8c39961deaf58f6913b1bf8832d9b6f62ec35bd93e97807e9cbc"}, + {file = "rpds_py-0.19.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:90bf55d9d139e5d127193170f38c584ed3c79e16638890d2e36f23aa1630b952"}, + {file = "rpds_py-0.19.0-cp311-none-win32.whl", hash = "sha256:8d6ad132b1bc13d05ffe5b85e7a01a3998bf3a6302ba594b28d61b8c2cf13aaf"}, + {file = "rpds_py-0.19.0-cp311-none-win_amd64.whl", hash = "sha256:7ec72df7354e6b7f6eb2a17fa6901350018c3a9ad78e48d7b2b54d0412539a67"}, + {file = "rpds_py-0.19.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:5095a7c838a8647c32aa37c3a460d2c48debff7fc26e1136aee60100a8cd8f68"}, + {file = "rpds_py-0.19.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6f2f78ef14077e08856e788fa482107aa602636c16c25bdf59c22ea525a785e9"}, + {file = "rpds_py-0.19.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b7cc6cb44f8636fbf4a934ca72f3e786ba3c9f9ba4f4d74611e7da80684e48d2"}, + {file = "rpds_py-0.19.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:cf902878b4af334a09de7a45badbff0389e7cf8dc2e4dcf5f07125d0b7c2656d"}, + {file = "rpds_py-0.19.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:688aa6b8aa724db1596514751ffb767766e02e5c4a87486ab36b8e1ebc1aedac"}, + {file = "rpds_py-0.19.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:57dbc9167d48e355e2569346b5aa4077f29bf86389c924df25c0a8b9124461fb"}, + {file = "rpds_py-0.19.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3b4cf5a9497874822341c2ebe0d5850fed392034caadc0bad134ab6822c0925b"}, + {file = "rpds_py-0.19.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8a790d235b9d39c70a466200d506bb33a98e2ee374a9b4eec7a8ac64c2c261fa"}, + {file = "rpds_py-0.19.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1d16089dfa58719c98a1c06f2daceba6d8e3fb9b5d7931af4a990a3c486241cb"}, + {file = "rpds_py-0.19.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:bc9128e74fe94650367fe23f37074f121b9f796cabbd2f928f13e9661837296d"}, + {file = "rpds_py-0.19.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c8f77e661ffd96ff104bebf7d0f3255b02aa5d5b28326f5408d6284c4a8b3248"}, + {file = "rpds_py-0.19.0-cp312-none-win32.whl", hash = "sha256:5f83689a38e76969327e9b682be5521d87a0c9e5a2e187d2bc6be4765f0d4600"}, + {file = "rpds_py-0.19.0-cp312-none-win_amd64.whl", hash = "sha256:06925c50f86da0596b9c3c64c3837b2481337b83ef3519e5db2701df695453a4"}, + {file = "rpds_py-0.19.0-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:52e466bea6f8f3a44b1234570244b1cff45150f59a4acae3fcc5fd700c2993ca"}, + {file = "rpds_py-0.19.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:e21cc693045fda7f745c790cb687958161ce172ffe3c5719ca1764e752237d16"}, + {file = "rpds_py-0.19.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6b31f059878eb1f5da8b2fd82480cc18bed8dcd7fb8fe68370e2e6285fa86da6"}, + {file = "rpds_py-0.19.0-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:1dd46f309e953927dd018567d6a9e2fb84783963650171f6c5fe7e5c41fd5666"}, + {file = "rpds_py-0.19.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:34a01a4490e170376cd79258b7f755fa13b1a6c3667e872c8e35051ae857a92b"}, + {file = "rpds_py-0.19.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bcf426a8c38eb57f7bf28932e68425ba86def6e756a5b8cb4731d8e62e4e0223"}, + {file = "rpds_py-0.19.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f68eea5df6347d3f1378ce992d86b2af16ad7ff4dcb4a19ccdc23dea901b87fb"}, + {file = "rpds_py-0.19.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:dab8d921b55a28287733263c0e4c7db11b3ee22aee158a4de09f13c93283c62d"}, + {file = "rpds_py-0.19.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:6fe87efd7f47266dfc42fe76dae89060038f1d9cb911f89ae7e5084148d1cc08"}, + {file = "rpds_py-0.19.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:535d4b52524a961d220875688159277f0e9eeeda0ac45e766092bfb54437543f"}, + {file = "rpds_py-0.19.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:8b1a94b8afc154fbe36978a511a1f155f9bd97664e4f1f7a374d72e180ceb0ae"}, + {file = "rpds_py-0.19.0-cp38-none-win32.whl", hash = "sha256:7c98298a15d6b90c8f6e3caa6457f4f022423caa5fa1a1ca7a5e9e512bdb77a4"}, + {file = "rpds_py-0.19.0-cp38-none-win_amd64.whl", hash = "sha256:b0da31853ab6e58a11db3205729133ce0df26e6804e93079dee095be3d681dc1"}, + {file = "rpds_py-0.19.0-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:5039e3cef7b3e7a060de468a4a60a60a1f31786da94c6cb054e7a3c75906111c"}, + {file = "rpds_py-0.19.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ab1932ca6cb8c7499a4d87cb21ccc0d3326f172cfb6a64021a889b591bb3045c"}, + {file = "rpds_py-0.19.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f2afd2164a1e85226fcb6a1da77a5c8896c18bfe08e82e8ceced5181c42d2179"}, + {file = "rpds_py-0.19.0-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b1c30841f5040de47a0046c243fc1b44ddc87d1b12435a43b8edff7e7cb1e0d0"}, + {file = "rpds_py-0.19.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f757f359f30ec7dcebca662a6bd46d1098f8b9fb1fcd661a9e13f2e8ce343ba1"}, + {file = "rpds_py-0.19.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:15e65395a59d2e0e96caf8ee5389ffb4604e980479c32742936ddd7ade914b22"}, + {file = "rpds_py-0.19.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cb0f6eb3a320f24b94d177e62f4074ff438f2ad9d27e75a46221904ef21a7b05"}, + {file = "rpds_py-0.19.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b228e693a2559888790936e20f5f88b6e9f8162c681830eda303bad7517b4d5a"}, + {file = "rpds_py-0.19.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:2575efaa5d949c9f4e2cdbe7d805d02122c16065bfb8d95c129372d65a291a0b"}, + {file = "rpds_py-0.19.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:5c872814b77a4e84afa293a1bee08c14daed1068b2bb1cc312edbf020bbbca2b"}, + {file = "rpds_py-0.19.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:850720e1b383df199b8433a20e02b25b72f0fded28bc03c5bd79e2ce7ef050be"}, + {file = "rpds_py-0.19.0-cp39-none-win32.whl", hash = "sha256:ce84a7efa5af9f54c0aa7692c45861c1667080814286cacb9958c07fc50294fb"}, + {file = "rpds_py-0.19.0-cp39-none-win_amd64.whl", hash = "sha256:1c26da90b8d06227d7769f34915913911222d24ce08c0ab2d60b354e2d9c7aff"}, + {file = "rpds_py-0.19.0-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:75969cf900d7be665ccb1622a9aba225cf386bbc9c3bcfeeab9f62b5048f4a07"}, + {file = "rpds_py-0.19.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:8445f23f13339da640d1be8e44e5baf4af97e396882ebbf1692aecd67f67c479"}, + {file = "rpds_py-0.19.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a5a7c1062ef8aea3eda149f08120f10795835fc1c8bc6ad948fb9652a113ca55"}, + {file = "rpds_py-0.19.0-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:462b0c18fbb48fdbf980914a02ee38c423a25fcc4cf40f66bacc95a2d2d73bc8"}, + {file = "rpds_py-0.19.0-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3208f9aea18991ac7f2b39721e947bbd752a1abbe79ad90d9b6a84a74d44409b"}, + {file = "rpds_py-0.19.0-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c3444fe52b82f122d8a99bf66777aed6b858d392b12f4c317da19f8234db4533"}, + {file = "rpds_py-0.19.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:88cb4bac7185a9f0168d38c01d7a00addece9822a52870eee26b8d5b61409213"}, + {file = "rpds_py-0.19.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6b130bd4163c93798a6b9bb96be64a7c43e1cec81126ffa7ffaa106e1fc5cef5"}, + {file = "rpds_py-0.19.0-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:a707b158b4410aefb6b054715545bbb21aaa5d5d0080217290131c49c2124a6e"}, + {file = "rpds_py-0.19.0-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:dc9ac4659456bde7c567107556ab065801622396b435a3ff213daef27b495388"}, + {file = "rpds_py-0.19.0-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:81ea573aa46d3b6b3d890cd3c0ad82105985e6058a4baed03cf92518081eec8c"}, + {file = "rpds_py-0.19.0-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:3f148c3f47f7f29a79c38cc5d020edcb5ca780020fab94dbc21f9af95c463581"}, + {file = "rpds_py-0.19.0-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:b0906357f90784a66e89ae3eadc2654f36c580a7d65cf63e6a616e4aec3a81be"}, + {file = "rpds_py-0.19.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f629ecc2db6a4736b5ba95a8347b0089240d69ad14ac364f557d52ad68cf94b0"}, + {file = "rpds_py-0.19.0-pp38-pypy38_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c6feacd1d178c30e5bc37184526e56740342fd2aa6371a28367bad7908d454fc"}, + {file = "rpds_py-0.19.0-pp38-pypy38_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ae8b6068ee374fdfab63689be0963333aa83b0815ead5d8648389a8ded593378"}, + {file = "rpds_py-0.19.0-pp38-pypy38_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:78d57546bad81e0da13263e4c9ce30e96dcbe720dbff5ada08d2600a3502e526"}, + {file = "rpds_py-0.19.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a8b6683a37338818646af718c9ca2a07f89787551057fae57c4ec0446dc6224b"}, + {file = "rpds_py-0.19.0-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e8481b946792415adc07410420d6fc65a352b45d347b78fec45d8f8f0d7496f0"}, + {file = "rpds_py-0.19.0-pp38-pypy38_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:bec35eb20792ea64c3c57891bc3ca0bedb2884fbac2c8249d9b731447ecde4fa"}, + {file = "rpds_py-0.19.0-pp38-pypy38_pp73-musllinux_1_2_i686.whl", hash = "sha256:aa5476c3e3a402c37779e95f7b4048db2cb5b0ed0b9d006983965e93f40fe05a"}, + {file = "rpds_py-0.19.0-pp38-pypy38_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:19d02c45f2507b489fd4df7b827940f1420480b3e2e471e952af4d44a1ea8e34"}, + {file = "rpds_py-0.19.0-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:a3e2fd14c5d49ee1da322672375963f19f32b3d5953f0615b175ff7b9d38daed"}, + {file = "rpds_py-0.19.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:93a91c2640645303e874eada51f4f33351b84b351a689d470f8108d0e0694210"}, + {file = "rpds_py-0.19.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e5b9fc03bf76a94065299d4a2ecd8dfbae4ae8e2e8098bbfa6ab6413ca267709"}, + {file = "rpds_py-0.19.0-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5a4b07cdf3f84310c08c1de2c12ddadbb7a77568bcb16e95489f9c81074322ed"}, + {file = "rpds_py-0.19.0-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ba0ed0dc6763d8bd6e5de5cf0d746d28e706a10b615ea382ac0ab17bb7388633"}, + {file = "rpds_py-0.19.0-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:474bc83233abdcf2124ed3f66230a1c8435896046caa4b0b5ab6013c640803cc"}, + {file = "rpds_py-0.19.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:329c719d31362355a96b435f4653e3b4b061fcc9eba9f91dd40804ca637d914e"}, + {file = "rpds_py-0.19.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ef9101f3f7b59043a34f1dccbb385ca760467590951952d6701df0da9893ca0c"}, + {file = "rpds_py-0.19.0-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:0121803b0f424ee2109d6e1f27db45b166ebaa4b32ff47d6aa225642636cd834"}, + {file = "rpds_py-0.19.0-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:8344127403dea42f5970adccf6c5957a71a47f522171fafaf4c6ddb41b61703a"}, + {file = "rpds_py-0.19.0-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:443cec402ddd650bb2b885113e1dcedb22b1175c6be223b14246a714b61cd521"}, + {file = "rpds_py-0.19.0.tar.gz", hash = "sha256:4fdc9afadbeb393b4bbbad75481e0ea78e4469f2e1d713a90811700830b553a9"}, ] -threadpoolctl = [ - {file = "threadpoolctl-2.1.0-py3-none-any.whl", hash = "sha256:38b74ca20ff3bb42caca8b00055111d74159ee95c4370882bbff2b93d24da725"}, - {file = "threadpoolctl-2.1.0.tar.gz", hash = "sha256:ddc57c96a38beb63db45d6c159b5ab07b6bced12c45a1f07b2b92f272aebfa6b"}, + +[[package]] +name = "scikit-learn" +version = "1.5.1" +description = "A set of python modules for machine learning and data mining" +optional = false +python-versions = ">=3.9" +files = [ + {file = "scikit_learn-1.5.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:781586c414f8cc58e71da4f3d7af311e0505a683e112f2f62919e3019abd3745"}, + {file = "scikit_learn-1.5.1-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:f5b213bc29cc30a89a3130393b0e39c847a15d769d6e59539cd86b75d276b1a7"}, + {file = "scikit_learn-1.5.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1ff4ba34c2abff5ec59c803ed1d97d61b036f659a17f55be102679e88f926fac"}, + {file = "scikit_learn-1.5.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:161808750c267b77b4a9603cf9c93579c7a74ba8486b1336034c2f1579546d21"}, + {file = "scikit_learn-1.5.1-cp310-cp310-win_amd64.whl", hash = "sha256:10e49170691514a94bb2e03787aa921b82dbc507a4ea1f20fd95557862c98dc1"}, + {file = "scikit_learn-1.5.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:154297ee43c0b83af12464adeab378dee2d0a700ccd03979e2b821e7dd7cc1c2"}, + {file = "scikit_learn-1.5.1-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:b5e865e9bd59396220de49cb4a57b17016256637c61b4c5cc81aaf16bc123bbe"}, + {file = "scikit_learn-1.5.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:909144d50f367a513cee6090873ae582dba019cb3fca063b38054fa42704c3a4"}, + {file = "scikit_learn-1.5.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:689b6f74b2c880276e365fe84fe4f1befd6a774f016339c65655eaff12e10cbf"}, + {file = "scikit_learn-1.5.1-cp311-cp311-win_amd64.whl", hash = "sha256:9a07f90846313a7639af6a019d849ff72baadfa4c74c778821ae0fad07b7275b"}, + {file = "scikit_learn-1.5.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:5944ce1faada31c55fb2ba20a5346b88e36811aab504ccafb9f0339e9f780395"}, + {file = "scikit_learn-1.5.1-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:0828673c5b520e879f2af6a9e99eee0eefea69a2188be1ca68a6121b809055c1"}, + {file = "scikit_learn-1.5.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:508907e5f81390e16d754e8815f7497e52139162fd69c4fdbd2dfa5d6cc88915"}, + {file = "scikit_learn-1.5.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:97625f217c5c0c5d0505fa2af28ae424bd37949bb2f16ace3ff5f2f81fb4498b"}, + {file = "scikit_learn-1.5.1-cp312-cp312-win_amd64.whl", hash = "sha256:da3f404e9e284d2b0a157e1b56b6566a34eb2798205cba35a211df3296ab7a74"}, + {file = "scikit_learn-1.5.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:88e0672c7ac21eb149d409c74cc29f1d611d5158175846e7a9c2427bd12b3956"}, + {file = "scikit_learn-1.5.1-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:7b073a27797a283187a4ef4ee149959defc350b46cbf63a84d8514fe16b69855"}, + {file = "scikit_learn-1.5.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b59e3e62d2be870e5c74af4e793293753565c7383ae82943b83383fdcf5cc5c1"}, + {file = "scikit_learn-1.5.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1bd8d3a19d4bd6dc5a7d4f358c8c3a60934dc058f363c34c0ac1e9e12a31421d"}, + {file = "scikit_learn-1.5.1-cp39-cp39-win_amd64.whl", hash = "sha256:5f57428de0c900a98389c4a433d4a3cf89de979b3aa24d1c1d251802aa15e44d"}, + {file = "scikit_learn-1.5.1.tar.gz", hash = "sha256:0ea5d40c0e3951df445721927448755d3fe1d80833b0b7308ebff5d2a45e6414"}, ] -tornado = [ - {file = "tornado-6.0.4-cp35-cp35m-win32.whl", hash = "sha256:5217e601700f24e966ddab689f90b7ea4bd91ff3357c3600fa1045e26d68e55d"}, - {file = "tornado-6.0.4-cp35-cp35m-win_amd64.whl", hash = "sha256:c98232a3ac391f5faea6821b53db8db461157baa788f5d6222a193e9456e1740"}, - {file = "tornado-6.0.4-cp36-cp36m-win32.whl", hash = "sha256:5f6a07e62e799be5d2330e68d808c8ac41d4a259b9cea61da4101b83cb5dc673"}, - {file = "tornado-6.0.4-cp36-cp36m-win_amd64.whl", hash = "sha256:c952975c8ba74f546ae6de2e226ab3cc3cc11ae47baf607459a6728585bb542a"}, - {file = "tornado-6.0.4-cp37-cp37m-win32.whl", hash = "sha256:2c027eb2a393d964b22b5c154d1a23a5f8727db6fda837118a776b29e2b8ebc6"}, - {file = "tornado-6.0.4-cp37-cp37m-win_amd64.whl", hash = "sha256:5618f72e947533832cbc3dec54e1dffc1747a5cb17d1fd91577ed14fa0dc081b"}, - {file = "tornado-6.0.4-cp38-cp38-win32.whl", hash = "sha256:22aed82c2ea340c3771e3babc5ef220272f6fd06b5108a53b4976d0d722bcd52"}, - {file = "tornado-6.0.4-cp38-cp38-win_amd64.whl", hash = "sha256:c58d56003daf1b616336781b26d184023ea4af13ae143d9dda65e31e534940b9"}, - {file = "tornado-6.0.4.tar.gz", hash = "sha256:0fe2d45ba43b00a41cd73f8be321a44936dc1aba233dee979f17a042b83eb6dc"}, + +[package.dependencies] +joblib = ">=1.2.0" +numpy = ">=1.19.5" +scipy = ">=1.6.0" +threadpoolctl = ">=3.1.0" + +[package.extras] +benchmark = ["matplotlib (>=3.3.4)", "memory_profiler (>=0.57.0)", "pandas (>=1.1.5)"] +build = ["cython (>=3.0.10)", "meson-python (>=0.16.0)", "numpy (>=1.19.5)", "scipy (>=1.6.0)"] +docs = ["Pillow (>=7.1.2)", "matplotlib (>=3.3.4)", "memory_profiler (>=0.57.0)", "numpydoc (>=1.2.0)", "pandas (>=1.1.5)", "plotly (>=5.14.0)", "polars (>=0.20.23)", "pooch (>=1.6.0)", "pydata-sphinx-theme (>=0.15.3)", "scikit-image (>=0.17.2)", "seaborn (>=0.9.0)", "sphinx (>=7.3.7)", "sphinx-copybutton (>=0.5.2)", "sphinx-design (>=0.5.0)", "sphinx-gallery (>=0.16.0)", "sphinx-prompt (>=1.4.0)", "sphinx-remove-toctrees (>=1.0.0.post1)", "sphinxcontrib-sass (>=0.3.4)", "sphinxext-opengraph (>=0.9.1)"] +examples = ["matplotlib (>=3.3.4)", "pandas (>=1.1.5)", "plotly (>=5.14.0)", "pooch (>=1.6.0)", "scikit-image (>=0.17.2)", "seaborn (>=0.9.0)"] +install = ["joblib (>=1.2.0)", "numpy (>=1.19.5)", "scipy (>=1.6.0)", "threadpoolctl (>=3.1.0)"] +maintenance = ["conda-lock (==2.5.6)"] +tests = ["black (>=24.3.0)", "matplotlib (>=3.3.4)", "mypy (>=1.9)", "numpydoc (>=1.2.0)", "pandas (>=1.1.5)", "polars (>=0.20.23)", "pooch (>=1.6.0)", "pyamg (>=4.0.0)", "pyarrow (>=12.0.0)", "pytest (>=7.1.2)", "pytest-cov (>=2.9.0)", "ruff (>=0.2.1)", "scikit-image (>=0.17.2)"] + +[[package]] +name = "scipy" +version = "1.13.1" +description = "Fundamental algorithms for scientific computing in Python" +optional = false +python-versions = ">=3.9" +files = [ + {file = "scipy-1.13.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:20335853b85e9a49ff7572ab453794298bcf0354d8068c5f6775a0eabf350aca"}, + {file = "scipy-1.13.1-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:d605e9c23906d1994f55ace80e0125c587f96c020037ea6aa98d01b4bd2e222f"}, + {file = "scipy-1.13.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cfa31f1def5c819b19ecc3a8b52d28ffdcc7ed52bb20c9a7589669dd3c250989"}, + {file = "scipy-1.13.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f26264b282b9da0952a024ae34710c2aff7d27480ee91a2e82b7b7073c24722f"}, + {file = "scipy-1.13.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:eccfa1906eacc02de42d70ef4aecea45415f5be17e72b61bafcfd329bdc52e94"}, + {file = "scipy-1.13.1-cp310-cp310-win_amd64.whl", hash = "sha256:2831f0dc9c5ea9edd6e51e6e769b655f08ec6db6e2e10f86ef39bd32eb11da54"}, + {file = "scipy-1.13.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:27e52b09c0d3a1d5b63e1105f24177e544a222b43611aaf5bc44d4a0979e32f9"}, + {file = "scipy-1.13.1-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:54f430b00f0133e2224c3ba42b805bfd0086fe488835effa33fa291561932326"}, + {file = "scipy-1.13.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e89369d27f9e7b0884ae559a3a956e77c02114cc60a6058b4e5011572eea9299"}, + {file = "scipy-1.13.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a78b4b3345f1b6f68a763c6e25c0c9a23a9fd0f39f5f3d200efe8feda560a5fa"}, + {file = "scipy-1.13.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:45484bee6d65633752c490404513b9ef02475b4284c4cfab0ef946def50b3f59"}, + {file = "scipy-1.13.1-cp311-cp311-win_amd64.whl", hash = "sha256:5713f62f781eebd8d597eb3f88b8bf9274e79eeabf63afb4a737abc6c84ad37b"}, + {file = "scipy-1.13.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:5d72782f39716b2b3509cd7c33cdc08c96f2f4d2b06d51e52fb45a19ca0c86a1"}, + {file = "scipy-1.13.1-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:017367484ce5498445aade74b1d5ab377acdc65e27095155e448c88497755a5d"}, + {file = "scipy-1.13.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:949ae67db5fa78a86e8fa644b9a6b07252f449dcf74247108c50e1d20d2b4627"}, + {file = "scipy-1.13.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:de3ade0e53bc1f21358aa74ff4830235d716211d7d077e340c7349bc3542e884"}, + {file = "scipy-1.13.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:2ac65fb503dad64218c228e2dc2d0a0193f7904747db43014645ae139c8fad16"}, + {file = "scipy-1.13.1-cp312-cp312-win_amd64.whl", hash = "sha256:cdd7dacfb95fea358916410ec61bbc20440f7860333aee6d882bb8046264e949"}, + {file = "scipy-1.13.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:436bbb42a94a8aeef855d755ce5a465479c721e9d684de76bf61a62e7c2b81d5"}, + {file = "scipy-1.13.1-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:8335549ebbca860c52bf3d02f80784e91a004b71b059e3eea9678ba994796a24"}, + {file = "scipy-1.13.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d533654b7d221a6a97304ab63c41c96473ff04459e404b83275b60aa8f4b7004"}, + {file = "scipy-1.13.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:637e98dcf185ba7f8e663e122ebf908c4702420477ae52a04f9908707456ba4d"}, + {file = "scipy-1.13.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a014c2b3697bde71724244f63de2476925596c24285c7a637364761f8710891c"}, + {file = "scipy-1.13.1-cp39-cp39-win_amd64.whl", hash = "sha256:392e4ec766654852c25ebad4f64e4e584cf19820b980bc04960bca0b0cd6eaa2"}, + {file = "scipy-1.13.1.tar.gz", hash = "sha256:095a87a0312b08dfd6a6155cbbd310a8c51800fc931b8c0b84003014b874ed3c"}, ] -traitlets = [ - {file = "traitlets-5.0.4-py3-none-any.whl", hash = "sha256:9664ec0c526e48e7b47b7d14cd6b252efa03e0129011de0a9c1d70315d4309c3"}, - {file = "traitlets-5.0.4.tar.gz", hash = "sha256:86c9351f94f95de9db8a04ad8e892da299a088a64fd283f9f6f18770ae5eae1b"}, + +[package.dependencies] +numpy = ">=1.22.4,<2.3" + +[package.extras] +dev = ["cython-lint (>=0.12.2)", "doit (>=0.36.0)", "mypy", "pycodestyle", "pydevtool", "rich-click", "ruff", "types-psutil", "typing_extensions"] +doc = ["jupyterlite-pyodide-kernel", "jupyterlite-sphinx (>=0.12.0)", "jupytext", "matplotlib (>=3.5)", "myst-nb", "numpydoc", "pooch", "pydata-sphinx-theme (>=0.15.2)", "sphinx (>=5.0.0)", "sphinx-design (>=0.4.0)"] +test = ["array-api-strict", "asv", "gmpy2", "hypothesis (>=6.30)", "mpmath", "pooch", "pytest", "pytest-cov", "pytest-timeout", "pytest-xdist", "scikit-umfpack", "threadpoolctl"] + +[[package]] +name = "send2trash" +version = "1.8.3" +description = "Send file to trash natively under Mac OS X, Windows and Linux" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" +files = [ + {file = "Send2Trash-1.8.3-py3-none-any.whl", hash = "sha256:0c31227e0bd08961c7665474a3d1ef7193929fedda4233843689baa056be46c9"}, + {file = "Send2Trash-1.8.3.tar.gz", hash = "sha256:b18e7a3966d99871aefeb00cfbcfdced55ce4871194810fc71f4aa484b953abf"}, ] -urllib3 = [ - {file = "urllib3-1.25.10-py2.py3-none-any.whl", hash = "sha256:e7983572181f5e1522d9c98453462384ee92a0be7fac5f1413a1e35c56cc0461"}, - {file = "urllib3-1.25.10.tar.gz", hash = "sha256:91056c15fa70756691db97756772bb1eb9678fa585d9184f24534b100dc60f4a"}, + +[package.extras] +nativelib = ["pyobjc-framework-Cocoa", "pywin32"] +objc = ["pyobjc-framework-Cocoa"] +win32 = ["pywin32"] + +[[package]] +name = "setuptools" +version = "70.3.0" +description = "Easily download, build, install, upgrade, and uninstall Python packages" +optional = false +python-versions = ">=3.8" +files = [ + {file = "setuptools-70.3.0-py3-none-any.whl", hash = "sha256:fe384da74336c398e0d956d1cae0669bc02eed936cdb1d49b57de1990dc11ffc"}, + {file = "setuptools-70.3.0.tar.gz", hash = "sha256:f171bab1dfbc86b132997f26a119f6056a57950d058587841a0082e8830f9dc5"}, ] -wcwidth = [ - {file = "wcwidth-0.2.5-py2.py3-none-any.whl", hash = "sha256:beb4802a9cebb9144e99086eff703a642a13d6a0052920003a230f3294bbe784"}, - {file = "wcwidth-0.2.5.tar.gz", hash = "sha256:c4d647b99872929fdb7bdcaa4fbe7f01413ed3d98077df798530e5b04f116c83"}, + +[package.extras] +doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "pyproject-hooks (!=1.1)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier"] +test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "importlib-metadata", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "jaraco.test", "mypy (==1.10.0)", "packaging (>=23.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-home (>=0.5)", "pytest-mypy", "pytest-perf", "pytest-ruff (>=0.3.2)", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] + +[[package]] +name = "six" +version = "1.16.0" +description = "Python 2 and 3 compatibility utilities" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" +files = [ + {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, + {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, ] -webencodings = [ + +[[package]] +name = "sniffio" +version = "1.3.1" +description = "Sniff out which async library your code is running under" +optional = false +python-versions = ">=3.7" +files = [ + {file = "sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2"}, + {file = "sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc"}, +] + +[[package]] +name = "soupsieve" +version = "2.5" +description = "A modern CSS selector implementation for Beautiful Soup." +optional = false +python-versions = ">=3.8" +files = [ + {file = "soupsieve-2.5-py3-none-any.whl", hash = "sha256:eaa337ff55a1579b6549dc679565eac1e3d000563bcb1c8ab0d0fefbc0c2cdc7"}, + {file = "soupsieve-2.5.tar.gz", hash = "sha256:5663d5a7b3bfaeee0bc4372e7fc48f9cff4940b3eec54a6451cc5299f1097690"}, +] + +[[package]] +name = "stack-data" +version = "0.6.3" +description = "Extract data from python stack frames and tracebacks for informative displays" +optional = false +python-versions = "*" +files = [ + {file = "stack_data-0.6.3-py3-none-any.whl", hash = "sha256:d5558e0c25a4cb0853cddad3d77da9891a08cb85dd9f9f91b9f8cd66e511e695"}, + {file = "stack_data-0.6.3.tar.gz", hash = "sha256:836a778de4fec4dcd1dcd89ed8abff8a221f58308462e1c4aa2a3cf30148f0b9"}, +] + +[package.dependencies] +asttokens = ">=2.1.0" +executing = ">=1.2.0" +pure-eval = "*" + +[package.extras] +tests = ["cython", "littleutils", "pygments", "pytest", "typeguard"] + +[[package]] +name = "terminado" +version = "0.18.1" +description = "Tornado websocket backend for the Xterm.js Javascript terminal emulator library." +optional = false +python-versions = ">=3.8" +files = [ + {file = "terminado-0.18.1-py3-none-any.whl", hash = "sha256:a4468e1b37bb318f8a86514f65814e1afc977cf29b3992a4500d9dd305dcceb0"}, + {file = "terminado-0.18.1.tar.gz", hash = "sha256:de09f2c4b85de4765f7714688fff57d3e75bad1f909b589fde880460c753fd2e"}, +] + +[package.dependencies] +ptyprocess = {version = "*", markers = "os_name != \"nt\""} +pywinpty = {version = ">=1.1.0", markers = "os_name == \"nt\""} +tornado = ">=6.1.0" + +[package.extras] +docs = ["myst-parser", "pydata-sphinx-theme", "sphinx"] +test = ["pre-commit", "pytest (>=7.0)", "pytest-timeout"] +typing = ["mypy (>=1.6,<2.0)", "traitlets (>=5.11.1)"] + +[[package]] +name = "threadpoolctl" +version = "3.5.0" +description = "threadpoolctl" +optional = false +python-versions = ">=3.8" +files = [ + {file = "threadpoolctl-3.5.0-py3-none-any.whl", hash = "sha256:56c1e26c150397e58c4926da8eeee87533b1e32bef131bd4bf6a2f45f3185467"}, + {file = "threadpoolctl-3.5.0.tar.gz", hash = "sha256:082433502dd922bf738de0d8bcc4fdcbf0979ff44c42bd40f5af8a282f6fa107"}, +] + +[[package]] +name = "tinycss2" +version = "1.3.0" +description = "A tiny CSS parser" +optional = false +python-versions = ">=3.8" +files = [ + {file = "tinycss2-1.3.0-py3-none-any.whl", hash = "sha256:54a8dbdffb334d536851be0226030e9505965bb2f30f21a4a82c55fb2a80fae7"}, + {file = "tinycss2-1.3.0.tar.gz", hash = "sha256:152f9acabd296a8375fbca5b84c961ff95971fcfc32e79550c8df8e29118c54d"}, +] + +[package.dependencies] +webencodings = ">=0.4" + +[package.extras] +doc = ["sphinx", "sphinx_rtd_theme"] +test = ["pytest", "ruff"] + +[[package]] +name = "tokenize-rt" +version = "5.2.0" +description = "A wrapper around the stdlib `tokenize` which roundtrips." +optional = false +python-versions = ">=3.8" +files = [ + {file = "tokenize_rt-5.2.0-py2.py3-none-any.whl", hash = "sha256:b79d41a65cfec71285433511b50271b05da3584a1da144a0752e9c621a285289"}, + {file = "tokenize_rt-5.2.0.tar.gz", hash = "sha256:9fe80f8a5c1edad2d3ede0f37481cc0cc1538a2f442c9c2f9e4feacd2792d054"}, +] + +[[package]] +name = "tomli" +version = "2.0.1" +description = "A lil' TOML parser" +optional = false +python-versions = ">=3.7" +files = [ + {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, + {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, +] + +[[package]] +name = "tornado" +version = "6.4.1" +description = "Tornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed." +optional = false +python-versions = ">=3.8" +files = [ + {file = "tornado-6.4.1-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:163b0aafc8e23d8cdc3c9dfb24c5368af84a81e3364745ccb4427669bf84aec8"}, + {file = "tornado-6.4.1-cp38-abi3-macosx_10_9_x86_64.whl", hash = "sha256:6d5ce3437e18a2b66fbadb183c1d3364fb03f2be71299e7d10dbeeb69f4b2a14"}, + {file = "tornado-6.4.1-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e2e20b9113cd7293f164dc46fffb13535266e713cdb87bd2d15ddb336e96cfc4"}, + {file = "tornado-6.4.1-cp38-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8ae50a504a740365267b2a8d1a90c9fbc86b780a39170feca9bcc1787ff80842"}, + {file = "tornado-6.4.1-cp38-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:613bf4ddf5c7a95509218b149b555621497a6cc0d46ac341b30bd9ec19eac7f3"}, + {file = "tornado-6.4.1-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:25486eb223babe3eed4b8aecbac33b37e3dd6d776bc730ca14e1bf93888b979f"}, + {file = "tornado-6.4.1-cp38-abi3-musllinux_1_2_i686.whl", hash = "sha256:454db8a7ecfcf2ff6042dde58404164d969b6f5d58b926da15e6b23817950fc4"}, + {file = "tornado-6.4.1-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:a02a08cc7a9314b006f653ce40483b9b3c12cda222d6a46d4ac63bb6c9057698"}, + {file = "tornado-6.4.1-cp38-abi3-win32.whl", hash = "sha256:d9a566c40b89757c9aa8e6f032bcdb8ca8795d7c1a9762910c722b1635c9de4d"}, + {file = "tornado-6.4.1-cp38-abi3-win_amd64.whl", hash = "sha256:b24b8982ed444378d7f21d563f4180a2de31ced9d8d84443907a0a64da2072e7"}, + {file = "tornado-6.4.1.tar.gz", hash = "sha256:92d3ab53183d8c50f8204a51e6f91d18a15d5ef261e84d452800d4ff6fc504e9"}, +] + +[[package]] +name = "traitlets" +version = "5.14.3" +description = "Traitlets Python configuration system" +optional = false +python-versions = ">=3.8" +files = [ + {file = "traitlets-5.14.3-py3-none-any.whl", hash = "sha256:b74e89e397b1ed28cc831db7aea759ba6640cb3de13090ca145426688ff1ac4f"}, + {file = "traitlets-5.14.3.tar.gz", hash = "sha256:9ed0579d3502c94b4b3732ac120375cda96f923114522847de4b3bb98b96b6b7"}, +] + +[package.extras] +docs = ["myst-parser", "pydata-sphinx-theme", "sphinx"] +test = ["argcomplete (>=3.0.3)", "mypy (>=1.7.0)", "pre-commit", "pytest (>=7.0,<8.2)", "pytest-mock", "pytest-mypy-testing"] + +[[package]] +name = "types-python-dateutil" +version = "2.9.0.20240316" +description = "Typing stubs for python-dateutil" +optional = false +python-versions = ">=3.8" +files = [ + {file = "types-python-dateutil-2.9.0.20240316.tar.gz", hash = "sha256:5d2f2e240b86905e40944dd787db6da9263f0deabef1076ddaed797351ec0202"}, + {file = "types_python_dateutil-2.9.0.20240316-py3-none-any.whl", hash = "sha256:6b8cb66d960771ce5ff974e9dd45e38facb81718cc1e208b10b1baccbfdbee3b"}, +] + +[[package]] +name = "typing-extensions" +version = "4.12.2" +description = "Backported and Experimental Type Hints for Python 3.8+" +optional = false +python-versions = ">=3.8" +files = [ + {file = "typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d"}, + {file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"}, +] + +[[package]] +name = "tzdata" +version = "2024.1" +description = "Provider of IANA time zone data" +optional = false +python-versions = ">=2" +files = [ + {file = "tzdata-2024.1-py2.py3-none-any.whl", hash = "sha256:9068bc196136463f5245e51efda838afa15aaeca9903f49050dfa2679db4d252"}, + {file = "tzdata-2024.1.tar.gz", hash = "sha256:2674120f8d891909751c38abcdfd386ac0a5a1127954fbc332af6b5ceae07efd"}, +] + +[[package]] +name = "uri-template" +version = "1.3.0" +description = "RFC 6570 URI Template Processor" +optional = false +python-versions = ">=3.7" +files = [ + {file = "uri-template-1.3.0.tar.gz", hash = "sha256:0e00f8eb65e18c7de20d595a14336e9f337ead580c70934141624b6d1ffdacc7"}, + {file = "uri_template-1.3.0-py3-none-any.whl", hash = "sha256:a44a133ea12d44a0c0f06d7d42a52d71282e77e2f937d8abd5655b8d56fc1363"}, +] + +[package.extras] +dev = ["flake8", "flake8-annotations", "flake8-bandit", "flake8-bugbear", "flake8-commas", "flake8-comprehensions", "flake8-continuation", "flake8-datetimez", "flake8-docstrings", "flake8-import-order", "flake8-literal", "flake8-modern-annotations", "flake8-noqa", "flake8-pyproject", "flake8-requirements", "flake8-typechecking-import", "flake8-use-fstring", "mypy", "pep8-naming", "types-PyYAML"] + +[[package]] +name = "urllib3" +version = "2.2.2" +description = "HTTP library with thread-safe connection pooling, file post, and more." +optional = false +python-versions = ">=3.8" +files = [ + {file = "urllib3-2.2.2-py3-none-any.whl", hash = "sha256:a448b2f64d686155468037e1ace9f2d2199776e17f0a46610480d311f73e3472"}, + {file = "urllib3-2.2.2.tar.gz", hash = "sha256:dd505485549a7a552833da5e6063639d0d177c04f23bc3864e41e5dc5f612168"}, +] + +[package.extras] +brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"] +h2 = ["h2 (>=4,<5)"] +socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] +zstd = ["zstandard (>=0.18.0)"] + +[[package]] +name = "wcwidth" +version = "0.2.13" +description = "Measures the displayed width of unicode strings in a terminal" +optional = false +python-versions = "*" +files = [ + {file = "wcwidth-0.2.13-py2.py3-none-any.whl", hash = "sha256:3da69048e4540d84af32131829ff948f1e022c1c6bdb8d6102117aac784f6859"}, + {file = "wcwidth-0.2.13.tar.gz", hash = "sha256:72ea0c06399eb286d978fdedb6923a9eb47e1c486ce63e9b4e64fc18303972b5"}, +] + +[[package]] +name = "webcolors" +version = "24.6.0" +description = "A library for working with the color formats defined by HTML and CSS." +optional = false +python-versions = ">=3.8" +files = [ + {file = "webcolors-24.6.0-py3-none-any.whl", hash = "sha256:8cf5bc7e28defd1d48b9e83d5fc30741328305a8195c29a8e668fa45586568a1"}, + {file = "webcolors-24.6.0.tar.gz", hash = "sha256:1d160d1de46b3e81e58d0a280d0c78b467dc80f47294b91b1ad8029d2cedb55b"}, +] + +[package.extras] +docs = ["furo", "sphinx", "sphinx-copybutton", "sphinx-inline-tabs", "sphinx-notfound-page", "sphinxext-opengraph"] +tests = ["coverage[toml]"] + +[[package]] +name = "webencodings" +version = "0.5.1" +description = "Character encoding aliases for legacy web content" +optional = false +python-versions = "*" +files = [ {file = "webencodings-0.5.1-py2.py3-none-any.whl", hash = "sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78"}, {file = "webencodings-0.5.1.tar.gz", hash = "sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923"}, ] -zipp = [ - {file = "zipp-3.1.0-py3-none-any.whl", hash = "sha256:aa36550ff0c0b7ef7fa639055d797116ee891440eac1a56f378e2d3179e0320b"}, - {file = "zipp-3.1.0.tar.gz", hash = "sha256:c599e4d75c98f6798c509911d08a22e6c021d074469042177c8c86fb92eefd96"}, + +[[package]] +name = "websocket-client" +version = "1.8.0" +description = "WebSocket client for Python with low level API options" +optional = false +python-versions = ">=3.8" +files = [ + {file = "websocket_client-1.8.0-py3-none-any.whl", hash = "sha256:17b44cc997f5c498e809b22cdf2d9c7a9e71c02c8cc2b6c56e7c2d1239bfa526"}, + {file = "websocket_client-1.8.0.tar.gz", hash = "sha256:3239df9f44da632f96012472805d40a23281a991027ce11d2f45a6f24ac4c3da"}, ] + +[package.extras] +docs = ["Sphinx (>=6.0)", "myst-parser (>=2.0.0)", "sphinx-rtd-theme (>=1.1.0)"] +optional = ["python-socks", "wsaccel"] +test = ["websockets"] + +[[package]] +name = "zipp" +version = "3.19.2" +description = "Backport of pathlib-compatible object wrapper for zip files" +optional = false +python-versions = ">=3.8" +files = [ + {file = "zipp-3.19.2-py3-none-any.whl", hash = "sha256:f091755f667055f2d02b32c53771a7a6c8b47e1fdbc4b72a8b9072b3eef8015c"}, + {file = "zipp-3.19.2.tar.gz", hash = "sha256:bf1dcf6450f873a13e952a29504887c89e6de7506209e5b1bcc3460135d4de19"}, +] + +[package.extras] +doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] +test = ["big-O", "importlib-resources", "jaraco.functools", "jaraco.itertools", "jaraco.test", "more-itertools", "pytest (>=6,!=8.1.*)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-ignore-flaky", "pytest-mypy", "pytest-ruff (>=0.2.1)"] + +[metadata] +lock-version = "2.0" +python-versions = "^3.9" +content-hash = "50d65895e6183867e6fe4c243acdc746a70d4353eb7fe17a6c03fa89c1c7176c" diff --git a/pyproject.toml b/pyproject.toml index 55e5a0c..225ba57 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,20 +1,43 @@ [build-system] -requires = ["poetry>=0.12"] -build-backend = "poetry.masonry.api" +requires = ["poetry-core"] +build-backend = "poetry.core.masonry.api" + [tool.poetry] -name = "workshop-machine-learning-for-beginners" -version = "0.1.0" +name = "intro-to-data-science" +version = "0.3.0" -authors = ["Alexander Hess "] -description = "An introductory workshop on machine learning" +authors = [ + "Alexander Hess ", +] +description = "An intro to data science for absolute beginners" +keywords = [ + "python", + "data-science", + "machine-learning", + "matplotlib", + "numpy", + "seaborn", + "sklearn", +] license = "MIT" -[tool.poetry.dependencies] -python = "^3.7" +readme = "README.md" +homepage = "https://github.com/webartifex/intro-to-data-science" +repository = "https://github.com/webartifex/intro-to-data-science" -jupyterlab = "^2.2.8" -matplotlib = "^3.3.2" -numpy = "^1.19.2" -pandas = "^1.1.2" -scikit-learn = "^0.23.2" +package-mode = false + + +[tool.poetry.dependencies] +python = "^3.9" + +jupyterlab = "^4.2" +matplotlib = "^3.9" +numpy = "^2.0" +pandas = "^2.2" +scikit-learn = "^1.5" + +[tool.poetry.group.dev.dependencies] +black = {extras = ["jupyter"], version = "^24.4"} +invoke = "^2.2" diff --git a/raw/python_general.png b/raw/python_general.png deleted file mode 100644 index 6c9d929..0000000 Binary files a/raw/python_general.png and /dev/null differ diff --git a/requirements.txt b/requirements.txt index 90a97c6..8760210 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,56 +1,115 @@ -attrs==19.3.0 -backcall==0.1.0 -bleach==3.1.0 -cycler==0.10.0 -decorator==4.4.1 -defusedxml==0.6.0 -entrypoints==0.3 -importlib-metadata==1.2.0 -ipykernel==5.1.3 -ipython==7.10.1 -ipython-genutils==0.2.0 -ipywidgets==7.5.1 -jedi==0.15.1 -Jinja2==2.10.3 -joblib==0.14.0 -jsonschema==3.2.0 -jupyter==1.0.0 -jupyter-client==5.3.4 -jupyter-console==6.0.0 -jupyter-core==4.6.1 -kiwisolver==1.1.0 -MarkupSafe==1.1.1 -matplotlib==3.1.2 -mistune==0.8.4 -more-itertools==8.0.0 -nbconvert==5.6.1 -nbformat==4.4.0 -notebook==6.0.2 -numpy==1.17.4 -pandas==0.25.3 -pandocfilters==1.4.2 -parso==0.5.1 -pexpect==4.7.0 -pickleshare==0.7.5 -prometheus-client==0.7.1 -prompt-toolkit==2.0.10 -ptyprocess==0.6.0 -Pygments==2.5.2 -pyparsing==2.4.5 -pyrsistent==0.15.6 -python-dateutil==2.8.1 -pytz==2019.3 -pyzmq==18.1.1 -qtconsole==4.6.0 -scikit-learn==0.22 -scipy==1.3.3 -Send2Trash==1.5.0 -six==1.13.0 -terminado==0.8.3 -testpath==0.4.4 -tornado==6.0.3 -traitlets==4.3.3 -wcwidth==0.1.7 -webencodings==0.5.1 -widgetsnbextension==3.5.1 -zipp==0.6.0 +anyio==4.4.0 ; python_version >= "3.9" and python_version < "4.0" +appnope==0.1.4 ; python_version >= "3.9" and python_version < "4.0" and platform_system == "Darwin" +argon2-cffi-bindings==21.2.0 ; python_version >= "3.9" and python_version < "4.0" +argon2-cffi==23.1.0 ; python_version >= "3.9" and python_version < "4.0" +arrow==1.3.0 ; python_version >= "3.9" and python_version < "4.0" +asttokens==2.4.1 ; python_version >= "3.9" and python_version < "4.0" +async-lru==2.0.4 ; python_version >= "3.9" and python_version < "4.0" +attrs==23.2.0 ; python_version >= "3.9" and python_version < "4.0" +babel==2.15.0 ; python_version >= "3.9" and python_version < "4.0" +beautifulsoup4==4.12.3 ; python_version >= "3.9" and python_version < "4.0" +bleach==6.1.0 ; python_version >= "3.9" and python_version < "4.0" +certifi==2024.7.4 ; python_version >= "3.9" and python_version < "4.0" +cffi==1.16.0 ; python_version >= "3.9" and python_version < "4.0" +charset-normalizer==3.3.2 ; python_version >= "3.9" and python_version < "4.0" +colorama==0.4.6 ; python_version >= "3.9" and python_version < "4.0" and sys_platform == "win32" +comm==0.2.2 ; python_version >= "3.9" and python_version < "4.0" +contourpy==1.2.1 ; python_version >= "3.9" and python_version < "4.0" +cycler==0.12.1 ; python_version >= "3.9" and python_version < "4.0" +debugpy==1.8.2 ; python_version >= "3.9" and python_version < "4.0" +decorator==5.1.1 ; python_version >= "3.9" and python_version < "4.0" +defusedxml==0.7.1 ; python_version >= "3.9" and python_version < "4.0" +exceptiongroup==1.2.2 ; python_version >= "3.9" and python_version < "3.11" +executing==2.0.1 ; python_version >= "3.9" and python_version < "4.0" +fastjsonschema==2.20.0 ; python_version >= "3.9" and python_version < "4.0" +fonttools==4.53.1 ; python_version >= "3.9" and python_version < "4.0" +fqdn==1.5.1 ; python_version >= "3.9" and python_version < "4" +h11==0.14.0 ; python_version >= "3.9" and python_version < "4.0" +httpcore==1.0.5 ; python_version >= "3.9" and python_version < "4.0" +httpx==0.27.0 ; python_version >= "3.9" and python_version < "4.0" +idna==3.7 ; python_version >= "3.9" and python_version < "4.0" +importlib-metadata==8.0.0 ; python_version >= "3.9" and python_version < "3.10" +importlib-resources==6.4.0 ; python_version >= "3.9" and python_version < "3.10" +ipykernel==6.29.5 ; python_version >= "3.9" and python_version < "4.0" +ipython==8.18.1 ; python_version >= "3.9" and python_version < "4.0" +isoduration==20.11.0 ; python_version >= "3.9" and python_version < "4.0" +jedi==0.19.1 ; python_version >= "3.9" and python_version < "4.0" +jinja2==3.1.4 ; python_version >= "3.9" and python_version < "4.0" +joblib==1.4.2 ; python_version >= "3.9" and python_version < "4.0" +json5==0.9.25 ; python_version >= "3.9" and python_version < "4.0" +jsonpointer==3.0.0 ; python_version >= "3.9" and python_version < "4.0" +jsonschema-specifications==2023.12.1 ; python_version >= "3.9" and python_version < "4.0" +jsonschema==4.23.0 ; python_version >= "3.9" and python_version < "4.0" +jsonschema[format-nongpl]==4.23.0 ; python_version >= "3.9" and python_version < "4.0" +jupyter-client==8.6.2 ; python_version >= "3.9" and python_version < "4.0" +jupyter-core==5.7.2 ; python_version >= "3.9" and python_version < "4.0" +jupyter-events==0.10.0 ; python_version >= "3.9" and python_version < "4.0" +jupyter-lsp==2.2.5 ; python_version >= "3.9" and python_version < "4.0" +jupyter-server-terminals==0.5.3 ; python_version >= "3.9" and python_version < "4.0" +jupyter-server==2.14.2 ; python_version >= "3.9" and python_version < "4.0" +jupyterlab-pygments==0.3.0 ; python_version >= "3.9" and python_version < "4.0" +jupyterlab-server==2.27.2 ; python_version >= "3.9" and python_version < "4.0" +jupyterlab==4.2.3 ; python_version >= "3.9" and python_version < "4.0" +kiwisolver==1.4.5 ; python_version >= "3.9" and python_version < "4.0" +markupsafe==2.1.5 ; python_version >= "3.9" and python_version < "4.0" +matplotlib-inline==0.1.7 ; python_version >= "3.9" and python_version < "4.0" +matplotlib==3.9.1 ; python_version >= "3.9" and python_version < "4.0" +mistune==3.0.2 ; python_version >= "3.9" and python_version < "4.0" +nbclient==0.10.0 ; python_version >= "3.9" and python_version < "4.0" +nbconvert==7.16.4 ; python_version >= "3.9" and python_version < "4.0" +nbformat==5.10.4 ; python_version >= "3.9" and python_version < "4.0" +nest-asyncio==1.6.0 ; python_version >= "3.9" and python_version < "4.0" +notebook-shim==0.2.4 ; python_version >= "3.9" and python_version < "4.0" +numpy==2.0.0 ; python_version >= "3.9" and python_version < "4.0" +overrides==7.7.0 ; python_version >= "3.9" and python_version < "4.0" +packaging==24.1 ; python_version >= "3.9" and python_version < "4.0" +pandas==2.2.2 ; python_version >= "3.9" and python_version < "4.0" +pandocfilters==1.5.1 ; python_version >= "3.9" and python_version < "4.0" +parso==0.8.4 ; python_version >= "3.9" and python_version < "4.0" +pexpect==4.9.0 ; python_version >= "3.9" and python_version < "4.0" and sys_platform != "win32" +pillow==10.4.0 ; python_version >= "3.9" and python_version < "4.0" +platformdirs==4.2.2 ; python_version >= "3.9" and python_version < "4.0" +prometheus-client==0.20.0 ; python_version >= "3.9" and python_version < "4.0" +prompt-toolkit==3.0.47 ; python_version >= "3.9" and python_version < "4.0" +psutil==6.0.0 ; python_version >= "3.9" and python_version < "4.0" +ptyprocess==0.7.0 ; python_version >= "3.9" and python_version < "4.0" and (os_name != "nt" or sys_platform != "win32") +pure-eval==0.2.2 ; python_version >= "3.9" and python_version < "4.0" +pycparser==2.22 ; python_version >= "3.9" and python_version < "4.0" +pygments==2.18.0 ; python_version >= "3.9" and python_version < "4.0" +pyparsing==3.1.2 ; python_version >= "3.9" and python_version < "4.0" +python-dateutil==2.9.0.post0 ; python_version >= "3.9" and python_version < "4.0" +python-json-logger==2.0.7 ; python_version >= "3.9" and python_version < "4.0" +pytz==2024.1 ; python_version >= "3.9" and python_version < "4.0" +pywin32==306 ; sys_platform == "win32" and platform_python_implementation != "PyPy" and python_version >= "3.9" and python_version < "4.0" +pywinpty==2.0.13 ; python_version >= "3.9" and python_version < "4.0" and os_name == "nt" +pyyaml==6.0.1 ; python_version >= "3.9" and python_version < "4.0" +pyzmq==26.0.3 ; python_version >= "3.9" and python_version < "4.0" +referencing==0.35.1 ; python_version >= "3.9" and python_version < "4.0" +requests==2.32.3 ; python_version >= "3.9" and python_version < "4.0" +rfc3339-validator==0.1.4 ; python_version >= "3.9" and python_version < "4.0" +rfc3986-validator==0.1.1 ; python_version >= "3.9" and python_version < "4.0" +rpds-py==0.19.0 ; python_version >= "3.9" and python_version < "4.0" +scikit-learn==1.5.1 ; python_version >= "3.9" and python_version < "4.0" +scipy==1.13.1 ; python_version >= "3.9" and python_version < "4.0" +send2trash==1.8.3 ; python_version >= "3.9" and python_version < "4.0" +setuptools==70.3.0 ; python_version >= "3.9" and python_version < "4.0" +six==1.16.0 ; python_version >= "3.9" and python_version < "4.0" +sniffio==1.3.1 ; python_version >= "3.9" and python_version < "4.0" +soupsieve==2.5 ; python_version >= "3.9" and python_version < "4.0" +stack-data==0.6.3 ; python_version >= "3.9" and python_version < "4.0" +terminado==0.18.1 ; python_version >= "3.9" and python_version < "4.0" +threadpoolctl==3.5.0 ; python_version >= "3.9" and python_version < "4.0" +tinycss2==1.3.0 ; python_version >= "3.9" and python_version < "4.0" +tomli==2.0.1 ; python_version >= "3.9" and python_version < "3.11" +tornado==6.4.1 ; python_version >= "3.9" and python_version < "4.0" +traitlets==5.14.3 ; python_version >= "3.9" and python_version < "4.0" +types-python-dateutil==2.9.0.20240316 ; python_version >= "3.9" and python_version < "4.0" +typing-extensions==4.12.2 ; python_version >= "3.9" and python_version < "3.11" +tzdata==2024.1 ; python_version >= "3.9" and python_version < "4.0" +uri-template==1.3.0 ; python_version >= "3.9" and python_version < "4.0" +urllib3==2.2.2 ; python_version >= "3.9" and python_version < "4.0" +wcwidth==0.2.13 ; python_version >= "3.9" and python_version < "4.0" +webcolors==24.6.0 ; python_version >= "3.9" and python_version < "4.0" +webencodings==0.5.1 ; python_version >= "3.9" and python_version < "4.0" +websocket-client==1.8.0 ; python_version >= "3.9" and python_version < "4.0" +zipp==3.19.2 ; python_version >= "3.9" and python_version < "3.10" diff --git a/static/link/README.md b/static/link/README.md new file mode 100644 index 0000000..f5c9136 --- /dev/null +++ b/static/link/README.md @@ -0,0 +1,2 @@ +This folder contains small images +that are used to enhance the links in the notebooks and markdown files. diff --git a/static/link/to_gh.png b/static/link/to_gh.png new file mode 100644 index 0000000..01f1a8a Binary files /dev/null and b/static/link/to_gh.png differ 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_py.png b/static/link/to_py.png new file mode 100644 index 0000000..53c6045 Binary files /dev/null and b/static/link/to_py.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 diff --git a/static/link/to_wiki.png b/static/link/to_wiki.png new file mode 100644 index 0000000..39ccb8c Binary files /dev/null and b/static/link/to_wiki.png differ diff --git a/tasks.py b/tasks.py new file mode 100644 index 0000000..de08af5 --- /dev/null +++ b/tasks.py @@ -0,0 +1,73 @@ +"""Maintenance tasks for the project.""" + +import json +import os +import sys +import tempfile +import tomllib + +import invoke + +try: + from jupyter_client import kernelspec +except ImportError: + raise RuntimeError('Install the "ipykernel" package first') from None + + +def _ensure_venv(): + # Source: https://stackoverflow.com/questions/1871549/how-to-determine-if-python-is-running-inside-a-virtualenv # pylint:disable=C0301 + if sys.prefix == sys.base_prefix: + raise RuntimeError("Run this command in an activated `virtualenv`") + + +def _get_pyproject_name(): + with open("pyproject.toml", "rb") as fp: + data = tomllib.load(fp) + + try: + project_name = data["tool"]["poetry"]["name"] + except KeyError: + raise RuntimeError('"pyproject.toml" seems to be malformed') from None + + return project_name + + +@invoke.task +def install_kernel(_c): + """Install the activated `virtualenv` as a `jupyter kernel`. + This helper task + """ + _ensure_venv() + project_name = _get_pyproject_name() + + with tempfile.TemporaryDirectory() as tmpdir: + spec = { + "argv": [ + sys.prefix + "/bin/python", + "-m", + "ipykernel_launcher", + "-f", + "{connection_file}", + ], + "display_name": project_name, + "env": {"PATH": os.environ["PATH"]}, + "interrupt_mode": "signal", + "language": "python", + "metadata": {"debugger": True}, + } + + with open(os.path.join(tmpdir, "kernel.json"), "w", encoding="utf-8") as fp: + json.dump(spec, fp, indent=4) + + manager = kernelspec.KernelSpecManager() + manager.install_kernel_spec(tmpdir, kernel_name=project_name, user=True) + + +@invoke.task +def remove_kernel(_c): + """Remove the `jupyter kernel` corresponding to the activated `virtualenv`.""" + _ensure_venv() + project_name = _get_pyproject_name() + + manager = kernelspec.KernelSpecManager() + manager.remove_kernel_spec(project_name) diff --git a/workshop.ipynb b/workshop.ipynb deleted file mode 100644 index 16f69e8..0000000 --- a/workshop.ipynb +++ /dev/null @@ -1,1674 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Workshop: Machine Learning for Beginners" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## What is Machine Learning" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Machine learning is the process of **extracting knowledge from data** in an automated fashion.\n", - "\n", - "The use cases usually are making predictions on new and unseen data or simply understanding a given dataset better by finding patterns.\n", - "\n", - "Central to machine learning is the idea of **automating** the **decision making** from data **without** the user specifying **explicit rules** how these decisions should be made." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Examples" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Types of Machine Learning" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "- **Supervised** (focus of this workshop): Each entry in the dataset comes with a \"label\". Examples are a list of emails where spam mail is already marked as such or a sample of handwritten digits. The goal is to use the historic data to make predictions.\n", - "\n", - "- **Unsupervised**: There is no desired output associated with a data entry. In a sense, one can think of unsupervised learning as a means of discovering labels from the data itself. A popular example is the clustering of customer data.\n", - "\n", - "- **Reinforcement**: Conceptually, this can be seen as \"learning by doing\". Some kind of \"reward function\" tells how good a predicted outcome is. For example, chess computers are typically programmed with this approach." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Types of Supervised Learning" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "- In **classification** tasks, the labels are *discrete*, such as \"spam\" or \"no spam\" for emails. Often, labels are nominal (e.g., colors of something), or ordinal (e.g., T-shirt sizes in S, M, or L).\n", - "- In **regression**, the labels are *continuous*. For example, given a person's age, education, and position, infer his/her salary." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Case Study: Iris Flower Classification" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Python for Scientific Computing: A brief Introduction" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Python itself does not come with any scientific algorithms. However, over time, many open source libraries emerged that are useful to build machine learning applications.\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", - "First, import the libraries:" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "import numpy as np\n", - "import pandas as pd\n", - "import matplotlib.pyplot as plt" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The following line is needed so that this Jupyter notebook creates the visiualizations in the notebook and not in a new window. This has nothing to do with Python." - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], - "source": [ - "%matplotlib inline" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Standard Python can do basic arithmetic operations ..." - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "3" - ] - }, - "execution_count": 3, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "a = 1\n", - "b = 2\n", - "\n", - "c = a + b\n", - "\n", - "c" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "... and provides some simple **data structures**, such as a list of values." - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[1, 2, 3, 4]" - ] - }, - "execution_count": 4, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "l = [a, b, c, 4]\n", - "\n", - "l" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Numpy provides a data structure 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. Arrays allow for much faster computations as they are implemented in the very fast [C language](https://en.wikipedia.org/wiki/C_%28programming_language%29)." - ] - }, - { - "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) function from the imported `np` module and provide it with a `list` of values." - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "array([1, 2, 3])" - ] - }, - "execution_count": 5, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "v1 = np.array([1, 2, 3])\n", - "\n", - "v1" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "A vector can be multiplied with a scalar." - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "array([3, 6, 9])" - ] - }, - "execution_count": 6, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "v2 = v1 * 3\n", - "\n", - "v2" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To create a matrix, just use a list of (row) list of values instead." - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "array([[1, 2, 3],\n", - " [4, 5, 6]])" - ] - }, - "execution_count": 7, - "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 to multiply a matrix with a vector to obtain a new vector ..." - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "array([14, 32])" - ] - }, - "execution_count": 8, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "v3 = np.dot(m1, v1)\n", - "\n", - "v3" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "... or simply transpose it." - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "array([[1, 4],\n", - " [2, 5],\n", - " [3, 6]])" - ] - }, - "execution_count": 9, - "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": 10, - "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 (= subset) of an array's data, we can \"index\" into it. For example, the first row of the matrix is ..." - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "array([1, 2, 3])" - ] - }, - "execution_count": 11, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "m1[0, :]" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "... while the second column is:" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "array([2, 5])" - ] - }, - "execution_count": 12, - "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": 13, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "6" - ] - }, - "execution_count": 13, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "m1[1, 2]" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Numpy also provides various other functions and constants, such as sinus or pi. To further illustrate the concept of **vectorization**, let us calculate the sinus curve over a range of values." - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "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": 14, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "x = np.linspace(-3*np.pi, 3*np.pi, 100)\n", - "\n", - "x" - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "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": 15, - "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": 16, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[]" - ] - }, - "execution_count": 16, - "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": [ - "Let us quickly generate some random data and draw a scatter plot." - ] - }, - { - "cell_type": "code", - "execution_count": 17, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 17, - "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)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Case Study (continued): Importing the Iris data" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The sklearn library provides several sample datasets, among which is also the Iris dataset.\n", - "\n", - "As a table, the dataset would look like:\n", - "\n", - "\n", - "However, the data object imported from sklearn is organized slightly different. In particular, the so-called **features** are seperated from the **labels**." - ] - }, - { - "cell_type": "code", - "execution_count": 18, - "metadata": {}, - "outputs": [], - "source": [ - "from sklearn.datasets import load_iris" - ] - }, - { - "cell_type": "code", - "execution_count": 19, - "metadata": {}, - "outputs": [], - "source": [ - "iris = load_iris()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Using Python's **dir()** function we can inspect the data object, i.e. find out what **attributes** it has." - ] - }, - { - "cell_type": "code", - "execution_count": 20, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "['DESCR',\n", - " 'data',\n", - " 'feature_names',\n", - " 'filename',\n", - " 'frame',\n", - " 'target',\n", - " 'target_names']" - ] - }, - "execution_count": 20, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "dir(iris)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "iris.data provides us with a Numpy array, where the first dimension equals the number of observed flowers (**instances**) and the second dimension lists the various features of a flower." - ] - }, - { - "cell_type": "code", - "execution_count": 21, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "array([[5.1, 3.5, 1.4, 0.2],\n", - " [4.9, 3. , 1.4, 0.2],\n", - " [4.7, 3.2, 1.3, 0.2],\n", - " [4.6, 3.1, 1.5, 0.2],\n", - " [5. , 3.6, 1.4, 0.2],\n", - " [5.4, 3.9, 1.7, 0.4],\n", - " [4.6, 3.4, 1.4, 0.3],\n", - " [5. , 3.4, 1.5, 0.2],\n", - " [4.4, 2.9, 1.4, 0.2],\n", - " [4.9, 3.1, 1.5, 0.1],\n", - " [5.4, 3.7, 1.5, 0.2],\n", - " [4.8, 3.4, 1.6, 0.2],\n", - " [4.8, 3. , 1.4, 0.1],\n", - " [4.3, 3. , 1.1, 0.1],\n", - " [5.8, 4. , 1.2, 0.2],\n", - " [5.7, 4.4, 1.5, 0.4],\n", - " [5.4, 3.9, 1.3, 0.4],\n", - " [5.1, 3.5, 1.4, 0.3],\n", - " [5.7, 3.8, 1.7, 0.3],\n", - " [5.1, 3.8, 1.5, 0.3],\n", - " [5.4, 3.4, 1.7, 0.2],\n", - " [5.1, 3.7, 1.5, 0.4],\n", - " [4.6, 3.6, 1. , 0.2],\n", - " [5.1, 3.3, 1.7, 0.5],\n", - " [4.8, 3.4, 1.9, 0.2],\n", - " [5. , 3. , 1.6, 0.2],\n", - " [5. , 3.4, 1.6, 0.4],\n", - " [5.2, 3.5, 1.5, 0.2],\n", - " [5.2, 3.4, 1.4, 0.2],\n", - " [4.7, 3.2, 1.6, 0.2],\n", - " [4.8, 3.1, 1.6, 0.2],\n", - " [5.4, 3.4, 1.5, 0.4],\n", - " [5.2, 4.1, 1.5, 0.1],\n", - " [5.5, 4.2, 1.4, 0.2],\n", - " [4.9, 3.1, 1.5, 0.2],\n", - " [5. , 3.2, 1.2, 0.2],\n", - " [5.5, 3.5, 1.3, 0.2],\n", - " [4.9, 3.6, 1.4, 0.1],\n", - " [4.4, 3. , 1.3, 0.2],\n", - " [5.1, 3.4, 1.5, 0.2],\n", - " [5. , 3.5, 1.3, 0.3],\n", - " [4.5, 2.3, 1.3, 0.3],\n", - " [4.4, 3.2, 1.3, 0.2],\n", - " [5. , 3.5, 1.6, 0.6],\n", - " [5.1, 3.8, 1.9, 0.4],\n", - " [4.8, 3. , 1.4, 0.3],\n", - " [5.1, 3.8, 1.6, 0.2],\n", - " [4.6, 3.2, 1.4, 0.2],\n", - " [5.3, 3.7, 1.5, 0.2],\n", - " [5. , 3.3, 1.4, 0.2],\n", - " [7. , 3.2, 4.7, 1.4],\n", - " [6.4, 3.2, 4.5, 1.5],\n", - " [6.9, 3.1, 4.9, 1.5],\n", - " [5.5, 2.3, 4. , 1.3],\n", - " [6.5, 2.8, 4.6, 1.5],\n", - " [5.7, 2.8, 4.5, 1.3],\n", - " [6.3, 3.3, 4.7, 1.6],\n", - " [4.9, 2.4, 3.3, 1. ],\n", - " [6.6, 2.9, 4.6, 1.3],\n", - " [5.2, 2.7, 3.9, 1.4],\n", - " [5. , 2. , 3.5, 1. ],\n", - " [5.9, 3. , 4.2, 1.5],\n", - " [6. , 2.2, 4. , 1. ],\n", - " [6.1, 2.9, 4.7, 1.4],\n", - " [5.6, 2.9, 3.6, 1.3],\n", - " [6.7, 3.1, 4.4, 1.4],\n", - " [5.6, 3. , 4.5, 1.5],\n", - " [5.8, 2.7, 4.1, 1. ],\n", - " [6.2, 2.2, 4.5, 1.5],\n", - " [5.6, 2.5, 3.9, 1.1],\n", - " [5.9, 3.2, 4.8, 1.8],\n", - " [6.1, 2.8, 4. , 1.3],\n", - " [6.3, 2.5, 4.9, 1.5],\n", - " [6.1, 2.8, 4.7, 1.2],\n", - " [6.4, 2.9, 4.3, 1.3],\n", - " [6.6, 3. , 4.4, 1.4],\n", - " [6.8, 2.8, 4.8, 1.4],\n", - " [6.7, 3. , 5. , 1.7],\n", - " [6. , 2.9, 4.5, 1.5],\n", - " [5.7, 2.6, 3.5, 1. ],\n", - " [5.5, 2.4, 3.8, 1.1],\n", - " [5.5, 2.4, 3.7, 1. ],\n", - " [5.8, 2.7, 3.9, 1.2],\n", - " [6. , 2.7, 5.1, 1.6],\n", - " [5.4, 3. , 4.5, 1.5],\n", - " [6. , 3.4, 4.5, 1.6],\n", - " [6.7, 3.1, 4.7, 1.5],\n", - " [6.3, 2.3, 4.4, 1.3],\n", - " [5.6, 3. , 4.1, 1.3],\n", - " [5.5, 2.5, 4. , 1.3],\n", - " [5.5, 2.6, 4.4, 1.2],\n", - " [6.1, 3. , 4.6, 1.4],\n", - " [5.8, 2.6, 4. , 1.2],\n", - " [5. , 2.3, 3.3, 1. ],\n", - " [5.6, 2.7, 4.2, 1.3],\n", - " [5.7, 3. , 4.2, 1.2],\n", - " [5.7, 2.9, 4.2, 1.3],\n", - " [6.2, 2.9, 4.3, 1.3],\n", - " [5.1, 2.5, 3. , 1.1],\n", - " [5.7, 2.8, 4.1, 1.3],\n", - " [6.3, 3.3, 6. , 2.5],\n", - " [5.8, 2.7, 5.1, 1.9],\n", - " [7.1, 3. , 5.9, 2.1],\n", - " [6.3, 2.9, 5.6, 1.8],\n", - " [6.5, 3. , 5.8, 2.2],\n", - " [7.6, 3. , 6.6, 2.1],\n", - " [4.9, 2.5, 4.5, 1.7],\n", - " [7.3, 2.9, 6.3, 1.8],\n", - " [6.7, 2.5, 5.8, 1.8],\n", - " [7.2, 3.6, 6.1, 2.5],\n", - " [6.5, 3.2, 5.1, 2. ],\n", - " [6.4, 2.7, 5.3, 1.9],\n", - " [6.8, 3. , 5.5, 2.1],\n", - " [5.7, 2.5, 5. , 2. ],\n", - " [5.8, 2.8, 5.1, 2.4],\n", - " [6.4, 3.2, 5.3, 2.3],\n", - " [6.5, 3. , 5.5, 1.8],\n", - " [7.7, 3.8, 6.7, 2.2],\n", - " [7.7, 2.6, 6.9, 2.3],\n", - " [6. , 2.2, 5. , 1.5],\n", - " [6.9, 3.2, 5.7, 2.3],\n", - " [5.6, 2.8, 4.9, 2. ],\n", - " [7.7, 2.8, 6.7, 2. ],\n", - " [6.3, 2.7, 4.9, 1.8],\n", - " [6.7, 3.3, 5.7, 2.1],\n", - " [7.2, 3.2, 6. , 1.8],\n", - " [6.2, 2.8, 4.8, 1.8],\n", - " [6.1, 3. , 4.9, 1.8],\n", - " [6.4, 2.8, 5.6, 2.1],\n", - " [7.2, 3. , 5.8, 1.6],\n", - " [7.4, 2.8, 6.1, 1.9],\n", - " [7.9, 3.8, 6.4, 2. ],\n", - " [6.4, 2.8, 5.6, 2.2],\n", - " [6.3, 2.8, 5.1, 1.5],\n", - " [6.1, 2.6, 5.6, 1.4],\n", - " [7.7, 3. , 6.1, 2.3],\n", - " [6.3, 3.4, 5.6, 2.4],\n", - " [6.4, 3.1, 5.5, 1.8],\n", - " [6. , 3. , 4.8, 1.8],\n", - " [6.9, 3.1, 5.4, 2.1],\n", - " [6.7, 3.1, 5.6, 2.4],\n", - " [6.9, 3.1, 5.1, 2.3],\n", - " [5.8, 2.7, 5.1, 1.9],\n", - " [6.8, 3.2, 5.9, 2.3],\n", - " [6.7, 3.3, 5.7, 2.5],\n", - " [6.7, 3. , 5.2, 2.3],\n", - " [6.3, 2.5, 5. , 1.9],\n", - " [6.5, 3. , 5.2, 2. ],\n", - " [6.2, 3.4, 5.4, 2.3],\n", - " [5.9, 3. , 5.1, 1.8]])" - ] - }, - "execution_count": 21, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "iris.data" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To find out what the four features are, we can list them:" - ] - }, - { - "cell_type": "code", - "execution_count": 22, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "['sepal length (cm)',\n", - " 'sepal width (cm)',\n", - " 'petal length (cm)',\n", - " 'petal width (cm)']" - ] - }, - "execution_count": 22, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "iris.feature_names" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Similarly, we can also print the flowers' labels (a.k.a. targets):" - ] - }, - { - "cell_type": "code", - "execution_count": 23, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n", - " 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n", - " 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n", - " 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n", - " 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,\n", - " 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,\n", - " 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2])" - ] - }, - "execution_count": 23, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "iris.target" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The three flower classes are encoded with integers. Let's show the corresponding names:" - ] - }, - { - "cell_type": "code", - "execution_count": 24, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "array(['setosa', 'versicolor', 'virginica'], dtype='" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "feature_index = 2\n", - "colors = ['blue', 'red', 'green']\n", - "\n", - "for label, color in zip(range(len(iris.target_names)), colors):\n", - " plt.hist(iris.data[iris.target==label, feature_index], \n", - " label=iris.target_names[label],\n", - " color=color)\n", - "\n", - "plt.xlabel(iris.feature_names[feature_index])\n", - "plt.legend(loc='upper right')\n", - "plt.show()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Also, we can draw scatter plots of two features." - ] - }, - { - "cell_type": "code", - "execution_count": 26, - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "first_feature_index = 1\n", - "second_feature_index = 0\n", - "\n", - "colors = ['blue', 'red', 'green']\n", - "\n", - "for label, color in zip(range(len(iris.target_names)), colors):\n", - " plt.scatter(iris.data[iris.target==label, first_feature_index], \n", - " iris.data[iris.target==label, second_feature_index],\n", - " label=iris.target_names[label],\n", - " c=color)\n", - "\n", - "plt.xlabel(iris.feature_names[first_feature_index])\n", - "plt.ylabel(iris.feature_names[second_feature_index])\n", - "plt.legend(loc='upper left')\n", - "plt.show()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Using the higher level library pandas, one can easily create a so-called **scatterplot matrix**." - ] - }, - { - "cell_type": "code", - "execution_count": 27, - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "iris_df = pd.DataFrame(iris.data, columns=iris.feature_names)\n", - "\n", - "pd.plotting.scatter_matrix(iris_df, figsize=(8, 8));" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Concept of Generalization" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The goal of a supervised machine learning model is to make predictions on new (i.e., previously unseen) data.\n", - "\n", - "In a real-world application, we are not interested in marking an already labeled email as spam or not. Instead, we want to make the user's life easier by automatically classifying new incoming mail.\n", - "\n", - "In order to get an idea of how good a model generalizes, a best practice is to split the available data into a training and a test set. Only the former is used to train the model. Then predictions are made on the test data and the predictions can be compared with the actual labels.\n", - "\n", - "Common splits are 75/25 or 60/40." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Case Study (continued): Train/Test Split for the Iris data" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "It is common practice to refer to the feature matrix as X and the vector of labels as y." - ] - }, - { - "cell_type": "code", - "execution_count": 28, - "metadata": {}, - "outputs": [], - "source": [ - "X, y = iris.data, iris.target" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "A naive splitting approach could be to use array slicing." - ] - }, - { - "cell_type": "code", - "execution_count": 29, - "metadata": {}, - "outputs": [], - "source": [ - "X_train, X_test, y_train, y_test = X[0:100, :], X[100:150, :], y[0:100], y[100:150]" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "However, this would lead to unbalanced label distributions. For example, the test set would only be made up of flowers of the same type." - ] - }, - { - "cell_type": "code", - "execution_count": 30, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "array([2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,\n", - " 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,\n", - " 2, 2, 2, 2, 2, 2])" - ] - }, - "execution_count": 30, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "y_test" - ] - }, - { - "cell_type": "code", - "execution_count": 31, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "array([ 0, 0, 50])" - ] - }, - "execution_count": 31, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "np.bincount(y_test)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "sklearn provides a function that not only randomizes the split but also ensures that the resulting label distribution is proportionate to the overall distribution (called **stratification**)." - ] - }, - { - "cell_type": "code", - "execution_count": 32, - "metadata": {}, - "outputs": [], - "source": [ - "from sklearn.model_selection import train_test_split" - ] - }, - { - "cell_type": "code", - "execution_count": 33, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "array([0, 0, 1, 2, 0, 0, 1, 1, 2, 0, 2, 0, 1, 0, 2, 0, 2, 1, 2, 0, 2, 2,\n", - " 2, 1, 2, 0, 2, 1, 1, 1, 1, 1, 0, 0, 2, 1, 2, 1, 0, 0, 1, 2, 1, 0,\n", - " 2])" - ] - }, - "execution_count": 33, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "X_train, X_test, y_train, y_test = train_test_split(X, y, train_size=0.7, test_size=0.3, stratify=y)\n", - "\n", - "y_test" - ] - }, - { - "cell_type": "code", - "execution_count": 34, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "array([15, 15, 15])" - ] - }, - "execution_count": 34, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "np.bincount(y_test)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## A simple Classification Model: k-Nearest Neighbors" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To predict the label for any observation, just determine the k \"nearest\" observations in the training set (e.g., by Euclidean distance) and use a simple majority vote." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Case Study (continued): Train and Predict the Iris data" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "sklearn provides a uniform interface for all its classification models. They all have a **fit()** and a **predict()** method that abstract away the actual machine learning algorithm." - ] - }, - { - "cell_type": "code", - "execution_count": 35, - "metadata": {}, - "outputs": [], - "source": [ - "from sklearn.neighbors import KNeighborsClassifier" - ] - }, - { - "cell_type": "code", - "execution_count": 36, - "metadata": {}, - "outputs": [], - "source": [ - "knn = KNeighborsClassifier(n_neighbors=5)\n", - "\n", - "knn.fit(X_train, y_train)\n", - "\n", - "y_pred = knn.predict(X_test)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us list the labels predicted for the test set ..." - ] - }, - { - "cell_type": "code", - "execution_count": 37, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "array([0, 0, 1, 2, 0, 0, 1, 1, 2, 0, 2, 0, 1, 0, 2, 0, 2, 1, 2, 0, 2, 2,\n", - " 2, 1, 2, 0, 2, 1, 1, 1, 1, 1, 0, 0, 2, 1, 2, 1, 0, 0, 1, 2, 1, 0,\n", - " 2])" - ] - }, - "execution_count": 37, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "y_pred" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "... and compare them with the actual labels." - ] - }, - { - "cell_type": "code", - "execution_count": 38, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "array([0, 0, 1, 2, 0, 0, 1, 1, 2, 0, 2, 0, 1, 0, 2, 0, 2, 1, 2, 0, 2, 2,\n", - " 2, 1, 2, 0, 2, 1, 1, 1, 1, 1, 0, 0, 2, 1, 2, 1, 0, 0, 1, 2, 1, 0,\n", - " 2])" - ] - }, - "execution_count": 38, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "y_test" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Numpy can show us the indices where the predictions are wrong." - ] - }, - { - "cell_type": "code", - "execution_count": 39, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "(array([], dtype=int64),)" - ] - }, - "execution_count": 39, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "np.where(y_pred != y_test)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Alternatively, we can calculate the fraction of correctly predicted flowers." - ] - }, - { - "cell_type": "code", - "execution_count": 40, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "1.0" - ] - }, - "execution_count": 40, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "np.sum(y_pred == y_test) / len(y_test)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "It is important to mention that we can also \"predict\" the training set. Surprisingly, the model does not get the training set 100% correct." - ] - }, - { - "cell_type": "code", - "execution_count": 41, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "0.9523809523809523" - ] - }, - "execution_count": 41, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "y_train_pred = knn.predict(X_train)\n", - "\n", - "np.sum(y_train_pred == y_train) / len(y_train)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "A visualization reveals that the misclassified flowers are right \"at the borderline\" between two neighboring clusters of flower classes." - ] - }, - { - "cell_type": "code", - "execution_count": 42, - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "first_feature_index = 3\n", - "second_feature_index = 0\n", - "\n", - "correct_idx = np.where(y_pred == y_test)[0]\n", - "incorrect_idx = np.where(y_pred != y_test)[0]\n", - "\n", - "colors = [\"darkblue\", \"darkgreen\", \"gray\"]\n", - "\n", - "for n, color in enumerate(colors):\n", - " idx = np.where(y_test == n)[0]\n", - " plt.scatter(X_test[idx, first_feature_index], X_test[idx, second_feature_index], color=color,\n", - " label=iris.target_names[n])\n", - "\n", - "plt.scatter(X_test[incorrect_idx, first_feature_index], X_test[incorrect_idx, second_feature_index],\n", - " color=\"darkred\", label='misclassified')\n", - "\n", - "plt.xlabel('sepal width [cm]')\n", - "plt.ylabel('petal length [cm]')\n", - "plt.legend(loc='best')\n", - "plt.title(\"Iris Classification results\")\n", - "plt.show()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "In practice, the number of neighbors is to chosen before the model is trained. Therefore, it is possible to \"optimize\" it. This process is referred to as **hyper-parameter** tuning. For the Iris dataset this does not make much of a difference." - ] - }, - { - "cell_type": "code", - "execution_count": 43, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "1 1.0\n", - "2 0.9555555555555556\n", - "3 1.0\n", - "4 0.9777777777777777\n", - "5 1.0\n", - "6 1.0\n", - "7 1.0\n", - "8 0.9777777777777777\n", - "9 0.9777777777777777\n", - "10 0.9777777777777777\n", - "11 0.9777777777777777\n", - "12 0.9777777777777777\n", - "13 1.0\n", - "14 0.9777777777777777\n", - "15 0.9555555555555556\n", - "16 0.9777777777777777\n", - "17 0.9555555555555556\n", - "18 0.9777777777777777\n", - "19 0.9777777777777777\n", - "20 0.9777777777777777\n", - "21 0.9555555555555556\n", - "22 0.9777777777777777\n", - "23 0.9555555555555556\n", - "24 0.9777777777777777\n", - "25 0.9555555555555556\n", - "26 0.9777777777777777\n", - "27 0.9555555555555556\n", - "28 0.9777777777777777\n", - "29 0.9777777777777777\n", - "30 0.9777777777777777\n" - ] - } - ], - "source": [ - "for i in range(1, 31):\n", - " knn = KNeighborsClassifier(n_neighbors=i)\n", - " knn.fit(X_train, y_train)\n", - " y_pred = knn.predict(X_test)\n", - " correct = np.sum(y_pred == y_test) / len(y_test)\n", - " print(i, correct)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## WHU's Python Course in the BSc program" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "- free [online book](https://github.com/webartifex/intro-to-python) by the author of this workshop" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Literature on Machine Learning" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Depending on the programming language one chooses, the following books are recommended:" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "- [Python Machine Learning](https://www.amazon.de/Python-Machine-Learning-scikit-learn-TensorFlow/dp/1787125939/ref=sr_1_1?__mk_de_DE=%C3%85M%C3%85%C5%BD%C3%95%C3%91&keywords=python+machine+learning&qid=1575545025&sr=8-1) by Sebastian Raschka\n", - "\n", - "" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "- [An Introduction to Statistical Learning](http://faculty.marshall.usc.edu/gareth-james/ISL/)\n", - "\n", - "" - ] - } - ], - "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.7.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 -}