链式方法分组和计算 Pandas DataFrame 中的差异

Chain method grouping and calculating differences in a Pandas DataFrame

提问人:R_Student 提问时间:9/20/2023 最后编辑:halferR_Student 更新时间:10/15/2023 访问量:49

问:

我有一个具有以下结构的 Pandas DataFrame:

import pandas as pd

data = {
    'glob_order': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11],
    'trans': ['A', 'A', 'A', 'A', 'B', 'B', 'B', 'C', 'C', 'C', 'C'],
    'chain': [1, 1, 2, 2, 1, 1, 2, 1, 1, 2, 2],
    'date': ['1/08/2023', '2/08/2023', '3/08/2023', '4/08/2023', '5/08/2023', '6/08/2023', '7/08/2023', '8/08/2023', '9/08/2023', '10/08/2023', '11/08/2023']
}

df = pd.DataFrame(data)

# Convert 'date' column to datetime
df['date'] = pd.to_datetime(df['date'], format='%d/%m/%Y')

print(df)

我想执行两个操作:

  • 按“trans”和“chain”列对 DataFrame 进行分组,然后从每个组中选择第一行。
  • 创建一个名为“delta”的新列,该列表示每个组中当前日期与上一个日期之间的天数差。

我尝试了以下代码:

(df
.groupby(['trans', 'chain'])
.first()
.assign(
 delta=lambda x: (x['date'] - x['date'].shift(1)).dt.total_seconds() / (60*60*24),
 ).reset_index()
 )

但是,我得到的输出并不像预期的那样。它似乎在每个单独组的第一个增量计算中插入 NaN,这不是我想要的

反式 glob_order 日期 三角洲
一个 1 1 2023-08-01
一个 2 3 2023-08-03 2.0
B 1 5 2023-08-05 2.0
B 2 7 2023-08-07 2.0
C 1 8 2023-08-08 1.0
C 2 10 2023-08-10 2.0

我想知道为什么会发生这种情况,以及我需要做什么才能获得所需的输出。

这是我想要的输出

反式 glob_order 日期 三角洲
一个 1 1 2023-08-01
一个 2 3 2023-08-03 2.0
B 1 5 2023-08-05
B 2 7 2023-08-07 2.0
C 1 8 2023-08-08
C 2 10 2023-08-10 2.0

我正在寻找一种解决方案,使用类似于链接的方法来提高清晰度和可读性,因为我对 Python 非常陌生。

Python pandas 方法链接

评论


答:

1赞 Andrej Kesely 9/20/2023 #1

如果我理解正确,你想要:

  • 作为第一步,按 / 分组,获取第一行"trans""chain"
  • 作为第二步,分组依据并得到天数之间的差值"trans"

我不认为简单的链接是可能的,但你可以使用运算符(但为了可读性,我建议将其拆分为两个单独的命令)::=

df = (df := df.groupby(["trans", "chain"], as_index=False).first()).assign(
    delta=df.groupby("trans")["date"].diff().dt.days
)
print(df)

指纹:

  trans  chain  glob_order       date  delta
0     A      1           1 2023-08-01    NaN
1     A      2           3 2023-08-03    2.0
2     B      1           5 2023-08-05    NaN
3     B      2           7 2023-08-07    2.0
4     C      1           8 2023-08-08    NaN
5     C      2          10 2023-08-10    2.0

评论

0赞 R_Student 9/20/2023
嘿安德烈!我记得你在其他问题上帮了我很多!!是的,你是对的,我忘记了后来 Trans 单独进行了摸索作为第二步,你能解释一下 : = 是做什么的吗?,以及你为什么选择 as_index=False 我发誓 Python 充满了神秘感,非常感谢我的男人
1赞 Andrej Kesely 9/20/2023
@R_Student我已添加到第一个不调用后一个。as_index=False.groupby.reset_index()
1赞 mozway 9/20/2023
为了使用两个答案中最好的答案,我会采用您的方法和 () 中的 lambda,海象在这里有点奇怪。如果你有很长的命令链,那将是不切实际的。assigndelta=lambda d: d.groupby("trans")["date"].diff().dt.days
2赞 Panda Kim 9/20/2023 #2

与 Groupby 和 Lambda 功能一起使用。assign

(df.groupby(['trans', 'chain']).first()
   .assign(delta=lambda x: x.groupby(level=0)['date'].diff().dt.days)
   .reset_index())

输出:

   trans    chain   glob_order  date        delta
0   A       1       1           2023-08-01  NaN
1   A       2       3           2023-08-03  2.0
2   B       1       5           2023-08-05  NaN
3   B       2       7           2023-08-07  2.0
4   C       1       8           2023-08-08  NaN
5   C       2       10          2023-08-10  2.0

评论

0赞 R_Student 9/20/2023
哦,天哪,这太酷了,你能解释一下 x.groyby 0 级吗?你的代码到底是怎么回事!
0赞 Panda Kim 9/20/2023
首先,运行代码。然后,在结果中使用 level = 0() 的 group by index。df.groupby(['trans', 'chain']).first()trans