Pandas dataframe apply 参考上一行来计算差异

Pandas dataframe apply refer to previous row to calculate difference

我有以下 pandas 数据框,其中包含 2 列(已简化)。第一列包含[=36​​=]玩家姓名,第二列包含[=36​​=]日期(datetime 个对象):

  player    date
  A         2010-01-01
  A         2010-01-09
  A         2010-01-11
  A         2010-01-15
  B         2010-02-01
  B         2010-02-10
  B         2010-02-21
  B         2010-02-23

我想添加一列 diff,它表示每个玩家 天数的时差。结果应如下所示:

  player    date            diff
  A         2010-01-01      0
  A         2010-01-09      8
  A         2010-01-11      2
  A         2010-01-15      4
  B         2010-02-01      0
  B         2010-02-10      9
  B         2010-02-21      11
  B         2010-02-23      2

第一行有 0 差异,因为没有更早的日期。第二行显示8,因为2010-01-012010-01-09相差八天。

问题不是计算两个 datetime 对象之间的天差。我只是不确定如何添加新列。我知道,我必须先制作 groupby (df.groupby('player')),然后使用 apply(或者 transform?)。但是,我被卡住了,因为为了计算差异,我需要参考应用函数中的 上一行 ,我不知道该怎么做,如果可能的话全部.

非常感谢。

更新: 在尝试了下面提出的两种解决方案之后,我发现它们不适用于我的代码。很头疼之后,我发现我的数据有重复的索引。因此,在我发现我有重复的索引后,一个简单的 df.reset_index() 解决了我的问题并且建议的解决方案有效。由于这两种解决方案都有效,但我只能将其中一种标记为正确,因此我将选择 more concise/shorter 解决方案。不过还是谢谢你们!

你可以简单地写:

df['difference'] = df.groupby('player')['date'].diff().fillna(0)

这给出了具有正确值的新 timedelta 列:

  player       date  difference
0      A 2010-01-01      0 days
1      A 2010-01-09      8 days
2      A 2010-01-11      2 days
3      A 2010-01-15      4 days
4      B 2010-02-01      0 days
5      B 2010-02-10      9 days
6      B 2010-02-21     11 days
7      B 2010-02-23      2 days

(我使用名称 "difference" 而不是 "diff" 来区分名称和方法 diff。)

如果您想手动实施,另一种方法是执行以下操作

def date_diff(df):
    df['difference'] = df['date'] - df['date'].shift()
    df['difference'].fillna(0 ,inplace = True)
    return df

In [30]:
df_final = df.groupby(df['player']).apply(date_diff)
df_final
Out[30]:
player  date    difference
A   2010-01-01  0 days
A   2010-01-09  8 days
A   2010-01-11  2 days
A   2010-01-15  4 days
B   2010-02-01  0 days
B   2010-02-10  9 days
B   2010-02-21  11 days
B   2010-02-23  2 days

shift()是一个很好的功能,但是,如果您需要避免数据重复,我建议使用以下方法。

def date_diff(row):
    index = df.index.get_loc(row.name)
    if index == 0:
        return np.nan
    prev_row = df.iloc[index - 1]
    return row['date'] - prev_row['date']

df['difference'] = df.apply(date_diff, axis=1)