【问题标题】:How to convert SQL Query result to PANDAS Data Structure?如何将 SQL 查询结果转换为 PANDAS 数据结构?
【发布时间】:2012-08-16 08:18:12
【问题描述】:

对于这个问题的任何帮助将不胜感激。

所以基本上我想对我的 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数据结构。
  • Pandas 听起来很有趣,我以前没听说过,但是这个问题几乎没有任何意义。你能试着澄清一下“没有提供任何有用的信息”是什么意思吗?
  • 因为我执行的查询给出了一个返回值,只是想知道我应该如何操作这个返回值并将它变成一个pandas数据结构。我对 python 很陌生,因此没有太多知识,就像我们在 PHP 中所做的只是做一个 sql_fetch_array 并且我们有“可用”数据。 =)

标签: python mysql data-structures pandas


【解决方案1】:

这是完成这项工作的最短代码:

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

您可以像 Paul 的回答那样去花哨地解析类型。

【讨论】:

  • 这对我来说适用于从 Oracle 数据库中获取的 1.000.000 条记录。
  • df = DataFrame(cursor.fetchall()) 返回ValueError: DataFrame constructor not properly called!,看来元组的元组对于 DataFrame 构造函数是不可接受的。在字典或元组模式下,光标上也没有.keys()
  • 请注意,keys 方法仅适用于使用 sqlalchemy 获得的结果。 Pyodbc 使用列的描述属性。
  • 这可以用于 Postgres 数据库吗?我正在尝试使用 keys() 函数获取结果数据框的列名,但无法正常工作。
  • @BowenLiu 是的,您可以与 psycopg2 一起使用 df.columns=[ x.name for x in recoverall.description ]
【解决方案2】:

编辑:2015 年 3 月

如下所述,pandas 现在使用SQLAlchemy 来读取(read_sql)和插入(to_sql)数据库。以下应该工作

import pandas as pd

df = pd.read_sql(sql, cnxn)

上一个答案: 来自similar question的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()
  • @openwonk 在上面的代码 sn-p 中哪里会实现pd.read_sql()
  • 实际上,自从我上次回复以来,我已经多次使用pyodbcpandas。以示例添加新答案,仅供参考。
【解决方案3】:

如果您使用 SQLAlchemy 的 ORM 而不是表达式语言,您可能会发现自己想要将 sqlalchemy.orm.query.Query 类型的对象转换为 Pandas 数据框。

最干净的方法是从查询的statement属性中获取生成的SQL,然后用pandas的@​​987654323@方法执行。例如,从名为 query 的 Query 对象开始:

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

【讨论】:

  • 一种更有效的方法是从 sqlalchemy 获取语句,然后让 pandas 自己使用 pandas.read_sql_query 进行查询,并将 query.statement 传递给它。看到这个答案:stackoverflow.com/a/29528804/1273938
  • 谢谢@LeoRochael!我编辑了我的答案。绝对干净!
【解决方案4】:

编辑 2014-09-30:

pandas 现在有一个read_sql 函数。你肯定想改用它。

原答案:

我无法在 SQLAlchemy 方面为您提供帮助——我总是根据需要使用 pyodbc、MySQLdb 或 Psychopg2。但是这样做时,像下面这样简单的功能往往会满足我的需求:

import decimal

import pyodbc #just corrected a typo here
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

【讨论】:

  • 我认为您需要在顶部的某处导入小数?
  • 这对某些人来说可能是相关的......我研究这个的原因是因为我的其他问题,在这里使用 read_sql() stackoverflow.com/questions/32847246/…
  • 这对于那些不能使用不支持所有数据库的SQLAlchemy的人来说是相关的。
  • @lamecicle 有点不同意。 IIRC,read_sql 仍然可以通过例如 pyodbc、psychpg2 等接受非 SQLAlchemy 连接
【解决方案5】:

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())

