python-pandy i bazy danych, takie jak mysql

97

Dokumentacja Pandas zawiera wiele przykładów najlepszych praktyk dotyczących pracy z danymi przechowywanymi w różnych formatach.

Nie mogę jednak znaleźć żadnych dobrych przykładów pracy z bazami danych, takimi jak na przykład MySQL.

Czy ktoś może wskazać mi linki lub podać fragmenty kodu, jak wydajnie konwertować wyniki zapytań za pomocą mysql-python na ramki danych w Pandas?

user1320615
źródło
Zobacz też: stackoverflow.com/questions/15231646/…
Ślimak mechaniczny
Spójrz także na Blaze .
osa
Jeśli chcesz wydać pieniądze, uważam, że książka Wesa McKinneya („Python do analizy danych”) zawiera kilka przydatnych przykładów.
MTrenfield,

Odpowiedzi:

102

Jak mówi Wes, zrobi to read_sql io / sql, gdy już uzyskasz połączenie z bazą danych za pomocą biblioteki kompatybilnej z DBI. Możemy spojrzeć na dwa krótkie przykłady przy użyciu bibliotek MySQLdbi cx_Oracledo łączenia się z Oracle i MySQL i wysyłania zapytań do ich słowników danych. Oto przykład dla 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()

A oto równoważny przykład dla 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
źródło
57

Dla niedawnych czytelników tego pytania: pandy mają następujące ostrzeżenie w swoich dokumentach dla wersji 14.0 :

Ostrzeżenie: niektóre z istniejących funkcji lub aliasów funkcji zostały wycofane i zostaną usunięte w przyszłych wersjach. Obejmuje to: tquery, uquery, read_frame, frame_query, write_frame.

I:

Ostrzeżenie: obsługa smaku „mysql” podczas korzystania z obiektów połączeń DBAPI została wycofana. MySQL będzie dalej wspierany przez silniki SQLAlchemy (GH6900).

To sprawia, że ​​wiele odpowiedzi tutaj jest nieaktualnych. Powinieneś użyć 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
źródło
ładowanie tabeli zawierającej 133 wiersze i 7 kolumn zajmuje około 30 sekund. Czy możesz podać kilka wskazówek, dlaczego tak się dzieje?
idoda
@idoda [generalnie nie jest to temat pytania i lepiej jest zadać nowe pytanie, aby uzyskać więcej opinii]. Czy na pewno nie jest to kwestia opóźnienia wniosku? Czy po prostu wysłanie zapytania i pobranie wyników jest znacznie szybsze?
Korem,
@Korem Myślałem o otwarciu nowego, ale najpierw chciałem się upewnić, że nie będzie to trywialne. Kiedy używam klienta mySql (Sequel pro) i odpytuję bazę danych, ponowne użycie jest dużo szybsze. Kiedy mówisz „po prostu wysyłanie, a następnie odzyskiwanie”, czy to masz na myśli? (używając klienta)
idoda
@idoda Mam na myśli porównanie czasu potrzebnego do wykonania engine.execute("select * FROM mytable")z czasem potrzebnym do wykonaniapd.read_sql_query('SELECT * FROM mytable', engine)
Korem
Czy można przekazać zapytanie sqlalchemy (session.query, jak w mojej odpowiedzi poniżej) bezpośrednio do metody pandy? To byłby zrywak!
dmvianna
23

Dla przypomnienia, oto przykład użycia bazy danych 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
źródło
1
Możesz określić kolumnę, która ma być używana jako indeks, określając index_col='timestamp'w frame_query.
Ślimak mechaniczny
19

Wolę tworzyć zapytania za pomocą SQLAlchemy , a następnie tworzyć z niego DataFrame. SQLAlchemy ułatwia łączenie warunków SQL w języku Python, jeśli zamierzasz ciągle mieszać i dopasowywać różne elementy.

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
źródło
Musisz także określić sterownik, jeśli nie jest taki sam, jak domyślny sterownik SQLAlchemy :dialect+driver://user:pwd@host:port/db
Nuno André
11

Przykład 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
źródło
7
frame_queryjest teraz przestarzała. Teraz użyj pd.read_sql(query, db)zamiast tego.
Robert Smith
8

Ta sama składnia działa również dla serwera Ms SQL przy użyciu podbc.

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()
żywopłot
źródło
5

W ten sposób łączysz się z PostgreSQL za pomocą sterownika psycopg2 (zainstaluj za pomocą "apt-get install python-psycopg2", jeśli używasz pochodnego systemu operacyjnego 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)
Będzie
źródło
4

Dla Sybase następujące prace (z 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
źródło
4

pandas.io.sql.frame_queryjest przestarzałe. Użyj pandas.read_sqlzamiast tego.

ajkl
źródło
1

zaimportuj moduł

import pandas as pd
import oursql

połączyć

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

Działa to dobrze i przy użyciu pandas.io.sql frame_works (z ostrzeżeniem o wycofaniu). Użyta baza danych to przykładowa baza danych z samouczka mysql.

user5925400
źródło
0

To powinno działać dobrze.

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))
MontyPython
źródło
0

Pomogło mi to połączyć się z AWS MYSQL (RDS) z funkcji lambda opartej na pythonie 3.x i załadować do pandy DataFrame

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
źródło
0

Dla użytkowników 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
źródło
1
Czy mógłbyś wskazać różnicę w odpowiedzi @Will i dlaczego warto wybrać Twoje rozwiązanie?
Sebastian