python-pandas y bases de datos como mysql

97

La documentación de Pandas tiene numerosos ejemplos de mejores prácticas para trabajar con datos almacenados en varios formatos.

Sin embargo, no puedo encontrar buenos ejemplos para trabajar con bases de datos como MySQL, por ejemplo.

¿Alguien puede señalarme enlaces o dar algunos fragmentos de código de cómo convertir los resultados de la consulta usando mysql-python en marcos de datos en Pandas de manera eficiente?

usuario1320615
fuente
1
Documentación: pandas.pydata.org/pandas-docs/stable/io.html#sql-queries
Caracol mecánico
Ver también: stackoverflow.com/questions/15231646/…
Caracol mecánico
También eche un vistazo a Blaze .
osa
Si está dispuesto a gastar dinero, creo que el libro de Wes McKinney ("Python para el análisis de datos") tiene algunos ejemplos útiles.
MTrenfield

Respuestas:

102

Como dice Wes, read_sql de io / sql lo hará, una vez que haya obtenido una conexión a la base de datos utilizando una biblioteca compatible con DBI. Podemos ver dos ejemplos cortos usando las bibliotecas MySQLdby cx_Oraclepara conectarse a Oracle y MySQL y consultar sus diccionarios de datos. Aquí está el ejemplo de cx_Oracle:

import pandas as pd
import cx_Oracle

ora_conn = cx_Oracle.connect('your_connection_string')
df_ora = pd.read_sql('select * from user_objects', con=ora_conn)    
print 'loaded dataframe from Oracle. # Records: ', len(df_ora)
ora_conn.close()

Y aquí está el ejemplo equivalente para MySQLdb:

import MySQLdb
mysql_cn= MySQLdb.connect(host='myhost', 
                port=3306,user='myusername', passwd='mypassword', 
                db='information_schema')
df_mysql = pd.read_sql('select * from VIEWS;', con=mysql_cn)    
print 'loaded dataframe from MySQL. records:', len(df_mysql)
mysql_cn.close()
Keith C. Campbell
fuente
57

Para los lectores recientes de esta pregunta: los pandas tienen la siguiente advertencia en sus documentos para la versión 14.0 :

Advertencia: Algunas de las funciones existentes o alias de funciones han quedado obsoletas y se eliminarán en versiones futuras. Esto incluye: tquery, uquery, read_frame, frame_query, write_frame.

Y:

Advertencia: La compatibilidad con el sabor 'mysql' cuando se utilizan objetos de conexión DBAPI ha quedado obsoleta. MySQL será compatible con los motores SQLAlchemy (GH6900).

Esto hace que muchas de las respuestas aquí estén desactualizadas. Deberías usar sqlalchemy:

from sqlalchemy import create_engine
import pandas as pd
engine = create_engine('dialect://user:pass@host:port/schema', echo=False)
f = pd.read_sql_query('SELECT * FROM mytable', engine, index_col = 'ID')
Korem
fuente
cargar una tabla con 133 filas y 7 columnas toma alrededor de 30 segundos. ¿Puede darnos algunas ideas sobre por qué?
idoda
@idoda [en general, este no es el tema de la pregunta y es mejor hacer una nueva pregunta para obtener más opiniones]. ¿Estás seguro de que no se trata de un retraso en la solicitud? ¿Simplemente enviar la consulta y recuperar los resultados es significativamente más rápido?
Korem
@Korem Pensé en abrir uno nuevo, pero primero quería asegurarme de que no sea trivial. Cuando uso un cliente mySql (Sequel pro) y consulto la base de datos, las reuslts aparecen mucho más rápido. Cuando dice "simplemente enviar y luego recuperar", ¿es eso lo que quiere decir? (usando un cliente)
idoda
@idoda Me refiero a comparar el tiempo que se tarda en ejecutar engine.execute("select * FROM mytable")con el tiempo que se tarda en ejecutarpd.read_sql_query('SELECT * FROM mytable', engine)
Korem
¿Se puede pasar una consulta sqlalchemy (session.query como en mi respuesta a continuación) directamente a un método pandas? ¡Eso sería un destripador!
dmvianna
23

Para el registro, aquí hay un ejemplo usando una base de datos sqlite:

import pandas as pd
import sqlite3

with sqlite3.connect("whatever.sqlite") as con:
    sql = "SELECT * FROM table_name"
    df = pd.read_sql_query(sql, con)
    print df.shape
mbatchkarov
fuente
1
Puede especificar la columna que se utilizará como índice especificando index_col='timestamp'en frame_query.
Caracol mecánico
19

Prefiero crear consultas con SQLAlchemy y luego hacer un DataFrame a partir de él. SQLAlchemy facilita la combinación de condiciones SQL Pythonically si tiene la intención de mezclar y combinar cosas una y otra vez.

from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Table
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from pandas import DataFrame
import datetime

