SQLクエリの結果をPANDASデータ構造に変換する方法


116

この問題に関するどんな助けでも大歓迎です。

したがって、基本的には、SQLデータベースに対してクエリを実行し、返されたデータを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 2012

パンダは非常に面白いように聞こえます、私はそれについて以前に聞いたことがありませんが、この質問はほとんど意味がありません。「有用な情報を提供していない」とはどういう意味ですか?
tadman 2012

1
私が実行したクエリは戻り値を返すので、この戻り値をどのように操作してpandasデータ構造にする必要があるのか​​疑問に思っています。私はpythonに非常に慣れていないため、PHPで行うのはsql_fetch_arrayを実行するだけで「使用可能な」データがあるため、知識があまりありません。=)
user1613017 2012

回答:


120

これが仕事をする最も短いコードです:

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

Paulの回答のように、より精巧にタイプを解析できます。


1
これは、Oracleデータベースから送信された1.000.000レコードに対して私に役立ちました。
Erdem KAYA 2018年

8
df = DataFrame(cursor.fetchall())が返されるValueError: DataFrame constructor not properly called!場合、タプルのタプルはDataFrameコンストラクターでは受け入れられないようです。.keys()辞書モードまたはタプルモードのどちらにもカーソルはありません。
Mobigital

3
keysメソッドは、sqlalchemyを使用して取得した結果でのみ機能することに注意してください。Pyodbcは列の説明属性を使用します。
フィリップ

これはPostgresデータベースで機能しますか?keys()関数を使用して結果データフレームの列名を取得しようとしていますが、機能しません。
Bowen Liu

1
@BowenLiuはい、psycopg2で使用できますdf.columns=[ x.name for x in recoverall.description ]
Gnudiff

136

編集:2015年3月

以下に示すように、パンダは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 2017

実は、私の最後の応答以来、私が使ってきたpyodbcし、pandas一緒にかなり。例、FYIを使用して新しい回答を追加します。
openwonk 2017

33

式言語ではなくSQLAlchemyのORMを使用している場合は、タイプのオブジェクトをsqlalchemy.orm.query.QueryPandasデータフレームに変換したいと思うかもしれません。

最もクリーンなアプローチは、生成された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に感謝!回答を編集しました。間違いなくすっきり!
Nathan Gould

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

10進数を上にインポートする必要があると思いますか?
joefromct

@joefromct多分、しかし、この答えは時代遅れなので、私は本当に全部を打って、パンダのメソッドを示すべきです。
ポールH

それはいくつかのためにreleventかもしれ...私はこのことを学んでいた理由は、(read_sqlを使用して、理由は私の他の問題があった)ここstackoverflow.com/questions/32847246/...
joefromct

これは、すべてのデータベースをサポートしていないSQLAlchemyを使用できない人に関係があります。
lamecicle

@lamecicleはややそう思わない。IIRCは、read_sqlたとえばpyodbc、psychopg2などを介してSQLAlchemy以外の接続を受け入れることができます
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)

8

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クエリの結果を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

resoverallsqlalchemy ResultProxyオブジェクトです。詳細については、sqlalchemyのドキュメントをご覧ください。後者のドキュメントでは、エンジンと接続の基本的な使用方法について説明しています。ここで重要なのは、resoveralldictのようなものです。

パンダは、データ構造を作成するオブジェクトのようなdictが好きです。オンラインドキュメントを参照してください

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など)で使用しました。


Pyodbcを使用してこのデータフレームをMSSQLに再度書き込む方法は?sqlalchemyを使用する以外
Ramsey

オブジェクトのto_sqlメソッドを使用しDataFrameます。このメソッドのデフォルトはSQLiteなので、MSSQLデータベースを指すオブジェクトを明示的に渡す必要があります。docsを参照してください。
openwonk

私は以下のものを試しました、そして私は13列で約20万行を持っています。15分経っても完成しません。何か案は?df.to_sql( 'tablename'、engine、schema = 'schemaname'、if_exists = 'append'、index = False)
Ramsey

それは遅いようです...おそらくコード全体が動作しているのを見る必要があるでしょう。pandas軽いETL作業用にもっと最適化されていればいいのですが、悲しいかな...
openwonk

3

この質問は古いですが、2セント追加したかったのです。質問を「自分の[my] SQLデータベースに対してクエリを実行し、返されたデータをPandasデータ構造[DataFrame]として保存したい」と読みました。

コードからは、mysqlデータベースを意味しているように見え、pandas 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

前回の投稿から長い時間ですが、誰かを助けるかもしれません...

ポールHよりも短い方法:

my_dic = session.query(query.all())
my_df = pandas.DataFrame.from_dict(my_dic)

0

私がこれを行う最良の方法

db.execute(query) where db=db_class() #database class
    mydata=[x for x in db.fetchall()]
    df=pd.DataFrame(data=mydata)

0

結果のタイプがResultSetの場合は、最初に辞書に変換する必要があります。次に、DataFrame列が自動的に収集されます。

これは私の場合に機能します:

df = pd.DataFrame([dict(r) for r in resoverall])
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.