【问题标题】:Executing an SQL query over a pandas dataset对 pandas 数据集执行 SQL 查询
【发布时间】:2018-02-02 13:43:29
【问题描述】:

我有一个名为“df”的 pandas 数据集。

我怎样才能做下面这样的事情;

df.query("select * from df")

谢谢。

对于那些了解 R 的人,有一个名为 sqldf 的库,您可以在其中执行 R 中的 SQL 代码,我的问题基本上是,python 中是否有类似 sqldf 的库

【问题讨论】:

  • 对不起,我们的想象力很差。请提供一些具体数据以及您实际想要什么。
  • print df?大声笑
  • 你想要的都是不可能的。数据框不是 SQL 数据库,不能像一个数据库一样查询。
  • 与您想要的最接近的是:pandas.pydata.org/pandas-docs/stable/generated/…,它不是 SQL。
  • 我只能提供我正在使用的包pandasql

标签: python sqlite pandas


【解决方案1】:

另一个解决方案是RBQL,它提供了类似 SQL 的查询语言,允许在 SELECT 和 WHERE 语句中使用 Python 表达式。它还提供了一个方便的%rbql 魔术命令,可以在 Jupyter/IPyhon 中使用:

# Get some test data:
!pip install vega_datasets
from vega_datasets import data
my_cars_df = data.cars()
# Install and use RBQL:
!pip install rbql
%load_ext rbql
%rbql SELECT * FROM my_cars_df WHERE a.Horsepower > 100 ORDER BY a.Weight_in_lbs DESC

在此示例中,my_cars_df 是 Pandas 数据框。

您可以在此演示 Google Colab notebook 中进行尝试。

