วิธีการแปลงผลลัพธ์ SQL Query เป็น PANDAS Data Structure?


118

ความช่วยเหลือใด ๆ เกี่ยวกับปัญหานี้จะได้รับการชื่นชมอย่างมาก

โดยพื้นฐานแล้วฉันต้องการเรียกใช้แบบสอบถามไปยังฐานข้อมูล SQL ของฉันและจัดเก็บข้อมูลที่ส่งคืนเป็นโครงสร้างข้อมูล Pandas

ฉันได้แนบรหัสสำหรับแบบสอบถาม

ฉันกำลังอ่านเอกสารเกี่ยวกับ Pandas แต่ฉันมีปัญหาในการระบุประเภทการส่งคืนของคำถามของฉัน

ฉันพยายามพิมพ์ผลการสืบค้น แต่ไม่ได้ให้ข้อมูลที่เป็นประโยชน์

ขอบคุณ !!!!

from sqlalchemy import create_engine

engine2 = create_engine('mysql://THE DATABASE I AM ACCESSING')
connection2 = engine2.connect()
dataid = 1022
resoverall = connection2.execute("
  SELECT 
      sum(BLABLA) AS BLA,
      sum(BLABLABLA2) AS BLABLABLA2,
      sum(SOME_INT) AS SOME_INT,
      sum(SOME_INT2) AS SOME_INT2,
      100*sum(SOME_INT2)/sum(SOME_INT) AS ctr,
      sum(SOME_INT2)/sum(SOME_INT) AS cpc
   FROM daily_report_cooked
   WHERE campaign_id = '%s'", %dataid)

ดังนั้นฉันจึงต้องการทำความเข้าใจว่ารูปแบบ / ประเภทข้อมูลของตัวแปร "resoverall" ของฉันคืออะไรและจะนำไปใช้กับโครงสร้างข้อมูล PANDAS ได้อย่างไร


โดยทั่วไปโครงสร้าง / ประเภทของตัวแปร "resoverall" คืออะไรและจะแปลงเป็นโครงสร้างข้อมูลของ Pandas ได้อย่างไร
user1613017

นุ่นฟังดูน่าสนใจมากฉันไม่เคยได้ยินมาก่อน แต่คำถามนี้แทบจะไม่สมเหตุสมผลเลย คุณช่วยอธิบายความหมายของ "ไม่ให้ข้อมูลที่เป็นประโยชน์" ได้ไหม
tadman

1
เนื่องจากแบบสอบถามที่ฉันดำเนินการให้ผลตอบแทนเพียงแค่สงสัยว่าฉันควรจัดการผลตอบแทนนี้และทำให้เป็นโครงสร้างข้อมูลแพนด้าได้อย่างไร ฉันใหม่มากกับ python ดังนั้นจึงไม่มีความรู้มากนักเช่นเดียวกับสิ่งที่เราทำใน PHP คือการทำ sql_fetch_array และเรามีข้อมูลที่ "ใช้งานได้" =)
user1613017

คำตอบ:


120

นี่คือรหัสที่สั้นที่สุดที่จะทำงาน:

from pandas import DataFrame
df = DataFrame(resoverall.fetchall())
df.columns = resoverall.keys()

คุณสามารถเพ้อฝันและแยกวิเคราะห์ประเภทต่างๆในคำตอบของ Paul


1
สิ่งนี้ใช้ได้ผลสำหรับฉันสำหรับ 1.000.000 บันทึกที่มาจากฐานข้อมูล Oracle
Erdem KAYA

8
df = DataFrame(cursor.fetchall())ผลตอบแทนValueError: DataFrame constructor not properly called!ปรากฏว่าทูเปิลของทูเปิลไม่เป็นที่ยอมรับสำหรับตัวสร้าง DataFrame นอกจากนี้ยังไม่มี.keys()เคอร์เซอร์ในพจนานุกรมหรือโหมดทูเพิล
Mobigital

