Pandas数据框分组函数计算日期差异

3
我有一个像这样的数据框:
id_a | date

12   | 2020-01-01
12   | 2020-01-02
13   | 2020-01-01
13   | 2020-01-03
14   | 2020-01-01
14   | 2020-01-02
14   | 2020-01-06

我希望能够根据id_a对每个组的最大日期和最小日期进行差异比较,以得到类似以下的结果:

id_a | date       | diff

12   | 2020-01-01 | 1
12   | 2020-01-02 | 1
13   | 2020-01-01 | 2
13   | 2020-01-03 | 2
14   | 2020-01-01 | 5
14   | 2020-01-02 | 5
14   | 2020-01-06 | 5

我正在尝试使用类似这样的东西来实现:
df['diff'] = df.groupby('id_a').apply(lambda x: max(x['date']) - min(x['date']))

但是我有些困难

我是否在正确的道路上?


为了回答这个问题,我们需要将“date”转换为日期格式,但是这些日期的格式无效,它们是哪一年?哪一个值是日,哪一个值是月? - Erfan
@Erfan 的日期格式为 YYYY-MM-dd。 - bAN
1
你的方法是正确的,唯一的问题是你不想聚合行,而是要保持数据框的相同形状,这就是为什么我们需要使用transform而不是apply: df.groupby('id_a')['date'].transform(lambda x: x.max() - x.min()) - Erfan
3个回答

5
您需要使用transform而不是apply。此外,np.ptp也可以实现同样的功能:
 # convert to datetime, ignore if already is
 df['date'] = pd.to_datetime(df['date'])

 df['date_diff'] = df.groupby('id_a')['date'].transform(np.ptp)

输出:

   id_a       date date_diff
0    12 2020-01-01    1 days
1    12 2020-01-02    1 days
2    13 2020-01-01    2 days
3    13 2020-01-03    2 days
4    14 2020-01-01    5 days
5    14 2020-01-02    5 days
6    14 2020-01-06    5 days

更新: 如果您想从date_a获取max和从date_b获取min:

groups = df.groupby('id_a')
min_dates = groups['date_b'].transform('min')
max_dates = groups['date_a'].transform('max')

df['date_diff'] = max_dates - min_dates

奇怪,你用的是哪个 numpy 版本?我尝试了相同的操作,但出现了 DatetimeIndex cannot perform the operation ptp 的错误。 - Erfan
@Erfan numpy '1.16.4',pandas '1.0.1'。另外,为什么你有DatetimeIndex - Quang Hoang
@QuangHoang 非常感谢,如果我需要使用两个不同的列呢?从 date_a 中获取最大日期,从 date_b 中获取最小日期?使用 transform 可以实现吗? - bAN

3
我们可以使用groupby,然后使用mapnp.timedelta来获取以天为单位的数字差异。
s = df.groupby(["id_a"]).agg(min_date=("date", "min"), max_date=("date", "max"))

df['day_diff'] = df["id_a"].map((s["max_date"] - s["min_date"]) / np.timedelta64(1, "D"))

print(df)

   id_a       date  day_diff
0    12 2020-01-01   1.0
1    12 2020-01-02   1.0
2    13 2020-01-01   2.0
3    13 2020-01-03   2.0
4    14 2020-01-01   5.0
5    14 2020-01-02   5.0
6    14 2020-01-06   5.0

0
你可以尝试使用连接操作。但这可能需要你创建额外的数据框架。
df_min = df.groupby('id_a', as_index=False).agg({'date':'min'})
df_max = df.groupby('id_a', as_index=False).agg({'date':'max'})

df2 = pd.merge(df,df_max,on=["id_a"],how="inner")
df2 = pd.merge(df2,df_min,on=["id_a"],how="inner")

df2.columns = ['id_a','date','max_date','min_date']
df2['diff'] = df2['max_date'] - df2['min_date']

df2.head()

   id_a       date   max_date   min_date   diff
0    12 2020-01-01 2020-01-02 2020-01-01 1 days
1    12 2020-01-02 2020-01-02 2020-01-01 1 days
2    13 2020-01-01 2020-01-03 2020-01-01 2 days
3    13 2020-01-03 2020-01-03 2020-01-01 2 days
4    14 2020-01-01 2020-01-06 2020-01-01 5 days

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接