python-pandas e bancos de dados como mysql

97

A documentação do Pandas contém vários exemplos de práticas recomendadas para trabalhar com dados armazenados em vários formatos.

No entanto, não consigo encontrar bons exemplos para trabalhar com bancos de dados como o MySQL, por exemplo.

Alguém pode me apontar para links ou dar alguns trechos de código de como converter os resultados da consulta usando mysql-python para quadros de dados no Pandas de forma eficiente?

user1320615
fonte
1
Documentação: pandas.pydata.org/pandas-docs/stable/io.html#sql-queries
Caracol mecânico de
Veja também: stackoverflow.com/questions/15231646/…
Caracol mecânico
Também dê uma olhada no Blaze .
osa
Se você está disposto a gastar dinheiro, acredito que o livro de Wes McKinney ("Python for Data Analysis") contém alguns exemplos úteis.
MTrenfield

Respostas:

102

Como Wes diz, read_sql de io / sql fará isso, uma vez que você tenha uma conexão de banco de dados usando uma biblioteca compatível com DBI. Podemos ver dois exemplos curtos usando as bibliotecas MySQLdbe cx_Oraclepara se conectar ao Oracle e ao MySQL e consultar seus dicionários de dados. Aqui está o exemplo para 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()

E aqui está o exemplo 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
fonte
57

Para leitores recentes desta questão: os pandas têm o seguinte aviso em seus documentos para a versão 14.0 :

Aviso: algumas das funções existentes ou aliases de função foram descontinuados e serão removidos em versões futuras. Isso inclui: tquery, uquery, read_frame, frame_query, write_frame.

E:

Aviso: O suporte para o tipo 'mysql' ao usar objetos de conexão DBAPI foi descontinuado. O MySQL terá mais suporte com os motores SQLAlchemy (GH6900).

Isso torna muitas das respostas aqui desatualizadas. Você deve 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
fonte
carregar uma tabela com 133 linhas e 7 colunas leva cerca de 30 segundos. Você pode nos dar algumas dicas sobre o motivo disso?
idoda
@idoda [em geral, este não é o tópico da pergunta e é melhor fazer uma nova pergunta para obter mais opiniões]. Tem certeza que não é uma questão de atraso na solicitação? O simples envio da consulta e a recuperação dos resultados são significativamente mais rápidos?
Korem de
@Korem Eu pensei em abrir um novo, mas primeiro queria ter certeza de que não é trivial. Quando eu uso um cliente mySql (Sequel pro) e procuro no banco de dados, os reuslts surgem muito mais rápido. Quando você diz "simplesmente enviando e recuperando", é isso que quer dizer? (usando um cliente)
idoda
@idoda, quero dizer, comparando o tempo que leva para executar engine.execute("select * FROM mytable")com o tempo que leva para executarpd.read_sql_query('SELECT * FROM mytable', engine)
Korem
Pode-se passar uma consulta sqlalchemy (session.query como na minha resposta abaixo) diretamente para um método pandas? Isso seria um estripador!
dmvianna
23

Para registro, aqui está um exemplo usando um banco de dados 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
fonte
1
Você pode especificar a coluna a ser usada como índice especificando index_col='timestamp'em frame_query.
Caracol mecânico de
19

Eu prefiro criar consultas com SQLAlchemy e, em seguida, fazer um DataFrame a partir dele. SQLAlchemy torna mais fácil combinar condições SQL Pythonically se você pretende misturar e combinar coisas repetidamente.

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
fonte
Também deve especificar o driver se não for o mesmo que o padrão do SQLAlchemy :dialect+driver://user:pwd@host:port/db
Nuno André
11

Exemplo 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)
aerenêmese
fonte
7
frame_queryagora está obsoleto. Agora use pd.read_sql(query, db).
Robert Smith
8

A mesma sintaxe funciona para o servidor MS SQL usando podbc também.

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()
cortador de sebes
fonte
5

E é assim que você se conecta ao PostgreSQL usando o driver psycopg2 (instale com "apt-get install python-psycopg2" se você estiver no sistema operacional derivado do 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)
Vai
fonte
4

Para Sybase, o seguinte funciona (com http://python-sybase.sourceforge.net )

import pandas.io.sql as psql
import Sybase

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

pandas.io.sql.frame_queryestá obsoleto. Use em seu pandas.read_sqllugar.

ajkl
fonte
1

importar o 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

Isso funciona bem e usando pandas.io.sql frame_works (com o aviso de descontinuação). O banco de dados usado é o banco de dados de amostra do tutorial do mysql.

user5925400
fonte
0

Isso deve funcionar muito bem.

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
fonte
0

Isso me ajudou a me conectar a AWS MYSQL (RDS) a partir da função lambda baseada em python 3.x e carregar em um DataFrame do 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
fonte
0

Para usuários 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
fonte
1
Você poderia apontar a diferença na resposta do @Will e por que sua solução deve ser escolhida?
Sebastian