Выполнение запроса SQL над набором данных pandas
У меня есть набор данных pandas, который называется 'df'.
Как я могу сделать что-то вроде ниже;
df.query("select * from df")
Спасибо.
Для тех, кто знает R, есть библиотека sqldf, где вы можете выполнять SQL-код в R, мой вопрос в основном, есть ли какая-нибудь библиотека, такая как sqldf в python
9 ответов
Это не pandas.query
должен сделать, вы можете посмотреть на пакет pandasql
(такой же как sqldf
в R)
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
Гораздо лучшим решением является использование 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: тестовые данные желтых такси Нью-Йорка ~ 120 МБ данных 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 раз
В этой статье приводятся подробные сведения и утверждается, что 1000-кратное улучшение по сравнению с pandasql: https://duckdb.org/2021/05/14/sql-on-pandas.html.
Через некоторое время я понял, что самый простой способ - просто сделать
from pandasql import sqldf
output = sqldf("select * from df")
Работает как шарм, где df
это фреймворк pandas. Вы можете установить pandasql: https://pypi.org/project/pandasql/
Ты можешь использовать 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
подразумевается.
На самом деле есть новый пакет, который я только что выпустил, под названием dataframe_sql. Это дает вам возможность запрашивать фреймы данных pandas с помощью SQL так, как вы хотите. Вы можете найти пакет здесь
Или вы можете использовать инструменты, которые делают то, что у них лучше всего:
Установить postgresql
Подключитесь к базе данных:
из sqlalchemy import create_engine
import urllib.parse
engconnect = "{0}: // {1}:{2}@{3}:{4} / {5}".format (dialect, user_uenc, pw_uenc, host, port, dbname)
dbengine = create_engine(engconnect)
database = dbengine.connect()
- Выгрузить фрейм данных в postgres
df.to_sql('mytablename', база данных, if_exists='replace')
- Напишите свой запрос со всеми вложениями SQL, с которыми может справиться ваш мозг.
myquery = "выбрать отдельный * из mytablename"
- Создайте фрейм данных, выполнив запрос:
newdf = pd.read_sql(myquery, база данных)
Я думаю лучшее решение чем
pandassql
будет duckdb. Способ, которым он обрабатывает сопоставление имени таблицы с объектом фрейма данных, немного чище, imo. Однако я не оценивал производительность.
Также есть 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
Другим решением является RBQL , который предоставляет SQL-подобный язык запросов, который позволяет использовать выражение Python внутри операторов SELECT и WHERE. Он также обеспечивает удобный
%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.