Поиск в диапазоне между столбцами с использованием sqlite3 в pandas

Я нашел решение своей проблемы в одном вопросе Объединить кадры данных pandas, где одно значение находится между двумя другими Я попытался изменить его для своей ситуации, но это не сработало. В приведенном ниже коде Мне нужно df, чтобы показать начало и конец для каждого проданного продукта и категории. Но он игнорирует дату, находящуюся между начальным и конечным периодом. как видно на экране для продажи Apple от 06.01.2020, период с 26.03.2020 по 31.07.2020 должен быть показан, но он показывает другое. Как мне уточнить SQL-запрос?

Поиск в диапазоне между столбцами с использованием sqlite3 в pandas

import pandas as pd
import sqlite3

dates_of_discount=pd.DataFrame({"Date_begining":['01/01/2021','01/02/2020','26/03/2020'],
                   "Date_ending":['31/12/2021', '25/02/2020', '31/07/2020'],
                   "Category":['Discount', 'Not Discount', "Discount"],
                   "d_Product":['Apple', 'Peach', "Apple"]})
purchase_dates=pd.DataFrame({"date":(["20/01/2020", "18/02/2020", "01/06/2020"]),
                          "Qty":[100, 200, 300],
                          "Price":[3.5,4, 20],
                          "p_Product":['Apple', 'Peach', "Apple"]})


conn = sqlite3.connect(':memory:')

dates_of_discount.to_sql('disc', conn, index=False)
purchase_dates.to_sql('purch', conn, index=False)

qry = '''
    select  
        purch.date Sold,
        purch.p_Product Prod,
        purch.Qty,
        purch.Price,
        Date_begining Period_Start,
        Date_ending Period_End,
        Category Output
    from
        purch join disc on
        date between Date_begining and Date_ending and
        d_Product = p_Product
    '''
df = pd.read_sql_query(qry, conn)
df

Формат даты, такой как 01/06/2020, несопоставим. Изменить на YYYY-MM-DD

forpas 14.05.2022 15:01

Спасибо! помогло, но если вместо дат цифры, допустим размер товара. Мин и Макс. Как заставить это работать?

Zaur Guliyev 14.05.2022 15:14
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
2
62
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Как уже отмечалось, при правильном преобразовании строк даты в фактические datetime в пандах с использованием pd.to_datetime операция соединения SQL должна возвращать ожидаемые результаты:

Входные данные (с преобразованием даты)

dates_of_discount = pd.DataFrame({
    "Date_begining": pd.to_datetime(
        ['01/01/2021','01/02/2020','26/03/2020'],
        format = "%d/%m/%Y"
    ),
    "Date_ending": pd.to_datetime(
        ['31/12/2021', '25/02/2020', '31/07/2020'],
        format = "%d/%m/%Y"
    ),
    "Category": ['Discount', 'Not Discount', "Discount"],
    "d_Product": ['Apple', 'Peach', "Apple"]
})

purchase_dates=pd.DataFrame({
    "date": pd.to_datetime(
        ["20/01/2020", "18/02/2020", "01/06/2020"],
        format = "%d/%m/%Y"
    ),
    "Qty":[100, 200, 300],
    "Price":[3.5,4, 20],
    "p_Product":['Apple', 'Peach', "Apple"]
})

SQLite-запрос

conn = sqlite3.connect(':memory:')

dates_of_discount.to_sql('disc', conn, index=False)
purchase_dates.to_sql('purch', conn, index=False)

qry = '''
    select  
        purch.date as Sold,
        purch.p_Product as Prod,
        purch.Qty,
        purch.Price,
        disc.Date_begining as Period_Start,
        disc.Date_ending as Period_End,
        disc.Category as Output
    from purch 
    join disc 
      on purch.date between disc.Date_begining and disc.Date_ending 
      and purch.p_Product = disc.d_Product
    '''
merge_df = pd.read_sql_query(qry, conn)
merge_df
#                   Sold   Prod  Qty  Price         Period_Start           Period_End        Output
# 0  2020-02-18 00:00:00  Peach  200    4.0  2020-02-01 00:00:00  2020-02-25 00:00:00  Not Discount
# 1  2020-06-01 00:00:00  Apple  300   20.0  2020-03-26 00:00:00  2020-07-31 00:00:00      Discount

Кстати, панды также могут выполнять аналогичную операцию с merge по продукту и query или фильтровать по датам (reindex и set_axis для подмножества и переименования столбцов):

merge_df = (
    purchase_dates.merge(
        dates_of_discount, left_on = "p_Product", right_on = "d_Product"   
    ).query(
        "date >= Date_begining & date <= Date_ending"
    ).reset_index(drop=True)
    .reindex(
        ["date", "p_Product", "Qty", "Price", "Date_begining", "Date_ending", "Category"],
        axis = "columns"
    ).set_axis(
        ["Sold", "Prod", "Qty", "Price", "Period_Start", "Period_End", "Output"],
        axis = "columns",
        inplace = False
    )
)
merge_df_pd
#         Sold   Prod  Qty  Price Period_Start Period_End        Output
# 0 2020-06-01  Apple  300   20.0   2020-03-26 2020-07-31      Discount
# 1 2020-02-18  Peach  200    4.0   2020-02-01 2020-02-25  Not Discount

Наконец, согласно вашему комментарию, та же логика должна работать при использовании чисел, таких как размер продукта, вместо дат как для SQL, так и для панд:

select  
    purch.date as Sold,
    purch.p_Product as Prod,
    purch.Qty,
    purch.Price,
    disc.min_product_size,
    disc.max_product_size,
    disc.Category as Output
from purch 
join disc 
  on purch.product_size between disc.min_product_size and disc.max_product_size
  and purch.p_Product = disc.d_Product
merge_df = (
    purchase_dates.merge(
        dates_of_discount, left_on = "p_Product", right_on = "d_Product"   
    ).query(
        "product_size >= min_product_size & product_size <= max_product_size"
    ).reset_index(drop=True)
    .reindex(
        ["date", "p_Product", "Qty", "Price", "min_product_size", "max_product_size", "Category"],
        axis = "columns"
    ).set_axis(
        ["Sold", "Prod", "Qty", "Price", "min_product_size", "max_product_size", "Output"],
        axis = "columns",
        inplace = False
    )
)

большое спасибо за такое подробное объяснение! это сработало!

Zaur Guliyev 14.05.2022 20:28

Другие вопросы по теме