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

时间:2021-02-17 15:22:58

标签: python pandas date

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

  1. 在特定年份出售
  2. 在特定天数售出,金额 > 0

数据框 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 个质量(qual)级别。

ID+qual level 的每一个组合都需要进行检查。

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

<块引用>

ID:123,质量:A

  • 有 2020 年和 2021 年的销售额 ❌
  • 至少有 4 行,数量 > 0 ❌
  • -> 没有通过
<块引用>

ID:123,质量:B

  • 有 2020 年和 2021 年的销售额✅
  • 至少有 4 行,数量 > 0 ✅
  • -> 确实通过了
<块引用>

ID:456,质量:A

  • 有 2020 年和 2021 年的销售额✅
  • 至少有 4 行,数量 > 0 ❌
  • -> 没有通过
<块引用>

ID: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))

我该怎么做?

2 个答案:

答案 0 :(得分: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) & 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

答案 1 :(得分:-1)

你可以在 Pandas 中更轻松地做到这一点。

要根据条件选择子集,您可以这样做:

subset = df[df["Column"] == value]

您还可以使用 & (AND) 和 | 将条件与 OR、AND 连接起来(或)

所以这看起来像这样:

subset = df[(df["Column"] == value) & (df["OtherColumn"] == othervalue)]

ID: 123 with qual: A 有 2020 年的销售额,但只有 3 行金额 > 0 -> 没有通过

ID: 123 with qual: B 有 2020 年的销售额并且 >= 4 行且金额 > 0 -> 确实通过了

有了上面提到的这两个条件,您可以:

 df[(df["ID"] == 123) & (df["qual"] == "A") & ("2020" in df["date"]) & (df["amount"] >= 4)]