df2['D'] = np.where((df2.A.shift(-1) == df2.A) & (df2.D.isnull() == True),
    fun2(df2, -1), df2.D)
df2['E'] = np.where((df2.A.shift(1) == df2.A) & (df2.E.shift(1).isnull() ==
    True), fun2(df2, +1), df2.E)
Apply function between subsequent rows in more efficient way with Pandas