在 Pandas/Dask 数据框中标记最后日期记录
Mark last date record in Pandas/Dask dataframes
在下面的 Dask 数据集中,我有一个 ID 列表(例如 1
和 2
)和日期(最后一列)。
我需要向数据框添加一个新列,如果日期是该 ID 的最后一个,则该列将具有 1
。例如,对于 id 2
,最后日期是 2021-05-01
。如果不是最后一个,则该列应为 None 或 0.
整个集合按 ID 和日期排序,以备不时之需。
我曾经用 SQL 来做到这一点,在 where 子句中有 where NOT EXISTS date > (select max(date)) ...
Pandas and/or Dask 可以吗?
pdf = pd.DataFrame({
'id': [1, 1, 1, 2, 2],
'balance': [150, 140, 130, 280, 260],
'date' : ['2021-03-01', '2021-04-01', '2021-05-01', '2021-01-01', '2021-02-01']
})
print(pdf)
id balance date
0 1 150 2021-03-01
1 1 140 2021-04-01
2 1 130 2021-05-01
3 2 280 2021-04-01
4 2 260 2021-05-01
pdf['date2'] = pd.to_datetime(pdf['date'])
ddf = dd.from_pandas(pdf, npartitions=1)
ddf.compute()
id balance date date2
0 1 150 2021-03-01 2021-03-01
1 1 140 2021-04-01 2021-04-01
2 1 130 2021-05-01 2021-05-01
3 2 280 2021-04-01 2021-04-01
4 2 260 2021-05-01 2021-05-01
例如最终结果将是
id balance date date2 last_date_flag
0 1 150 2021-03-01 2021-03-01 0
1 1 140 2021-04-01 2021-04-01 0
2 1 130 2021-05-01 2021-05-01 1
3 2 280 2021-04-01 2021-04-01 0
4 2 260 2021-05-01 2021-05-01 1
这是我将用于 pandas 的方法,不确定 Dask。
pdf['last_date_flag'] = pdf.groupby('id')['date'].transform(lambda x: x == x.max()).astype(int)
给予
id balance date date2 last_date_flag
0 1 150 2021-03-01 2021-03-01 0
1 1 140 2021-04-01 2021-04-01 0
2 1 130 2021-05-01 2021-05-01 1
3 2 280 2021-01-01 2021-01-01 0
4 2 260 2021-02-01 2021-02-01 1
如果您关心可伸缩性,这在大型数据集上执行得更快:
pdf['last_date_flag'] = (pdf['date'] == pdf['id'].map(pdf.groupby('id')['date'].max().to_dict())).astype(int)
pdf['date'] = pd.to_datetime(pdf['date'])
pdf['last_date_flag']=(pdf.groupby('id')['date'].transform(lambda x:x.max()).eq(pdf['date'])).astype(int)
id balance date last_date_flag
0 1 150 2021-03-01 0
1 1 140 2021-04-01 0
2 1 130 2021-05-01 1
3 2 280 2021-04-01 0
4 2 260 2021-05-01 1
在下面的 Dask 数据集中,我有一个 ID 列表(例如 1
和 2
)和日期(最后一列)。
我需要向数据框添加一个新列,如果日期是该 ID 的最后一个,则该列将具有 1
。例如,对于 id 2
,最后日期是 2021-05-01
。如果不是最后一个,则该列应为 None 或 0.
整个集合按 ID 和日期排序,以备不时之需。
我曾经用 SQL 来做到这一点,在 where 子句中有 where NOT EXISTS date > (select max(date)) ...
Pandas and/or Dask 可以吗?
pdf = pd.DataFrame({
'id': [1, 1, 1, 2, 2],
'balance': [150, 140, 130, 280, 260],
'date' : ['2021-03-01', '2021-04-01', '2021-05-01', '2021-01-01', '2021-02-01']
})
print(pdf)
id balance date
0 1 150 2021-03-01
1 1 140 2021-04-01
2 1 130 2021-05-01
3 2 280 2021-04-01
4 2 260 2021-05-01
pdf['date2'] = pd.to_datetime(pdf['date'])
ddf = dd.from_pandas(pdf, npartitions=1)
ddf.compute()
id balance date date2
0 1 150 2021-03-01 2021-03-01
1 1 140 2021-04-01 2021-04-01
2 1 130 2021-05-01 2021-05-01
3 2 280 2021-04-01 2021-04-01
4 2 260 2021-05-01 2021-05-01
例如最终结果将是
id balance date date2 last_date_flag
0 1 150 2021-03-01 2021-03-01 0
1 1 140 2021-04-01 2021-04-01 0
2 1 130 2021-05-01 2021-05-01 1
3 2 280 2021-04-01 2021-04-01 0
4 2 260 2021-05-01 2021-05-01 1
这是我将用于 pandas 的方法,不确定 Dask。
pdf['last_date_flag'] = pdf.groupby('id')['date'].transform(lambda x: x == x.max()).astype(int)
给予
id balance date date2 last_date_flag
0 1 150 2021-03-01 2021-03-01 0
1 1 140 2021-04-01 2021-04-01 0
2 1 130 2021-05-01 2021-05-01 1
3 2 280 2021-01-01 2021-01-01 0
4 2 260 2021-02-01 2021-02-01 1
如果您关心可伸缩性,这在大型数据集上执行得更快:
pdf['last_date_flag'] = (pdf['date'] == pdf['id'].map(pdf.groupby('id')['date'].max().to_dict())).astype(int)
pdf['date'] = pd.to_datetime(pdf['date'])
pdf['last_date_flag']=(pdf.groupby('id')['date'].transform(lambda x:x.max()).eq(pdf['date'])).astype(int)
id balance date last_date_flag
0 1 150 2021-03-01 0
1 1 140 2021-04-01 0
2 1 130 2021-05-01 1
3 2 280 2021-04-01 0
4 2 260 2021-05-01 1