Добавление новой строки индекса в существующий фрейм данных и сортировка по ней

У меня есть большой кадр данных pandas с данными временных рядов и довольно большим мультииндексом. Указанный индекс содержит различную информацию о временных рядах, такую ​​как, например, местоположение, тип данных и т.д.

Теперь я хочу добавить в индекс новую строку с целым числом (или с плавающей запятой, не имеет большого значения), содержащим расстояние до определенной точки. После этого я хочу отсортировать кадр данных по этому расстоянию.

Я не знаю, как добавить новый уровень индекса и как присвоить новые значения вручную. Кроме того, могут ли панды даже сортировать столбцы после случайного числа на одном из уровней индекса?

Пример

(код из здесь)

header=pd.MultiIndex.from_product([['location1','location2'],['S1','S2','S3']],names=['loc','S'])
df = pd.DataFrame(np.random.randn(5, 6), index=['a','b','c','d','e'], columns = header)

Выглядит так:

loc  location1                      location2                    
S           S1        S2        S3         S1        S2        S3
a     1.530590  0.536364  1.295848   0.422256 -1.853786  1.334981
b     0.275857 -0.848685 -1.212584  -0.464235 -0.855600  0.680985
c    -1.209607  0.265359 -0.695233   0.643896  1.315216 -0.751027
d    -1.591613 -0.178605  0.878567   0.647389 -0.454313 -1.972509
e     1.098193 -0.766810  0.087173   0.714301 -0.886545 -0.826163

То, что я хочу сделать, это на первом этапе добавить некоторые расстояния к каждому столбцу, например location1 S1 add dist 200, location1 S2 add dist 760 и т. д., в результате чего получится следующее:

loc  location1                      location2                    
S           S1        S2        S3         S1        S2        S3
dist       200       760        10       1000       340        70
a     1.530590  0.536364  1.295848   0.422256 -1.853786  1.334981
b     0.275857 -0.848685 -1.212584  -0.464235 -0.855600  0.680985
c    -1.209607  0.265359 -0.695233   0.643896  1.315216 -0.751027
d    -1.591613 -0.178605  0.878567   0.647389 -0.454313 -1.972509
e     1.098193 -0.766810  0.087173   0.714301 -0.886545 -0.826163

А затем сделайте что-то вроде df.sortlevel('dist'), в результате чего

loc location1 location2 location1 location2 location1 location2
S          S3        S3        S1        S2        S2        S1
dist       10        70       200       340       760      1000
a    1.295848  1.334981  1.530590 -1.853786  0.536364  0.422256
b   -1.212584  0.680985  0.275857 -0.855600 -0.848685 -0.464235
…

Так что все это отсортировано по расстоянию для таких вещей, как plt.matshow(df.corr()).

Могут ли панды даже сортировать df после случайного индекса с целым числом? Потому что у меня есть другой кадр данных, в мультииндексе которого уже есть целое число, и здесь some_otherdf.sortlevel('HZB') приводит к TypeError: can only sort by level with a hierarchical index

Изменить:

На данный момент есть два ответа, оба из которых отлично подходят для моего тестового примера. Я думаю, что ответ @Pedro M Duarte может быть более правильным, учитывая, что он использует мультииндекс по назначению. Однако для моих реальных данных потребуется либо много переделки, либо много ввода для 7-уровневого глубокого мультииндекса и 50 рядов данных, что очень подвержено ошибкам. @Nader Hisham проигнорировал мою просьбу остаться в моем мультииндексе, но для этого требуется просто быстро, легко и просто проверить запись простой строки чисел (сэкономив мне много времени), которую я затем могу удалить после сортировки. для других людей с похожим вопросом это может быть иначе.


person JC_CL    schedule 15.11.2015    source источник


Ответы (2)


