Python-编写原始SQL来处理Python中的数据框

时间:2018-06-21 18:06:42

标签: python sql pandas

我试图在Python数据框上执行SQL语言功能,就像它们是Microsoft SQL Server中的表一样。仔细研究,看来R具有模块sqldf,Python具有与pandasql兼容的记录-但是,如果这是必需的,我将无法使Rodeo正常工作。

This Blog具有以上记录。我无法通过运行

的任意组合来导入sqldf或pandasql
import pandasql as pdsql
from pandasql import sqldf
pysql = lambda q: pdsql.sqldf(q, globals())
which I scavenged from here and there.

在SAS中,您可以使用PROC SQL这样操作SAS数据集:

PROC SQL;
    SELECT 
        b.patid,
        CASE WHEN ECD='1234' THEN 'ACTIVE' ELSE 'ACTIVE' END AS ACTIVE_INACTIVE,        
        b.SUMMARY_ID
    FROM SAStable1 a
    LEFT JOIN SAStable2 b
        ON a.patient_id=b.patid
       ;
QUIT;

这样可以在SAS中的SAS数据集上键入SQL查询。这不同于pandas.read_sql_query(query,connection)函数,该函数非常适用于在连接的数据库上运行SQL查询,但是一旦在Python中就会在实际的数据帧中运行(除非我遗漏了一些东西)。

Python是否有类似的东西?鉴于它在SAS和R中可用,我会感到惊讶,但是我的搜索没有任何可操作的地方。

谢谢!

2 个答案:

答案 0 :(得分:2)

您不需要SQL在熊猫中执行此操作。 您可以使用以下方法加入两个数据框:

df1.set_index('patient_id').join(df2.set_index('patid'))

您可以根据条件创建一列,类似于CASE WHEN ECD='1234' THEN 'ACTIVE' ELSE 'ACTIVE' END AS ACTIVE_INACTIVE, 通过执行类似的操作:

import pandas as pd
df1 = pd.DataFrame([[100,1234],[101,1234],[102,4356]], columns=['patient_id','ECD'])
df2 = pd.DataFrame([[100,345],[101,23423],[102,3423]], columns=['patid','SUMMARY_ID'])
df3 = df1.set_index('patient_id').join(df2.set_index('patid'))

def active(row):
     if row['ECD'] == 1234 :
         return 'ACTIVE'
     else:
         return 'INACTIVE'

df3['ACTIVE_INACTIVE'] = df3.apply(active, axis=1))

如果您确实需要使用SQL,可以使用以下命令安装pandasql

sudo -H pip3 install pandasql

然后您可以像期望的那样使用它:

from pandasql import sqldf
pysqldf = lambda q: sqldf(q, globals())
q = """SELECT
        *,
        CASE WHEN a.ECD='1234' THEN 'ACTIVE' ELSE 'INACTIVE' END AS ACTIVE_INACTIVE        
        FROM
        df1 a
      JOIN
        df2 b
           ON a.patient_id = b.patid;"""
print(pysqldf(q).head())

答案 1 :(得分:1)

正如源代码所示,R的sqldf和Python的pandasql实际上都运行内存中 SQLite实例(R默认为SQLite)。因此,实际上,您可以通过与pandasql实际上在后台进行的read_sql接口来使用pandas的SQL方法(to_sqlSQLAlchemy)来复制功能!具体来说,请结合演示示例考虑以下内容:

  1. 将所有需要的环境数据帧导入内存中的SQLite数据库:

    import numpy as np
    import pandas as pd
    from sqlalchemy import create_engine
    
    # IN-MEMORY DATABASE (NO PATH SPECIFIED)
    engine = create_engine('sqlite://')
    
    dates = pd.date_range('2018-01-01', '2018-06-22', freq='D')
    df1 = pd.DataFrame({'current_date': np.random.choice(dates, 50),
                        'analysis_tool': 'pandas',                  
                        'num_value': np.random.randint(100, size=50)*1000                           
                       }, columns=['current_date', 'analysis_tool', 'num_value'])
    
    df2 = pd.DataFrame({'current_date': np.random.choice(dates, 50),
                        'analysis_tool': 'r',                  
                        'num_value': np.random.randint(100, size=50)*1000                           
                       }, columns=['current_date', 'analysis_tool', 'num_value'])
    
    df3 = pd.DataFrame({'current_date': np.random.choice(dates, 50),
                        'analysis_tool': 'sas',                  
                        'num_value': np.random.randint(100, size=50)*1000                           
                       }, columns=['current_date', 'analysis_tool', 'num_value'])
    
    df1.to_sql("df1", con=engine, if_exists='replace')
    df2.to_sql("df2", con=engine, if_exists='replace')
    df3.to_sql("df3", con=engine, if_exists='replace')
    
  2. 运行所需的SQL查询以更新和处理数据:

    # QUERIES RUN IN A TRANSACTION
    with engine.begin() as cn:
       cn.execute("UPDATE df1 SET analysis_tool = 'python pandas'")
       cn.execute("INSERT INTO df3 (analytic_tool, current_date, num_value) VALUES (?, ?, ?)", 
                  ('sas', '2018-06-23', 51000))
    
  3. 作为熊猫数据框导入:

    strSQL = """SELECT * FROM df1
                UNION ALL
                SELECT * FROM df2
                UNION ALL
                SELECT * FROM df3;"""
    
    df_all = pd.read_sql(strSQL, engine)
    
    engine.dispose()                       # IN-MEMORY DATABASE DESTROYED