我有一个数据框架,如下图所示
Session slot_num ID prob
s1 1 A 0.2
s1 2 B 0.9
s1 2 B 0.4
s1 3 C 0.7
s1 4 D 0.8
s1 4 D 0.3
s1 5 E 0.6
s1 6 F 0.5
s1 7 G 0.7
s2 1 A1 0.6
s2 2 B1 0.5
s2 3 C1 1.1
s2 3 C1 0.6
s2 4 D1 0.7
s2 5 E1 0.6
s2 6 F1 0.7
s2 7 G1 1.2
s2 7 G1 0.7
其排序如下图所示
df = df.sort_values(['Session', 'slot_num'], ascending=True)
然后我想创建一个新的列,叫做overbook,如下所述。
如果我们有多个相同的Session和slot_num,第一个是'yes',第二个是'booking',如果有更多的除了第一个以外的其他都是bookingelse: df['overbook']='no'
同时将第二行的ID替换为'TBF'。
预期的输出。
Session slot_num ID prob overbook
s1 1 A 0.2 no
s1 2 B 0.9 yes
s1 2 TBF 0.4 booking
s1 3 C 0.7 no
s1 4 D 0.8 yes
s1 4 TBF 0.3 booking
s1 5 E 0.6 no
s1 6 F 0.5 no
s1 7 G 0.7 no
s2 1 A1 0.6 no
s2 2 B1 0.5 no
s2 3 C1 1.1 yes
s2 3 TBF 0.6 booking
s2 4 D1 0.7 no
s2 5 E1 0.6 no
s2 6 F1 0.7 no
s2 7 G1 1.2 yes
s2 7 TBF 0.7 booking
我的想法是使用 Series.map
计数器 GroupBy.cumcount
,但只适用于重复排列的行,所以使用了 numpy.where
与 DataFrame.duplicated
:
df = df.sort_values(['Session', 'slot_num'], ascending=True)
m = df.duplicated(['Session', 'slot_num'], keep=False)
s = df.groupby(['Session', 'slot_num']).cumcount()
d = {0:'yes', 1:'booking'}
df['overbook'] = np.where(m, s.map(d), 'no')
print (df)
Session slot_num ID prob overbook
0 s1 1 A 0.2 no
1 s1 2 B 0.9 yes
2 s1 2 B 0.4 booking
3 s1 3 C 0.7 no
4 s1 4 D 0.8 yes
5 s1 4 D 0.3 booking
6 s1 5 E 0.6 no
7 s1 6 F 0.5 no
8 s1 7 G 0.7 no
9 s2 1 A1 0.6 no
10 s2 2 B1 0.5 no
11 s2 3 C1 1.1 yes
12 s2 3 C1 0.6 booking
13 s2 4 D1 0.7 no
14 s2 5 E1 0.6 no
15 s2 6 F1 0.7 no
16 s2 7 G1 1.2 yes
17 s2 7 G1 0.7 booking