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-01
和2010-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)
我有以下 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-01
和2010-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)