#python #pandas #date
#python #панды #Дата
Вопрос:
Мне нужно проверить 2 условия для данных о продажах:
- был продан в определенные годы
- было продано за определенное количество дней с количеством> 0
Dataframe df:
date | id | qual | amount
2020-09-01 | 123 | A | 100
2020-09-02 | 123 | A | 0
2020-09-03 | 123 | A | 90
2020-09-04 | 123 | A | 80
2020-09-01 | 123 | B | 8
2020-09-02 | 123 | B | 6
2020-09-03 | 123 | B | 4
2020-09-04 | 123 | B | 2
2021-02-01 | 123 | B | 18
2020-02-01 | 456 | A | 96
2021-02-02 | 456 | A | 90
2021-01-01 | 789 | A | 30
2021-01-02 | 789 | A | 31
2021-01-03 | 789 | A | 32
2021-01-04 | 789 | A | 29
Фрейм данных имеет 10_000 идентификаторов с ~ 1000 датами для каждого идентификатора и 1 или 2 уровня качества (qual) на идентификатор.
Проверка должна выполняться для каждой комбинации ID уровень качества.
После проверки каждого ID Qual я хочу отфильтровать свой фрейм данных так, чтобы он содержал только комбинации IDs Qual, которые прошли эту проверку.
ИДЕНТИФИКАТОР: 123 с качеством: A
- в продаже есть 2020 и 2021 год ❌
- имеет не менее 4 строк с количеством> 0 ❌
- -> не проходит
ИДЕНТИФИКАТОР: 123 с качеством: B
- в продаже есть 2020 и 2021 год ✅
- имеет не менее 4 строк с количеством> 0 ✅
- -> проходит
ИДЕНТИФИКАТОР: 456 с качеством: A
- в продаже есть 2020 и 2021 год ✅
- имеет не менее 4 строк с количеством> 0 ❌
- -> не проходит
ИДЕНТИФИКАТОР: 789 с качеством: A
- в продаже есть 2020 и 2021 год ❌
- имеет не менее 4 строк с количеством> 0 ✅
- -> не проходит
Результат должен выглядеть следующим образом:
date | id | qual | amount
2020-09-01 | 123 | B | 8
2020-09-02 | 123 | B | 6
2020-09-03 | 123 | B | 4
2020-09-04 | 123 | B | 2
2021-02-01 | 123 | B | 18
Мой код до сих пор:
required_sales_years= [2020, 2021]
required_sales_days = 4
has_required_sales = []
for id in df["id"].unique().tolist():
for qual in df["qual"].unique().tolist():
temp = df.query(
"id== @id and qual == @qual and amount > 0"
)
sales_years = temp["date"].dt.year.unique().tolist()
check_sales_year = all(item in sales_years for item in required_sales_years)
check_sales_days = len(temp.index) >= required_sales_days
if check_sales_year and check_sales_days:
has_required_sales.append((id, qual))
Как я могу это сделать?
Ответ №1:
Используется groupby().transform
для подсчета действительных продаж:
required_sale_years = [2020, 2021]
required_sales_days = 4
# intermediate variables
df['year'] = df.date.dt.year
df['valid'] = df['year'].isin(required_sales_years) amp; df['amount'].gt(0)
# groupby
groups = df.groupby(['id','qual'])
has_years = groups['year'].transform(lambda x: set(required_sales_years).issubset(set(x)))
valid_sales = groups['valid'].transform('sum') >= required_sales_days
output = df[has_years amp; valid_sales]
Вывод:
date id qual amount year valid
4 2020-09-01 123 B 8 2020 True
5 2020-09-02 123 B 6 2020 True
6 2020-09-03 123 B 4 2020 True
7 2020-09-04 123 B 2 2020 True
8 2021-02-01 123 B 18 2021 True
Комментарии:
1. Это хорошо, но вам не хватает условия в поле даты, чтобы проверить, что год 2020
2. Я думаю, вам нужно каким-то образом включить год в группу и вернуть исходную дату в индекс
3. @Robert Я вижу, пропустил эту часть. Обновлен ответ. Спасибо.
4. Спасибо, но вы проверяете только, есть ли test[«date»].dt.year.isin(required_sale_years), который пройдет, если продажи будут только в 2020 году.
5. Я не понимаю вашу точку зрения? Разве вы не считаете только (положительные) продажи за эти годы? Или положительные продажи в другие годы также учитываются?