pandas 中如何在 Groupby 和 Concat 之后分配数据

How to Assign Data after Groupby and Concat in pandas

我是 python 的新手。我有一个巨大的 dataframe,其中包含数百万行和 ID。我的数据如下所示:

Time    ID  X   Y
8:00    A   23  100
9:00    B   24  110
10:00   B   25  120
11:00   C   26  130
12:00   C   27  140
13:00   A   28  150
14:00   A   29  160
15:00   D   30  170
16:00   C   31  180
17:00   B   32  190
18:00   A   33  200
19:00   C   34  210
20:00   A   35  220
21:00   B   36  230
22:00   C   37  240
23:00   B   38  250

我把数据按id和时间排序了

Time    ID  X   Y
8:00    A   23  100
13:00   A   28  150
14:00   A   29  160
18:00   A   33  200
20:00   A   35  220
9:00    B   24  110
10:00   B   25  120
17:00   B   32  190
21:00   B   36  230
23:00   B   38  250
11:00   C   26  130
12:00   C   27  140
16:00   C   31  180
19:00   C   34  210
22:00   C   37  240
15:00   D   30  170

我只想选择 "The first and the last" 的 id 并删除其余的。结果如下所示:

Time    ID  X   Y
8:00    A   23  100
20:00   A   35  220
9:00    B   24  110
23:00   B   38  250
11:00   C   26  130
22:00   C   37  240
15:00   D   30  170

我使用了这个代码:

df = pd.read_csv("data.csv")
g = df.groupby('ID')
g_1 = pd.concat([g.head(1),g.tail(1)]).drop_duplicates().sort_values('ID').reset_index(drop=True)
g_1.to_csv('result.csv')

但我想在新列中将每一行分配或注释为 "first" 和 "last"。
我的预期结果如下所示:

Time    ID  X   Y   Annotation
8:00    A   23  100 First
20:00   A   35  220 Last
9:00    B   24  110 First
23:00   B   38  250 Last
11:00   C   26  130 First
22:00   C   37  240 Last
15:00   D   30  170 

有人可以帮我解决这个问题吗?请多多指教谢谢

排序后

不需要 groupby 使用 drop_duplicates
df=pd.concat([df.drop_duplicates(['ID']).assign(sign='first'),df.drop_duplicates(['ID'],keep='last').assign(sign='last')]).sort_values('ID')
df
     Time ID   X    Y   sign
0    8:00  A  23  100  first
4   20:00  A  35  220   last
5    9:00  B  24  110  first
9   23:00  B  38  250   last
10  11:00  C  26  130  first
14  22:00  C  37  240   last
15  15:00  D  30  170  first
15  15:00  D  30  170   last

您可以使用 groupby agg,first 和 last。非常适合列注释。作为奖励,这将适用于原始数据框,因此无需排序

df3.groupby('ID').agg(['first', 'last']).stack().reset_index().rename(columns = {'level_1': 'Annotation'})

    ID  Annotation  Time    X   Y
0   A   first   8:00    23  100
1   A   last    20:00   35  220
2   B   first   9:00    24  110
3   B   last    23:00   38  250
4   C   first   11:00   26  130
5   C   last    22:00   37  240
6   D   first   15:00   30  170
7   D   last    15:00   30  170

尝试:

df.groupby('ID').agg(['first','last'])\
  .stack(1).reset_index()\
  .rename(columns={'level_1':'Annotation'})

输出:

  ID Annotation   Time   X    Y
0  A      first   8:00  23  100
1  A       last  20:00  35  220
2  B      first   9:00  24  110
3  B       last  23:00  38  250
4  C      first  11:00  26  130
5  C       last  22:00  37  240
6  D      first  15:00  30  170
7  D       last  15:00  30  170