Python-Pandas und Datenbanken wie MySQL

97

Die Dokumentation für Pandas enthält zahlreiche Beispiele für bewährte Methoden für die Arbeit mit Daten, die in verschiedenen Formaten gespeichert sind.

Ich kann jedoch keine guten Beispiele für die Arbeit mit Datenbanken wie beispielsweise MySQL finden.

Kann mich jemand auf Links verweisen oder einige Codefragmente geben, wie Abfrageergebnisse mit mysql-python effizient in Datenrahmen in Pandas konvertiert werden können ?

user1320615
quelle
1
Dokumentation: pandas.pydata.org/pandas-docs/stable/io.html#sql-queries
Mechanische Schnecke
Siehe auch: stackoverflow.com/questions/15231646/…
Mechanische Schnecke
Schauen Sie sich auch Blaze an .
osa
Wenn Sie bereit sind, Geld auszugeben, glaube ich, dass Wes McKinneys Buch ("Python for Data Analysis") einige nützliche Beispiele enthält.
MTrenfield

Antworten:

102

Wie Wes sagt, wird read / sql von io / sql dies tun, sobald Sie eine Datenbankverbindung mit einer DBI-kompatiblen Bibliothek hergestellt haben. Wir können uns zwei kurze Beispiele ansehen, in denen die Bibliotheken MySQLdbund verwendet werden cx_Oracle, um eine Verbindung zu Oracle und MySQL herzustellen und deren Datenwörterbücher abzufragen. Hier ist das Beispiel für 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()

Und hier ist das entsprechende Beispiel für 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
quelle
57

Für neuere Leser dieser Frage: Pandas haben die folgende Warnung in ihren Dokumenten für Version 14.0 :

Warnung: Einige der vorhandenen Funktionen oder Funktionsaliasnamen sind veraltet und werden in zukünftigen Versionen entfernt. Dies beinhaltet: tquery, uquery, read_frame, frame_query, write_frame.

Und:

Warnung: Die Unterstützung der MySQL-Variante bei Verwendung von DBAPI-Verbindungsobjekten ist veraltet. MySQL wird weiterhin mit SQLAlchemy-Engines (GH6900) unterstützt.

Dies macht viele der Antworten hier veraltet. Sie sollten verwenden 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
quelle
Das Laden einer Tabelle mit 133 Zeilen und 7 Spalten dauert ungefähr 30 Sekunden. Können Sie einige Einblicke geben, warum das so ist?
Idoda
@idoda [im Allgemeinen ist dies nicht das Thema der Frage und es ist besser, eine neue Frage zu stellen, damit Sie mehr Meinungen erhalten]. Sind Sie sicher, dass dies keine Frage der Anforderungsverzögerung ist? Ist das einfache Senden der Abfrage und das Abrufen der Ergebnisse erheblich schneller?
Korem
@Korem Ich habe darüber nachgedacht, ein neues zu eröffnen, aber ich wollte zuerst sicherstellen, dass es kein triviales ist. Wenn ich einen mySql-Client (Sequel Pro) verwende und die Datenbank abfrage, werden Wiederverwendungen viel schneller ausgeführt. Wenn Sie "einfach senden und dann abrufen" sagen, meinen Sie das? (mit einem Client)
Idoda
@idoda Ich meine, die Zeit, die für die Ausführung benötigt wird, engine.execute("select * FROM mytable")mit der Zeit zu vergleichen, die für die Ausführung benötigt wirdpd.read_sql_query('SELECT * FROM mytable', engine)
Korem
Kann man eine SQLalchemie-Abfrage (session.query wie in meiner Antwort unten) direkt an eine Pandas-Methode übergeben? Das wäre ein Ripper!
dmvianna
23

Hier ist ein Beispiel für die Verwendung einer SQLite-Datenbank:

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
quelle
1
Sie können die Spalte angeben, die als Index verwendet werden soll, indem Sie index_col='timestamp'in angeben frame_query.
Mechanische Schnecke
19

Ich ziehe es vor, Abfragen mit SQLAlchemy zu erstellen und dann einen DataFrame daraus zu erstellen . SQLAlchemy erleichtert das Python- Kombinieren von SQL- Bedingungen, wenn Sie beabsichtigen, Dinge immer wieder zu mischen und anzupassen.

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
quelle
Außerdem müssen Sie den Treiber angeben, wenn er nicht mit dem Standardtreiber der SQLAlchemy identisch ist :dialect+driver://user:pwd@host:port/db
Nuno André
11

MySQL-Beispiel:

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
quelle
7
frame_queryist jetzt veraltet. Verwenden Sie jetzt pd.read_sql(query, db)stattdessen.
Robert Smith
8

Die gleiche Syntax funktioniert auch für MS SQL Server, die podbc verwenden.

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()
Hedgcutter
quelle
5

Und so stellen Sie mit dem psycopg2-Treiber eine Verbindung zu PostgreSQL her (installieren Sie mit "apt-get install python-psycopg2", wenn Sie ein von Debian Linux abgeleitetes Betriebssystem verwenden).

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)
Wille
quelle
4

Für Sybase funktioniert Folgendes (mit 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
quelle
4

pandas.io.sql.frame_queryist veraltet. Verwenden Sie pandas.read_sqlstattdessen.

ajkl
quelle
1

Importieren Sie das Modul

import pandas as pd
import oursql

verbinden

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

Das funktioniert einwandfrei und mit pandas.io.sql frame_works (mit der Verfallswarnung). Die verwendete Datenbank ist die Beispieldatenbank aus dem MySQL-Tutorial.

user5925400
quelle
0

Dies sollte gut funktionieren.

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

Dies hat mir geholfen, eine Verbindung zu AWS MYSQL (RDS) über eine auf Python 3.x basierende Lambda-Funktion herzustellen und in einen Pandas-DataFrame zu laden

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

Für Postgres-Benutzer

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
quelle
1
Können Sie auf den Unterschied zur Antwort von @Will hinweisen und warum Ihre Lösung gewählt werden sollte?
Sebastian