# We are connecting to an existing service
engine = create_engine('dialect://user:pwd@host:port/db', echo=False)
Session = sessionmaker(bind=engine)
session = Session()
Base = declarative_base()

# And we want to query an existing table
tablename = Table('tablename', 
    Base.metadata, 
    autoload=True, 
    autoload_with=engine, 
    schema='ownername')

# These are the "Where" parameters, but I could as easily 
# create joins and limit results
us = tablename.c.country_code.in_(['US','MX'])
dc = tablename.c.locn_name.like('%DC%')
dt = tablename.c.arr_date >= datetime.date.today() # Give me convenience or...

q = session.query(tablename).\
            filter(us & dc & dt) # That's where the magic happens!!!

def querydb(query):
    """
    Function to execute query and return DataFrame.
    """
    df = DataFrame(query.all());
    df.columns = [x['name'] for x in query.column_descriptions]
    return df

querydb(q)
dmvianna
fuente
También debe especificar el controlador si no es el mismo que el predeterminado de SQLAlchemy :dialect+driver://user:pwd@host:port/db
Nuno André
11

Ejemplo de MySQL:

import MySQLdb as db
from pandas import DataFrame
from pandas.io.sql import frame_query

database = db.connect('localhost','username','password','database')
data     = frame_query("SELECT * FROM data", database)
aerkenemesis
fuente
7
frame_queryahora está en desuso. Ahora use pd.read_sql(query, db)en su lugar.
Robert Smith
8

La misma sintaxis funciona para Ms SQL Server que usa podbc también.

import pyodbc
import pandas.io.sql as psql

cnxn = pyodbc.connect('DRIVER={SQL Server};SERVER=servername;DATABASE=mydb;UID=username;PWD=password') 
cursor = cnxn.cursor()
sql = ("""select * from mytable""")

df = psql.frame_query(sql, cnxn)
cnxn.close()
cortasetos
fuente
5

Y así es como se conecta a PostgreSQL usando el controlador psycopg2 (instálelo con "apt-get install python-psycopg2" si tiene un sistema operativo derivado de Debian Linux).

import pandas.io.sql as psql
import psycopg2

conn = psycopg2.connect("dbname='datawarehouse' user='user1' host='localhost' password='uberdba'")

q = """select month_idx, sum(payment) from bi_some_table"""

df3 = psql.frame_query(q, conn)
Será
fuente
4

Para Sybase, los siguientes trabajos (con http://python-sybase.sourceforge.net )

import pandas.io.sql as psql
import Sybase

df = psql.frame_query("<Query>", con=Sybase.connect("<dsn>", "<user>", "<pwd>"))
usuario1827356
fuente
4

pandas.io.sql.frame_queryes obsoleto. Úselo en su pandas.read_sqllugar.

ajkl
fuente
1

importar el módulo

import pandas as pd
import oursql

conectar

conn=oursql.connect(host="localhost",user="me",passwd="mypassword",db="classicmodels")
sql="Select customerName, city,country from customers order by customerName,country,city"
df_mysql = pd.read_sql(sql,conn)
print df_mysql

Eso funciona bien y usando pandas.io.sql frame_works (con la advertencia de obsolescencia). La base de datos utilizada es la base de datos de muestra del tutorial de mysql.

usuario5925400
fuente
0

Esto debería funcionar bien.

import MySQLdb as mdb
import pandas as pd
con = mdb.connect(‘127.0.0.1’, root’, password’, database_name’);
with con:
 cur = con.cursor()
 cur.execute(“select random_number_one, random_number_two, random_number_three from randomness.a_random_table”)
 rows = cur.fetchall()
 df = pd.DataFrame( [[ij for ij in i] for i in rows] )
 df.rename(columns={0: Random Number One’, 1: Random Number Two’, 2: Random Number Three’}, inplace=True);
 print(df.head(20))
Monty Python
fuente
0

Esto me ayudó a conectarme a AWS MYSQL (RDS) desde la función lambda basada en python 3.xy cargar en un DataFrame de pandas

import json
import boto3
import pymysql
import pandas as pd
user = 'username'
password = 'XXXXXXX'
client = boto3.client('rds')
def lambda_handler(event, context):
    conn = pymysql.connect(host='xxx.xxxxus-west-2.rds.amazonaws.com', port=3306, user=user, passwd=password, db='database name', connect_timeout=5)
    df= pd.read_sql('select * from TableName limit 10',con=conn)
    print(df)
    # TODO implement
    #return {
    #    'statusCode': 200,
    #    'df': df
    #}
Dheeraj
fuente
0

Para usuarios de Postgres

import psycopg2
import pandas as pd

conn = psycopg2.connect("database='datawarehouse' user='user1' host='localhost' password='uberdba'")

customers = 'select * from customers'

customers_df = pd.read_sql(customers,conn)

customers_df
EvaMwangi
fuente
1
¿Podría señalar la diferencia con la respuesta de @Will y por qué se debe elegir su solución?
Sebastián