3
โปรดทราบว่าวิธีการคีย์จะใช้ได้เฉพาะกับผลลัพธ์ที่ได้จาก sqlalchemy Pyodbc ใช้แอตทริบิวต์คำอธิบายสำหรับคอลัมน์
Filip

สามารถใช้กับฐานข้อมูล Postgres ได้หรือไม่ ฉันพยายามหาชื่อคอลัมน์สำหรับดาต้าเฟรมผลลัพธ์ที่มีkeys()ฟังก์ชัน แต่ไม่สามารถใช้งานได้
Bowen Liu

1
@BowenLiu ใช่คุณสามารถใช้กับ psycopg2df.columns=[ x.name for x in recoverall.description ]
Gnudiff

138

แก้ไข: มี.ค. 2558

ดังที่ระบุไว้ด้านล่างตอนนี้แพนด้าใช้SQLAlchemyเพื่ออ่านจาก ( read_sql ) และแทรกลงในฐานข้อมูล( to_sql ) สิ่งต่อไปนี้ควรใช้งานได้

import pandas as pd

df = pd.read_sql(sql, cnxn)

คำตอบก่อนหน้า: ผ่าน mikebmassey จากคำถามที่คล้ายกัน

import pyodbc
import pandas.io.sql as psql

cnxn = pyodbc.connect(connection_info) 
cursor = cnxn.cursor()
sql = "SELECT * FROM TABLE"

df = psql.frame_query(sql, cnxn)
cnxn.close()

ดูเหมือนว่าจะเป็นวิธีที่ดีที่สุดเนื่องจากคุณไม่จำเป็นต้องใช้ .keys () ด้วยตนเองเพื่อรับดัชนีคอลัมน์ คำตอบของแดเนียลอาจถูกเขียนขึ้นก่อนที่วิธีนี้จะมีอยู่จริง คุณยังสามารถใช้ pandas.io.sql.read_frame ()
RobinL

1
@openwonk จะนำไปใช้ที่ใดpd.read_sql()ในข้อมูลโค้ดด้านบน
3kstc

อันที่จริงตั้งแต่การตอบกลับครั้งล่าสุดของฉันฉันใช้pyodbcและpandasร่วมกันไม่น้อย เพิ่มคำตอบใหม่ด้วยตัวอย่าง FYI
openwonk

33

หากคุณกำลังใช้ ORM ของ SQLAlchemy แทนภาษานิพจน์คุณอาจพบว่าตัวเองต้องการแปลงวัตถุประเภทsqlalchemy.orm.query.Queryเป็นเฟรมข้อมูล Pandas

วิธีการที่สะอาดที่สุดคือการรับ SQL ที่สร้างขึ้นจากแอตทริบิวต์คำสั่งของแบบสอบถามจากนั้นดำเนินการด้วยread_sql()วิธีการของแพนด้า เช่นเริ่มต้นด้วยวัตถุ Query ที่เรียกว่าquery:

df = pd.read_sql(query.statement, query.session.bind)

5
วิธีที่มีประสิทธิภาพมากขึ้นคือการรับข้อความจาก sqlalchemy และปล่อยให้แพนด้าทำแบบสอบถามเองโดยpandas.read_sql_queryส่งผ่านquery.statementไป ดูคำตอบนี้: stackoverflow.com/a/29528804/1273938
LeoRochael

ขอบคุณ @LeoRochael! ฉันแก้ไขคำตอบของฉัน สะอาดกว่าแน่นอน!
นาธานโกลด์

23

แก้ไข 2014-09-30:

ตอนนี้แพนด้ามี read_sqlฟังก์ชั่น แน่นอนคุณต้องการใช้แทน

คำตอบเดิม:

ฉันไม่สามารถช่วยคุณเกี่ยวกับ SQLAlchemy - ฉันใช้ pyodbc, MySQLdb หรือ psychopg2 เสมอตามต้องการ แต่เมื่อทำเช่นนั้นฟังก์ชันที่เรียบง่ายอย่างฟังก์ชันด้านล่างนี้มักจะเหมาะกับความต้องการของฉัน:

