Как бы я разделить индекс на несколько индексов следующим образом? - PullRequest
0 голосов
/ 03 апреля 2019

У меня большой файл Excel с тысячами строк и около 100 столбцов.Проблема в том, что столбец индекса включает около 50 показателей (продажи, дома, люди) и 70 компаний.Что я действительно хочу, так это иметь два индекса, один для метрик, а другой для компаний.рассмотрим следующий код в качестве примера:

import pandas as pd
import numpy as np
idx=['Sales','Company 1', 'Company 2', 'Company 3','Houses','Company 1',     
'Company 2', 'Company 3','People','Company 1', 'Company 2', 'Company 3']
dt=['2010','2011','2012','2013']
data = np.array([np.arange(12)]*4).T
df = pd.DataFrame(data, index=idx, columns=dt)
df.iloc[4,::]=0;df.iloc[8,::]=0 
df

результат выглядит как прикрепленное изображение enter image description here

Мой вопрос заключается в том, как мне манипулировать кадром данных, чтобыПервый индекс будет «Продажи», «Продажи», «Продажи» .... а вторым индексом будет «Компания 1», «Компания 2», «Компания 3» для каждой метрики («Продажи», «Дома» и т. д.)?

1 Ответ

2 голосов
/ 03 апреля 2019

Настройка

c = 3 # number of companies
metrics = df.index[::c+1]
companies = df.index[1:c+1]

Этот ответ просто берет метрики, находит компании, создает MultiIndex и переназначает. Он работает с одним допущением: компании находятся в одинаковом порядке между каждой метрикой :

idx = pd.MultiIndex.from_product([metrics, companies])
df.drop(df.index[::c+1]).set_index(idx)

                  2010  2011  2012  2013
Sales  Company 1     1     1     1     1
       Company 2     2     2     2     2
       Company 3     3     3     3     3
Houses Company 1     5     5     5     5
       Company 2     6     6     6     6
       Company 3     7     7     7     7
People Company 1     9     9     9     9
       Company 2    10    10    10    10
       Company 3    11    11    11    11

Если вы не можете гарантировать это ограничение, оно становится немного сложнее:

u = pd.Series(df.index)
idx = u.groupby(u.index // (c + 1)).transform('first') + '|' + u
f = df.drop(df.index[::c+1])
f[['metric', 'company']] = (idx.drop(idx.index[::c+1])
                               .str.split('|', expand=True).set_index(f.index))    
f.set_index(['metric', 'company'])

                  2010  2011  2012  2013
metric company
Sales  Company 1     1     1     1     1
       Company 2     2     2     2     2
       Company 3     3     3     3     3
Houses Company 1     5     5     5     5
       Company 2     6     6     6     6
       Company 3     7     7     7     7
People Company 1     9     9     9     9
       Company 2    10    10    10    10
       Company 3    11    11    11    11
...