【问题标题】:Calculating difference between first and individual occurence (Python Pandas)计算首次出现和个别出现之间的差异(Python Pandas)
【发布时间】:2021-07-05 03:17:40
【问题描述】:

我们以一个简单的 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”)

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

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

【问题讨论】:

  • Jill 2018中hit100after的数量应该是1?
  • 100 在 2018 年首次出现在法律领域。所以 hit100after 的值只能为 0,因为距离这个“发生事件”已经过去了 0 年。

标签: python python-3.x pandas data-science


【解决方案1】:

您可以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() 那些first100 年由Department 减去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)

【讨论】:

    【解决方案2】:

    你可以试试:

    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 &gt;= 100,所以分配时有NaNs;因此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
    

    【讨论】:

    • +1 我很少看到query,很高兴看到它在使用中。出于好奇,我对其进行了计时,但它似乎比我的版本稍微慢。
    • @tdy 你的更简洁、可读和健壮(例如,当索引有重复时我的失败)并且更快(我尝试了一个数据框,其中多个部门 >= 100;慢两倍然后)。我还有很多东西要学!
    • 非常感谢你们两位,你们帮了我很多,这两种解决方案都实现了我想要实现的目标!这些解释帮助我理解了您所做的事情,并帮助我自己完成了类似的任务。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-02-08
    • 2023-03-12
    • 2022-08-06
    • 2019-05-11
    • 1970-01-01
    相关资源
    最近更新 更多