In [35]:
df.loc['dist' , : ] = [200,760,10,1000,340,70]
df
Out[35]:
loc                location1                 location2
S     S1              S2            S3            S1          S2    S3
a     0.348766  -0.326088   -0.891929   -0.704856   -1.514304   0.611692
b    -0.546026  -0.111232   -1.022104   -1.246002   0.328385    0.576465
c    -0.743512  -0.362791   -0.617021   -0.859157   -0.300368   0.292980
d     0.090178  1.369648    0.171753    -0.411466   0.478654    1.814878
e    -0.380414  -1.568492   -0.432858   1.034861    -0.633563   1.403627
dist 200.000000 760.000000  10.000000   1000.000000 340.000000  70.000000


In [36]:
order = np.argsort(df.loc['dist' , :]).values
order
Out[36]:
array([2, 5, 0, 4, 1, 3], dtype=int64)

In [37]:

df.iloc[: , order]
Out[37]:
loc    location1    location2   location1   location2   location1   location2
S            S3      S3            S1         S2          S2           S1
a     -0.891929    0.611692     0.348766    -1.514304   -0.326088   -0.704856
b     -1.022104    0.576465    -0.546026    0.328385    -0.111232   -1.246002
c     -0.617021    0.292980    -0.743512    -0.300368   -0.362791   -0.859157
d     0.171753     1.814878     0.090178    0.478654    1.369648    -0.411466
e     -0.432858    1.403627     -0.380414   -0.633563   -1.568492   1.034861
dist  10.000000    70.000000    200.000000  340.000000  760.000000  1000.000000

если вы хотите сделать свой индекс dist первым индексом, вы можете сделать следующее

person Nader Hisham    schedule 15.11.2015
comment
Вы просто добавляете новую строку dist в часть данных фрейма данных, но не в индекс. Я не уверен, что это не вызовет у меня проблем с такими вещами, как сюжет сериала. Поиграем с ним немного. - person JC_CL; 15.11.2015
comment
Да, но это такой индекс, как a, b и т. д., а не часть мультииндекса, например loc и S. Когда я делаю df.plot(), он также показывает часть dist. - person JC_CL; 15.11.2015
comment
Хорошо, я могу сделать по-вашему и после сортировки удалить строку droppeddf = dfordered.drop('dist'), чтобы получить правильный сюжет. Кажется немного хакерским, но, возможно, быстрее, чем решение Педро М. Дуарте. Я немного поиграю с обоими и посмотрю, что лучше для меня. - person JC_CL; 15.11.2015
comment
Я укажу, что я стрелял в общность, а не в скорость. Обратите внимание, что я использовал словарь для получения значения dist из значений loc и S. В вашем приложении, возможно, у вас есть функция, которая вычисляет dist, вы могли бы просто подключить эту функцию вместо словаря, который я использовал. - person Pedro M Duarte; 15.11.2015

person    schedule
comment
Выглядит неплохо. Мне нужно немного поиграть с ним, чтобы посмотреть, смогу ли я адаптировать его к моим реальным данным. Не могли бы вы подробнее рассказать о части df.columns = pd.MultiIndex.from_tuples( [(key[0], key[1], distances[key],) for key in index.get_values()], names=[index.get_level_values(0).name, index.get_level_values(1).name, 'dist'] )? Я не уверен на 100%, что именно он делает. - person JC_CL; 15.11.2015
comment
Цель этой строки — создать MultiIndex с нуля, сохранив значения уровня из исходного index и добавив новый уровень для dist. Я использую конструктор from_tuples для MultiIndex. Вы должны передать ему список кортежей, где каждый кортеж содержит информацию для записи в индексе. Вы также передаете ему names, который будет использоваться для установки имен уровней. В этом случае искомое MultiIndex имеет три уровня, поэтому каждый кортеж в списке кортежей имеет len==3, как и список names. - person Pedro M Duarte; 15.11.2015
comment
Чтобы создать список кортежей, необходимых в from_tuples, я использовал понимание списка, перебирая index.get_values(). Здесь index.get_values() дает нам удобное представление исходного MultiIndex в виде списка tuples. Поскольку исходный MultiIndex имеет два уровня, я могу получить доступ к значениям через key[0] и key[1]. - person Pedro M Duarte; 15.11.2015