import decimal

import pydobc
import numpy as np
import pandas

cnn, cur = myConnectToDBfunction()
cmd = "SELECT * FROM myTable"
cur.execute(cmd)
dataframe = __processCursor(cur, dataframe=True)

def __processCursor(cur, dataframe=False, index=None):
    '''
    Processes a database cursor with data on it into either
    a structured numpy array or a pandas dataframe.

    input:
    cur - a pyodbc cursor that has just received data
    dataframe - bool. if false, a numpy record array is returned
                if true, return a pandas dataframe
    index - list of column(s) to use as index in a pandas dataframe
    '''
    datatypes = []
    colinfo = cur.description
    for col in colinfo:
        if col[1] == unicode:
            datatypes.append((col[0], 'U%d' % col[3]))
        elif col[1] == str:
            datatypes.append((col[0], 'S%d' % col[3]))
        elif col[1] in [float, decimal.Decimal]:
            datatypes.append((col[0], 'f4'))
        elif col[1] == datetime.datetime:
            datatypes.append((col[0], 'O4'))
        elif col[1] == int:
            datatypes.append((col[0], 'i4'))

    data = []
    for row in cur:
        data.append(tuple(row))

    array = np.array(data, dtype=datatypes)
    if dataframe:
        output = pandas.DataFrame.from_records(array)

        if index is not None:
            output = output.set_index(index)

    else:
        output = array

    return output

ฉันคิดว่าคุณต้องนำเข้าทศนิยมไว้ด้านบนหรือไม่?
joefromct

@joefromct บางที แต่คำตอบนี้ล้าสมัยมากฉันควรจะตีทุกอย่างและแสดงวิธีการของแพนด้า
Paul H

อาจเกี่ยวข้องกับบางคน ... สาเหตุที่ฉันศึกษาเรื่องนี้เป็นเพราะปัญหาอื่นของฉันโดยใช้ read_sql () ที่นี่stackoverflow.com/questions/32847246/…
joefromct

เกี่ยวข้องกับผู้ที่ไม่สามารถใช้ SQLAlchemy ซึ่งไม่รองรับฐานข้อมูลทั้งหมด
lamecicle

@lamecicle ค่อนข้างไม่เห็นด้วย IIRC read_sqlยังคงสามารถยอมรับการเชื่อมต่อที่ไม่ใช่ SQLAlchemy ผ่านเช่น pyodbc, psychopg2 เป็นต้น
Paul H

16

ตัวเชื่อมต่อ MySQL

สำหรับผู้ที่ทำงานกับตัวเชื่อมต่อ mysql คุณสามารถใช้รหัสนี้เพื่อเริ่มต้น (ขอบคุณข้อมูล @Daniel Velkov)

ใช้อ้างอิง:


import pandas as pd
import mysql.connector

# Setup MySQL connection
db = mysql.connector.connect(
    host="<IP>",              # your host, usually localhost
    user="<USER>",            # your username
    password="<PASS>",        # your password
    database="<DATABASE>"     # name of the data base
)   

# You must create a Cursor object. It will let you execute all the queries you need
cur = db.cursor()

# Use all the SQL you like
cur.execute("SELECT * FROM <TABLE>")

# Put it all to a data frame
sql_data = pd.DataFrame(cur.fetchall())
sql_data.columns = cur.column_names

# Close the session
db.close()

# Show the data
print(sql_data.head())

9

นี่คือรหัสที่ฉันใช้ หวังว่านี่จะช่วยได้

import pandas as pd
from sqlalchemy import create_engine

def getData():
  # Parameters
  ServerName = "my_server"
  Database = "my_db"
  UserPwd = "user:pwd"
  Driver = "driver=SQL Server Native Client 11.0"

  # Create the connection
  engine = create_engine('mssql+pyodbc://' + UserPwd + '@' + ServerName + '/' + Database + "?" + Driver)

  sql = "select * from mytable"
  df = pd.read_sql(sql, engine)
  return df

