Home > Software design >  Reverse the order of the rows by chunks of n rows
Reverse the order of the rows by chunks of n rows

Time:01-08

Consider the following sequence:

df = pd.DataFrame(np.random.randint(0,100,size=(100, 4)), columns=list('ABCD'))

which produces:

     A   B   C   D
0   56  83  99  46
1   40  70  22  51
2   70   9  78  33
3   65  72  79  87
4    0   6  22  73
..  ..  ..  ..  ..
95  35  76  62  97
96  86  85  50  65
97  15  79  82  62
98  21  20  19  32
99  21   0  51  89

I can reverse the sequence with the following command:

df.iloc[::-1]

That gives me the following result:

     A   B   C   D
99  21   0  51  89
98  21  20  19  32
97  15  79  82  62
96  86  85  50  65
95  35  76  62  97
..  ..  ..  ..  ..
4    0   6  22  73
3   65  72  79  87
2   70   9  78  33
1   40  70  22  51
0   56  83  99  46

How would I rewrite the code if I wanted to reverse the sequence every nth row, e.g. every 4th row?

CodePudding user response:

IIUC, you want to reverse by chunk (3, 2, 1, 0, 8, 7, 6, 5…):

One option is to use groupby with a custom group:

N = 4

group = df.index//N

# if the index is not a linear range
# import numpy as np
# np.arange(len(df))//N

df.groupby(group).apply(lambda d: d.iloc[::-1]).droplevel(0)

output:

     A   B   C   D
3   45  33  73  77
2   91  34  19  68
1   12  25  55  19
0   65  48  17   4
7   99  99  95   9
..  ..  ..  ..  ..
92  89  68  48  67
99  99  28  52  87
98  47  49  21   8
97  80  18  92   5
96  49  12  24  40

[100 rows x 4 columns]

CodePudding user response:

A very fast method, based only on indexing is to use numpy to generate a list of the indices reversed by chunk:

import numpy as np

N = 4
idx = np.arange(len(df)).reshape(-1, N)[:, ::-1].ravel()
# array([ 3,  2,  1,  0,  7,  6,  5,  4, 11, ...])

# slice using iloc
df.iloc[idx]
  •  Tags:  
  • Related