rank is cythonized so should be very fast. And you can pass the same options as df.rank()
here are the docs for rank. As you can see, tie-breaks can be done in one of five different ways via the method argument.
Its also possible you simply want the .cumcount() of the group.
In [12]: df.groupby('group')['value'].rank(ascending=False)
Out[12]:
0 4
1 1
2 3
3 2
4 3
5 2
6 1
7 4
dtype: float64