【讨论】:

    【解决方案6】:

    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)
    

    【讨论】:

    • 简单而伟大的答案!
    【解决方案7】:

    这是我使用的代码。希望这会有所帮助。

    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)
    

    【讨论】:

      【解决方案8】:

      这是对您问题的简短回答:

      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】:

        像 Nathan 一样,我经常想将 sqlalchemy 或 sqlsoup 查询的结果转储到 Pandas 数据框中。我自己的解决方案是:

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

        【讨论】:

        • 如果你有一个查询对象。从 sqlalchemy 获取语句并让 pandas 自己使用pandas.read_sql_query 进行查询,将query.statement 传递给它,效率更高。看到这个答案:stackoverflow.com/a/29528804/1273938
        【解决方案10】:

        resoverall 是一个 sqlalchemy ResultProxy 对象。您可以在sqlalchemy docs 中阅读更多相关信息,后者解释了使用引擎和连接的基本用法。这里重要的是 resoverall 是 dict 。

        Pandas 喜欢 dict 之类的对象来创建其数据结构,请参阅online docs

        祝 sqlalchemy 和 pandas 好运。

        【讨论】:

          【解决方案11】:

          只需将pandaspyodbc 一起使用。您必须根据您的数据库规范修改您的连接字符串 (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
          • DataFrame 对象使用to_sql 方法。该方法默认为 SQLite,因此您必须显式地向它传递一个指向 MSSQL 数据库的对象。见docs
          • 我尝试了下面的一个,我有大约 200K 行和 13 列。 15分钟后也没有完成。有任何想法吗? df.to_sql('tablename',engine,schema='schemaname',if_exists='append',index=False)
          • 这看起来确实很慢......我可能需要查看整个代码的运行情况,抱歉。我希望 pandas 更适合轻量级 ETL 工作,但是唉...
          【解决方案12】:

          这个问题很老了,但我想加上我的两分钱。我将问题读作“我想对我的 [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。

          【讨论】:

            【解决方案13】:

            上一篇文章已经很久了,但也许它对某人有帮助......

            比 Paul H 短:

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

            【讨论】:

              【解决方案14】:

              这是我的。以防万一您使用的是“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
              

              【讨论】:

                【解决方案15】:

                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 to Pandas - DataFrame not working - Shape of passed values is (x,y), indices imply (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)
                

                【讨论】:

                • 这是迄今为止最简单的方法
                【解决方案16】:

                最好的方法

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

                【讨论】:

                  【解决方案17】:

                  如果结果类型是ResultSet,则应先将其转换为字典。然后会自动收集 DataFrame 列

                  这适用于我的情况:

                  df = pd.DataFrame([dict(r) for r in resoverall])
                  

                  【讨论】:

                    【解决方案18】:

                    这是一个我喜欢的简单解决方案:

                    将您的数据库连接信息放在一个安全位置的 YAML 文件中(不要在代码仓库中对其进行版本化)。

                    ---
                    host: 'hostname'
                    port: port_number_integer
                    database: 'databasename'
                    user: 'username'
                    password: 'password'
                    

                    然后在字典中加载conf,打开db连接,在数据框中加载SQL查询的结果集:

                    import yaml
                    import pymysql
                    import pandas as pd
                    
                    db_conf_path = '/path/to/db-conf.yaml'
                    
                    # Load DB conf
                    with open(db_conf_path) as db_conf_file:
                        db_conf = yaml.safe_load(db_conf_file)
                    
                    # Connect to the DB
                    db_connection = pymysql.connect(**db_conf)
                    
                    # Load the data into a DF
                    query = '''
                    SELECT *
                    FROM my_table
                    LIMIT 10
                    '''
                    
                    df = pd.read_sql(query, con=db_connection)
                    

                    【讨论】:

                      猜你喜欢
                      • 1970-01-01
                      • 2012-12-18
                      • 2021-09-21
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      相关资源
                      最近更新 更多