├── .gitignore ├── LICENSE ├── README.md └── notebooks ├── EX-1.0-Getting-to-Know-the-Clickhouse-driver-Client.ipynb ├── EX-1.1-Something-You-Should-Not-Do.ipynb ├── EX-2-ClickHouse-SQL-Alchemy.ipynb ├── EX-3-Sql-Magic-Functions.ipynb ├── EX-4-Pivot-Using-SQL-And-Pandas.ipynb ├── EX-5-Airline-OnTime-Data.ipynb ├── README.md ├── iris.csv └── iris_with_names.csv /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | *.egg-info/ 24 | .installed.cfg 25 | *.egg 26 | MANIFEST 27 | 28 | # PyInstaller 29 | # Usually these files are written by a python script from a template 30 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 31 | *.manifest 32 | *.spec 33 | 34 | # Installer logs 35 | pip-log.txt 36 | pip-delete-this-directory.txt 37 | 38 | # Unit test / coverage reports 39 | htmlcov/ 40 | .tox/ 41 | .coverage 42 | .coverage.* 43 | .cache 44 | nosetests.xml 45 | coverage.xml 46 | *.cover 47 | .hypothesis/ 48 | .pytest_cache/ 49 | 50 | # Translations 51 | *.mo 52 | *.pot 53 | 54 | # Django stuff: 55 | *.log 56 | local_settings.py 57 | db.sqlite3 58 | 59 | # Flask stuff: 60 | instance/ 61 | .webassets-cache 62 | 63 | # Scrapy stuff: 64 | .scrapy 65 | 66 | # Sphinx documentation 67 | docs/_build/ 68 | 69 | # PyBuilder 70 | target/ 71 | 72 | # Jupyter Notebook 73 | .ipynb_checkpoints 74 | 75 | # pyenv 76 | .python-version 77 | 78 | # celery beat schedule file 79 | celerybeat-schedule 80 | 81 | # SageMath parsed files 82 | *.sage.py 83 | 84 | # Environments 85 | .env 86 | .venv 87 | env/ 88 | venv/ 89 | ENV/ 90 | env.bak/ 91 | venv.bak/ 92 | 93 | # Spyder project settings 94 | .spyderproject 95 | .spyproject 96 | 97 | # Rope project settings 98 | .ropeproject 99 | 100 | # mkdocs documentation 101 | /site 102 | 103 | # mypy 104 | .mypy_cache/ 105 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Altinity 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ClickHouse Python Samples 2 | 3 | This project contains Python samples for ClickHouse. For now the samples 4 | consist of Jupyter Notebook files in the notebooks directory. 5 | -------------------------------------------------------------------------------- /notebooks/EX-1.0-Getting-to-Know-the-Clickhouse-driver-Client.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Getting to know the ClickHouse-driver Client\n", 8 | "\n", 9 | "This notebook has samples that were included in the [Altinity blog article that introduces the clickhouse-driver client library](https://www.altinity.com/blog/clickhouse-and-python-getting-to-know-the-clickhouse-driver-client).\n", 10 | "\n", 11 | "_WARNING_: If you run the whole notebook it will hang. You must run the samples one by one as one of them is designed to hang and must be cancelled manually. " 12 | ] 13 | }, 14 | { 15 | "cell_type": "markdown", 16 | "metadata": {}, 17 | "source": [ 18 | "It's easy to load the clickhouse driver. The `Client` class is the main client interface. " 19 | ] 20 | }, 21 | { 22 | "cell_type": "code", 23 | "execution_count": null, 24 | "metadata": {}, 25 | "outputs": [], 26 | "source": [ 27 | "from clickhouse_driver import Client" 28 | ] 29 | }, 30 | { 31 | "cell_type": "markdown", 32 | "metadata": {}, 33 | "source": [ 34 | "If you are running against an unencrypted local server setting up a connection is as simple as the following. Instantiating a client does not actually connect to ClickHouse. It just sets up the data structure used to connect later on when your code does something. " 35 | ] 36 | }, 37 | { 38 | "cell_type": "code", 39 | "execution_count": null, 40 | "metadata": {}, 41 | "outputs": [], 42 | "source": [ 43 | "client = Client('localhost')" 44 | ] 45 | }, 46 | { 47 | "cell_type": "markdown", 48 | "metadata": {}, 49 | "source": [ 50 | "Servers with sensitive data should be encrypted with a user/password and encrypted communications. The following command shows how to connect to a server with self-signed certificate using an explicit database name. " 51 | ] 52 | }, 53 | { 54 | "cell_type": "code", 55 | "execution_count": null, 56 | "metadata": {}, 57 | "outputs": [], 58 | "source": [ 59 | "client = Client('localhost', \n", 60 | " user='python', \n", 61 | " password='secret', \n", 62 | " secure=True, \n", 63 | " verify=False, \n", 64 | " database='default',\n", 65 | " compression=True)" 66 | ] 67 | }, 68 | { 69 | "cell_type": "markdown", 70 | "metadata": {}, 71 | "source": [ 72 | "The Python driver uses the Client.execute() method to issue select commands. Results are returned as a list of tuples. Let's send a very simple query and take apart the results to see values and types. \n", 73 | "\n", 74 | "*NOTE*: If you get an error about an unknown timezone, ensure your server has the timezone set properly. " 75 | ] 76 | }, 77 | { 78 | "cell_type": "code", 79 | "execution_count": null, 80 | "metadata": { 81 | "scrolled": false 82 | }, 83 | "outputs": [], 84 | "source": [ 85 | "result = client.execute('SELECT now(), version()')\n", 86 | "print(\"RESULT: {0}: {1}\".format(type(result), result))\n", 87 | "for t in result:\n", 88 | " print(\" ROW: {0}: {1}\".format(type(t), t))\n", 89 | " for v in t:\n", 90 | " print(\" COLUMN: {0}: {1}\".format(type(v), v))" 91 | ] 92 | }, 93 | { 94 | "cell_type": "markdown", 95 | "metadata": {}, 96 | "source": [ 97 | "Create the iris table, dropping any previously existing table of the same name. The print statements show that result sets from DDL are empty. " 98 | ] 99 | }, 100 | { 101 | "cell_type": "code", 102 | "execution_count": null, 103 | "metadata": {}, 104 | "outputs": [], 105 | "source": [ 106 | "r1 = client.execute('DROP TABLE IF EXISTS iris')\n", 107 | "print(r1)\n", 108 | "r2 = client.execute('CREATE TABLE iris ('\n", 109 | " 'sepal_length Float64, sepal_width Float64, '\n", 110 | " 'petal_length Float64, petal_width Float64, '\n", 111 | " 'species String) ENGINE = MergeTree '\n", 112 | " ' PARTITION BY species ORDER BY (species)')\n", 113 | "print(r2)" 114 | ] 115 | }, 116 | { 117 | "cell_type": "markdown", 118 | "metadata": {}, 119 | "source": [ 120 | "Add some data to the table. Note that the values are given in a separate array of tuples. " 121 | ] 122 | }, 123 | { 124 | "cell_type": "code", 125 | "execution_count": null, 126 | "metadata": {}, 127 | "outputs": [], 128 | "source": [ 129 | "client.execute(\n", 130 | " 'INSERT INTO iris (sepal_length, sepal_width, petal_length, petal_width, species) VALUES',\n", 131 | " [(5.1, 3.7, 1.5, 0.4, 'Iris-setosa'), (4.6, 3.6, 1.0, 0.2, 'Iris-setosa')]\n", 132 | ")\n", 133 | "print(client.execute(\"SELECT * FROM iris\"))" 134 | ] 135 | }, 136 | { 137 | "cell_type": "markdown", 138 | "metadata": {}, 139 | "source": [ 140 | "Here is an example of how to insert CSV. We read the values line by line using csv.DictReader() running inside the generator function row_reader(). This results in a tuple for each line. Note that *you must* assign types or your values will not convert. The csv module converts everything to a string. " 141 | ] 142 | }, 143 | { 144 | "cell_type": "code", 145 | "execution_count": null, 146 | "metadata": { 147 | "scrolled": true 148 | }, 149 | "outputs": [], 150 | "source": [ 151 | "client.execute(\"TRUNCATE TABLE iris\")\n", 152 | "\n", 153 | "import datetime\n", 154 | "import csv\n", 155 | "\n", 156 | "# Create a generator to fetch parsed rows. CSV must have variable names in header row.\n", 157 | "def row_reader():\n", 158 | " with open('iris_with_names.csv') as iris_csv:\n", 159 | " # Use DictReader to get values as a dictionary with column names.\n", 160 | " for line in csv.DictReader(iris_csv):\n", 161 | " yield {\n", 162 | " 'sepal_length': float(line['sepal_length']), \n", 163 | " 'sepal_width': float(line['sepal_width']), \n", 164 | " 'petal_length': float(line['petal_length']), \n", 165 | " 'petal_width': float(line['petal_width']), \n", 166 | " 'species': str(line['species']), \n", 167 | " }\n", 168 | "\n", 169 | "# Use a generator expression to load values as a list of dictionaries. \n", 170 | "client.execute(\"INSERT INTO iris VALUES\", (line for line in row_reader()))\n", 171 | "client.execute(\"SELECT count(*) FROM iris\")" 172 | ] 173 | }, 174 | { 175 | "cell_type": "markdown", 176 | "metadata": {}, 177 | "source": [ 178 | "That was painful. We dislike pain. A better approach to non-toy CSV files is to use Pandas, which has a very good method for reading CSV that automatically coerces types. This is much simpler! " 179 | ] 180 | }, 181 | { 182 | "cell_type": "code", 183 | "execution_count": null, 184 | "metadata": {}, 185 | "outputs": [], 186 | "source": [ 187 | "client.execute(\"TRUNCATE TABLE iris\")\n", 188 | "\n", 189 | "import pandas as pd\n", 190 | "df = pd.read_csv('iris_with_names.csv')\n", 191 | "\n", 192 | "client.execute(\"INSERT INTO iris VALUES\", [tuple(x) for x in df.values])\n", 193 | "client.execute(\"SELECT count(*) FROM iris\")" 194 | ] 195 | }, 196 | { 197 | "cell_type": "markdown", 198 | "metadata": {}, 199 | "source": [ 200 | "The next few queries show examples of select statements. " 201 | ] 202 | }, 203 | { 204 | "cell_type": "code", 205 | "execution_count": null, 206 | "metadata": {}, 207 | "outputs": [], 208 | "source": [ 209 | "result = client.execute('SELECT COUNT(*), species FROM iris '\n", 210 | " 'WHERE petal_length > 3.4 '\n", 211 | " 'GROUP BY species ORDER BY species')\n", 212 | "print(result)" 213 | ] 214 | }, 215 | { 216 | "cell_type": "code", 217 | "execution_count": null, 218 | "metadata": {}, 219 | "outputs": [], 220 | "source": [ 221 | "result = client.execute('SELECT COUNT(*), species FROM iris '\n", 222 | " 'WHERE petal_length > %(max_len)s '\n", 223 | " 'GROUP BY species ORDER BY species', \n", 224 | " {'max_len': 3.4})\n", 225 | "print(result)" 226 | ] 227 | }, 228 | { 229 | "cell_type": "markdown", 230 | "metadata": {}, 231 | "source": [ 232 | "Show how to get the column names for results. Note that we also get the column types, which is convenient for conversions. " 233 | ] 234 | }, 235 | { 236 | "cell_type": "code", 237 | "execution_count": null, 238 | "metadata": {}, 239 | "outputs": [], 240 | "source": [ 241 | "result, columns = client.execute('SELECT COUNT(*), species FROM iris '\n", 242 | " 'WHERE petal_length > %(max_len)s '\n", 243 | " 'GROUP BY species ORDER BY species', \n", 244 | " {'max_len': 3.4},\n", 245 | " with_column_types=True)\n", 246 | "print(result)\n", 247 | "print(columns)" 248 | ] 249 | }, 250 | { 251 | "cell_type": "markdown", 252 | "metadata": {}, 253 | "source": [ 254 | "This final example shows how to put a result set into a pandas data frame. We'll use the column names so that the DataFrame has correct labels." 255 | ] 256 | }, 257 | { 258 | "cell_type": "code", 259 | "execution_count": null, 260 | "metadata": { 261 | "scrolled": true 262 | }, 263 | "outputs": [], 264 | "source": [ 265 | "import pandas\n", 266 | "result, columns = client.execute('SELECT * FROM iris WHERE species = %(species)s LIMIT 5', \n", 267 | " {'species': \"Iris-setosa\"}, with_column_types=True)\n", 268 | "df = pandas.DataFrame(result, columns=[tuple[0] for tuple in columns])\n", 269 | "df.tail()" 270 | ] 271 | }, 272 | { 273 | "cell_type": "markdown", 274 | "metadata": {}, 275 | "source": [ 276 | "Since we're using pandas and may like to put this data into graphs, etc., we need to ensure the data types are correct. Let's describe the data set to ensure that the columns with numbers really appear as numbers. The following should show metrics for length and width values but nothing for species, which is a string. " 277 | ] 278 | }, 279 | { 280 | "cell_type": "code", 281 | "execution_count": null, 282 | "metadata": {}, 283 | "outputs": [], 284 | "source": [ 285 | "df.describe()" 286 | ] 287 | }, 288 | { 289 | "cell_type": "code", 290 | "execution_count": null, 291 | "metadata": {}, 292 | "outputs": [], 293 | "source": [] 294 | } 295 | ], 296 | "metadata": { 297 | "kernelspec": { 298 | "display_name": "Python 3", 299 | "language": "python", 300 | "name": "python3" 301 | }, 302 | "language_info": { 303 | "codemirror_mode": { 304 | "name": "ipython", 305 | "version": 3 306 | }, 307 | "file_extension": ".py", 308 | "mimetype": "text/x-python", 309 | "name": "python", 310 | "nbconvert_exporter": "python", 311 | "pygments_lexer": "ipython3", 312 | "version": "3.7.1" 313 | } 314 | }, 315 | "nbformat": 4, 316 | "nbformat_minor": 2 317 | } 318 | -------------------------------------------------------------------------------- /notebooks/EX-1.1-Something-You-Should-Not-Do.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Something You Should Not Do\n", 8 | "\n", 9 | "This notebook has samples that were included in the [Altinity blog article that introduces the clickhouse-driver client library](https://www.altinity.com/blog/clickhouse-and-python-getting-to-know-the-clickhouse-driver-client).\n", 10 | "\n", 11 | "_WARNING_: The final example hangs. It must be cancelled manually. " 12 | ] 13 | }, 14 | { 15 | "cell_type": "markdown", 16 | "metadata": {}, 17 | "source": [ 18 | "Load the clickhouse driver and connect to a local server. " 19 | ] 20 | }, 21 | { 22 | "cell_type": "code", 23 | "execution_count": null, 24 | "metadata": {}, 25 | "outputs": [], 26 | "source": [ 27 | "from clickhouse_driver import Client\n", 28 | "client = Client('localhost')" 29 | ] 30 | }, 31 | { 32 | "cell_type": "markdown", 33 | "metadata": {}, 34 | "source": [ 35 | "Create the iris table, dropping any previously existing table of the same name. " 36 | ] 37 | }, 38 | { 39 | "cell_type": "code", 40 | "execution_count": null, 41 | "metadata": {}, 42 | "outputs": [], 43 | "source": [ 44 | "client.execute('DROP TABLE IF EXISTS iris')\n", 45 | "client.execute('CREATE TABLE iris ('\n", 46 | " 'sepal_length Float64, sepal_width Float64, '\n", 47 | " 'petal_length Float64, petal_width Float64, '\n", 48 | " 'species String) ENGINE = MergeTree '\n", 49 | " ' PARTITION BY species ORDER BY (species)')" 50 | ] 51 | }, 52 | { 53 | "cell_type": "markdown", 54 | "metadata": {}, 55 | "source": [ 56 | "If you try to insert values using a single string INSERT command that works with clickhouse-client the results will be disappointing. This command will hang. Once you see it hang, press the STOP button in your Jupyter environment. " 57 | ] 58 | }, 59 | { 60 | "cell_type": "code", 61 | "execution_count": null, 62 | "metadata": {}, 63 | "outputs": [], 64 | "source": [ 65 | "# Don’t do this.\n", 66 | "try:\n", 67 | " client.execute(\n", 68 | " \"INSERT INTO iris (sepal_length, sepal_width, petal_length, petal_width, species) \" \n", 69 | " \"VALUES (5.1, 3.7, 1.5, 0.4, 'Iris-setosa'), (4.6, 3.6, 1.0, 0.2, 'Iris-setosa')\"\n", 70 | " )\n", 71 | "except:\n", 72 | " print(\"The command failed as expected\")" 73 | ] 74 | }, 75 | { 76 | "cell_type": "markdown", 77 | "metadata": {}, 78 | "source": [ 79 | "You have to put insert data in a separate array. Python cannot translate this the way clickhouse-client does. (It creates the array transparently.)" 80 | ] 81 | }, 82 | { 83 | "cell_type": "code", 84 | "execution_count": null, 85 | "metadata": {}, 86 | "outputs": [], 87 | "source": [] 88 | } 89 | ], 90 | "metadata": { 91 | "kernelspec": { 92 | "display_name": "Python 3", 93 | "language": "python", 94 | "name": "python3" 95 | }, 96 | "language_info": { 97 | "codemirror_mode": { 98 | "name": "ipython", 99 | "version": 3 100 | }, 101 | "file_extension": ".py", 102 | "mimetype": "text/x-python", 103 | "name": "python", 104 | "nbconvert_exporter": "python", 105 | "pygments_lexer": "ipython3", 106 | "version": "3.7.1" 107 | } 108 | }, 109 | "nbformat": 4, 110 | "nbformat_minor": 2 111 | } 112 | -------------------------------------------------------------------------------- /notebooks/EX-2-ClickHouse-SQL-Alchemy.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# ClickHouse SQLAlchemy\n", 8 | "\n", 9 | "This notebook provides simple examples from the clickhouse-sqlalchemy driver including a demonstration of integration with pandas and matplotlib. " 10 | ] 11 | }, 12 | { 13 | "cell_type": "markdown", 14 | "metadata": {}, 15 | "source": [ 16 | "Import SQLAlchemy + clickhouse-sqlalchemy entities." 17 | ] 18 | }, 19 | { 20 | "cell_type": "code", 21 | "execution_count": 1, 22 | "metadata": { 23 | "scrolled": true 24 | }, 25 | "outputs": [], 26 | "source": [ 27 | "from sqlalchemy import create_engine, Column, MetaData, literal\n", 28 | "from clickhouse_sqlalchemy import Table, make_session, get_declarative_base, types, engines" 29 | ] 30 | }, 31 | { 32 | "cell_type": "markdown", 33 | "metadata": {}, 34 | "source": [ 35 | "Initialize SQLAlchemy to use local server with native connectivity. If you leave off '+native' the driver will use http[s]. " 36 | ] 37 | }, 38 | { 39 | "cell_type": "code", 40 | "execution_count": 2, 41 | "metadata": {}, 42 | "outputs": [], 43 | "source": [ 44 | "uri = 'clickhouse+native://default:@localhost/default'\n", 45 | "\n", 46 | "engine = create_engine(uri)\n", 47 | "session = make_session(engine)\n", 48 | "metadata = MetaData(bind=engine)\n", 49 | "\n", 50 | "Base = get_declarative_base(metadata=metadata)" 51 | ] 52 | }, 53 | { 54 | "cell_type": "markdown", 55 | "metadata": {}, 56 | "source": [ 57 | "Define a class to represent sensor data from devices. " 58 | ] 59 | }, 60 | { 61 | "cell_type": "code", 62 | "execution_count": 3, 63 | "metadata": {}, 64 | "outputs": [], 65 | "source": [ 66 | "class SensorData(Base):\n", 67 | " dev_id = Column(types.Int32, primary_key=True)\n", 68 | " type = Column(types.String)\n", 69 | " mdate = Column(types.Date)\n", 70 | " mdatetime = Column(types.DateTime, primary_key=True)\n", 71 | " value = Column(types.Float64)\n", 72 | "\n", 73 | " __table_args__ = (\n", 74 | " engines.MergeTree('mdate', ('dev_id', 'mdate')),\n", 75 | " )" 76 | ] 77 | }, 78 | { 79 | "cell_type": "markdown", 80 | "metadata": {}, 81 | "source": [ 82 | "Drop and then recreate the SQL table. Ignore errors if the table does not exist previously. " 83 | ] 84 | }, 85 | { 86 | "cell_type": "code", 87 | "execution_count": 4, 88 | "metadata": {}, 89 | "outputs": [], 90 | "source": [ 91 | "table = SensorData.__table__\n", 92 | "try:\n", 93 | " table.drop()\n", 94 | "except:\n", 95 | " # Exceptions are ignored\n", 96 | " pass\n", 97 | "table.create()" 98 | ] 99 | }, 100 | { 101 | "cell_type": "markdown", 102 | "metadata": {}, 103 | "source": [ 104 | "Create sensor data for 5 mythical devices. Readings increase linearly from a base that is randomly selected for each device. " 105 | ] 106 | }, 107 | { 108 | "cell_type": "code", 109 | "execution_count": 5, 110 | "metadata": {}, 111 | "outputs": [ 112 | { 113 | "data": { 114 | "text/plain": [ 115 | "" 116 | ] 117 | }, 118 | "execution_count": 5, 119 | "metadata": {}, 120 | "output_type": "execute_result" 121 | } 122 | ], 123 | "source": [ 124 | "from datetime import date, datetime, timedelta\n", 125 | "from random import random\n", 126 | "today = date.today()\n", 127 | "this_instant = datetime.today()\n", 128 | "data = []\n", 129 | "for i in range(5):\n", 130 | " base = random()\n", 131 | " for j in range(10): \n", 132 | " data.append({'dev_id': i, \n", 133 | " 'type': 'widget-a', \n", 134 | " 'mdate': today, \n", 135 | " 'mdatetime': this_instant + timedelta(minutes=j), \n", 136 | " 'value': base + j * 0.1})\n", 137 | "session.execute(table.insert(), data)" 138 | ] 139 | }, 140 | { 141 | "cell_type": "markdown", 142 | "metadata": {}, 143 | "source": [ 144 | "Enable %sql magic function. " 145 | ] 146 | }, 147 | { 148 | "cell_type": "code", 149 | "execution_count": 6, 150 | "metadata": {}, 151 | "outputs": [ 152 | { 153 | "data": { 154 | "text/plain": [ 155 | "'Connected: default@default'" 156 | ] 157 | }, 158 | "execution_count": 6, 159 | "metadata": {}, 160 | "output_type": "execute_result" 161 | } 162 | ], 163 | "source": [ 164 | "%load_ext sql\n", 165 | "%sql clickhouse://default:@localhost/default" 166 | ] 167 | }, 168 | { 169 | "cell_type": "markdown", 170 | "metadata": {}, 171 | "source": [ 172 | "Prove that the magic function works by showing tables. %sql can handle any query. " 173 | ] 174 | }, 175 | { 176 | "cell_type": "code", 177 | "execution_count": 7, 178 | "metadata": {}, 179 | "outputs": [ 180 | { 181 | "name": "stdout", 182 | "output_type": "stream", 183 | "text": [ 184 | " * clickhouse://default:***@localhost/default\n", 185 | "Done.\n" 186 | ] 187 | }, 188 | { 189 | "data": { 190 | "text/html": [ 191 | "\n", 192 | " \n", 193 | " \n", 194 | " \n", 195 | " \n", 196 | " \n", 197 | " \n", 198 | " \n", 199 | " \n", 200 | " \n", 201 | " \n", 202 | " \n", 203 | " \n", 204 | " \n", 205 | " \n", 206 | " \n", 207 | " \n", 208 | " \n", 209 | " \n", 210 | " \n", 211 | " \n", 212 | " \n", 213 | " \n", 214 | " \n", 215 | " \n", 216 | " \n", 217 | " \n", 218 | " \n", 219 | " \n", 220 | " \n", 221 | " \n", 222 | " \n", 223 | " \n", 224 | " \n", 225 | " \n", 226 | " \n", 227 | " \n", 228 | " \n", 229 | " \n", 230 | " \n", 231 | "
name
airports
f
f_1
f_long
iris
iris_from_csv
iris_remote
iris_url_local
iris_web
ontime
sdata
sensor_data
" 232 | ], 233 | "text/plain": [ 234 | "[('airports',),\n", 235 | " ('f',),\n", 236 | " ('f_1',),\n", 237 | " ('f_long',),\n", 238 | " ('iris',),\n", 239 | " ('iris_from_csv',),\n", 240 | " ('iris_remote',),\n", 241 | " ('iris_url_local',),\n", 242 | " ('iris_web',),\n", 243 | " ('ontime',),\n", 244 | " ('sdata',),\n", 245 | " ('sensor_data',)]" 246 | ] 247 | }, 248 | "execution_count": 7, 249 | "metadata": {}, 250 | "output_type": "execute_result" 251 | } 252 | ], 253 | "source": [ 254 | "%sql show tables" 255 | ] 256 | }, 257 | { 258 | "cell_type": "markdown", 259 | "metadata": {}, 260 | "source": [ 261 | "Select all rows back and convert to a data frame. " 262 | ] 263 | }, 264 | { 265 | "cell_type": "code", 266 | "execution_count": 8, 267 | "metadata": {}, 268 | "outputs": [ 269 | { 270 | "name": "stdout", 271 | "output_type": "stream", 272 | "text": [ 273 | " * clickhouse://default:***@localhost/default\n", 274 | "Done.\n" 275 | ] 276 | }, 277 | { 278 | "data": { 279 | "text/html": [ 280 | "
\n", 281 | "\n", 294 | "\n", 295 | " \n", 296 | " \n", 297 | " \n", 298 | " \n", 299 | " \n", 300 | " \n", 301 | " \n", 302 | " \n", 303 | " \n", 304 | " \n", 305 | " \n", 306 | " \n", 307 | " \n", 308 | " \n", 309 | " \n", 310 | " \n", 311 | " \n", 312 | " \n", 313 | " \n", 314 | " \n", 315 | " \n", 316 | " \n", 317 | " \n", 318 | " \n", 319 | " \n", 320 | " \n", 321 | " \n", 322 | " \n", 323 | " \n", 324 | " \n", 325 | " \n", 326 | " \n", 327 | " \n", 328 | " \n", 329 | " \n", 330 | " \n", 331 | " \n", 332 | " \n", 333 | " \n", 334 | " \n", 335 | " \n", 336 | " \n", 337 | " \n", 338 | " \n", 339 | " \n", 340 | " \n", 341 | " \n", 342 | " \n", 343 | " \n", 344 | " \n", 345 | " \n", 346 | " \n", 347 | " \n", 348 | " \n", 349 | " \n", 350 | " \n", 351 | " \n", 352 | " \n", 353 | " \n", 354 | " \n", 355 | " \n", 356 | " \n", 357 | " \n", 358 | " \n", 359 | " \n", 360 | " \n", 361 | " \n", 362 | " \n", 363 | " \n", 364 | " \n", 365 | " \n", 366 | " \n", 367 | " \n", 368 | " \n", 369 | " \n", 370 | " \n", 371 | " \n", 372 | " \n", 373 | " \n", 374 | " \n", 375 | " \n", 376 | " \n", 377 | " \n", 378 | " \n", 379 | " \n", 380 | " \n", 381 | " \n", 382 | " \n", 383 | " \n", 384 | " \n", 385 | " \n", 386 | " \n", 387 | " \n", 388 | " \n", 389 | " \n", 390 | " \n", 391 | " \n", 392 | " \n", 393 | " \n", 394 | " \n", 395 | " \n", 396 | " \n", 397 | " \n", 398 | " \n", 399 | " \n", 400 | " \n", 401 | " \n", 402 | " \n", 403 | " \n", 404 | " \n", 405 | " \n", 406 | " \n", 407 | " \n", 408 | " \n", 409 | " \n", 410 | " \n", 411 | " \n", 412 | " \n", 413 | " \n", 414 | " \n", 415 | " \n", 416 | " \n", 417 | " \n", 418 | " \n", 419 | " \n", 420 | " \n", 421 | " \n", 422 | " \n", 423 | " \n", 424 | " \n", 425 | " \n", 426 | " \n", 427 | " \n", 428 | " \n", 429 | " \n", 430 | " \n", 431 | " \n", 432 | " \n", 433 | " \n", 434 | " \n", 435 | " \n", 436 | " \n", 437 | " \n", 438 | " \n", 439 | " \n", 440 | " \n", 441 | " \n", 442 | " \n", 443 | " \n", 444 | " \n", 445 | " \n", 446 | " \n", 447 | " \n", 448 | " \n", 449 | " \n", 450 | " \n", 451 | " \n", 452 | " \n", 453 | " \n", 454 | " \n", 455 | " \n", 456 | " \n", 457 | " \n", 458 | " \n", 459 | " \n", 460 | " \n", 461 | " \n", 462 | " \n", 463 | " \n", 464 | " \n", 465 | " \n", 466 | " \n", 467 | " \n", 468 | " \n", 469 | " \n", 470 | " \n", 471 | " \n", 472 | " \n", 473 | " \n", 474 | " \n", 475 | " \n", 476 | " \n", 477 | " \n", 478 | " \n", 479 | " \n", 480 | " \n", 481 | " \n", 482 | " \n", 483 | " \n", 484 | " \n", 485 | " \n", 486 | " \n", 487 | " \n", 488 | " \n", 489 | " \n", 490 | " \n", 491 | " \n", 492 | " \n", 493 | " \n", 494 | " \n", 495 | " \n", 496 | " \n", 497 | " \n", 498 | " \n", 499 | " \n", 500 | " \n", 501 | " \n", 502 | " \n", 503 | " \n", 504 | " \n", 505 | " \n", 506 | " \n", 507 | " \n", 508 | " \n", 509 | " \n", 510 | " \n", 511 | " \n", 512 | " \n", 513 | " \n", 514 | " \n", 515 | " \n", 516 | " \n", 517 | " \n", 518 | " \n", 519 | " \n", 520 | " \n", 521 | " \n", 522 | " \n", 523 | " \n", 524 | " \n", 525 | " \n", 526 | " \n", 527 | " \n", 528 | " \n", 529 | " \n", 530 | " \n", 531 | " \n", 532 | " \n", 533 | " \n", 534 | " \n", 535 | " \n", 536 | " \n", 537 | " \n", 538 | " \n", 539 | " \n", 540 | " \n", 541 | " \n", 542 | " \n", 543 | " \n", 544 | " \n", 545 | " \n", 546 | " \n", 547 | " \n", 548 | " \n", 549 | " \n", 550 | " \n", 551 | " \n", 552 | " \n", 553 | " \n", 554 | " \n", 555 | " \n", 556 | " \n", 557 | " \n", 558 | " \n", 559 | " \n", 560 | " \n", 561 | " \n", 562 | " \n", 563 | " \n", 564 | " \n", 565 | " \n", 566 | " \n", 567 | " \n", 568 | " \n", 569 | " \n", 570 | " \n", 571 | " \n", 572 | " \n", 573 | " \n", 574 | " \n", 575 | " \n", 576 | " \n", 577 | " \n", 578 | " \n", 579 | " \n", 580 | " \n", 581 | " \n", 582 | " \n", 583 | " \n", 584 | " \n", 585 | " \n", 586 | " \n", 587 | " \n", 588 | " \n", 589 | " \n", 590 | " \n", 591 | " \n", 592 | " \n", 593 | " \n", 594 | " \n", 595 | " \n", 596 | " \n", 597 | " \n", 598 | " \n", 599 | " \n", 600 | " \n", 601 | " \n", 602 | " \n", 603 | " \n", 604 | " \n", 605 | " \n", 606 | " \n", 607 | " \n", 608 | " \n", 609 | " \n", 610 | " \n", 611 | " \n", 612 | " \n", 613 | " \n", 614 | " \n", 615 | " \n", 616 | " \n", 617 | " \n", 618 | " \n", 619 | " \n", 620 | " \n", 621 | " \n", 622 | " \n", 623 | " \n", 624 | " \n", 625 | " \n", 626 | " \n", 627 | " \n", 628 | " \n", 629 | " \n", 630 | " \n", 631 | " \n", 632 | " \n", 633 | " \n", 634 | " \n", 635 | " \n", 636 | " \n", 637 | " \n", 638 | " \n", 639 | " \n", 640 | " \n", 641 | " \n", 642 | " \n", 643 | " \n", 644 | " \n", 645 | " \n", 646 | " \n", 647 | " \n", 648 | " \n", 649 | " \n", 650 | " \n", 651 | " \n", 652 | " \n", 653 | " \n", 654 | " \n", 655 | " \n", 656 | " \n", 657 | " \n", 658 | " \n", 659 | " \n", 660 | " \n", 661 | " \n", 662 | " \n", 663 | " \n", 664 | " \n", 665 | " \n", 666 | " \n", 667 | " \n", 668 | " \n", 669 | " \n", 670 | " \n", 671 | " \n", 672 | " \n", 673 | " \n", 674 | " \n", 675 | " \n", 676 | " \n", 677 | " \n", 678 | " \n", 679 | " \n", 680 | " \n", 681 | " \n", 682 | " \n", 683 | " \n", 684 | " \n", 685 | " \n", 686 | " \n", 687 | " \n", 688 | " \n", 689 | " \n", 690 | " \n", 691 | " \n", 692 | " \n", 693 | " \n", 694 | " \n", 695 | " \n", 696 | " \n", 697 | " \n", 698 | " \n", 699 | " \n", 700 | " \n", 701 | " \n", 702 | " \n", 703 | " \n", 704 | " \n", 705 | " \n", 706 | " \n", 707 | "
dev_idtypemdatemdatetimevalue
00widget-a2019-02-242019-02-24 00:03:590.470658
10widget-a2019-02-242019-02-24 00:04:590.570658
20widget-a2019-02-242019-02-24 00:05:590.670658
30widget-a2019-02-242019-02-24 00:06:590.770658
40widget-a2019-02-242019-02-24 00:07:590.870658
50widget-a2019-02-242019-02-24 00:08:590.970658
60widget-a2019-02-242019-02-24 00:09:591.070658
70widget-a2019-02-242019-02-24 00:10:591.170658
80widget-a2019-02-242019-02-24 00:11:591.270658
90widget-a2019-02-242019-02-24 00:12:591.370658
101widget-a2019-02-242019-02-24 00:03:590.308329
111widget-a2019-02-242019-02-24 00:04:590.408329
121widget-a2019-02-242019-02-24 00:05:590.508329
131widget-a2019-02-242019-02-24 00:06:590.608329
141widget-a2019-02-242019-02-24 00:07:590.708329
151widget-a2019-02-242019-02-24 00:08:590.808329
161widget-a2019-02-242019-02-24 00:09:590.908329
171widget-a2019-02-242019-02-24 00:10:591.008329
181widget-a2019-02-242019-02-24 00:11:591.108329
191widget-a2019-02-242019-02-24 00:12:591.208329
202widget-a2019-02-242019-02-24 00:03:590.766993
212widget-a2019-02-242019-02-24 00:04:590.866993
222widget-a2019-02-242019-02-24 00:05:590.966993
232widget-a2019-02-242019-02-24 00:06:591.066993
242widget-a2019-02-242019-02-24 00:07:591.166993
252widget-a2019-02-242019-02-24 00:08:591.266993
262widget-a2019-02-242019-02-24 00:09:591.366993
272widget-a2019-02-242019-02-24 00:10:591.466993
282widget-a2019-02-242019-02-24 00:11:591.566993
292widget-a2019-02-242019-02-24 00:12:591.666993
303widget-a2019-02-242019-02-24 00:03:590.880996
313widget-a2019-02-242019-02-24 00:04:590.980996
323widget-a2019-02-242019-02-24 00:05:591.080996
333widget-a2019-02-242019-02-24 00:06:591.180996
343widget-a2019-02-242019-02-24 00:07:591.280996
353widget-a2019-02-242019-02-24 00:08:591.380996
363widget-a2019-02-242019-02-24 00:09:591.480996
373widget-a2019-02-242019-02-24 00:10:591.580996
383widget-a2019-02-242019-02-24 00:11:591.680996
393widget-a2019-02-242019-02-24 00:12:591.780996
404widget-a2019-02-242019-02-24 00:03:590.673713
414widget-a2019-02-242019-02-24 00:04:590.773713
424widget-a2019-02-242019-02-24 00:05:590.873713
434widget-a2019-02-242019-02-24 00:06:590.973713
444widget-a2019-02-242019-02-24 00:07:591.073713
454widget-a2019-02-242019-02-24 00:08:591.173713
464widget-a2019-02-242019-02-24 00:09:591.273713
474widget-a2019-02-242019-02-24 00:10:591.373713
484widget-a2019-02-242019-02-24 00:11:591.473713
494widget-a2019-02-242019-02-24 00:12:591.573713
\n", 708 | "
" 709 | ], 710 | "text/plain": [ 711 | " dev_id type mdate mdatetime value\n", 712 | "0 0 widget-a 2019-02-24 2019-02-24 00:03:59 0.470658\n", 713 | "1 0 widget-a 2019-02-24 2019-02-24 00:04:59 0.570658\n", 714 | "2 0 widget-a 2019-02-24 2019-02-24 00:05:59 0.670658\n", 715 | "3 0 widget-a 2019-02-24 2019-02-24 00:06:59 0.770658\n", 716 | "4 0 widget-a 2019-02-24 2019-02-24 00:07:59 0.870658\n", 717 | "5 0 widget-a 2019-02-24 2019-02-24 00:08:59 0.970658\n", 718 | "6 0 widget-a 2019-02-24 2019-02-24 00:09:59 1.070658\n", 719 | "7 0 widget-a 2019-02-24 2019-02-24 00:10:59 1.170658\n", 720 | "8 0 widget-a 2019-02-24 2019-02-24 00:11:59 1.270658\n", 721 | "9 0 widget-a 2019-02-24 2019-02-24 00:12:59 1.370658\n", 722 | "10 1 widget-a 2019-02-24 2019-02-24 00:03:59 0.308329\n", 723 | "11 1 widget-a 2019-02-24 2019-02-24 00:04:59 0.408329\n", 724 | "12 1 widget-a 2019-02-24 2019-02-24 00:05:59 0.508329\n", 725 | "13 1 widget-a 2019-02-24 2019-02-24 00:06:59 0.608329\n", 726 | "14 1 widget-a 2019-02-24 2019-02-24 00:07:59 0.708329\n", 727 | "15 1 widget-a 2019-02-24 2019-02-24 00:08:59 0.808329\n", 728 | "16 1 widget-a 2019-02-24 2019-02-24 00:09:59 0.908329\n", 729 | "17 1 widget-a 2019-02-24 2019-02-24 00:10:59 1.008329\n", 730 | "18 1 widget-a 2019-02-24 2019-02-24 00:11:59 1.108329\n", 731 | "19 1 widget-a 2019-02-24 2019-02-24 00:12:59 1.208329\n", 732 | "20 2 widget-a 2019-02-24 2019-02-24 00:03:59 0.766993\n", 733 | "21 2 widget-a 2019-02-24 2019-02-24 00:04:59 0.866993\n", 734 | "22 2 widget-a 2019-02-24 2019-02-24 00:05:59 0.966993\n", 735 | "23 2 widget-a 2019-02-24 2019-02-24 00:06:59 1.066993\n", 736 | "24 2 widget-a 2019-02-24 2019-02-24 00:07:59 1.166993\n", 737 | "25 2 widget-a 2019-02-24 2019-02-24 00:08:59 1.266993\n", 738 | "26 2 widget-a 2019-02-24 2019-02-24 00:09:59 1.366993\n", 739 | "27 2 widget-a 2019-02-24 2019-02-24 00:10:59 1.466993\n", 740 | "28 2 widget-a 2019-02-24 2019-02-24 00:11:59 1.566993\n", 741 | "29 2 widget-a 2019-02-24 2019-02-24 00:12:59 1.666993\n", 742 | "30 3 widget-a 2019-02-24 2019-02-24 00:03:59 0.880996\n", 743 | "31 3 widget-a 2019-02-24 2019-02-24 00:04:59 0.980996\n", 744 | "32 3 widget-a 2019-02-24 2019-02-24 00:05:59 1.080996\n", 745 | "33 3 widget-a 2019-02-24 2019-02-24 00:06:59 1.180996\n", 746 | "34 3 widget-a 2019-02-24 2019-02-24 00:07:59 1.280996\n", 747 | "35 3 widget-a 2019-02-24 2019-02-24 00:08:59 1.380996\n", 748 | "36 3 widget-a 2019-02-24 2019-02-24 00:09:59 1.480996\n", 749 | "37 3 widget-a 2019-02-24 2019-02-24 00:10:59 1.580996\n", 750 | "38 3 widget-a 2019-02-24 2019-02-24 00:11:59 1.680996\n", 751 | "39 3 widget-a 2019-02-24 2019-02-24 00:12:59 1.780996\n", 752 | "40 4 widget-a 2019-02-24 2019-02-24 00:03:59 0.673713\n", 753 | "41 4 widget-a 2019-02-24 2019-02-24 00:04:59 0.773713\n", 754 | "42 4 widget-a 2019-02-24 2019-02-24 00:05:59 0.873713\n", 755 | "43 4 widget-a 2019-02-24 2019-02-24 00:06:59 0.973713\n", 756 | "44 4 widget-a 2019-02-24 2019-02-24 00:07:59 1.073713\n", 757 | "45 4 widget-a 2019-02-24 2019-02-24 00:08:59 1.173713\n", 758 | "46 4 widget-a 2019-02-24 2019-02-24 00:09:59 1.273713\n", 759 | "47 4 widget-a 2019-02-24 2019-02-24 00:10:59 1.373713\n", 760 | "48 4 widget-a 2019-02-24 2019-02-24 00:11:59 1.473713\n", 761 | "49 4 widget-a 2019-02-24 2019-02-24 00:12:59 1.573713" 762 | ] 763 | }, 764 | "execution_count": 8, 765 | "metadata": {}, 766 | "output_type": "execute_result" 767 | } 768 | ], 769 | "source": [ 770 | "result = %sql select * from sensor_data\n", 771 | "df = result.DataFrame()\n", 772 | "df" 773 | ] 774 | }, 775 | { 776 | "cell_type": "code", 777 | "execution_count": 12, 778 | "metadata": {}, 779 | "outputs": [ 780 | { 781 | "data": { 782 | "text/html": [ 783 | "
\n", 784 | "\n", 797 | "\n", 798 | " \n", 799 | " \n", 800 | " \n", 801 | " \n", 802 | " \n", 803 | " \n", 804 | " \n", 805 | " \n", 806 | " \n", 807 | " \n", 808 | " \n", 809 | " \n", 810 | " \n", 811 | " \n", 812 | " \n", 813 | " \n", 814 | " \n", 815 | " \n", 816 | " \n", 817 | " \n", 818 | " \n", 819 | " \n", 820 | " \n", 821 | " \n", 822 | " \n", 823 | " \n", 824 | " \n", 825 | " \n", 826 | " \n", 827 | " \n", 828 | " \n", 829 | " \n", 830 | " \n", 831 | " \n", 832 | " \n", 833 | " \n", 834 | " \n", 835 | " \n", 836 | " \n", 837 | " \n", 838 | " \n", 839 | " \n", 840 | " \n", 841 | " \n", 842 | " \n", 843 | " \n", 844 | " \n", 845 | " \n", 846 | " \n", 847 | "
dev_idvalue
count50.00000050.000000
mean2.0000001.070138
std1.4285710.357015
min0.0000000.308329
25%1.0000000.822995
50%2.0000001.072185
75%3.0000001.345493
max4.0000001.780996
\n", 848 | "
" 849 | ], 850 | "text/plain": [ 851 | " dev_id value\n", 852 | "count 50.000000 50.000000\n", 853 | "mean 2.000000 1.070138\n", 854 | "std 1.428571 0.357015\n", 855 | "min 0.000000 0.308329\n", 856 | "25% 1.000000 0.822995\n", 857 | "50% 2.000000 1.072185\n", 858 | "75% 3.000000 1.345493\n", 859 | "max 4.000000 1.780996" 860 | ] 861 | }, 862 | "execution_count": 12, 863 | "metadata": {}, 864 | "output_type": "execute_result" 865 | } 866 | ], 867 | "source": [ 868 | "df.describe()" 869 | ] 870 | }, 871 | { 872 | "cell_type": "markdown", 873 | "metadata": {}, 874 | "source": [ 875 | "Data frames integrate nicely with graphics. Use selection on the data frame to pull out rows for each device in sucession and plot them as separate lines. " 876 | ] 877 | }, 878 | { 879 | "cell_type": "code", 880 | "execution_count": 9, 881 | "metadata": {}, 882 | "outputs": [ 883 | { 884 | "data": { 885 | "image/png": "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\n", 886 | "text/plain": [ 887 | "
" 888 | ] 889 | }, 890 | "metadata": { 891 | "needs_background": "light" 892 | }, 893 | "output_type": "display_data" 894 | } 895 | ], 896 | "source": [ 897 | "import matplotlib.pyplot as plt\n", 898 | "%matplotlib inline\n", 899 | "\n", 900 | "# Break up the data frame and graph each device separately. \n", 901 | "markers = ['o', 'x', '^', '+', '*']\n", 902 | "for i in range(5):\n", 903 | " df_segment = df[df['dev_id'] == i]\n", 904 | " plt.plot('mdatetime', 'value', data=df_segment, linestyle='--', marker=markers[i])\n", 905 | " \n", 906 | "plt.xticks(rotation=90)\n", 907 | "plt.show()" 908 | ] 909 | }, 910 | { 911 | "cell_type": "markdown", 912 | "metadata": {}, 913 | "source": [ 914 | "It's more common to use ClickHouse to compute aggregates. Find the min, average, and max values for each device and likewise convert them to a data frame." 915 | ] 916 | }, 917 | { 918 | "cell_type": "code", 919 | "execution_count": 10, 920 | "metadata": {}, 921 | "outputs": [ 922 | { 923 | "name": "stdout", 924 | "output_type": "stream", 925 | "text": [ 926 | " * clickhouse://default:***@localhost/default\n", 927 | "Done.\n" 928 | ] 929 | }, 930 | { 931 | "data": { 932 | "text/html": [ 933 | "
\n", 934 | "\n", 947 | "\n", 948 | " \n", 949 | " \n", 950 | " \n", 951 | " \n", 952 | " \n", 953 | " \n", 954 | " \n", 955 | " \n", 956 | " \n", 957 | " \n", 958 | " \n", 959 | " \n", 960 | " \n", 961 | " \n", 962 | " \n", 963 | " \n", 964 | " \n", 965 | " \n", 966 | " \n", 967 | " \n", 968 | " \n", 969 | " \n", 970 | " \n", 971 | " \n", 972 | " \n", 973 | " \n", 974 | " \n", 975 | " \n", 976 | " \n", 977 | " \n", 978 | " \n", 979 | " \n", 980 | " \n", 981 | " \n", 982 | " \n", 983 | " \n", 984 | " \n", 985 | " \n", 986 | " \n", 987 | " \n", 988 | " \n", 989 | " \n", 990 | " \n", 991 | " \n", 992 | " \n", 993 | " \n", 994 | "
dev_idmin(value)avg(value)max(value)
000.4706580.9206581.370658
110.3083290.7583291.208329
220.7669931.2169931.666993
330.8809961.3309961.780996
440.6737131.1237131.573713
\n", 995 | "
" 996 | ], 997 | "text/plain": [ 998 | " dev_id min(value) avg(value) max(value)\n", 999 | "0 0 0.470658 0.920658 1.370658\n", 1000 | "1 1 0.308329 0.758329 1.208329\n", 1001 | "2 2 0.766993 1.216993 1.666993\n", 1002 | "3 3 0.880996 1.330996 1.780996\n", 1003 | "4 4 0.673713 1.123713 1.573713" 1004 | ] 1005 | }, 1006 | "execution_count": 10, 1007 | "metadata": {}, 1008 | "output_type": "execute_result" 1009 | } 1010 | ], 1011 | "source": [ 1012 | "result = %sql select dev_id, min(value), avg(value), max(value) from sensor_data group by dev_id order by dev_id\n", 1013 | "df2 = result.DataFrame()\n", 1014 | "df2" 1015 | ] 1016 | }, 1017 | { 1018 | "cell_type": "markdown", 1019 | "metadata": {}, 1020 | "source": [ 1021 | "Let's put the average values per device into a nice bar chart. It's easy to add additional sets of bars or create subplots but this will do for today. " 1022 | ] 1023 | }, 1024 | { 1025 | "cell_type": "code", 1026 | "execution_count": 11, 1027 | "metadata": {}, 1028 | "outputs": [ 1029 | { 1030 | "data": { 1031 | "image/png": "iVBORw0KGgoAAAANSUhEUgAAAYUAAAEWCAYAAACJ0YulAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDMuMC4yLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvOIA7rQAAGSVJREFUeJzt3Xm0ZWV95vHvQxUgIIJa5UQxqYWABNEUSBaJooAWJIBJjAEnNEil7aAR7LRoIipqEqMGZUEaqxUJKCA4VmxsIM3khFIiEAEhJYhVAUKBgIhjkV//sffdHC93Krj7Hrj3+1nrrrWH97znt+/07PE9qSokSQLYYNgFSJIeOQwFSVLHUJAkdQwFSVLHUJAkdQwFSVLHUNCjWpJ3J/nUNPRzcpJ3TkdN0qOZoTDLJbk4yV1JNh52LY9kVfXfquq9w65DD2h/d98w7DrmGkNhFkuyHfB7QAEH9fQe8/voVzPPn6XAUJjtXgtcBpwKHDayMMmeSW5LMm9g2R8mubqd3iDJMUl+kOTOJGcneUK7brskleTwJD8CLmyXn9P2eU+SS5M8e6DvJyb5lyQ/SXJ5kvcl+drA+h2TXJDkx0muT/KK8TYoyfZJLklyb5ILgAWj1u+Z5BtJ7k5yVZK92+WHJFk5qu1RSVa006cmed/AuoOTXNnW/IMkS9vlWyT5RJJbk/xHuy3zGEN7auucJJ9q6/23JDskeXuS25OsTvKSgfbj9p3kGUkubH8edyT5dJItB177tvY197bfw33G2a69k6wZmP9h+9qrgfuSzE/ytCSfS7I2yU1J3tzTNr0uydeSfKg9mr0pyf7tuvfT7NCcmOSnSU5M4/j2fe5JcnWSXcb7XdFDVFV+zdIvYBXw34HfBn4NPHlg3Q+A/QbmzwGOaaffQhMmi4CNgY8BZ7brtqM58jgN2AzYpF3+Z8DmbfuPAFcO9H1W+7UpsDOwGvhau26zdv71wHzgecAdwLPH2aZvAv/Yvs8LgHuBT7XrtgLuBA6g2eHZr51f2L73vcDigb4uBw5pp08F3tdO7wHc075+g7bfHdt1X2y/H5sBTwK+Dfz5OLW+G/gF8NJ2204DbgL+GtgQOAK4aaD9uH0Dz2zr2bjdnkuBj7TrntV+D5828DN6xujtauf3BtYMzP8QuBLYGtik3d7vAMcCGwFPB24EXtrDNr2O5vfyCGAe8EbgFiDt+ouBNwz09dK2ti2BADsBTx3239ls+xp6AX719IOF323/4Ba0898HjhpY/z7glHZ6c+A+YNt2/jpgn4G2T237ms8DofD0Cd57y7bNFu0f+6+BZ41675FQ+FPgq6Ne/zHgXWP0uw2wDthsYNkZPBAKbwNOH/Wa84DD2ulPAce204tpQmLTdr7759m+//FjvP+TgV/SBmG77FDgonG+D+8GLhiYPxD4KTBv4Pte7fdrfft+GfDddvqZwO3AvsCGo9p129XO782DQ+HPBuafD/xoVB9vBz453dtEEwqrBtZt2r72Ke38xfxmKLwYuAHYE9hg2H9js/XLc4iz12HA+VV1Rzt/Rrvs+IH5byR5I/BHwBVVdXO7blvgC0n+a6C/+2n+yEesHploTwe8H/gTmr3YkdctoNn7nD/YftT0tsDzk9w9sGw+cPoY2/Q04K6qum9g2c00e7kjff1JkgMH1m8IXDSwzR8GjgNeCXyxqn42xvtsDZw7xvJt2/5uTTKybINR2zPafw5M/xy4o6ruH5gHeGy7beP2neRJwAk0p1Q2b9fdBVBVq5K8heYf9rOTnAccXVW3TFDXoNE/j6eN+nnMA7463dvUum1koqp+1rZ77FhFVtWFSU4ETgK2SfIF4H9U1U8m3UJNmaEwCyXZBHgFMC/JyB/dxsCWSZ5TVVdV1bVJbgb2p/kHecZAF6tp9h6/Pkbf27WTg8PrvhI4mGZP9Yc0Rwh30Rzir6XZu19Es5cHD/wTH3mvS6pqvyls2q3A45NsNhAM2wzUsprmSOGIcV5/PrAgyW40e6xHjdNuNfCMcZb/kuboa90U6l0fk/X9dzTbuWtV3ZnkZcCJIyur6gzgjCSPoznS+QDwGpojwE0H+nnKGH0P/ixX05z+WfxwNmagr4fz/XrQEM5VdQJwQhuSZwN/BXgr8TTyQvPs9DKaPfudgd3ar51o9vZeO9DuDODNNOfmzxlYfjLw/iTbAiRZmOTgCd5vc5o//jtp/gH97ciKdg/y88C7k2yaZMdRNXwZ2CHJa5Js2H7tnmSn0W/SHsmsBN6TZKMkv0tz+mLEp4ADk7w0ybwkj2kvrC5qX78O+CzwQeAJwAXjbM8ngNcn2SfNRfetkuxYVbfSBMuHkzyuXfeMJC+c4HszJVPoe3Oa0zR3J9mK5p8hAEmeleTFaW47/gXN3vrInvuVwAFJnpDkKTTXiybybeAn7cXnTdrv4y5Jdu9hmybznzTXNABofy+en2RDmrD7BQ9sp6aJoTA7HUZzDvhHVXXbyBfNnuWr8sCth2fSnGO+cOA0E8BHgRXA+Unupbno/PwJ3u80mtM4/wFc27YfdCTN0cNtNKeFzqQJEarqXuAlwCE0Fxlvo9nLHe+5ile2tfwYeFf73rR9raY5YnkHzRHKapp/noO/52fQHNGcM97ea1V9m+bC9/E0F5wvoTmtAk2gbdRu5100IfPUcWpdXxP1/R6ai/D3AP+HJmhHbAz8Pc0F+ttoLui+o113OnAVzRHc+cBnJiqgDfEDaXYkbmr7/DjNz2+6t2kyHwVe3t6ZdALwOOB/t/3cTLMT8qGHWJfGMXKVX5oxST5AczHxsEkbS5pRHimod2meQ9i1vc98D+Bw4AvDrkvSg/UWCklOaR8y+d4k7XZPcn+Sl/dVi4Zuc5rTHffRXBz8MPCloVYkaUy9nT5K8gKaC2OnVdWYTx22tzJeQHPB6JSq+mwvxUiSpqS3I4WqupTmYuBE3gR8jubBG0nSkA3tOYX2tro/pHlKccLb3ZIsA5YBbLbZZr+944479l+gJM0i3/nOd+6oqoWTtRvmw2sfAd5WVfcPPO04pqpaDiwHWLJkSa1cuXLC9pKk39Q+rDqpYYbCEuCsNhAW0Dxgs66qvjjEmiRpThtaKFTV9iPTSU4FvmwgSNJw9RYKSUaell2QZvz2d9EMjkVVndzX+0qSHrreQqGqDl2Ptq/rqw5J0tT5RLMkqWMoSJI6hoIkqWMoSJI6hoIkqePHcUpzwPEX3DB5o0eBo/bbYdglzHoeKUiSOoaCJKljKEiSOoaCJKljKEiSOoaCJKljKEiSOoaCJKljKEiSOoaCJKljKEiSOoaCJKljKEiSOoaCJKljKEiSOoaCJKnT24fsJDkF+APg9qraZYz1rwLe1s7+FHhjVV3VVz2a22bLh8yAHzSjfvV5pHAqsHSC9TcBL6yqXYH3Ast7rEWSNAW9HSlU1aVJtptg/TcGZi8DFvVViyRpah4p1xQOB74y3soky5KsTLJy7dq1M1iWJM0tQw+FJC+iCYW3jdemqpZX1ZKqWrJw4cKZK06S5pjeTh9NRZJdgY8D+1fVncOsRZI0xCOFJNsAnwdeU1Wz59YQSXoU6/OW1DOBvYEFSdYA7wI2BKiqk4FjgScC/5QEYF1VLemrHknS5Pq8++jQSda/AXhDX+8vSVp/Q7/QLEl65DAUJEkdQ0GS1DEUJEkdQ0GS1DEUJEmdoT7RLEl9c9j09eORgiSpYyhIkjqGgiSpYyhIkjqGgiSpYyhIkjqGgiSpYyhIkjqGgiSpYyhIkjqGgiSpYyhIkjqGgiSpYyhIkjqGgiSp01soJDklye1JvjfO+iQ5IcmqJFcneV5ftUiSpqbPI4VTgaUTrN8fWNx+LQP+V4+1SJKmoLdQqKpLgR9P0ORg4LRqXAZsmeSpfdUjSZrcMK8pbAWsHphf0y57kCTLkqxMsnLt2rUzUpwkzUXDDIWMsazGalhVy6tqSVUtWbhwYc9lSdLcNcxQWANsPTC/CLhlSLVIkhhuKKwAXtvehbQncE9V3TrEeiRpzpvfV8dJzgT2BhYkWQO8C9gQoKpOBs4FDgBWAT8DXt9XLZKkqektFKrq0EnWF/AXfb2/JGn9+USzJKljKEiSOoaCJKljKEiSOoaCJKljKEiSOoaCJKnT23MKj0THX3DDsEuYNkftt8OwS5A0C3mkIEnqGAqSpI6hIEnqGAqSpI6hIEnqGAqSpI6hIEnqGAqSpI6hIEnqGAqSpI6hIEnqGAqSpI6hIEnqGAqSpE6voZBkaZLrk6xKcswY67dJclGS7ya5OskBfdYjSZpYb6GQZB5wErA/sDNwaJKdRzX7G+DsqnoucAjwT33VI0maXJ9HCnsAq6rqxqr6FXAWcPCoNgU8rp3eArilx3okSZPoMxS2AlYPzK9plw16N/DqJGuAc4E3jdVRkmVJViZZuXbt2j5qlSTRbyhkjGU1av5Q4NSqWgQcAJye5EE1VdXyqlpSVUsWLlzYQ6mSJOg3FNYAWw/ML+LBp4cOB84GqKpvAo8BFvRYkyRpAn2GwuXA4iTbJ9mI5kLyilFtfgTsA5BkJ5pQ8PyQJA1Jb6FQVeuAI4HzgOto7jK6JslxSQ5qm70VOCLJVcCZwOuqavQpJknSDJk/WYMkTwb+FnhaVe3f3lb6O1X1icleW1Xn0lxAHlx27MD0tcBe6121JKkXUzlSOJVmb/9p7fwNwFv6KkiSNDyTHikAC6rq7CRvh+a0UJL7e65LPTj+ghuGXcK0OWq/HYZdgjQrTeVI4b4kT6S9nTTJnsA9vVYlSRqKqRwpHE1z19AzknwdWAi8vNeqJElDMWkoVNUVSV4IPIvmgbTrq+rXvVcmSZpxU7n76LWjFj0vCVV1Wk81SZKGZCqnj3YfmH4MzcNmVwCGgiTNMlM5ffQbg9Ql2QI4vbeKJElD81CeaP4ZsHi6C5EkDd9Urin8Cw+MbroBzQfmnN1nUZKk4ZjKNYUPDUyvA26uqjU91SNJGqKpXFO4ZCYKkSQN37ihkOReHvyhONA8q1BV9bgx1kmSHsXGDYWq2nwmC5EkDd9UrikAkORJNM8pAFBVP+qlIknS0Ex6S2qSg5L8O3ATcAnwQ+ArPdclSRqCqTyn8F5gT+CGqtqe5onmr/dalSRpKKYSCr+uqjuBDZJsUFUXAbv1XJckaQimck3h7iSPBb4KfDrJ7TTPK0iSZplxjxSSnJhkL+BgmqEt3gL8X+AHwIEzU54kaSZNdKTw7zRPMz8V+AxwZlX984xUJUkainGPFKrqo1X1O8ALgR8Dn0xyXZJ3JvEDciVpFpr0QnNV3VxVH6iq5wKvBP4IuG4qnSdZmuT6JKuSHDNOm1ckuTbJNUnOWK/qJUnTaiqjpG4ILAUOobkd9RLgPVN43TzgJGA/YA1weZIVVXXtQJvFwNuBvarqrvYBOUnSkEw09tF+wKHA7wPfBs4CllXVfVPsew9gVVXd2PZ3Fs1F62sH2hwBnFRVdwFU1e3rvQWSpGkz0emjdwDfBHaqqgOr6tPrEQgAWwGrB+bXtMsG7QDskOTrSS5LsnSsjpIsS7Iyycq1a9euRwmSpPUx0YB4L3qYfWesbsd4/8XA3sAi4KtJdqmqu0fVshxYDrBkyZKxRm6VJE2Dh/JxnFO1Bth6YH4RcMsYbb5UVb+uqpuA6/GjPiVpaPoMhcuBxUm2T7IRzYXqFaPafBF4EUCSBTSnk27ssSZJ0gR6C4WqWgccCZxHcwvr2VV1TZLjkhzUNjsPuDPJtcBFwF+14yxJkoZgyp+n8FBU1bnAuaOWHTswXcDR7Zckacj6PH0kSXqUMRQkSR1DQZLUMRQkSR1DQZLUMRQkSR1DQZLUMRQkSR1DQZLUMRQkSR1DQZLUMRQkSR1DQZLUMRQkSR1DQZLUMRQkSR1DQZLUMRQkSR1DQZLUMRQkSR1DQZLUMRQkSZ1eQyHJ0iTXJ1mV5JgJ2r08SSVZ0mc9kqSJ9RYKSeYBJwH7AzsDhybZeYx2mwNvBr7VVy2SpKnp80hhD2BVVd1YVb8CzgIOHqPde4F/AH7RYy2SpCnoMxS2AlYPzK9pl3WSPBfYuqq+3GMdkqQp6jMUMsay6lYmGwDHA2+dtKNkWZKVSVauXbt2GkuUJA3qMxTWAFsPzC8CbhmY3xzYBbg4yQ+BPYEVY11srqrlVbWkqpYsXLiwx5IlaW7rMxQuBxYn2T7JRsAhwIqRlVV1T1UtqKrtqmo74DLgoKpa2WNNkqQJ9BYKVbUOOBI4D7gOOLuqrklyXJKD+npfSdJDN7/PzqvqXODcUcuOHaft3n3WIkmanE80S5I6hoIkqWMoSJI6hoIkqWMoSJI6hoIkqWMoSJI6hoIkqWMoSJI6hoIkqWMoSJI6hoIkqWMoSJI6hoIkqWMoSJI6hoIkqWMoSJI6hoIkqWMoSJI6hoIkqWMoSJI6hoIkqWMoSJI6vYZCkqVJrk+yKskxY6w/Osm1Sa5O8v+SbNtnPZKkifUWCknmAScB+wM7A4cm2XlUs+8CS6pqV+CzwD/0VY8kaXJ9HinsAayqqhur6lfAWcDBgw2q6qKq+lk7exmwqMd6JEmT6DMUtgJWD8yvaZeN53DgK2OtSLIsycokK9euXTuNJUqSBvUZChljWY3ZMHk1sAT44Fjrq2p5VS2pqiULFy6cxhIlSYPm99j3GmDrgflFwC2jGyXZF/hr4IVV9cse65EkTaLPI4XLgcVJtk+yEXAIsGKwQZLnAh8DDqqq23usRZI0Bb2FQlWtA44EzgOuA86uqmuSHJfkoLbZB4HHAuckuTLJinG6kyTNgD5PH1FV5wLnjlp27MD0vn2+vyRp/fhEsySpYyhIkjqGgiSpYyhIkjqGgiSpYyhIkjqGgiSpYyhIkjqGgiSpYyhIkjqGgiSpYyhIkjqGgiSpYyhIkjqGgiSpYyhIkjqGgiSpYyhIkjqGgiSpYyhIkjqGgiSpYyhIkjq9hkKSpUmuT7IqyTFjrN84yWfa9d9Ksl2f9UiSJtZbKCSZB5wE7A/sDByaZOdRzQ4H7qqqZwLHAx/oqx5J0uT6PFLYA1hVVTdW1a+As4CDR7U5GPjndvqzwD5J0mNNkqQJzO+x762A1QPza4Dnj9emqtYluQd4InDHYKMky4Bl7exPk1zfS8XTZwGjtmG6Hd1n5w9P79sOc3v73fZHpEfD7/22U2nUZyiMtcdfD6ENVbUcWD4dRc2EJCurasmw6xiGubztMLe3322fHdve5+mjNcDWA/OLgFvGa5NkPrAF8OMea5IkTaDPULgcWJxk+yQbAYcAK0a1WQEc1k6/HLiwqh50pCBJmhm9nT5qrxEcCZwHzANOqaprkhwHrKyqFcAngNOTrKI5Qjikr3pm2KPmVFcP5vK2w9zefrd9Fog75pKkET7RLEnqGAqSpI6hMI0mG9ZjNktySpLbk3xv2LXMtCRbJ7koyXVJrknyl8OuaSYleUySbye5qt3+9wy7ppmWZF6S7yb58rBrebgMhWkyxWE9ZrNTgaXDLmJI1gFvraqdgD2Bv5hjP/tfAi+uqucAuwFLk+w55Jpm2l8C1w27iOlgKEyfqQzrMWtV1aXM0WdMqurWqrqinb6X5p/DVsOtauZU46ft7Ibt15y5gyXJIuD3gY8Pu5bpYChMn7GG9Zgz/xjUaEf6fS7wreFWMrPa0ydXArcDF1TVXNr+jwD/E/ivYRcyHQyF6TOlITs0eyV5LPA54C1V9ZNh1zOTqur+qtqNZuSCPZLsMuyaZkKSPwBur6rvDLuW6WIoTJ+pDOuhWSrJhjSB8Omq+vyw6xmWqrobuJi5c31pL+CgJD+kOWX84iSfGm5JD4+hMH2mMqyHZqF2uPdPANdV1T8Ou56ZlmRhki3b6U2AfYHvD7eqmVFVb6+qRVW1Hc3f/IVV9eohl/WwGArTpKrWASPDelwHnF1V1wy3qpmT5Ezgm8CzkqxJcviwa5pBewGvodlLvLL9OmDYRc2gpwIXJbmaZufogqp61N+aOVc5zIUkqeORgiSpYyhIkjqGgiSpYyhIkjqGgiSpYyhozklyf3vb6DXtyJ5HJ3lIfwtJliQ5YRpqOjXJy9vpi9vRdq9O8v0kJ448ByD1zVDQXPTzqtqtqp4N7AccALzroXRUVSur6s3TWl3jVVW1K7ArzSikX+rhPaQHMRQ0p1XV7cAy4Mg05iX5YJLL2z31PwdI8pnBB9LaPfs/TrL3yBj6SR6b5JNJ/q197R+3y1+S5JtJrkhyTjtG0lTr+xXNYGvbJHnOdG67NBZDQXNeVd1I87fwJOBw4J6q2h3YHTgiyfY049r8KUA7jMk+wLmjunpn+9rfavfyL0yyAPgbYN+qeh6wEjh6Peu7H7gK2PEhbqI0ZfOHXYD0CDEyyu1LgF1Hzu8DWwCLga8AJyTZmGawt0ur6ufNsEedfWnGvwGgqu5qR9HcGfh623YjmuFAHmp9Uq8MBc15SZ4O3E/zWQAB3lRV543R7mLgpTRHDGeO1RUPHi49NGMBHfow6psH/Baz5JO99Mjm6SPNaUkWAicDJ1YzENh5wBvbobBJskOSzdrmZwGvB36vbTfa+TSDIo70/XjgMmCvJM9sl22aZIf1qG9D4O+A1VV19fpun7S+DAXNRZuM3JIK/CvNP/ORD5v/OHAtcEWS7wEf44Ej6vOBFwD/2l4AHu19wOOTfC/JVcCLqmot8DrgzHYU0cuY2rWBT7ftvwdsxhz6aFcNl6OkSpI6HilIkjqGgiSpYyhIkjqGgiSpYyhIkjqGgiSpYyhIkjr/H6366ib3DbP3AAAAAElFTkSuQmCC\n", 1032 | "text/plain": [ 1033 | "
" 1034 | ] 1035 | }, 1036 | "metadata": { 1037 | "needs_background": "light" 1038 | }, 1039 | "output_type": "display_data" 1040 | } 1041 | ], 1042 | "source": [ 1043 | "plt.bar('dev_id', 'avg(value)', data=df2, align='center', alpha=0.5)\n", 1044 | "plt.title('Average device measurements')\n", 1045 | "plt.xlabel('Device ID')\n", 1046 | "plt.ylabel('Value')\n", 1047 | "plt.show()" 1048 | ] 1049 | }, 1050 | { 1051 | "cell_type": "markdown", 1052 | "metadata": {}, 1053 | "source": [] 1054 | } 1055 | ], 1056 | "metadata": { 1057 | "kernelspec": { 1058 | "display_name": "Python 3", 1059 | "language": "python", 1060 | "name": "python3" 1061 | }, 1062 | "language_info": { 1063 | "codemirror_mode": { 1064 | "name": "ipython", 1065 | "version": 3 1066 | }, 1067 | "file_extension": ".py", 1068 | "mimetype": "text/x-python", 1069 | "name": "python", 1070 | "nbconvert_exporter": "python", 1071 | "pygments_lexer": "ipython3", 1072 | "version": "3.7.1" 1073 | } 1074 | }, 1075 | "nbformat": 4, 1076 | "nbformat_minor": 2 1077 | } 1078 | -------------------------------------------------------------------------------- /notebooks/EX-3-Sql-Magic-Functions.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Using Sql Magic Function with ClickHouse\n", 8 | "\n", 9 | "This notebook goes from nothing to a nice graph in three steps. We'll extract data using the %sql magic function. You'll need to have created the iris table for this to work. Run the EX-1-Getting-to-Know-the-Clickhouse-driver-Client.ipynb notebook to load data into the iris table if you have not already done so. " 10 | ] 11 | }, 12 | { 13 | "cell_type": "markdown", 14 | "metadata": {}, 15 | "source": [ 16 | "First import SQLAlchemy and activate the %sql function. This just needs to be done once. " 17 | ] 18 | }, 19 | { 20 | "cell_type": "code", 21 | "execution_count": 1, 22 | "metadata": { 23 | "scrolled": true 24 | }, 25 | "outputs": [], 26 | "source": [ 27 | "from sqlalchemy import create_engine\n", 28 | "%load_ext sql" 29 | ] 30 | }, 31 | { 32 | "cell_type": "markdown", 33 | "metadata": {}, 34 | "source": [ 35 | "Connect to a local server using native protocol, select data from the iris table, and pop it into a data frame. You should see 150 rows in the data frame. " 36 | ] 37 | }, 38 | { 39 | "cell_type": "code", 40 | "execution_count": 2, 41 | "metadata": { 42 | "scrolled": true 43 | }, 44 | "outputs": [ 45 | { 46 | "name": "stdout", 47 | "output_type": "stream", 48 | "text": [ 49 | " * clickhouse://default:***@localhost/default\n", 50 | "Done.\n" 51 | ] 52 | }, 53 | { 54 | "data": { 55 | "text/html": [ 56 | "
\n", 57 | "\n", 70 | "\n", 71 | " \n", 72 | " \n", 73 | " \n", 74 | " \n", 75 | " \n", 76 | " \n", 77 | " \n", 78 | " \n", 79 | " \n", 80 | " \n", 81 | " \n", 82 | " \n", 83 | " \n", 84 | " \n", 85 | " \n", 86 | " \n", 87 | " \n", 88 | " \n", 89 | " \n", 90 | " \n", 91 | " \n", 92 | " \n", 93 | " \n", 94 | " \n", 95 | " \n", 96 | " \n", 97 | " \n", 98 | " \n", 99 | " \n", 100 | " \n", 101 | " \n", 102 | " \n", 103 | " \n", 104 | " \n", 105 | " \n", 106 | " \n", 107 | " \n", 108 | " \n", 109 | " \n", 110 | " \n", 111 | " \n", 112 | " \n", 113 | " \n", 114 | " \n", 115 | " \n", 116 | " \n", 117 | " \n", 118 | " \n", 119 | " \n", 120 | " \n", 121 | " \n", 122 | " \n", 123 | "
sepal_lengthsepal_widthpetal_lengthpetal_widthspecies
1455.73.04.21.2Iris-versicolor
1465.72.94.21.3Iris-versicolor
1476.22.94.31.3Iris-versicolor
1485.12.53.01.1Iris-versicolor
1495.72.84.11.3Iris-versicolor
\n", 124 | "
" 125 | ], 126 | "text/plain": [ 127 | " sepal_length sepal_width petal_length petal_width species\n", 128 | "145 5.7 3.0 4.2 1.2 Iris-versicolor\n", 129 | "146 5.7 2.9 4.2 1.3 Iris-versicolor\n", 130 | "147 6.2 2.9 4.3 1.3 Iris-versicolor\n", 131 | "148 5.1 2.5 3.0 1.1 Iris-versicolor\n", 132 | "149 5.7 2.8 4.1 1.3 Iris-versicolor" 133 | ] 134 | }, 135 | "execution_count": 2, 136 | "metadata": {}, 137 | "output_type": "execute_result" 138 | } 139 | ], 140 | "source": [ 141 | "%sql clickhouse://default:@localhost/default\n", 142 | "result = %sql SELECT * FROM iris\n", 143 | "df = result.DataFrame()\n", 144 | "df.tail()" 145 | ] 146 | }, 147 | { 148 | "cell_type": "markdown", 149 | "metadata": {}, 150 | "source": [ 151 | "Everybody likes a nice picture. Let's make a scatter graph that shows data with different markers for each species of iris. We'll use standard pandas tricks to find the species names and query for each one of the. \n", 152 | "\n", 153 | "Pro tip: For large datasets you could get unique names using SQL. We'll just cheat and use the pandas unique() method on the data frame." 154 | ] 155 | }, 156 | { 157 | "cell_type": "code", 158 | "execution_count": 5, 159 | "metadata": {}, 160 | "outputs": [ 161 | { 162 | "data": { 163 | "image/png": "iVBORw0KGgoAAAANSUhEUgAAAXwAAAEKCAYAAAARnO4WAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDMuMC4yLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvOIA7rQAAIABJREFUeJzt3XmYFOX16PHvYRgFFEU2jYOCel2iLMMewbBIBHdBAVGjEhVcrnFJooLGXRQ1Jmb5XRE14BYFRdCfC5KwiKKCM6yCSxQFgRhHkFEZ0Jmec/+o7pnunl6q6erq7unzeZ5+Zqq6uup0oWeqT5/3LVFVjDHGNH5Nsh2AMcYYf1jCN8aYAmEJ3xhjCoQlfGOMKRCW8I0xpkBYwjfGmAJhCd8YYwqEJXxjjCkQlvCNMaZANM12AOHatm2rnTp1ynYYxhiTN8rLy79W1XZuts2phN+pUyfKysqyHYYxxuQNEdngdlsr6RhjTIGwhG+MMQUiYwlfRI4UkZVhj29F5JpMHc8YY0xiGavhq+pHQCmAiBQBm4HZqe6nurqaTZs2sWvXLo8jNOlo1qwZHTp0oLi4ONuhGGNc8utL2yHAp6rq+suFkE2bNtGyZUs6deqEiGQgNJMqVWXr1q1s2rSJQw45JNvhGGNc8quGPwZ4JtYTIjJeRMpEpKyioqLB87t27aJNmzaW7HOIiNCmTRv71GVMnsn4Fb6I7AGcDkyM9byqTgWmAvTq1Svm7bcs2ece+zcxhW7Ois3c//pHbNm+kwNbNee6YUcyvHtJtsNKyI+SzknAclX9rw/HMsaYjJuzYjMTX1jDzuoAAJu372TiC2sAcjrp+1HSOYc45Zx8sffee8d9rl+/fmnv/6WXXmLy5Mkpv87NsS+55BLWrVu3O2EZY+K4//WP6pJ9yM7qAPe//lGWInIno1f4ItICOAG4NJPHyYZAIEBRURFvv/122vs6/fTTOf300xusr6mpoWnT+P9Ebo796KOPphWbMaahLdt3prQ+V2T0Cl9Vq1S1japWZvI44eas2Ez/yQs4ZMIr9J+8gDkrNnu270WLFjF48GDOPfdcunTpAtRf/f/nP/9hwIABlJaW0rlzZ958880Gr+/bty9r166tWx40aBDl5eVMnz6dK6+8EoCxY8fym9/8hsGDB3PDDTdQUVHBCSecQI8ePbj00kvp2LEjX3/9dcSxFy1axKBBgxg5ciRHHXUU5513Hqpad4zQdBVz586lR48edOvWjSFDhgCwbNky+vXrR/fu3enXrx8ffZTbVyjG5IIDWzVPaX2uaFQjbUN1tc3bd6LU19W8TPrLli1j0qRJDcok//jHPxg2bBgrV65k1apVlJaWNnjtmDFjmDlzJuD8gdiyZQs9e/ZssN3HH3/Mv/71Lx544AFuv/12jj/+eJYvX86IESPYuHFjzLhWrFjBgw8+yLp161i/fj1LliyJeL6iooJx48Yxa9YsVq1axXPPPQfAUUcdxeLFi1mxYgV33HEHN954426dF2MKyXXDjqR5cVHEuubFRVw37MgsReROo0r4ftTV+vTpE7P3vHfv3kybNo3bbruNNWvW0LJlywbbjB49ui7Rzpw5k1GjRsU8xqhRoygqcv5jeuuttxgzZgwAJ554Ivvtt1/cuDp06ECTJk0oLS3l888/j3j+3XffZcCAAXWxt27dGoDKykpGjRpF586dufbaayM+gRhjYhvevYQeB+8bsa7Hwfvm9Be20MgSvh91tb322ivm+gEDBrB48WJKSko4//zzeeKJJ5g9ezalpaWUlpZSVlZGSUkJbdq0YfXq1cyYMaMukSc6Rqg0k8yee+5Z93tRURE1NTURz6tqzFbKm2++mcGDB/P+++/zv//7v9Zbb4wLv5+zhiWfbotYt+TTbfx+zposReROo0r42ayrbdiwgfbt2zNu3DguvvjiuhLMypUrWblyJb169QKcss59991HZWVl3fcAiRx33HF1ZaB58+bxzTff7FZ8xx57LG+88QafffYZANu2Of+xVlZWUlLiXJVMnz59t/ZtTKF5ZukXKa3PFY0q4WezrrZo0SJKS0vp3r07s2bN4uqrr4653ciRI3n22WcZPXq0q/3eeuutzJs3jx49evDaa6/xk5/8JGa5KJl27doxdepUzjzzTLp168bZZ58NwPXXX8/EiRPp378/gUAgyV6MMQCBOJ+8463PFeK2ZOCHXr16afQNUD744AN++tOfut5HPo5+S+SHH36gqKiIpk2b8s4773D55ZezcuXKbIcFpP5vY0y+SJZHDpv4aszkXiTCp/ec7GeoiEi5qvZys21O3fHKC8O7l+R1go+2ceNGRo8eTW1tLXvssQePPPJItkMyplFzM4r2nL4H8dS7DTvm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\n", 164 | "text/plain": [ 165 | "
" 166 | ] 167 | }, 168 | "metadata": { 169 | "needs_background": "light" 170 | }, 171 | "output_type": "display_data" 172 | } 173 | ], 174 | "source": [ 175 | "import matplotlib.pyplot as plt\n", 176 | "%matplotlib inline\n", 177 | "\n", 178 | "# Break up the data frame and graph each species separately. \n", 179 | "species = df.species.unique()\n", 180 | "markers = ['o', 'x', '^']\n", 181 | "for i in range(3):\n", 182 | " df_segment = df[df['species'] == species[i]]\n", 183 | " plt.scatter('sepal_length', \n", 184 | " 'petal_length', \n", 185 | " data=df_segment, \n", 186 | " marker=markers[i],\n", 187 | " label=species[i])\n", 188 | "# Add proper labels and show the result. \n", 189 | "plt.xlabel('sepal length [cm]')\n", 190 | "plt.ylabel('petal length [cm]')\n", 191 | "plt.legend(loc='upper left')\n", 192 | "plt.show()" 193 | ] 194 | }, 195 | { 196 | "cell_type": "markdown", 197 | "metadata": {}, 198 | "source": [ 199 | "From this we can see that iris-setosa is linearly separable from the other two species. This is significant for running machine learning. \n", 200 | "\n", 201 | "One final note is that when you don't know what's coming back it's good to describe the data set to ensure the values you think are numeric actually are. For example ClickHouse Decimal values don't automatically coerce to floats which means data science stack operations won't work as expected. " 202 | ] 203 | }, 204 | { 205 | "cell_type": "code", 206 | "execution_count": 4, 207 | "metadata": {}, 208 | "outputs": [ 209 | { 210 | "data": { 211 | "text/html": [ 212 | "
\n", 213 | "\n", 226 | "\n", 227 | " \n", 228 | " \n", 229 | " \n", 230 | " \n", 231 | " \n", 232 | " \n", 233 | " \n", 234 | " \n", 235 | " \n", 236 | " \n", 237 | " \n", 238 | " \n", 239 | " \n", 240 | " \n", 241 | " \n", 242 | " \n", 243 | " \n", 244 | " \n", 245 | " \n", 246 | " \n", 247 | " \n", 248 | " \n", 249 | " \n", 250 | " \n", 251 | " \n", 252 | " \n", 253 | " \n", 254 | " \n", 255 | " \n", 256 | " \n", 257 | " \n", 258 | " \n", 259 | " \n", 260 | " \n", 261 | " \n", 262 | " \n", 263 | " \n", 264 | " \n", 265 | " \n", 266 | " \n", 267 | " \n", 268 | " \n", 269 | " \n", 270 | " \n", 271 | " \n", 272 | " \n", 273 | " \n", 274 | " \n", 275 | " \n", 276 | " \n", 277 | " \n", 278 | " \n", 279 | " \n", 280 | " \n", 281 | " \n", 282 | " \n", 283 | " \n", 284 | " \n", 285 | " \n", 286 | " \n", 287 | " \n", 288 | " \n", 289 | " \n", 290 | " \n", 291 | " \n", 292 | " \n", 293 | " \n", 294 | "
sepal_lengthsepal_widthpetal_lengthpetal_width
count150.000000150.000000150.000000150.000000
mean5.8433333.0573333.7580001.199333
std0.8280660.4358661.7652980.762238
min4.3000002.0000001.0000000.100000
25%5.1000002.8000001.6000000.300000
50%5.8000003.0000004.3500001.300000
75%6.4000003.3000005.1000001.800000
max7.9000004.4000006.9000002.500000
\n", 295 | "
" 296 | ], 297 | "text/plain": [ 298 | " sepal_length sepal_width petal_length petal_width\n", 299 | "count 150.000000 150.000000 150.000000 150.000000\n", 300 | "mean 5.843333 3.057333 3.758000 1.199333\n", 301 | "std 0.828066 0.435866 1.765298 0.762238\n", 302 | "min 4.300000 2.000000 1.000000 0.100000\n", 303 | "25% 5.100000 2.800000 1.600000 0.300000\n", 304 | "50% 5.800000 3.000000 4.350000 1.300000\n", 305 | "75% 6.400000 3.300000 5.100000 1.800000\n", 306 | "max 7.900000 4.400000 6.900000 2.500000" 307 | ] 308 | }, 309 | "execution_count": 4, 310 | "metadata": {}, 311 | "output_type": "execute_result" 312 | } 313 | ], 314 | "source": [ 315 | "import pandas\n", 316 | "df.describe()" 317 | ] 318 | }, 319 | { 320 | "cell_type": "code", 321 | "execution_count": null, 322 | "metadata": {}, 323 | "outputs": [], 324 | "source": [] 325 | } 326 | ], 327 | "metadata": { 328 | "kernelspec": { 329 | "display_name": "Python 3", 330 | "language": "python", 331 | "name": "python3" 332 | }, 333 | "language_info": { 334 | "codemirror_mode": { 335 | "name": "ipython", 336 | "version": 3 337 | }, 338 | "file_extension": ".py", 339 | "mimetype": "text/x-python", 340 | "name": "python", 341 | "nbconvert_exporter": "python", 342 | "pygments_lexer": "ipython3", 343 | "version": "3.7.1" 344 | } 345 | }, 346 | "nbformat": 4, 347 | "nbformat_minor": 2 348 | } 349 | -------------------------------------------------------------------------------- /notebooks/EX-4-Pivot-Using-SQL-And-Pandas.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Pivoting SQL results in Panda\n", 8 | "\n", 9 | "This notebook shows how to pivot array data using SQL ARRAY JOIN and pandas DataFrame.pivot(). This problem appeared as a [question on Stack Overflow](https://stackoverflow.com/questions/54811905/return-clickhouse-array-as-column). " 10 | ] 11 | }, 12 | { 13 | "cell_type": "markdown", 14 | "metadata": {}, 15 | "source": [ 16 | "First create some test data. We'll use clickhouse-driver for this so we can see the SQL. " 17 | ] 18 | }, 19 | { 20 | "cell_type": "code", 21 | "execution_count": 1, 22 | "metadata": {}, 23 | "outputs": [], 24 | "source": [ 25 | "from clickhouse_driver import Client\n", 26 | "client = Client('localhost')\n", 27 | "client.execute('CREATE TABLE IF NOT EXISTS f '\n", 28 | " '(f1 String, f2 Array(Int32), f3 Array(String)) '\n", 29 | " 'ENGINE = Memory')\n", 30 | "client.execute('TRUNCATE TABLE f')\n", 31 | "client.execute(\n", 32 | " 'INSERT INTO f (f1, f2, f3) VALUES', [\n", 33 | " ('a', [1,2,3], ['x', 'y', 'z']),\n", 34 | " ('b', [4,5,6], ['x', 'y', 'z']),\n", 35 | " ]\n", 36 | ")" 37 | ] 38 | }, 39 | { 40 | "cell_type": "markdown", 41 | "metadata": {}, 42 | "source": [ 43 | "Now load SQLAlchemy. " 44 | ] 45 | }, 46 | { 47 | "cell_type": "code", 48 | "execution_count": 2, 49 | "metadata": { 50 | "scrolled": true 51 | }, 52 | "outputs": [], 53 | "source": [ 54 | "from sqlalchemy import create_engine\n", 55 | "%load_ext sql" 56 | ] 57 | }, 58 | { 59 | "cell_type": "markdown", 60 | "metadata": {}, 61 | "source": [ 62 | "Connect to ClickHouse, which is assumed to be on localhost with default user. " 63 | ] 64 | }, 65 | { 66 | "cell_type": "code", 67 | "execution_count": 3, 68 | "metadata": {}, 69 | "outputs": [ 70 | { 71 | "data": { 72 | "text/plain": [ 73 | "'Connected: default@default'" 74 | ] 75 | }, 76 | "execution_count": 3, 77 | "metadata": {}, 78 | "output_type": "execute_result" 79 | } 80 | ], 81 | "source": [ 82 | "%sql clickhouse://default:@localhost/default" 83 | ] 84 | }, 85 | { 86 | "cell_type": "markdown", 87 | "metadata": {}, 88 | "source": [ 89 | "Use SQL query with ARRAY JOIN to flip matching array indexes in f2, f3 to row values with f1. " 90 | ] 91 | }, 92 | { 93 | "cell_type": "code", 94 | "execution_count": 13, 95 | "metadata": {}, 96 | "outputs": [ 97 | { 98 | "name": "stdout", 99 | "output_type": "stream", 100 | "text": [ 101 | " * clickhouse://default:***@localhost/default\n", 102 | "Done.\n" 103 | ] 104 | }, 105 | { 106 | "data": { 107 | "text/html": [ 108 | "
\n", 109 | "\n", 122 | "\n", 123 | " \n", 124 | " \n", 125 | " \n", 126 | " \n", 127 | " \n", 128 | " \n", 129 | " \n", 130 | " \n", 131 | " \n", 132 | " \n", 133 | " \n", 134 | " \n", 135 | " \n", 136 | " \n", 137 | " \n", 138 | " \n", 139 | " \n", 140 | " \n", 141 | " \n", 142 | " \n", 143 | " \n", 144 | " \n", 145 | " \n", 146 | " \n", 147 | " \n", 148 | " \n", 149 | " \n", 150 | " \n", 151 | " \n", 152 | " \n", 153 | " \n", 154 | " \n", 155 | " \n", 156 | " \n", 157 | " \n", 158 | " \n", 159 | " \n", 160 | " \n", 161 | " \n", 162 | " \n", 163 | " \n", 164 | " \n", 165 | " \n", 166 | " \n", 167 | " \n", 168 | " \n", 169 | " \n", 170 | " \n", 171 | " \n", 172 | " \n", 173 | " \n", 174 | " \n", 175 | " \n", 176 | " \n", 177 | " \n", 178 | " \n", 179 | " \n", 180 | " \n", 181 | " \n", 182 | " \n", 183 | " \n", 184 | " \n", 185 | " \n", 186 | " \n", 187 | " \n", 188 | " \n", 189 | " \n", 190 | " \n", 191 | " \n", 192 | " \n", 193 | " \n", 194 | " \n", 195 | " \n", 196 | " \n", 197 | " \n", 198 | " \n", 199 | " \n", 200 | " \n", 201 | " \n", 202 | " \n", 203 | " \n", 204 | " \n", 205 | " \n", 206 | " \n", 207 | " \n", 208 | " \n", 209 | " \n", 210 | " \n", 211 | " \n", 212 | " \n", 213 | " \n", 214 | " \n", 215 | " \n", 216 | " \n", 217 | "
f1f2f3
0a1x
1a2y
2a3z
3b4x
4b5y
5b6z
6c7y
7c8z
8c9aa
9c10bb
10c7y
11c8z
12c9aa
13c10bb
\n", 218 | "
" 219 | ], 220 | "text/plain": [ 221 | " f1 f2 f3\n", 222 | "0 a 1 x\n", 223 | "1 a 2 y\n", 224 | "2 a 3 z\n", 225 | "3 b 4 x\n", 226 | "4 b 5 y\n", 227 | "5 b 6 z\n", 228 | "6 c 7 y\n", 229 | "7 c 8 z\n", 230 | "8 c 9 aa\n", 231 | "9 c 10 bb\n", 232 | "10 c 7 y\n", 233 | "11 c 8 z\n", 234 | "12 c 9 aa\n", 235 | "13 c 10 bb" 236 | ] 237 | }, 238 | "execution_count": 13, 239 | "metadata": {}, 240 | "output_type": "execute_result" 241 | } 242 | ], 243 | "source": [ 244 | "result = %sql SELECT * FROM f ARRAY JOIN f2, f3\n", 245 | "df = result.DataFrame()\n", 246 | "df" 247 | ] 248 | }, 249 | { 250 | "cell_type": "markdown", 251 | "metadata": {}, 252 | "source": [ 253 | "Now we can pivot f2 and f3 into a new data frame that has the f3 array entries as columns. " 254 | ] 255 | }, 256 | { 257 | "cell_type": "code", 258 | "execution_count": 15, 259 | "metadata": {}, 260 | "outputs": [ 261 | { 262 | "name": "stdout", 263 | "output_type": "stream", 264 | "text": [ 265 | "f3 aa bb x y z\n", 266 | "f1 \n", 267 | "a NaN NaN 1.0 2.0 3.0\n", 268 | "b NaN NaN 4.0 5.0 6.0\n", 269 | "c 9.0 10.0 NaN 7.0 8.0\n" 270 | ] 271 | } 272 | ], 273 | "source": [ 274 | "dfp = df.pivot_table(columns='f3', values='f2', index='f1')\n", 275 | "print(dfp)" 276 | ] 277 | }, 278 | { 279 | "cell_type": "markdown", 280 | "metadata": {}, 281 | "source": [ 282 | "This approach works if we add additional data with new property names in the f3 array. Try adding a row to the table and then rerun the cells that select and pivot data. " 283 | ] 284 | }, 285 | { 286 | "cell_type": "code", 287 | "execution_count": 12, 288 | "metadata": { 289 | "scrolled": false 290 | }, 291 | "outputs": [], 292 | "source": [ 293 | "client.execute(\n", 294 | " 'INSERT INTO f (f1, f2, f3) VALUES', [\n", 295 | " ('c', [7,8,9,10], ['y', 'z', 'aa', 'bb']),\n", 296 | " ]\n", 297 | ")" 298 | ] 299 | }, 300 | { 301 | "cell_type": "markdown", 302 | "metadata": {}, 303 | "source": [ 304 | "If you try this again the duplicate rows will be ignored. " 305 | ] 306 | } 307 | ], 308 | "metadata": { 309 | "kernelspec": { 310 | "display_name": "Python 3", 311 | "language": "python", 312 | "name": "python3" 313 | }, 314 | "language_info": { 315 | "codemirror_mode": { 316 | "name": "ipython", 317 | "version": 3 318 | }, 319 | "file_extension": ".py", 320 | "mimetype": "text/x-python", 321 | "name": "python", 322 | "nbconvert_exporter": "python", 323 | "pygments_lexer": "ipython3", 324 | "version": "3.7.1" 325 | }, 326 | "widgets": { 327 | "application/vnd.jupyter.widget-state+json": { 328 | "state": {}, 329 | "version_major": 1, 330 | "version_minor": 0 331 | } 332 | } 333 | }, 334 | "nbformat": 4, 335 | "nbformat_minor": 2 336 | } 337 | -------------------------------------------------------------------------------- /notebooks/EX-5-Airline-OnTime-Data.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Graphing Airline Ontime Data\n", 8 | "\n", 9 | "This notebook shows how to create a time-series graph from airline ontime data, which can be downloaded from the [US Bureau of Transportation Statistics](https://www.transtats.bts.gov/tables.asp?DB_ID=120). See https://github.com/Altinity/altinity-datasets for tools to help with loading. " 10 | ] 11 | }, 12 | { 13 | "cell_type": "markdown", 14 | "metadata": {}, 15 | "source": [ 16 | "First import SQLAlchemy and activate the %sql function. This just needs to be done once. " 17 | ] 18 | }, 19 | { 20 | "cell_type": "code", 21 | "execution_count": 1, 22 | "metadata": { 23 | "scrolled": true 24 | }, 25 | "outputs": [], 26 | "source": [ 27 | "from sqlalchemy import create_engine\n", 28 | "%load_ext sql" 29 | ] 30 | }, 31 | { 32 | "cell_type": "markdown", 33 | "metadata": {}, 34 | "source": [ 35 | "Run a query using %%sql. This needs to go in a separate cell. " 36 | ] 37 | }, 38 | { 39 | "cell_type": "code", 40 | "execution_count": 2, 41 | "metadata": {}, 42 | "outputs": [ 43 | { 44 | "name": "stdout", 45 | "output_type": "stream", 46 | "text": [ 47 | "Done.\n" 48 | ] 49 | }, 50 | { 51 | "data": { 52 | "text/html": [ 53 | "\n", 54 | " \n", 55 | " \n", 56 | " \n", 57 | " \n", 58 | " \n", 59 | " \n", 60 | " \n", 61 | " \n", 62 | " \n", 63 | " \n", 64 | " \n", 65 | " \n", 66 | " \n", 67 | " \n", 68 | " \n", 69 | " \n", 70 | " \n", 71 | " \n", 72 | " \n", 73 | " \n", 74 | " \n", 75 | " \n", 76 | " \n", 77 | " \n", 78 | " \n", 79 | " \n", 80 | " \n", 81 | " \n", 82 | " \n", 83 | " \n", 84 | " \n", 85 | " \n", 86 | " \n", 87 | " \n", 88 | " \n", 89 | " \n", 90 | " \n", 91 | " \n", 92 | " \n", 93 | " \n", 94 | " \n", 95 | " \n", 96 | " \n", 97 | " \n", 98 | " \n", 99 | " \n", 100 | " \n", 101 | " \n", 102 | " \n", 103 | " \n", 104 | " \n", 105 | " \n", 106 | " \n", 107 | " \n", 108 | " \n", 109 | " \n", 110 | " \n", 111 | " \n", 112 | " \n", 113 | " \n", 114 | " \n", 115 | " \n", 116 | " \n", 117 | " \n", 118 | " \n", 119 | " \n", 120 | " \n", 121 | " \n", 122 | " \n", 123 | " \n", 124 | " \n", 125 | " \n", 126 | " \n", 127 | " \n", 128 | " \n", 129 | " \n", 130 | " \n", 131 | " \n", 132 | " \n", 133 | " \n", 134 | " \n", 135 | " \n", 136 | " \n", 137 | " \n", 138 | " \n", 139 | " \n", 140 | " \n", 141 | " \n", 142 | " \n", 143 | " \n", 144 | " \n", 145 | " \n", 146 | " \n", 147 | " \n", 148 | " \n", 149 | " \n", 150 | " \n", 151 | " \n", 152 | " \n", 153 | " \n", 154 | " \n", 155 | " \n", 156 | " \n", 157 | " \n", 158 | " \n", 159 | " \n", 160 | " \n", 161 | " \n", 162 | " \n", 163 | " \n", 164 | " \n", 165 | " \n", 166 | " \n", 167 | " \n", 168 | " \n", 169 | " \n", 170 | " \n", 171 | " \n", 172 | " \n", 173 | " \n", 174 | " \n", 175 | " \n", 176 | " \n", 177 | " \n", 178 | " \n", 179 | " \n", 180 | " \n", 181 | " \n", 182 | " \n", 183 | " \n", 184 | " \n", 185 | " \n", 186 | " \n", 187 | " \n", 188 | " \n", 189 | " \n", 190 | " \n", 191 | " \n", 192 | " \n", 193 | " \n", 194 | " \n", 195 | " \n", 196 | " \n", 197 | " \n", 198 | " \n", 199 | " \n", 200 | " \n", 201 | " \n", 202 | " \n", 203 | " \n", 204 | " \n", 205 | " \n", 206 | " \n", 207 | " \n", 208 | " \n", 209 | " \n", 210 | " \n", 211 | " \n", 212 | " \n", 213 | " \n", 214 | " \n", 215 | " \n", 216 | " \n", 217 | " \n", 218 | " \n", 219 | "
tcancelleddelayed
19870.0150058010742278310.15847681018671683
19880.0096428439613571150.13082207633230913
19890.0147117749742124890.16047806077917956
19900.0099523932661884810.1329419891468106
19910.0085691634207714310.11384922960256455
19920.0103759565936399850.11081983528787506
19930.0118025812439441390.118570334568517
19940.0128840504952849860.12803356262335794
19950.017251266322348370.1554094981919066
19960.0240165187370737150.18197890389412671
19970.0180646408256854470.15648458390237854
19980.026836859328459170.16164161522946127
19990.0279150213716496220.1695536664662283
20000.032991104947750740.19912962183842575
20010.038741039381478540.1598262670540804
20020.0123579137751763830.1360878665255013
20030.015958936039617280.13144318872073027
20040.017920067552498360.1665800285302703
20050.0190690455730729950.18150869494248564
20060.017072995196531130.1994948978720294
20070.0215692986265900760.210983416444704
20080.019605901856934210.18941510695282526
20090.0138562869702656550.16836124295283075
20100.0175585962239134560.1726871000944634
20110.0190587747714526250.17160785179846255
20120.012935062907162850.16289138398382616
20130.0150737532502643080.19332121513177994
20140.0218192652647998360.2053970481171983
20150.0154464306121295140.18173906901762288
20160.0117239248099474910.16974030814976632
20170.013998818968705090.19478701373546048
20180.0106691141598627030.17753310427890504
" 220 | ], 221 | "text/plain": [ 222 | "[(1987, 0.015005801074227831, 0.15847681018671683),\n", 223 | " (1988, 0.009642843961357115, 0.13082207633230913),\n", 224 | " (1989, 0.014711774974212489, 0.16047806077917956),\n", 225 | " (1990, 0.009952393266188481, 0.1329419891468106),\n", 226 | " (1991, 0.008569163420771431, 0.11384922960256455),\n", 227 | " (1992, 0.010375956593639985, 0.11081983528787506),\n", 228 | " (1993, 0.011802581243944139, 0.118570334568517),\n", 229 | " (1994, 0.012884050495284986, 0.12803356262335794),\n", 230 | " (1995, 0.01725126632234837, 0.1554094981919066),\n", 231 | " (1996, 0.024016518737073715, 0.18197890389412671),\n", 232 | " (1997, 0.018064640825685447, 0.15648458390237854),\n", 233 | " (1998, 0.02683685932845917, 0.16164161522946127),\n", 234 | " (1999, 0.027915021371649622, 0.1695536664662283),\n", 235 | " (2000, 0.03299110494775074, 0.19912962183842575),\n", 236 | " (2001, 0.03874103938147854, 0.1598262670540804),\n", 237 | " (2002, 0.012357913775176383, 0.1360878665255013),\n", 238 | " (2003, 0.01595893603961728, 0.13144318872073027),\n", 239 | " (2004, 0.01792006755249836, 0.1665800285302703),\n", 240 | " (2005, 0.019069045573072995, 0.18150869494248564),\n", 241 | " (2006, 0.01707299519653113, 0.1994948978720294),\n", 242 | " (2007, 0.021569298626590076, 0.210983416444704),\n", 243 | " (2008, 0.01960590185693421, 0.18941510695282526),\n", 244 | " (2009, 0.013856286970265655, 0.16836124295283075),\n", 245 | " (2010, 0.017558596223913456, 0.1726871000944634),\n", 246 | " (2011, 0.019058774771452625, 0.17160785179846255),\n", 247 | " (2012, 0.01293506290716285, 0.16289138398382616),\n", 248 | " (2013, 0.015073753250264308, 0.19332121513177994),\n", 249 | " (2014, 0.021819265264799836, 0.2053970481171983),\n", 250 | " (2015, 0.015446430612129514, 0.18173906901762288),\n", 251 | " (2016, 0.011723924809947491, 0.16974030814976632),\n", 252 | " (2017, 0.01399881896870509, 0.19478701373546048),\n", 253 | " (2018, 0.010669114159862703, 0.17753310427890504)]" 254 | ] 255 | }, 256 | "execution_count": 2, 257 | "metadata": {}, 258 | "output_type": "execute_result" 259 | } 260 | ], 261 | "source": [ 262 | "%%sql clickhouse://default:@localhost/airline\n", 263 | "SELECT toYear(FlightDate) t, \n", 264 | " sum(Cancelled)/count(*) cancelled, \n", 265 | " sum(DepDel15)/count(*) delayed\n", 266 | "FROM airline.ontime GROUP BY t ORDER BY t" 267 | ] 268 | }, 269 | { 270 | "cell_type": "markdown", 271 | "metadata": {}, 272 | "source": [ 273 | "Turn the result into a nice dataframe and prove it has some data in it. " 274 | ] 275 | }, 276 | { 277 | "cell_type": "code", 278 | "execution_count": 3, 279 | "metadata": {}, 280 | "outputs": [ 281 | { 282 | "data": { 283 | "text/html": [ 284 | "
\n", 285 | "\n", 298 | "\n", 299 | " \n", 300 | " \n", 301 | " \n", 302 | " \n", 303 | " \n", 304 | " \n", 305 | " \n", 306 | " \n", 307 | " \n", 308 | " \n", 309 | " \n", 310 | " \n", 311 | " \n", 312 | " \n", 313 | " \n", 314 | " \n", 315 | " \n", 316 | " \n", 317 | " \n", 318 | " \n", 319 | " \n", 320 | " \n", 321 | " \n", 322 | " \n", 323 | " \n", 324 | " \n", 325 | " \n", 326 | " \n", 327 | " \n", 328 | " \n", 329 | " \n", 330 | " \n", 331 | " \n", 332 | " \n", 333 | " \n", 334 | " \n", 335 | " \n", 336 | " \n", 337 | " \n", 338 | " \n", 339 | "
tcancelleddelayed
2720140.0218190.205397
2820150.0154460.181739
2920160.0117240.169740
3020170.0139990.194787
3120180.0106690.177533
\n", 340 | "
" 341 | ], 342 | "text/plain": [ 343 | " t cancelled delayed\n", 344 | "27 2014 0.021819 0.205397\n", 345 | "28 2015 0.015446 0.181739\n", 346 | "29 2016 0.011724 0.169740\n", 347 | "30 2017 0.013999 0.194787\n", 348 | "31 2018 0.010669 0.177533" 349 | ] 350 | }, 351 | "execution_count": 3, 352 | "metadata": {}, 353 | "output_type": "execute_result" 354 | } 355 | ], 356 | "source": [ 357 | "result = _\n", 358 | "df = result.DataFrame()\n", 359 | "df.tail()" 360 | ] 361 | }, 362 | { 363 | "cell_type": "markdown", 364 | "metadata": {}, 365 | "source": [ 366 | "Time to make a quick graph using matplotlib. I'm not the greatest at this but once you have a data frame everything is possible. " 367 | ] 368 | }, 369 | { 370 | "cell_type": "code", 371 | "execution_count": 4, 372 | "metadata": {}, 373 | "outputs": [ 374 | { 375 | "data": { 376 | "image/png": "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\n", 377 | "text/plain": [ 378 | "
" 379 | ] 380 | }, 381 | "metadata": { 382 | "needs_background": "light" 383 | }, 384 | "output_type": "display_data" 385 | } 386 | ], 387 | "source": [ 388 | "import matplotlib.pyplot as plt\n", 389 | "%matplotlib inline\n", 390 | "\n", 391 | "plt.plot('t', 'cancelled', \n", 392 | " data=df, linestyle='--', \n", 393 | " marker='o', label='Cancelled')\n", 394 | "plt.plot('t', 'delayed', \n", 395 | " data=df, linestyle='--', \n", 396 | " marker='o', label='Delayed')\n", 397 | "plt.xlabel('Year')\n", 398 | "plt.ylabel('Percentage')\n", 399 | "plt.legend(loc='upper left')\n", 400 | "plt.title('Fetch data the easy way')\n", 401 | "plt.show()" 402 | ] 403 | }, 404 | { 405 | "cell_type": "markdown", 406 | "metadata": {}, 407 | "source": [ 408 | "The %sql magic function is great but we can also do the same thing using the clickhouse-driver client library and direct API calls. " 409 | ] 410 | }, 411 | { 412 | "cell_type": "code", 413 | "execution_count": 5, 414 | "metadata": {}, 415 | "outputs": [ 416 | { 417 | "data": { 418 | "text/html": [ 419 | "
\n", 420 | "\n", 433 | "\n", 434 | " \n", 435 | " \n", 436 | " \n", 437 | " \n", 438 | " \n", 439 | " \n", 440 | " \n", 441 | " \n", 442 | " \n", 443 | " \n", 444 | " \n", 445 | " \n", 446 | " \n", 447 | " \n", 448 | " \n", 449 | " \n", 450 | " \n", 451 | " \n", 452 | " \n", 453 | " \n", 454 | " \n", 455 | " \n", 456 | " \n", 457 | " \n", 458 | " \n", 459 | " \n", 460 | " \n", 461 | " \n", 462 | " \n", 463 | " \n", 464 | " \n", 465 | " \n", 466 | " \n", 467 | " \n", 468 | " \n", 469 | " \n", 470 | " \n", 471 | " \n", 472 | " \n", 473 | " \n", 474 | "
tcancelleddelayed
2720140.0218190.205397
2820150.0154460.181739
2920160.0117240.169740
3020170.0139990.194787
3120180.0106690.177533
\n", 475 | "
" 476 | ], 477 | "text/plain": [ 478 | " t cancelled delayed\n", 479 | "27 2014 0.021819 0.205397\n", 480 | "28 2015 0.015446 0.181739\n", 481 | "29 2016 0.011724 0.169740\n", 482 | "30 2017 0.013999 0.194787\n", 483 | "31 2018 0.010669 0.177533" 484 | ] 485 | }, 486 | "execution_count": 5, 487 | "metadata": {}, 488 | "output_type": "execute_result" 489 | } 490 | ], 491 | "source": [ 492 | "import pandas\n", 493 | "from clickhouse_driver import Client\n", 494 | "\n", 495 | "client = Client('localhost', database='airline')\n", 496 | "result, columns = client.execute(\n", 497 | " 'SELECT toYear(FlightDate) t,'\n", 498 | " 'sum(Cancelled)/count(*) cancelled,'\n", 499 | " 'sum(DepDel15)/count(*) delayed '\n", 500 | " 'FROM airline.ontime GROUP BY t ORDER BY t', \n", 501 | " with_column_types=True)\n", 502 | "\n", 503 | "df2 = pandas.DataFrame(result, columns=[tuple[0] for tuple in columns])\n", 504 | "df2.tail()" 505 | ] 506 | }, 507 | { 508 | "cell_type": "markdown", 509 | "metadata": {}, 510 | "source": [ 511 | "The graph looks just the same, so we change the title to tell them apart. " 512 | ] 513 | }, 514 | { 515 | "cell_type": "code", 516 | "execution_count": 6, 517 | "metadata": {}, 518 | "outputs": [ 519 | { 520 | "data": { 521 | "image/png": "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\n", 522 | "text/plain": [ 523 | "
" 524 | ] 525 | }, 526 | "metadata": { 527 | "needs_background": "light" 528 | }, 529 | "output_type": "display_data" 530 | } 531 | ], 532 | "source": [ 533 | "import matplotlib.pyplot as plt\n", 534 | "%matplotlib inline\n", 535 | "\n", 536 | "plt.plot('t', 'cancelled', data=df2, \n", 537 | " linestyle='--', marker='o', label='Cancelled')\n", 538 | "plt.plot('t', 'delayed', data=df2, \n", 539 | " linestyle='--', marker='o', label='Delayed')\n", 540 | "plt.xlabel('Year')\n", 541 | "plt.ylabel('Percentage')\n", 542 | "plt.legend(loc='upper left')\n", 543 | "plt.title('Fetch data the hard way')\n", 544 | "plt.show()" 545 | ] 546 | }, 547 | { 548 | "cell_type": "markdown", 549 | "metadata": {}, 550 | "source": [ 551 | "That's all folks!" 552 | ] 553 | }, 554 | { 555 | "cell_type": "code", 556 | "execution_count": null, 557 | "metadata": {}, 558 | "outputs": [], 559 | "source": [] 560 | } 561 | ], 562 | "metadata": { 563 | "kernelspec": { 564 | "display_name": "Python 3", 565 | "language": "python", 566 | "name": "python3" 567 | }, 568 | "language_info": { 569 | "codemirror_mode": { 570 | "name": "ipython", 571 | "version": 3 572 | }, 573 | "file_extension": ".py", 574 | "mimetype": "text/x-python", 575 | "name": "python", 576 | "nbconvert_exporter": "python", 577 | "pygments_lexer": "ipython3", 578 | "version": "3.7.1" 579 | } 580 | }, 581 | "nbformat": 4, 582 | "nbformat_minor": 2 583 | } 584 | -------------------------------------------------------------------------------- /notebooks/README.md: -------------------------------------------------------------------------------- 1 | # Juypter Notebooks for ClickHouse 2 | 3 | This directory contains sample notebooks showing how to connect Python 4 | to ClickHouse. 5 | 6 | Notebook code has been tested on Ubuntu using Anaconda and Python 3.7. 7 | They should work from Python 3.5 onwards. 8 | 9 | To get started you'll need to add the following packages using conda: 10 | ``` 11 | conda install -c conda-forge clickhouse-driver 12 | conda install -c conda-forge clickhouse-sqlalchemy 13 | ``` 14 | 15 | Examples use sample data from the iris dataset. 16 | -------------------------------------------------------------------------------- /notebooks/iris.csv: -------------------------------------------------------------------------------- 1 | 5.1,3.5,1.4,0.2,Iris-setosa 2 | 4.9,3.0,1.4,0.2,Iris-setosa 3 | 4.7,3.2,1.3,0.2,Iris-setosa 4 | 4.6,3.1,1.5,0.2,Iris-setosa 5 | 5.0,3.6,1.4,0.2,Iris-setosa 6 | 5.4,3.9,1.7,0.4,Iris-setosa 7 | 4.6,3.4,1.4,0.3,Iris-setosa 8 | 5.0,3.4,1.5,0.2,Iris-setosa 9 | 4.4,2.9,1.4,0.2,Iris-setosa 10 | 4.9,3.1,1.5,0.1,Iris-setosa 11 | 5.4,3.7,1.5,0.2,Iris-setosa 12 | 4.8,3.4,1.6,0.2,Iris-setosa 13 | 4.8,3.0,1.4,0.1,Iris-setosa 14 | 4.3,3.0,1.1,0.1,Iris-setosa 15 | 5.8,4.0,1.2,0.2,Iris-setosa 16 | 5.7,4.4,1.5,0.4,Iris-setosa 17 | 5.4,3.9,1.3,0.4,Iris-setosa 18 | 5.1,3.5,1.4,0.3,Iris-setosa 19 | 5.7,3.8,1.7,0.3,Iris-setosa 20 | 5.1,3.8,1.5,0.3,Iris-setosa 21 | 5.4,3.4,1.7,0.2,Iris-setosa 22 | 5.1,3.7,1.5,0.4,Iris-setosa 23 | 4.6,3.6,1.0,0.2,Iris-setosa 24 | 5.1,3.3,1.7,0.5,Iris-setosa 25 | 4.8,3.4,1.9,0.2,Iris-setosa 26 | 5.0,3.0,1.6,0.2,Iris-setosa 27 | 5.0,3.4,1.6,0.4,Iris-setosa 28 | 5.2,3.5,1.5,0.2,Iris-setosa 29 | 5.2,3.4,1.4,0.2,Iris-setosa 30 | 4.7,3.2,1.6,0.2,Iris-setosa 31 | 4.8,3.1,1.6,0.2,Iris-setosa 32 | 5.4,3.4,1.5,0.4,Iris-setosa 33 | 5.2,4.1,1.5,0.1,Iris-setosa 34 | 5.5,4.2,1.4,0.2,Iris-setosa 35 | 4.9,3.1,1.5,0.2,Iris-setosa 36 | 5.0,3.2,1.2,0.2,Iris-setosa 37 | 5.5,3.5,1.3,0.2,Iris-setosa 38 | 4.9,3.6,1.4,0.1,Iris-setosa 39 | 4.4,3.0,1.3,0.2,Iris-setosa 40 | 5.1,3.4,1.5,0.2,Iris-setosa 41 | 5.0,3.5,1.3,0.3,Iris-setosa 42 | 4.5,2.3,1.3,0.3,Iris-setosa 43 | 4.4,3.2,1.3,0.2,Iris-setosa 44 | 5.0,3.5,1.6,0.6,Iris-setosa 45 | 5.1,3.8,1.9,0.4,Iris-setosa 46 | 4.8,3.0,1.4,0.3,Iris-setosa 47 | 5.1,3.8,1.6,0.2,Iris-setosa 48 | 4.6,3.2,1.4,0.2,Iris-setosa 49 | 5.3,3.7,1.5,0.2,Iris-setosa 50 | 5.0,3.3,1.4,0.2,Iris-setosa 51 | 7.0,3.2,4.7,1.4,Iris-versicolor 52 | 6.4,3.2,4.5,1.5,Iris-versicolor 53 | 6.9,3.1,4.9,1.5,Iris-versicolor 54 | 5.5,2.3,4.0,1.3,Iris-versicolor 55 | 6.5,2.8,4.6,1.5,Iris-versicolor 56 | 5.7,2.8,4.5,1.3,Iris-versicolor 57 | 6.3,3.3,4.7,1.6,Iris-versicolor 58 | 4.9,2.4,3.3,1.0,Iris-versicolor 59 | 6.6,2.9,4.6,1.3,Iris-versicolor 60 | 5.2,2.7,3.9,1.4,Iris-versicolor 61 | 5.0,2.0,3.5,1.0,Iris-versicolor 62 | 5.9,3.0,4.2,1.5,Iris-versicolor 63 | 6.0,2.2,4.0,1.0,Iris-versicolor 64 | 6.1,2.9,4.7,1.4,Iris-versicolor 65 | 5.6,2.9,3.6,1.3,Iris-versicolor 66 | 6.7,3.1,4.4,1.4,Iris-versicolor 67 | 5.6,3.0,4.5,1.5,Iris-versicolor 68 | 5.8,2.7,4.1,1.0,Iris-versicolor 69 | 6.2,2.2,4.5,1.5,Iris-versicolor 70 | 5.6,2.5,3.9,1.1,Iris-versicolor 71 | 5.9,3.2,4.8,1.8,Iris-versicolor 72 | 6.1,2.8,4.0,1.3,Iris-versicolor 73 | 6.3,2.5,4.9,1.5,Iris-versicolor 74 | 6.1,2.8,4.7,1.2,Iris-versicolor 75 | 6.4,2.9,4.3,1.3,Iris-versicolor 76 | 6.6,3.0,4.4,1.4,Iris-versicolor 77 | 6.8,2.8,4.8,1.4,Iris-versicolor 78 | 6.7,3.0,5.0,1.7,Iris-versicolor 79 | 6.0,2.9,4.5,1.5,Iris-versicolor 80 | 5.7,2.6,3.5,1.0,Iris-versicolor 81 | 5.5,2.4,3.8,1.1,Iris-versicolor 82 | 5.5,2.4,3.7,1.0,Iris-versicolor 83 | 5.8,2.7,3.9,1.2,Iris-versicolor 84 | 6.0,2.7,5.1,1.6,Iris-versicolor 85 | 5.4,3.0,4.5,1.5,Iris-versicolor 86 | 6.0,3.4,4.5,1.6,Iris-versicolor 87 | 6.7,3.1,4.7,1.5,Iris-versicolor 88 | 6.3,2.3,4.4,1.3,Iris-versicolor 89 | 5.6,3.0,4.1,1.3,Iris-versicolor 90 | 5.5,2.5,4.0,1.3,Iris-versicolor 91 | 5.5,2.6,4.4,1.2,Iris-versicolor 92 | 6.1,3.0,4.6,1.4,Iris-versicolor 93 | 5.8,2.6,4.0,1.2,Iris-versicolor 94 | 5.0,2.3,3.3,1.0,Iris-versicolor 95 | 5.6,2.7,4.2,1.3,Iris-versicolor 96 | 5.7,3.0,4.2,1.2,Iris-versicolor 97 | 5.7,2.9,4.2,1.3,Iris-versicolor 98 | 6.2,2.9,4.3,1.3,Iris-versicolor 99 | 5.1,2.5,3.0,1.1,Iris-versicolor 100 | 5.7,2.8,4.1,1.3,Iris-versicolor 101 | 6.3,3.3,6.0,2.5,Iris-virginica 102 | 5.8,2.7,5.1,1.9,Iris-virginica 103 | 7.1,3.0,5.9,2.1,Iris-virginica 104 | 6.3,2.9,5.6,1.8,Iris-virginica 105 | 6.5,3.0,5.8,2.2,Iris-virginica 106 | 7.6,3.0,6.6,2.1,Iris-virginica 107 | 4.9,2.5,4.5,1.7,Iris-virginica 108 | 7.3,2.9,6.3,1.8,Iris-virginica 109 | 6.7,2.5,5.8,1.8,Iris-virginica 110 | 7.2,3.6,6.1,2.5,Iris-virginica 111 | 6.5,3.2,5.1,2.0,Iris-virginica 112 | 6.4,2.7,5.3,1.9,Iris-virginica 113 | 6.8,3.0,5.5,2.1,Iris-virginica 114 | 5.7,2.5,5.0,2.0,Iris-virginica 115 | 5.8,2.8,5.1,2.4,Iris-virginica 116 | 6.4,3.2,5.3,2.3,Iris-virginica 117 | 6.5,3.0,5.5,1.8,Iris-virginica 118 | 7.7,3.8,6.7,2.2,Iris-virginica 119 | 7.7,2.6,6.9,2.3,Iris-virginica 120 | 6.0,2.2,5.0,1.5,Iris-virginica 121 | 6.9,3.2,5.7,2.3,Iris-virginica 122 | 5.6,2.8,4.9,2.0,Iris-virginica 123 | 7.7,2.8,6.7,2.0,Iris-virginica 124 | 6.3,2.7,4.9,1.8,Iris-virginica 125 | 6.7,3.3,5.7,2.1,Iris-virginica 126 | 7.2,3.2,6.0,1.8,Iris-virginica 127 | 6.2,2.8,4.8,1.8,Iris-virginica 128 | 6.1,3.0,4.9,1.8,Iris-virginica 129 | 6.4,2.8,5.6,2.1,Iris-virginica 130 | 7.2,3.0,5.8,1.6,Iris-virginica 131 | 7.4,2.8,6.1,1.9,Iris-virginica 132 | 7.9,3.8,6.4,2.0,Iris-virginica 133 | 6.4,2.8,5.6,2.2,Iris-virginica 134 | 6.3,2.8,5.1,1.5,Iris-virginica 135 | 6.1,2.6,5.6,1.4,Iris-virginica 136 | 7.7,3.0,6.1,2.3,Iris-virginica 137 | 6.3,3.4,5.6,2.4,Iris-virginica 138 | 6.4,3.1,5.5,1.8,Iris-virginica 139 | 6.0,3.0,4.8,1.8,Iris-virginica 140 | 6.9,3.1,5.4,2.1,Iris-virginica 141 | 6.7,3.1,5.6,2.4,Iris-virginica 142 | 6.9,3.1,5.1,2.3,Iris-virginica 143 | 5.8,2.7,5.1,1.9,Iris-virginica 144 | 6.8,3.2,5.9,2.3,Iris-virginica 145 | 6.7,3.3,5.7,2.5,Iris-virginica 146 | 6.7,3.0,5.2,2.3,Iris-virginica 147 | 6.3,2.5,5.0,1.9,Iris-virginica 148 | 6.5,3.0,5.2,2.0,Iris-virginica 149 | 6.2,3.4,5.4,2.3,Iris-virginica 150 | 5.9,3.0,5.1,1.8,Iris-virginica 151 | -------------------------------------------------------------------------------- /notebooks/iris_with_names.csv: -------------------------------------------------------------------------------- 1 | sepal_length,sepal_width,petal_length,petal_width,species 2 | 5.1,3.5,1.4,0.2,Iris-setosa 3 | 4.9,3.0,1.4,0.2,Iris-setosa 4 | 4.7,3.2,1.3,0.2,Iris-setosa 5 | 4.6,3.1,1.5,0.2,Iris-setosa 6 | 5.0,3.6,1.4,0.2,Iris-setosa 7 | 5.4,3.9,1.7,0.4,Iris-setosa 8 | 4.6,3.4,1.4,0.3,Iris-setosa 9 | 5.0,3.4,1.5,0.2,Iris-setosa 10 | 4.4,2.9,1.4,0.2,Iris-setosa 11 | 4.9,3.1,1.5,0.1,Iris-setosa 12 | 5.4,3.7,1.5,0.2,Iris-setosa 13 | 4.8,3.4,1.6,0.2,Iris-setosa 14 | 4.8,3.0,1.4,0.1,Iris-setosa 15 | 4.3,3.0,1.1,0.1,Iris-setosa 16 | 5.8,4.0,1.2,0.2,Iris-setosa 17 | 5.7,4.4,1.5,0.4,Iris-setosa 18 | 5.4,3.9,1.3,0.4,Iris-setosa 19 | 5.1,3.5,1.4,0.3,Iris-setosa 20 | 5.7,3.8,1.7,0.3,Iris-setosa 21 | 5.1,3.8,1.5,0.3,Iris-setosa 22 | 5.4,3.4,1.7,0.2,Iris-setosa 23 | 5.1,3.7,1.5,0.4,Iris-setosa 24 | 4.6,3.6,1.0,0.2,Iris-setosa 25 | 5.1,3.3,1.7,0.5,Iris-setosa 26 | 4.8,3.4,1.9,0.2,Iris-setosa 27 | 5.0,3.0,1.6,0.2,Iris-setosa 28 | 5.0,3.4,1.6,0.4,Iris-setosa 29 | 5.2,3.5,1.5,0.2,Iris-setosa 30 | 5.2,3.4,1.4,0.2,Iris-setosa 31 | 4.7,3.2,1.6,0.2,Iris-setosa 32 | 4.8,3.1,1.6,0.2,Iris-setosa 33 | 5.4,3.4,1.5,0.4,Iris-setosa 34 | 5.2,4.1,1.5,0.1,Iris-setosa 35 | 5.5,4.2,1.4,0.2,Iris-setosa 36 | 4.9,3.1,1.5,0.2,Iris-setosa 37 | 5.0,3.2,1.2,0.2,Iris-setosa 38 | 5.5,3.5,1.3,0.2,Iris-setosa 39 | 4.9,3.6,1.4,0.1,Iris-setosa 40 | 4.4,3.0,1.3,0.2,Iris-setosa 41 | 5.1,3.4,1.5,0.2,Iris-setosa 42 | 5.0,3.5,1.3,0.3,Iris-setosa 43 | 4.5,2.3,1.3,0.3,Iris-setosa 44 | 4.4,3.2,1.3,0.2,Iris-setosa 45 | 5.0,3.5,1.6,0.6,Iris-setosa 46 | 5.1,3.8,1.9,0.4,Iris-setosa 47 | 4.8,3.0,1.4,0.3,Iris-setosa 48 | 5.1,3.8,1.6,0.2,Iris-setosa 49 | 4.6,3.2,1.4,0.2,Iris-setosa 50 | 5.3,3.7,1.5,0.2,Iris-setosa 51 | 5.0,3.3,1.4,0.2,Iris-setosa 52 | 7.0,3.2,4.7,1.4,Iris-versicolor 53 | 6.4,3.2,4.5,1.5,Iris-versicolor 54 | 6.9,3.1,4.9,1.5,Iris-versicolor 55 | 5.5,2.3,4.0,1.3,Iris-versicolor 56 | 6.5,2.8,4.6,1.5,Iris-versicolor 57 | 5.7,2.8,4.5,1.3,Iris-versicolor 58 | 6.3,3.3,4.7,1.6,Iris-versicolor 59 | 4.9,2.4,3.3,1.0,Iris-versicolor 60 | 6.6,2.9,4.6,1.3,Iris-versicolor 61 | 5.2,2.7,3.9,1.4,Iris-versicolor 62 | 5.0,2.0,3.5,1.0,Iris-versicolor 63 | 5.9,3.0,4.2,1.5,Iris-versicolor 64 | 6.0,2.2,4.0,1.0,Iris-versicolor 65 | 6.1,2.9,4.7,1.4,Iris-versicolor 66 | 5.6,2.9,3.6,1.3,Iris-versicolor 67 | 6.7,3.1,4.4,1.4,Iris-versicolor 68 | 5.6,3.0,4.5,1.5,Iris-versicolor 69 | 5.8,2.7,4.1,1.0,Iris-versicolor 70 | 6.2,2.2,4.5,1.5,Iris-versicolor 71 | 5.6,2.5,3.9,1.1,Iris-versicolor 72 | 5.9,3.2,4.8,1.8,Iris-versicolor 73 | 6.1,2.8,4.0,1.3,Iris-versicolor 74 | 6.3,2.5,4.9,1.5,Iris-versicolor 75 | 6.1,2.8,4.7,1.2,Iris-versicolor 76 | 6.4,2.9,4.3,1.3,Iris-versicolor 77 | 6.6,3.0,4.4,1.4,Iris-versicolor 78 | 6.8,2.8,4.8,1.4,Iris-versicolor 79 | 6.7,3.0,5.0,1.7,Iris-versicolor 80 | 6.0,2.9,4.5,1.5,Iris-versicolor 81 | 5.7,2.6,3.5,1.0,Iris-versicolor 82 | 5.5,2.4,3.8,1.1,Iris-versicolor 83 | 5.5,2.4,3.7,1.0,Iris-versicolor 84 | 5.8,2.7,3.9,1.2,Iris-versicolor 85 | 6.0,2.7,5.1,1.6,Iris-versicolor 86 | 5.4,3.0,4.5,1.5,Iris-versicolor 87 | 6.0,3.4,4.5,1.6,Iris-versicolor 88 | 6.7,3.1,4.7,1.5,Iris-versicolor 89 | 6.3,2.3,4.4,1.3,Iris-versicolor 90 | 5.6,3.0,4.1,1.3,Iris-versicolor 91 | 5.5,2.5,4.0,1.3,Iris-versicolor 92 | 5.5,2.6,4.4,1.2,Iris-versicolor 93 | 6.1,3.0,4.6,1.4,Iris-versicolor 94 | 5.8,2.6,4.0,1.2,Iris-versicolor 95 | 5.0,2.3,3.3,1.0,Iris-versicolor 96 | 5.6,2.7,4.2,1.3,Iris-versicolor 97 | 5.7,3.0,4.2,1.2,Iris-versicolor 98 | 5.7,2.9,4.2,1.3,Iris-versicolor 99 | 6.2,2.9,4.3,1.3,Iris-versicolor 100 | 5.1,2.5,3.0,1.1,Iris-versicolor 101 | 5.7,2.8,4.1,1.3,Iris-versicolor 102 | 6.3,3.3,6.0,2.5,Iris-virginica 103 | 5.8,2.7,5.1,1.9,Iris-virginica 104 | 7.1,3.0,5.9,2.1,Iris-virginica 105 | 6.3,2.9,5.6,1.8,Iris-virginica 106 | 6.5,3.0,5.8,2.2,Iris-virginica 107 | 7.6,3.0,6.6,2.1,Iris-virginica 108 | 4.9,2.5,4.5,1.7,Iris-virginica 109 | 7.3,2.9,6.3,1.8,Iris-virginica 110 | 6.7,2.5,5.8,1.8,Iris-virginica 111 | 7.2,3.6,6.1,2.5,Iris-virginica 112 | 6.5,3.2,5.1,2.0,Iris-virginica 113 | 6.4,2.7,5.3,1.9,Iris-virginica 114 | 6.8,3.0,5.5,2.1,Iris-virginica 115 | 5.7,2.5,5.0,2.0,Iris-virginica 116 | 5.8,2.8,5.1,2.4,Iris-virginica 117 | 6.4,3.2,5.3,2.3,Iris-virginica 118 | 6.5,3.0,5.5,1.8,Iris-virginica 119 | 7.7,3.8,6.7,2.2,Iris-virginica 120 | 7.7,2.6,6.9,2.3,Iris-virginica 121 | 6.0,2.2,5.0,1.5,Iris-virginica 122 | 6.9,3.2,5.7,2.3,Iris-virginica 123 | 5.6,2.8,4.9,2.0,Iris-virginica 124 | 7.7,2.8,6.7,2.0,Iris-virginica 125 | 6.3,2.7,4.9,1.8,Iris-virginica 126 | 6.7,3.3,5.7,2.1,Iris-virginica 127 | 7.2,3.2,6.0,1.8,Iris-virginica 128 | 6.2,2.8,4.8,1.8,Iris-virginica 129 | 6.1,3.0,4.9,1.8,Iris-virginica 130 | 6.4,2.8,5.6,2.1,Iris-virginica 131 | 7.2,3.0,5.8,1.6,Iris-virginica 132 | 7.4,2.8,6.1,1.9,Iris-virginica 133 | 7.9,3.8,6.4,2.0,Iris-virginica 134 | 6.4,2.8,5.6,2.2,Iris-virginica 135 | 6.3,2.8,5.1,1.5,Iris-virginica 136 | 6.1,2.6,5.6,1.4,Iris-virginica 137 | 7.7,3.0,6.1,2.3,Iris-virginica 138 | 6.3,3.4,5.6,2.4,Iris-virginica 139 | 6.4,3.1,5.5,1.8,Iris-virginica 140 | 6.0,3.0,4.8,1.8,Iris-virginica 141 | 6.9,3.1,5.4,2.1,Iris-virginica 142 | 6.7,3.1,5.6,2.4,Iris-virginica 143 | 6.9,3.1,5.1,2.3,Iris-virginica 144 | 5.8,2.7,5.1,1.9,Iris-virginica 145 | 6.8,3.2,5.9,2.3,Iris-virginica 146 | 6.7,3.3,5.7,2.5,Iris-virginica 147 | 6.7,3.0,5.2,2.3,Iris-virginica 148 | 6.3,2.5,5.0,1.9,Iris-virginica 149 | 6.5,3.0,5.2,2.0,Iris-virginica 150 | 6.2,3.4,5.4,2.3,Iris-virginica 151 | 5.9,3.0,5.1,1.8,Iris-virginica 152 | --------------------------------------------------------------------------------