df2 = getData()
print(df2)

9

นี่คือคำตอบที่สั้นและชัดเจนสำหรับปัญหาของคุณ:

from __future__ import print_function
import MySQLdb
import numpy as np
import pandas as pd
import xlrd

# Connecting to MySQL Database
connection = MySQLdb.connect(
             host="hostname",
             port=0000,
             user="userID",
             passwd="password",
             db="table_documents",
             charset='utf8'
           )
print(connection)
#getting data from database into a dataframe
sql_for_df = 'select * from tabledata'
df_from_database = pd.read_sql(sql_for_df , connection)

9

1. ใช้ MySQL-connector-python

# pip install mysql-connector-python

import mysql.connector
import pandas as pd

mydb = mysql.connector.connect(
    host = 'host',
    user = 'username',
    passwd = 'pass',
    database = 'db_name'
)
query = 'select * from table_name'
df = pd.read_sql(query, con = mydb)
print(df)

2. การใช้ SQLAlchemy

# pip install pymysql
# pip install sqlalchemy

import pandas as pd
import sqlalchemy

engine = sqlalchemy.create_engine('mysql+pymysql://username:password@localhost:3306/db_name')

query = '''
select * from table_name
'''
df = pd.read_sql_query(query, engine)
print(df)

คำตอบที่ง่ายและยอดเยี่ยม!
Lucas Aimaretto

5

เช่นเดียวกับนาธานฉันมักต้องการถ่ายโอนผลลัพธ์ของ sqlalchemy หรือ sqlsoup Query ลงใน data frame ของ Pandas ทางออกของฉันเองสำหรับสิ่งนี้คือ:

query = session.query(tbl.Field1, tbl.Field2)
DataFrame(query.all(), columns=[column['name'] for column in query.column_descriptions])

1
หากคุณมีวัตถุแบบสอบถาม มีประสิทธิภาพมากกว่าในการรับข้อความจาก sqlalchemy และปล่อยให้แพนด้าทำแบบสอบถามเองโดยpandas.read_sql_queryส่งผ่านquery.statementไป ดูคำตอบนี้: stackoverflow.com/a/29528804/1273938
LeoRochael

4

resoverallเป็นอ็อบเจ็กต์ sqlalchemy ResultProxy คุณสามารถอ่านเพิ่มเติมเกี่ยวกับเรื่องนี้ได้ในเอกสาร sqlalchemyส่วนหลังจะอธิบายถึงการใช้งานพื้นฐานในการทำงานกับ Engines และ Connections สิ่งสำคัญที่นี่คือคำสั่งresoverallเช่น

หมีแพนด้าชอบบงการเหมือนอ็อบเจกต์เพื่อสร้างโครงสร้างข้อมูลดูเอกสารออนไลน์

ขอให้โชคดีกับ sqlalchemy และแพนด้า


4

เพียงแค่ใช้pandasและpyodbcร่วมกัน คุณจะต้องแก้ไขสตริงการเชื่อมต่อของคุณ ( connstr) ตามข้อกำหนดฐานข้อมูลของคุณ

import pyodbc
import pandas as pd

# MSSQL Connection String Example
connstr = "Server=myServerAddress;Database=myDB;User Id=myUsername;Password=myPass;"

# Query Database and Create DataFrame Using Results
df = pd.read_sql("select * from myTable", pyodbc.connect(connstr))

ฉันเคยใช้pyodbcกับฐานข้อมูลขององค์กรหลายแห่ง (เช่น SQL Server, MySQL, MariaDB, IBM)


จะเขียน dataframe นี้กลับไปที่ MSSQL โดยใช้ Pyodbc ได้อย่างไร อื่น ๆ นอกเหนือจากการใช้ sqlalchemy
Ramsey

ใช้to_sqlวิธีการบนDataFrameวัตถุ วิธีการนั้นมีค่าเริ่มต้นเป็น SQLite ดังนั้นคุณต้องส่งผ่านวัตถุที่ชี้ไปยังฐานข้อมูล MSSQL อย่างชัดเจน ดูเอกสาร
openwonk

