Попробуйте сделать это в 3 шага:
- найти наиболее распространенный B (как в вашем коде):
df2 = (df.groupby('A', sort=False)['B']).apply(lambda x: x.value_counts().head(1)).reset_index()
построить DataFrame с максимальным D для каждой комбинации A и B
df3 = df.groupby(['A','B']).agg({'D':max}).reset_index()
объедините 2 кадра данных, чтобы найти максимальное D, соответствующее ранее выбранным парам AB
df2.merge(df3, left_on=['A','level_1'], right_on=['A','B'])
Столбец D в результирующем кадре данных будет тем, что вам нужно
A level_1 B_x B_y D
0 a x 2 x 2
1 b w 1 w 4