{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Mini tutorial de SQL para científicos" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Hoy en día no se puede seguir trabajando con ficheros de texto habiendo tantas alternativas y, sobretodo, a medida que el tamaño de la información crece y crece y se hace inmanejable tratar ficheros de varios cientos de Mb. Es por ello que hoy vamos a ver por encima cómo podemos hacer consultas, modificar y crear nueva información en una base de datos SQL.\n", "\n", "[Descargo de responsabilidad] Esto no pretende ser un tutorial ni algo serio y riguroso, solo un análisis superficial sobre lo que puede ofrecer el manejo de SQL para trabajar con datos y va dirigido, principalmente, a científicos (o no) que se manejan todo el día con ficheros \\*.dat, \\*.txt o \\*.csv." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# ¿Qué es SQL?" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "SQL es un acrónimo para **S**tructured **Q**uery **L**anguage. Es un lenguaje que nos permite acceder a bases de datos SQL (bases de datos relacionales). Un RDBMS (**R**elational **D**ata**B**ase **M**anagement **S**ystem) es un sistema que nos permite acceder, crear, editar y gestionar bases de datos relacionales. Existen RDBMS muy populares como MySQL (MariaDB), PostgreSQL o SQLite. En el presente tutorial vamos a trabajar con SQLite por simplicidad y porque viene disponible con CPython." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# ¿Y Pandas?" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Pandas dispone de funcionalidad que nos permite leer y escribir información en bases de datos relacionales." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Vamos a crear una base de datos SQLite" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Las bases de datos SQLite son bases de datos que no necesitan un servidor y que se guardan en disco. Para más información [pulsa aquí](https://duckduckgo.com/?q=sqlite). Podéis inspeccionar la base de datos que vayamos a crear, bastante simple, con [SQLite manager, un addon para firefox](https://addons.mozilla.org/en-US/firefox/addon/sqlite-manager/)." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Como siempre, primero importamos todo lo necesario" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "collapsed": false }, "outputs": [], "source": [ "import sqlite3\n", "import datetime as dt\n", "\n", "import pandas as pd\n", "import numpy as np" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Mi configuración es la siguiente:" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "collapsed": false }, "outputs": [ { "data": { "application/json": { "Software versions": [ { "module": "Python", "version": "3.4.0 64bit [GCC 4.8.2]" }, { "module": "IPython", "version": "3.0.0" }, { "module": "OS", "version": "Linux 3.13.0 24 generic x86_64 with LinuxMint 17 qiana" }, { "module": "pandas", "version": "0.15.2" }, { "module": "numpy", "version": "1.9.2" } ] }, "text/html": [ "
SoftwareVersion
Python3.4.0 64bit [GCC 4.8.2]
IPython3.0.0
OSLinux 3.13.0 24 generic x86_64 with LinuxMint 17 qiana
pandas0.15.2
numpy1.9.2
Thu Mar 12 20:07:15 2015 CET
" ], "text/latex": [ "\\begin{tabular}{|l|l|}\\hline\n", "{\\bf Software} & {\\bf Version} \\\\ \\hline\\hline\n", "Python & 3.4.0 64bit [GCC 4.8.2] \\\\ \\hline\n", "IPython & 3.0.0 \\\\ \\hline\n", "OS & Linux 3.13.0 24 generic x86\\_64 with LinuxMint 17 qiana \\\\ \\hline\n", "pandas & 0.15.2 \\\\ \\hline\n", "numpy & 1.9.2 \\\\ \\hline\n", "\\hline \\multicolumn{2}{|l|}{Thu Mar 12 20:07:15 2015 CET} \\\\ \\hline\n", "\\end{tabular}\n" ], "text/plain": [ "Software versions\n", "Python 3.4.0 64bit [GCC 4.8.2]\n", "IPython 3.0.0\n", "OS Linux 3.13.0 24 generic x86_64 with LinuxMint 17 qiana\n", "pandas 0.15.2\n", "numpy 1.9.2\n", "Thu Mar 12 20:07:15 2015 CET" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "%load_ext version_information\n", "%version_information pandas, numpy" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Primero necesitamos poder conectar con la base de datos. Esto es de lo poco que diferirá con respecto a otros RDBMSs." ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "collapsed": true }, "outputs": [], "source": [ "conn = sqlite3.connect('pybodb.sqlite')\n", "\n", "# ejemplo con PostgreSQL usando psycopg2\n", "# import psycopg2\n", "# conn = psycopg2.connect(database='ejemplodb', user='kiko') \n", "\n", "# ejemplo con MS ACCESS usando pyodbc (sí, en el trabajo tengo que usar estas cosas)\n", "# import pyodbc\n", "# conn = pyodbc.connect(\"Driver={Microsoft Access Driver (*.mdb, *.accdb)};DBQ=ejemplodb;\") \n", "\n", "# ..." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Ahora que ya tenemos una conexión a la base de datos Pandas se puede encargar del trabajo sucio de 'hablar' con la base de datos y ayudarnos a interactuar directamente con los datos de la forma habitual y potente de Pandas." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Vamos a crear un DataFrame que usaremos como una tabla para insertar en la base de datos. Este DataFrame tendrá una columna de fechas, una de medidas de temperatura promedio diaria (inventada), una de precipitación acumulada en 24h (inventada), una columna con el tipo de sensor que midió la temperatura ese día y una última con el sensor que midió la precipitación." ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "collapsed": false }, "outputs": [], "source": [ "# fechas para cada día del 2014\n", "fechas = pd.date_range(dt.datetime(2014, 1, 1), dt.datetime(2014, 12, 31))\n", "# Temperatura media diaria durante 2014 en algún lugar del hemisferio Norte\n", "tmed = (np.random.randint(-5, 5, size = 365) + \n", " 20 * np.cos(np.arange(0 - 180, 365 - 180) * 2 * np.pi / 365) \n", " + 10)\n", "# Precipitación acumulada en 24h\n", "prec = (20 * np.abs(np.random.randn(365) * \n", " np.cos(np.arange(0, 365) * 2 * np.pi / 365)))\n", "# Sensor que midió la temperatura\n", "marcaT = np.random.choice(['marcaT1', 'marcaT2', 'marcaT3'], size = 365)\n", "# Sensor midió la precipitación\n", "marcaP = np.random.choice(['marcaP1', 'marcaP2'], size = 365)\n", "\n", "# Creamos el dataframe y lo guardamos en una tabla llamada 'datos'\n", "df = pd.DataFrame(\n", " np.array([fechas.values, tmed, prec, marcaT, marcaP]).T,\n", " columns = ['fecha', 'tmedia','precipitacion','sensorT','sensorP'])\n", "df['fecha'] = pd.to_datetime(df['fecha'])\n", "df.to_sql('datos', con = conn, dtype = {'time': 'TIMESTAMP'})" ] }, { "cell_type": "markdown", "metadata": { "collapsed": false }, "source": [ "Vamos a crear una segunda tabla para añadir un poco de complejidad a las consultas que hagamos posteriormente a la base de datos. Esta tabla contendrá información de los sensores usados para las medidas." ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "collapsed": false }, "outputs": [], "source": [ "# fechas para cada día del 2014\n", "sensores = ['marcaT1', 'marcaT2', 'marcaT3',\n", " 'marcaP1', 'marcaP2']\n", "\n", "# Precisión de los sensores\n", "precision = [0.1, 0.5, 1,\n", " 2, 5]\n", "\n", "df = pd.DataFrame({'sensores': sensores, 'precision': precision})\n", "df.to_sql('sensores', con = conn)" ] }, { "cell_type": "markdown", "metadata": { "collapsed": true }, "source": [ "# Consultando la base de datos" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Dentro de SQL tenemos comandos que se pueden integrar en diferentes categorías. Ahora vamos a usar *dql (data query language)* que se usa para hacer consultas a la base de datos. Mirad en [esta chuleta para conocer más](http://www.sql-tutorial.net/SQL-Cheat-Sheet.pdf)." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Como SQL no hace distinción de mayúsculas y minúsculas usaré mayúsculas para las palabras clave de SQL y así las distinguiremos un poco mejor. Para hacer una petición se usa `SELECT`. Veamos como es una consulta para conocer las tablas que existen en la base de datos (esta consulta es específica para SQLite):" ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " name\n", "0 datos\n", "1 sensores\n" ] } ], "source": [ "# Esto es específico para sqlite\n", "print(pd.read_sql(\"SELECT name FROM sqlite_master WHERE type='table';\", conn))\n", "# Para otras BBDD puedes buscar en internet :-)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "En la consulta anterior hemos usados varias palabras clave: `SELECT`, `FROM`, `WHERE`. Este tipo de consultas serán de lo más habitual. Vamos a explotar lo que ya sabemos.\n", "\n", "Quiero los datos de todas las columnas de la tabla sensores (y pandas me lo meterá en un DataFrame, maravilloso!!!)" ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "collapsed": true }, "outputs": [], "source": [ "df = pd.read_sql(\"SELECT * FROM sensores;\", conn)" ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " index precision sensores\n", "0 0 0.1 marcaT1\n", "1 1 0.5 marcaT2\n", "2 2 1.0 marcaT3\n", "3 3 2.0 marcaP1\n", "4 4 5.0 marcaP2\n" ] } ], "source": [ "print(df)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Ahora queremos los datos de precipitación de Junio junto con su fecha. Fijaos que el valor superior del rango no es inclusivo (`BETWEEN '2014-06-01' AND '2014-07-01'` nos da el dato hasta antes de `fecha = '2014-07-01'`):" ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "collapsed": true }, "outputs": [], "source": [ "df = pd.read_sql(\"SELECT fecha, precipitacion FROM datos WHERE fecha BETWEEN '2014-06-01' AND '2014-07-01';\", conn)" ] }, { "cell_type": "code", "execution_count": 12, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " fecha precipitacion\n", "0 2014-06-01 00:00:00 21.090544\n", "1 2014-06-02 00:00:00 19.514893\n", "2 2014-06-03 00:00:00 1.356933\n", "3 2014-06-04 00:00:00 14.466592\n", "4 2014-06-05 00:00:00 12.780801\n", "5 2014-06-06 00:00:00 28.293163\n", "6 2014-06-07 00:00:00 7.841272\n", "7 2014-06-08 00:00:00 22.278980\n", "8 2014-06-09 00:00:00 24.386602\n", "9 2014-06-10 00:00:00 4.158349\n", "10 2014-06-11 00:00:00 8.850627\n", "11 2014-06-12 00:00:00 24.572156\n", "12 2014-06-13 00:00:00 30.675862\n", "13 2014-06-14 00:00:00 5.986650\n", "14 2014-06-15 00:00:00 19.186014\n", "15 2014-06-16 00:00:00 36.980785\n", "16 2014-06-17 00:00:00 11.822683\n", "17 2014-06-18 00:00:00 1.774325\n", "18 2014-06-19 00:00:00 8.043394\n", "19 2014-06-20 00:00:00 9.909083\n", "20 2014-06-21 00:00:00 26.050138\n", "21 2014-06-22 00:00:00 32.829371\n", "22 2014-06-23 00:00:00 1.067285\n", "23 2014-06-24 00:00:00 41.178811\n", "24 2014-06-25 00:00:00 4.357684\n", "25 2014-06-26 00:00:00 36.863093\n", "26 2014-06-27 00:00:00 18.923454\n", "27 2014-06-28 00:00:00 5.641863\n", "28 2014-06-29 00:00:00 5.831242\n", "29 2014-06-30 00:00:00 45.159804\n" ] } ], "source": [ "print(df)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Ahora quiero los datos de temperatura de los sensores con una precisión superior a 0.5 (el sensor *marcaT1* es el único que me da precisión superior a 0.5):" ] }, { "cell_type": "code", "execution_count": 13, "metadata": { "collapsed": true }, "outputs": [], "source": [ "df = pd.read_sql(\"SELECT fecha, tmedia FROM datos WHERE datos.sensorT = 'marcaT1';\", conn)" ] }, { "cell_type": "code", "execution_count": 14, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " fecha tmedia\n", "0 2014-01-01 00:00:00 -5.981482\n", "1 2014-01-08 00:00:00 -9.733159\n", "2 2014-01-09 00:00:00 -12.674186\n", "3 2014-01-11 00:00:00 -5.538770\n", "4 2014-01-13 00:00:00 -5.380197\n", "5 2014-01-15 00:00:00 -13.198654\n", "6 2014-01-17 00:00:00 -12.994357\n", "7 2014-01-19 00:00:00 -8.767548\n", "8 2014-01-31 00:00:00 -8.950818\n", "9 2014-02-02 00:00:00 -4.575402\n", "10 2014-02-03 00:00:00 -7.380298\n", "11 2014-02-09 00:00:00 -4.109866\n", "12 2014-02-10 00:00:00 -7.882079\n", "13 2014-02-13 00:00:00 -8.172534\n", "14 2014-02-16 00:00:00 -1.425199\n", "15 2014-02-18 00:00:00 -0.906962\n", "16 2014-02-20 00:00:00 -7.373428\n", "17 2014-02-24 00:00:00 -1.263014\n", "18 2014-02-27 00:00:00 -3.394876\n", "19 2014-03-05 00:00:00 -1.577839\n", "20 2014-03-07 00:00:00 4.049144\n", "21 2014-03-08 00:00:00 0.366216\n", "22 2014-03-20 00:00:00 3.320033\n", "23 2014-03-24 00:00:00 10.681308\n", "24 2014-03-28 00:00:00 11.053572\n", "25 2014-03-29 00:00:00 5.397594\n", "26 2014-03-31 00:00:00 14.086071\n", "27 2014-04-08 00:00:00 15.830806\n", "28 2014-04-15 00:00:00 16.190236\n", "29 2014-04-18 00:00:00 11.180340\n", ".. ... ...\n", "94 2014-10-11 00:00:00 6.982189\n", "95 2014-10-12 00:00:00 6.645535\n", "96 2014-10-13 00:00:00 3.310172\n", "97 2014-10-16 00:00:00 8.312816\n", "98 2014-10-18 00:00:00 4.656174\n", "99 2014-10-20 00:00:00 -1.992949\n", "100 2014-10-22 00:00:00 3.366216\n", "101 2014-10-30 00:00:00 1.900779\n", "102 2014-11-04 00:00:00 -6.545832\n", "103 2014-11-08 00:00:00 -4.642068\n", "104 2014-11-11 00:00:00 0.574801\n", "105 2014-11-15 00:00:00 -5.413343\n", "106 2014-11-18 00:00:00 -8.109866\n", "107 2014-11-21 00:00:00 -2.766101\n", "108 2014-11-22 00:00:00 -4.975587\n", "109 2014-11-25 00:00:00 -6.575402\n", "110 2014-11-28 00:00:00 -9.131020\n", "111 2014-11-30 00:00:00 -5.476142\n", "112 2014-12-03 00:00:00 -5.954868\n", "113 2014-12-10 00:00:00 -4.883750\n", "114 2014-12-11 00:00:00 -13.994357\n", "115 2014-12-12 00:00:00 -8.099335\n", "116 2014-12-14 00:00:00 -13.292284\n", "117 2014-12-16 00:00:00 -8.462367\n", "118 2014-12-18 00:00:00 -8.609383\n", "119 2014-12-21 00:00:00 -13.786284\n", "120 2014-12-23 00:00:00 -12.874932\n", "121 2014-12-25 00:00:00 -7.940023\n", "122 2014-12-26 00:00:00 -11.963711\n", "123 2014-12-27 00:00:00 -8.981482\n", "\n", "[124 rows x 2 columns]\n" ] } ], "source": [ "print(df)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Si os fijáis, en la consulta anterior he usado `datos.sensorT` (*tabla.columna*). Esto solo será necesario si estamos trabajando con varias tablas y una columna se puede llamar igual en varias tablas. De esta forma no hay posibilidad de equivocarse ya que usamos 'nombres y apellidos'.\n", "\n", "Vamos a hacer una consulta que nos dé el mismo resultado pero que enlaza varias consultas (un `SELECT` dentro de un `SELECT`). También la represento de forma un poco más estructurada para que sea más legible:" ] }, { "cell_type": "code", "execution_count": 17, "metadata": { "collapsed": false }, "outputs": [], "source": [ "# La misma consulta de antes pero sin saber la precisión de cada uno de los sensores a priori\n", "q = \"\"\"\n", "SELECT \n", " fecha, tmedia \n", "FROM \n", " datos \n", "WHERE \n", " datos.sensorT = \n", " (SELECT \n", " sensores \n", " FROM \n", " sensores \n", " WHERE \n", " precision < 0.5);\"\"\"\n", "\n", "df = pd.read_sql(q, conn)" ] }, { "cell_type": "code", "execution_count": 18, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " fecha tmedia\n", "0 2014-01-01 00:00:00 -5.981482\n", "1 2014-01-08 00:00:00 -9.733159\n", "2 2014-01-09 00:00:00 -12.674186\n", "3 2014-01-11 00:00:00 -5.538770\n", "4 2014-01-13 00:00:00 -5.380197\n", "5 2014-01-15 00:00:00 -13.198654\n", "6 2014-01-17 00:00:00 -12.994357\n", "7 2014-01-19 00:00:00 -8.767548\n", "8 2014-01-31 00:00:00 -8.950818\n", "9 2014-02-02 00:00:00 -4.575402\n", "10 2014-02-03 00:00:00 -7.380298\n", "11 2014-02-09 00:00:00 -4.109866\n", "12 2014-02-10 00:00:00 -7.882079\n", "13 2014-02-13 00:00:00 -8.172534\n", "14 2014-02-16 00:00:00 -1.425199\n", "15 2014-02-18 00:00:00 -0.906962\n", "16 2014-02-20 00:00:00 -7.373428\n", "17 2014-02-24 00:00:00 -1.263014\n", "18 2014-02-27 00:00:00 -3.394876\n", "19 2014-03-05 00:00:00 -1.577839\n", "20 2014-03-07 00:00:00 4.049144\n", "21 2014-03-08 00:00:00 0.366216\n", "22 2014-03-20 00:00:00 3.320033\n", "23 2014-03-24 00:00:00 10.681308\n", "24 2014-03-28 00:00:00 11.053572\n", "25 2014-03-29 00:00:00 5.397594\n", "26 2014-03-31 00:00:00 14.086071\n", "27 2014-04-08 00:00:00 15.830806\n", "28 2014-04-15 00:00:00 16.190236\n", "29 2014-04-18 00:00:00 11.180340\n", ".. ... ...\n", "94 2014-10-11 00:00:00 6.982189\n", "95 2014-10-12 00:00:00 6.645535\n", "96 2014-10-13 00:00:00 3.310172\n", "97 2014-10-16 00:00:00 8.312816\n", "98 2014-10-18 00:00:00 4.656174\n", "99 2014-10-20 00:00:00 -1.992949\n", "100 2014-10-22 00:00:00 3.366216\n", "101 2014-10-30 00:00:00 1.900779\n", "102 2014-11-04 00:00:00 -6.545832\n", "103 2014-11-08 00:00:00 -4.642068\n", "104 2014-11-11 00:00:00 0.574801\n", "105 2014-11-15 00:00:00 -5.413343\n", "106 2014-11-18 00:00:00 -8.109866\n", "107 2014-11-21 00:00:00 -2.766101\n", "108 2014-11-22 00:00:00 -4.975587\n", "109 2014-11-25 00:00:00 -6.575402\n", "110 2014-11-28 00:00:00 -9.131020\n", "111 2014-11-30 00:00:00 -5.476142\n", "112 2014-12-03 00:00:00 -5.954868\n", "113 2014-12-10 00:00:00 -4.883750\n", "114 2014-12-11 00:00:00 -13.994357\n", "115 2014-12-12 00:00:00 -8.099335\n", "116 2014-12-14 00:00:00 -13.292284\n", "117 2014-12-16 00:00:00 -8.462367\n", "118 2014-12-18 00:00:00 -8.609383\n", "119 2014-12-21 00:00:00 -13.786284\n", "120 2014-12-23 00:00:00 -12.874932\n", "121 2014-12-25 00:00:00 -7.940023\n", "122 2014-12-26 00:00:00 -11.963711\n", "123 2014-12-27 00:00:00 -8.981482\n", "\n", "[124 rows x 2 columns]\n" ] } ], "source": [ "print(df)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Podemos decirle que nos pase solo una serie de valores. Por ejemplo, solo quiero los tres valores más altos de precipitación de diciembre:" ] }, { "cell_type": "code", "execution_count": 19, "metadata": { "collapsed": false }, "outputs": [], "source": [ "q = \"\"\"\n", "SELECT \n", " fecha, precipitacion \n", "FROM \n", " datos \n", "WHERE \n", " fecha > '2014-11-30'\n", "ORDER BY\n", " precipitacion DESC\n", "LIMIT\n", " 3\"\"\"\n", "\n", "df = pd.read_sql(q, conn)" ] }, { "cell_type": "code", "execution_count": 20, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " fecha precipitacion\n", "0 2014-12-31 00:00:00 50.047120\n", "1 2014-12-01 00:00:00 43.913895\n", "2 2014-12-04 00:00:00 37.344830\n" ] } ], "source": [ "print(df)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "En la consulta anterior le hemos pedido que nos ordenase por los valores de precipitación de forma descendente (es decir, por el final) y le hemos pedido que nos limitase la búsqueda a tres valores, los tres valores más altos." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# ¿Os ha picado el gusanillo?" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Todo esto era para ver si os picaba un poco el gusanillo y dejáis (dejamos) de usar tanto fichero de texto/excel/csv y usamos opciones más ricas y potentes que existen por ahí." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Enlaces" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "* Un [minitutorial sobre SQL](http://opentechschool.github.io/sql-tutorial/index.html) muy ameno.\n", "\n", "* Nuestro (inacabado) [tutorial sobre PyTables](http://pybonacci.org/tag/pytables/).\n", "\n", "* Y [¿por qué no usar netCDF?](http://pybonacci.org/2012/12/03/por-que-usar-netcdf/)\n", "\n", "* Funcionalidad [SQL en pandas](http://pandas.pydata.org/pandas-docs/stable/io.html?highlight=read_sql#io-sql).\n", "\n", "* [IPython-sql](https://github.com/catherinedevlin/ipython-sql), para trabajar con sql en el notebook.\n", "\n", "* [SQLAlchemy](http://www.sqlalchemy.org/) para facilitarnos la vida cuando trabajamos con Pandas y bases de datos.\n", "\n", "* [SQLite manager, un addon para firefox](https://addons.mozilla.org/en-US/firefox/addon/sqlite-manager/)." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Y cerramos la conexión (literal) por hoy." ] }, { "cell_type": "code", "execution_count": 22, "metadata": { "collapsed": true }, "outputs": [], "source": [ "conn.close() # :-)" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.4.0" } }, "nbformat": 4, "nbformat_minor": 0 }