ฉันลองด้านล่างและฉันมีประมาณ 200K แถวที่มี 13 คอลัมน์ หลังจาก 15 นาทียังไม่เสร็จ ความคิดใด ๆ ? df.to_sql ('tablename', engine, schema = 'schemaname', if_exists = 'append', index = False)
แรมซีย์

ดูเหมือนจะช้า ... ฉันอาจจะต้องดูโค้ดทั้งหมดในการทำงานขออภัย ฉันหวังว่าจะpandasได้รับการปรับให้เหมาะสมยิ่งขึ้นสำหรับงาน ETL แบบเบา ๆ แต่อนิจจา ...
openwonk

3

คำถามนี้เก่า แต่ฉันต้องการเพิ่มสองเซ็นต์ ฉันอ่านคำถามว่า "ฉันต้องการเรียกใช้การสืบค้นไปยังฐานข้อมูล SQL [ของฉัน] ของฉันและเก็บข้อมูลที่ส่งคืนเป็นโครงสร้างข้อมูล Pandas [DataFrame]"

จากรหัสดูเหมือนว่าคุณหมายถึงฐานข้อมูล mysql และสมมติว่าคุณหมายถึง DataFrame แพนด้า

import MySQLdb as mdb
import pandas.io.sql as sql
from pandas import *

conn = mdb.connect('<server>','<user>','<pass>','<db>');
df = sql.read_frame('<query>', conn)

ตัวอย่างเช่น,

conn = mdb.connect('localhost','myname','mypass','testdb');
df = sql.read_frame('select * from testTable', conn)

ซึ่งจะนำเข้าแถวทั้งหมดของ testTable ไปยัง DataFrame


1

ที่นี่เป็นของฉัน ในกรณีที่คุณใช้ "pymysql":

import pymysql
from pandas import DataFrame

host   = 'localhost'
port   = 3306
user   = 'yourUserName'
passwd = 'yourPassword'
db     = 'yourDatabase'

cnx    = pymysql.connect(host=host, port=port, user=user, passwd=passwd, db=db)
cur    = cnx.cursor()

query  = """ SELECT * FROM yourTable LIMIT 10"""
cur.execute(query)

field_names = [i[0] for i in cur.description]
get_data = [xx for xx in cur]

cur.close()
cnx.close()

df = DataFrame(get_data)
df.columns = field_names

1

pandas.io.sql.write_frame เลิกใช้แล้ว https://pandas.pydata.org/pandas-docs/version/0.15.2/generated/pandas.io.sql.write_frame.html

ควรเปลี่ยนไปใช้ pandas.DataFrame.to_sql https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.to_sql.html

มีวิธีแก้ไขอีกวิธีหนึ่ง PYODBC ถึง Pandas - DataFrame ไม่ทำงาน - รูปร่างของค่าที่ส่งผ่านคือ (x, y) ดัชนีบ่งบอกถึง (w, z)

ในฐานะของ Pandas 0.12 (ฉันเชื่อว่า) คุณสามารถทำได้:

import pandas
import pyodbc

sql = 'select * from table'
cnn = pyodbc.connect(...)

data = pandas.read_sql(sql, cnn)

ก่อนหน้า 0.12 คุณสามารถทำได้:

import pandas
from pandas.io.sql import read_frame
import pyodbc

sql = 'select * from table'
cnn = pyodbc.connect(...)

data = read_frame(sql, cnn)

นี่เป็นวิธีที่ง่ายที่สุด
Wilmer E.Henao



0

หากประเภทผลลัพธ์เป็นResultSetคุณควรแปลงเป็นพจนานุกรมก่อน จากนั้นคอลัมน์ DataFrameจะถูกรวบรวมโดยอัตโนมัติ

สิ่งนี้ใช้ได้กับกรณีของฉัน:

df = pd.DataFrame([dict(r) for r in resoverall])
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.