我如何过滤数据帧的每个子集满足2个条件?



我需要检查销售数据的两个条件:

  1. 按年销售
  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个ID,每个ID有~1000个日期,每个ID有1或2个质量(质量)级别。

需要对ID +质量级别的每个组合执行检查。

在我检查每个ID + Qual之后,我想过滤我的数据帧,以便它只包含通过该检查的ID + Qual组合。

ID: 123 with quality: A

  • 有2020年和2021年的销售❌
  • 至少有4行,数量为>0❌
  • →未通过

ID: 123 with quality: B

  • 有2020年和2021年的销售✅
  • 至少有4行,数量为>0✅
  • →并通过

ID: 456 with quality: A

  • 有2020年和2021年的销售✅
  • 至少有4行,数量为>0❌
  • →未通过

ID: 789 with quality: 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))

我该怎么做?

使用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) & 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 & 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

最新更新