df.groupby.diff()
グループ数が多いときに上記のようにすると結構遅い。groupbyはapplyしたあとに返り値がスカラーなのかサイズのそろったベクトルなのか等を型判定してうまい具合につなげて返してくれるが、この部分がbottle neckになっているのかも。pandasが列指向型というのもあるかも。
index名を'name'、columns名を'value'とでもして、
temp_df=pd.concat([df.reset_index(), df.reset_index().shift(1).rename(columns=lambda s:s+'_shift')], axis=1)
df_with_diff=temp_df.loc[(temp_df['name']==temp_df['name_shift']), slice(None)]
df_with_diff['diff']=df_with_diff['value']-df_with_diff['value_shift']
こんな感じにすると高速化できる。1行ずらしたdataframeをconcatして、name列が同じ行だけを抜き出して差を取る形。dfは差分を取りたい順番に事前にソートしてあるものとします。
なお、reset_indexで出現した'name', 'name_diff'カラムを取り除きたければ、以下。
df_with_diff[slice(None), ~(temp_df.columns.str.startwith('name')]