Reputation: 188
constructed a dataframe by concatenating several dataframes with the keys [a,b,c] as Index
+-------+----------+----------+
| Index | IndexPos | SomeData |
+-------+----------+----------+
| a | 1 | some1 |
| | 2 | some2 |
| | 3 | some3 |
| b | 1 | some1 |
| | 2 | some2 |
| | 3 | some3 |
| c | 1 | some1 |
| | 2 | some2 |
| | 3 | some3 |
+-------+----------+----------+
and now want slice it down to the last 2 elements like:
df.groupby(df.index.levels[0].name).tail(2)
After that I want to recount the remaining elements IndexPos to get this:
+-------+----------+----------+
| Index | IndexPos | SomeData |
+-------+----------+----------+
| a | 1 | some2 |
| | 2 | some3 |
| b | 1 | some2 |
| | 2 | some3 |
| c | 1 | some2 |
| | 2 | some3 |
+-------+----------+----------+
Is there a way to do this, or do I have to slice it before concatenating?
Upvotes: 1
Views: 241
Reputation: 71707
First groupby
on level=0
and get the last two rows from each group using tail
, then using groupby
+ cumcount
on sliced dataframe create a sequential counter for each group and set it as new index at level=1
:
d = df.groupby(level=0).tail(2)
d = d.droplevel(1).set_index(d.groupby(level=0).cumcount().add(1), append=True)
Or using factorize
in place of groupby
+ cumcount
inspired by @anky's solution:
d = df.groupby(level=0).tail(2)
d = d.droplevel(1).set_index(d.index.get_level_values(1).factorize()[0] + 1, append=True)
Result:
print(d)
SomeData
Index
a 1 some2
2 some3
b 1 some2
2 some3
c 1 some2
2 some3
Upvotes: 2