Как переиндексировать фрейм данных в Pandas?

#python #pandas #dataframe

#python #pandas #фрейм данных

Вопрос:

Я использую pandas Python, и я выполнил некоторые вычисления перекрестных таблиц и конкатенации, и в итоге получился фрейм данных, который выглядит следующим образом:

 ID        5    6    7    8     9    10   11   12    13
Total     87.0  3.0  9.0  6.0  92.0  7.0  3.0  3.0  20.0
Regular   72.0  2.0  8.0  5.0  81.0  7.0  3.0  3.0  18.0
CR        22.0  0.0  0.0  0.0  17.0  0.0  0.0  0.0   3.0
HDG       20.0  0.0  0.0  0.0  24.0  4.0  0.0  0.0   1.0
PPG       30.0  2.0  8.0  5.0  40.0  3.0  3.0  3.0  14.0
Superior  15.0  1.0  1.0  1.0  11.0  0.0  0.0  0.0   2.0
CR         3.0  0.0  0.0  0.0   2.0  0.0  0.0  0.0   0.0
HDG        5.0  1.0  1.0  1.0   4.0  0.0  0.0  0.0   0.0
PPG        7.0  0.0  0.0  0.0   5.0  0.0  0.0  0.0   2.0
  

Проблема в том, что я хочу, чтобы последние 4 строки, которые начинаются с Superior , были местами перед Total строкой. Итак, я просто хочу поменять позиции последних 4 строк на 4 строки, которые начинаются с Regular . Как я могу добиться этого в pandas ? Так что я получаю это:

 ID        5    6    7    8     9    10   11   12    13
Total     87.0  3.0  9.0  6.0  92.0  7.0  3.0  3.0  20.0
Superior  15.0  1.0  1.0  1.0  11.0  0.0  0.0  0.0   2.0
CR         3.0  0.0  0.0  0.0   2.0  0.0  0.0  0.0   0.0
HDG        5.0  1.0  1.0  1.0   4.0  0.0  0.0  0.0   0.0
PPG        7.0  0.0  0.0  0.0   5.0  0.0  0.0  0.0   2.0
Regular   72.0  2.0  8.0  5.0  81.0  7.0  3.0  3.0  18.0
CR        22.0  0.0  0.0  0.0  17.0  0.0  0.0  0.0   3.0
HDG       20.0  0.0  0.0  0.0  24.0  4.0  0.0  0.0   1.0
PPG       30.0  2.0  8.0  5.0  40.0  3.0  3.0  3.0  14.0
  

Комментарии:

1. Вам нужно обобщенное решение или специфичное для данного набора данных?

2. Это больше похоже на замену строк, а не на переиндексацию. На этот вопрос есть множество ответов SO.

Ответ №1:

Более обобщенное решение, Categorical и argsort я знаю, что этот df был упорядочен, поэтому ffill здесь безопасно

 s=df.ID
s=s.where(s.isin(['Total','Regular','Superior'])).ffill()
s=pd.Categorical(s,['Total','Superior','Regular'],ordered=True)
df=df.iloc[np.argsort(s)]
df
Out[188]: 
         ID     5    6    7    8     9   10   11   12    13
0     Total  87.0  3.0  9.0  6.0  92.0  7.0  3.0  3.0  20.0
5  Superior  15.0  1.0  1.0  1.0  11.0  0.0  0.0  0.0   2.0
6        CR   3.0  0.0  0.0  0.0   2.0  0.0  0.0  0.0   0.0
7       HDG   5.0  1.0  1.0  1.0   4.0  0.0  0.0  0.0   0.0
8       PPG   7.0  0.0  0.0  0.0   5.0  0.0  0.0  0.0   2.0
1   Regular  72.0  2.0  8.0  5.0  81.0  7.0  3.0  3.0  18.0
2        CR  22.0  0.0  0.0  0.0  17.0  0.0  0.0  0.0   3.0
3       HDG  20.0  0.0  0.0  0.0  24.0  4.0  0.0  0.0   1.0
4       PPG  30.0  2.0  8.0  5.0  40.0  3.0  3.0  3.0  14.0
  

Ответ №2:

Вот один из способов:

 import numpy as np
df.iloc[1:,:] = np.roll(df.iloc[1:,:].values, 4, axis=0)

       ID     5     6    7    8     9   10   11   12    13
0     Total  87.0  3.0  9.0  6.0  92.0  7.0  3.0  3.0  20.0
1  Superior  15.0  1.0  1.0  1.0  11.0  0.0  0.0  0.0   2.0
2        CR   3.0  0.0  0.0  0.0   2.0  0.0  0.0  0.0   0.0
3       HDG   5.0  1.0  1.0  1.0   4.0  0.0  0.0  0.0   0.0
4       PPG   7.0  0.0  0.0  0.0   5.0  0.0  0.0  0.0   2.0
5   Regular  72.0  2.0  8.0  5.0  81.0  7.0  3.0  3.0  18.0
6        CR  22.0  0.0  0.0  0.0  17.0  0.0  0.0  0.0   3.0
7       HDG  20.0  0.0  0.0  0.0  24.0  4.0  0.0  0.0   1.0
8       PPG  30.0  2.0  8.0  5.0  40.0  3.0  3.0  3.0  14.0
  

Ответ №3:

Для конкретного ответа на этот вопрос просто используйте iloc

 df.iloc[[0,5,6,7,8,1,2,3,4],:]
  

Для более обобщенного решения,

 m = (df.ID.eq('Superior') | df.ID.eq('Regular')).cumsum()
pd.concat([df[m==0], df[m==2], df[m==1]])
  

или

 order = (2,1)
pd.concat([df[m==0], *[df[m==c] for c in order]])
  

где order определяется сопоставление предыдущего порядка с новым порядком.