【讨论】:

    【解决方案2】:

    还有FugueSQL

    pip install fugue[sql]
    
    import pandas as pd
    from fugue_sql import fsql
    
    comics_df = pd.DataFrame({'book': ['Secret Wars 8',
                                       'Tomb of Dracula 10',
                                       'Amazing Spider-Man 252',
                                       'New Mutants 98',
                                       'Eternals 1',
                                       'Amazing Spider-Man 300',
                                       'Department of Truth 1'],
                              'publisher': ['Marvel', 'Marvel', 'Marvel', 'Marvel', 'Marvel', 'Marvel', 'Image'],
                              'grade': [9.6, 5.0, 7.5, 8.0, 9.2, 6.5, 9.8],
                              'value': [400, 2500, 300, 600, 400, 750, 175]})
    
    # which of my books are graded above 8.0?
    query = """
    SELECT book, publisher, grade, value FROM comics_df
    WHERE grade > 8.0
    PRINT
    """
    
    fsql(query).run()
    

    输出

    PandasDataFrame
    book:str                                                      |publisher:str|grade:double|value:long
    --------------------------------------------------------------+-------------+------------+----------
    Secret Wars 8                                                 |Marvel       |9.6         |400       
    Eternals 1                                                    |Marvel       |9.2         |400       
    Department of Truth 1                                         |Image        |9.8         |175       
    Total count: 3
    

    参考文献

    https://fugue-tutorials.readthedocs.io/tutorials/beginner/beginner_sql.html

    https://www.kdnuggets.com/2021/10/query-pandas-dataframes-sql.html

    【讨论】:

      【解决方案3】:

      更好的解决方案是使用duckdb

      pip install duckdb
      
      import pandas as pd
      import duckdb
      test_df = pd.DataFrame.from_dict({"i":[1, 2, 3, 4], "j":["one", "two", "three", "four"]})
      
      duckdb.query("SELECT * FROM test_df where i>2").df() # returns a result dataframe
      

      对 pandasql 的性能改进: 测试数据 NYC 黄色出租车 ~120mb 的 csv 数据

      nyc = pd.read_csv('https://s3.amazonaws.com/nyc-tlc/trip+data/yellow_tripdata_2021-01.csv',low_memory=False)
      
      from pandasql import sqldf
      pysqldf = lambda q: sqldf(q, globals())
      
      pysqldf("SELECT * FROM nyc where trip_distance>10")
      # wall time 16.1s
      
      duckdb.query("SELECT * FROM nyc where trip_distance>10").df()
      # wall time 183ms
      

      速度提高了大约 100 倍

      这篇文章提供了很好的细节,并声称比 pandasql 改进了 1000 倍: https://duckdb.org/2021/05/14/sql-on-pandas.html

      【讨论】:

        【解决方案4】:

        我认为比pandassql 更好的解决方案是duckdb。它处理表名映射到数据框对象的方式更简洁一些。不过我还没有评估性能。

        【讨论】:

          【解决方案5】:

          这不是pandas.query 应该做的。您可以查看包 pandasql(与 R 中的 sqldf 相同)

          import pandas as pd
          import pandasql as ps
          
          df = pd.DataFrame([[1234, 'Customer A', '123 Street', np.nan],
                         [1234, 'Customer A', np.nan, '333 Street'],
                         [1233, 'Customer B', '444 Street', '333 Street'],
                        [1233, 'Customer B', '444 Street', '666 Street']], columns=
          ['ID', 'Customer', 'Billing Address', 'Shipping Address'])
          
          q1 = """SELECT ID FROM df """
          
          print(ps.sqldf(q1, locals()))
          
               ID
          0  1234
          1  1234
          2  1233
          3  1233
          

          2020 年 7 月 10 日更新

          更新pandasql

          ps.sqldf("select * from df")
          

          【讨论】:

          • 由于未导入 numpy,我收到此错误:回溯(最近一次调用最后一次):文件“”,第 1 行,在 NameError: name 'np' is not defined
          • @Jas 只是数据导入,如果您将 np.nan 更改为 1000 ,它将消失
          • 仅供参考,这看起来不再有效了。我收到错误AttributeError: 'Connection' object has no attribute 'cursor'。它可能适用于旧版本的pandas;我正在使用 v1.3.4。
          • @MattSosna 它仍然对我有用~
          【解决方案6】:

          或者,您可以使用最擅长的工具:

          1. 安装postgresql

          2. 连接数据库:

          从 sqlalchemy 导入 create_engine
          导入 urllib.parse
          engconnect = "{0}://{1}:{2}@{3}:{4}/{5}".format(dialect,user_uenc, pw_uenc, host,port, dbname)
          dbengine = create_engine(engconnect)
          数据库 = dbengine.connect()

          1. 将数据帧转储到 postgres 中

          df.to_sql('mytablename', database, if_exists='replace')

          1. 使用您的大脑可以处理的所有 SQL 嵌套编写查询。

          myquery = "select distinct * from mytablename"

          1. 通过运行查询创建数据框:

          newdf = pd.read_sql(myquery, 数据库)

          【讨论】:

          • 太恐怖了,请不要在现实生活中这样做
          【解决方案7】:

          其实我刚刚发布了一个新的包,叫做dataframe_sql。这使您能够随心所欲地使用 SQL 查询 pandas 数据帧。你可以找到包here

          【讨论】:

          • 我找不到相同的 conda 发行版,我们的支持团队只能使用 conda 工具安装包,而不是 pip。你有发布它的计划吗?
          • @Sajal 我当然可以调查一下,你介意在 GitHub 上提出这个问题吗?
          【解决方案8】:

          在使用了一段时间后,我意识到最简单的方法就是这样做

          from pandasql import sqldf
          
          output = sqldf("select * from df")
          

          df 是 pandas 数据框的魅力所在 可以安装pandasql:https://pypi.org/project/pandasql/

          【讨论】:

          • 很好,我还在用旧版本的 pandasql ,也更新一下我的答案,谢谢~
          【解决方案9】:

          您可以使用DataFrame.query(condition) 来返回匹配condition 的数据框的子集,如下所示:

          df = pd.DataFrame(np.arange(9).reshape(3,3), columns=list('ABC'))
          df
             A  B  C
          0  0  1  2
          1  3  4  5
          2  6  7  8
          
          df.query('C < 6')
             A  B  C
          0  0  1  2
          1  3  4  5
          
          
          df.query('2*B <= C')
             A  B  C
          0  0  1  2
          
          
          df.query('A % 2 == 0')
             A  B  C
          0  0  1  2
          2  6  7  8
          

          这与 SQL 语句的效果基本相同,只是隐含了SELECT * FROM df WHERE

          【讨论】:

          猜你喜欢
          • 2022-09-22
          • 1970-01-01
          • 2018-07-16
          • 2020-02-12
          • 2021-09-10
          • 1970-01-01
          • 2023-03-15
          • 1970-01-01
          • 2019-03-18
          相关资源
          最近更新 更多