计算首次出现和个体出现之间的差异 (Python Pandas)

Calculating difference between first and individual occurence (Python Pandas)

让我们以一个简单的 HR 数据框为例:

Name Year Department Salary New column: hit100after
John 2018 R&D 80 0
Marie 2018 Legal 90 0
Jill 2018 Legal 100 0
John 2019 R&D 85 0
Marie 2019 Legal 95 0
Jill 2019 Legal 105 1
John 2020 R&D 90 0
Marie 2020 Legal 100 2
Jill 2020 Legal 110 2

问题:在同一部门的第一个人达到薪水>=100之后,任何数据集花费了多少时间(以年为单位)? (参见新专栏 'hit100after')

我实际上正在努力实施。我的步骤是按部门分组,找到第一次出现的 salary >= 100 并用新的布尔类型或第二个数据框标记那一年。然后我会计算 >= 100 的个人与其部门中第一次出现之间的差异。

知道如何为大型数据框编写代码吗?

您可以 groupby() Department 并找到 Year.min() 其中 Salary >= 100:

first100 = df.groupby('Department').apply(
    lambda g: g[g.Salary >= 100].Year.min())

# Department
# Legal    2018.0
# R&D         NaN
# dtype: float64

然后 map() first100Department 并从 Year 中减去。结果在Result中进行比较:

df['Result'] = df.Year - df.Department.map(first100)
df.loc[df.Salary < 100, 'Result'] = 0

#     Name  Year Department  Salary  Hit100after  Result
# 0   John  2018        R&D      80            0     0.0
# 1  Marie  2018      Legal      90            0     0.0
# 2   Jill  2018      Legal     100            0     0.0
# 3   John  2019        R&D      85            0     0.0
# 4  Marie  2019      Legal      95            0     0.0
# 5   Jill  2019      Legal     105            1     1.0
# 6   John  2020        R&D      90            0     0.0
# 7  Marie  2020      Legal     100            2     2.0
# 8   Jill  2020      Legal     110            2     2.0

当前答案的时间安排

method %timeit with 1 million rows
this answer 3.07 ms ± 23.1 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
query() answer 4.33 ms ± 354 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

你可以试试:

new_col = (df.query("Salary >= 100")
             .groupby("Department")
             .apply(lambda x: x.Year - x.iloc[0].Year)
             .reset_index(level=0, drop=True)
             .T)
df["hit100after"] = new_col
df["hit100after"] = df["hit100after"].fillna(0).astype(int)

首先我们查看薪水大于 100 的条目 (query),然后按部门对它们进行分组 (groupby),应用一个函数来获取相对于部门中的第一个条目(applyiloc[0]),删除部门名称(reset_index 在第 0 级,dropTrue)并取一个转置 (T) 以确保它是垂直的,以便于与原始 df.

对齐

最后,我们将这个新列分配给 df,但由于我们只选择了带有 Salary >= 100 的列,因此在分配时有 NaN;因此 fillna(0)。由于 NaN 在技术上是一个浮点数,它使系列浮动,所以我们最后转换为 int

获得:

    Name  Year Department  Salary  hit100after
0   John  2018        R&D      80            0
1  Marie  2018      Legal      90            0
2   Jill  2018      Legal     100            0
3   John  2019        R&D      85            0
4  Marie  2019      Legal      95            0
5   Jill  2019      Legal     105            1
6   John  2020        R&D      90            0
7  Marie  2020      Legal     100            2
8   Jill  2020      Legal     110            2