соответствие pandas на уровне иерархического индекса

#python #pandas #indexing

#python #pandas #индексирование

Вопрос:

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

Вот пример игрушки:

 import numpy as np
import pandas as pd

arrays = [np.hstack([ ['one']*3, ['two']*3]), ['Dog', 'Bird', 'Cat']*2]
columns = pd.MultiIndex.from_arrays(arrays, names=['foo', 'bar'])

df = pd.DataFrame(np.zeros((3,6)),columns=columns,
                  index=pd.date_range('20000103',periods=3))

df['one'] = pd.DataFrame({'Bird' : np.ones(3)*2,
                          'Dog' : np.ones(3),
                          'Cat' : np.ones(3)*3},
                          index= pd.date_range('20000103',periods=3))
df['two'] = pd.DataFrame({'Dog' : np.ones(3)*4,
                          'Bird' : np.ones(3)*5,
                          'Cat' : np.ones(3)*6,},
                          index= pd.date_range('20000103',periods=3))
  

Результат таков:

 foo            one          two
bar        Dog Bird Cat Dog Bird Cat
2000-01-03 2   3    1   5   6    4
2000-01-04 2   3    1   5   6    4
2000-01-05 2   3    1   5   6    4
  

Где я ожидал бы:

 foo            one          two
bar        Dog Bird Cat Dog Bird Cat
2000-01-03 1   2    3   4   5    6
2000-01-04 1   2    3   4   5    6
2000-01-05 1   2    3   4   5    6
  

Проблема в том, что фрейм отсортирован в алфавитном порядке по столбцам. Затем он вставляется в больший фрейм с отсортированными значениями, и тогда метка столбца становится неправильной.

Итак, мой вопрос в том, есть ли способ убедиться, что метки столбцов совпадают?

Ответ №1:

Это должно выровняться по уровням (хотя существует некоторая двусмысленность, как это сделать, например, на каком уровне). https://github.com/pydata/pandas/issues/7655

Вы должны сделать это вместо:

 In [10]: one = pd.DataFrame({'Bird' : np.ones(3)*2,
                             'Dog' : np.ones(3),
                             'Cat' : np.ones(3)*3},
                             index= pd.date_range('20000103',periods=3))

In [11]: two = pd.DataFrame({'Dog' : np.ones(3)*4,
   ....:                     'Bird' : np.ones(3)*5,
   ....:                     'Cat' : np.ones(3)*6,},
   ....:                     index= pd.date_range('20000103',periods=3))

In [12]: one
Out[12]: 
            Bird  Cat  Dog
2000-01-03     2    3    1
2000-01-04     2    3    1
2000-01-05     2    3    1

In [13]: two
Out[13]: 
            Bird  Cat  Dog
2000-01-03     5    6    4
2000-01-04     5    6    4
2000-01-05     5    6    4

In [14]: concat([one,two],keys=['one','two'],axis=1)
Out[14]: 
             one             two          
            Bird  Cat  Dog  Bird  Cat  Dog
2000-01-03     2    3    1     5    6    4
2000-01-04     2    3    1     5    6    4
2000-01-05     2    3    1     5    6    4
  

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

1. В итоге я просто добавил columns = df [‘one’], как предложено ниже. Я думал, что это будет сделано автоматически. Возможно, принудительное выполнение этого назначения — лучший способ исправить это. По крайней мере, это выдало бы ошибку, если бы они не совпадали.

Ответ №2:

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

 In [50]: df['one'] = pd.DataFrame({'Bird' : np.ones(3)*2,
                                   'Dog' : np.ones(3),
                                   'Cat' : np.ones(3)*3},
                                   index= pd.date_range('20000103',periods=3))
                                   [df['one'].columns]

In [51]: df['two'] = pd.DataFrame({'Dog' : np.ones(3)*4,
                                   'Bird' : np.ones(3)*5,
                                   'Cat' : np.ones(3)*6,},
                                   index= pd.date_range('20000103',periods=3))
                                   [df['two'].columns]

In [52]: df
Out[52]: 
foo         one             two           
bar         Dog  Bird  Cat  Dog  Bird  Cat
2000-01-03    1     2    3    4     5    6
2000-01-04    1     2    3    4     5    6
2000-01-05    1     2    3    4     5    6