2014-12-11 5 views
3

Данные в Excel листов сохраняется следующим образом:Панды: синтаксический объединить столбцы заголовков из Excel

Area  |   Product1  |  Product2  |  Product3 
      |  sales|sales.Value| sales |sales.Value | sales |sales.Value 
    Location1 | 20  | 20000  |  25 | 10000  | 200 | 100 
    Location2 | 30  | 30000  |  3 | 12300  | 213 | 10 

название продукта является слияние 2-х ячеек двух строк «нет продаж» и «значение продаж» для каждой из 1000 или около того областей за данный месяц. Аналогичным образом для каждого месяца существуют отдельные файлы за последние 5 лет. Кроме того, новые продукты были добавлены и удалены в разные месяцы. Так другой месяц файл может выглядеть следующим образом:

Area  |   Product1  |  Product4  |  Product3 

Может форум предложить лучший способ читать эти данные с помощью панд? я не могу использовать индекс, так как столбцы продукта отличаются каждый месяц

В идеале я хотел бы преобразовать первоначальный формат выше:

Area  | Product1.sales|Product1.sales.Value| Product2.sales |Product2.sales.Value | 
Location1 | 20   | 20000    | 25    | 10000    | 
Location2 | 30   | 30000    | 3    | 12300    | 

import pandas as pd 
xl_file = read_excel("file path", skiprow=2, sheetname=0) 
/* since the first two rows are always blank */ 


        0   1  2    3      4 
     0   NaN   NaN  NaN  Auto loan     NaN 
     1 Branch Code Branch Name Region No of accounts Portfolio Outstanding 
     2   3000  Name1 Central    0      0 
     3   3001  Name2 Central    0      0 

Я хочу, чтобы преобразовать его до Auto loan.No of account, Auto loan.Portfolio Outstanding в качестве заголовков.

+0

Можете ли вы опубликовать пример того, как выглядит DataFrame при загрузке файла с помощью 'df = pd.read_excel (...)'? Что такое 'df.index' и' df.columns'? – unutbu

+0

thx, я понял это. В файлах 5x12 = 60 всего 4 комбинации мета-столбцов. Поэтому я просто использую словарь для всех 4 комбинаций. –

+0

@unutbu: мой EDIT ясно выражает мое требование? ваша помощь приветствуется, поскольку мое решение не изящно. –

ответ

7

Пусть ваш DataFrame является df:

import numpy as np 
import pandas as pd 

nan = np.nan 
df = pd.DataFrame([ 
    (nan, nan, nan, 'Auto loan', nan) 
    , ('Branch Code', 'Branch Name', 'Region', 'No of accounts' 
     , 'Portfolio Outstanding') 
    , (3000, 'Name1', 'Central', 0, 0) 
    , (3001, 'Name2', 'Central', 0, 0) 
]) 

так, что это выглядит следующим образом:

   0   1  2    3      4 
0   NaN   NaN  NaN  Auto loan     NaN 
1 Branch Code Branch Name Region No of accounts Portfolio Outstanding 
2   3000  Name1 Central    0      0 
3   3001  Name2 Central    0      0 

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

df.iloc[0:2] = df.iloc[0:2].fillna(method='ffill', axis=1) 

Следующая заполнить оставшиеся NaNs с пустыми строками:

df.iloc[0:2] = df.iloc[0:2].fillna('') 

Теперь соедините два ряда вместе с . и присвоить, что в качестве значения уровня столбца:

df.columns = df.iloc[0:2].apply(lambda x: '.'.join([y for y in x if y]), axis=0) 

И, наконец, , удалите первые два ряда:

df = df.iloc[2:] 

Это дает

Branch Code Branch Name Region Auto loan.No of accounts \ 
2  3000  Name1 Central      0 
3  3001  Name2 Central      0 

    Auto loan.Portfolio Outstanding 
2        0 
3        0 

В качестве альтернативы, вы можете создать столбец мультииндексных вместо создания плоского индекса столбца:

import numpy as np 
import pandas as pd 

nan = np.nan 
df = pd.DataFrame([ 
    (nan, nan, nan, 'Auto loan', nan) 
    , ('Branch Code', 'Branch Name', 'Region', 'No of accounts' 
     , 'Portfolio Outstanding') 
    , (3000, 'Name1', 'Central', 0, 0) 
    , (3001, 'Name2', 'Central', 0, 0) 
]) 
df.iloc[0:2] = df.iloc[0:2].fillna(method='ffill', axis=1) 
df.iloc[0:2] = df.iloc[0:2].fillna('Area') 

df.columns = pd.MultiIndex.from_tuples(
    zip(*df.iloc[0:2].to_records(index=False).tolist())) 
df = df.iloc[2:] 

Теперь df выглядит следующим образом:

  Area       Auto loan      
    Branch Code Branch Name Region No of accounts Portfolio Outstanding 
2  3000  Name1 Central    0      0 
3  3001  Name2 Central    0      0 

столбец - это MultiIndex:

In [275]: df.columns 
Out[275]: 
MultiIndex(levels=[[u'Area', u'Auto loan'], [u'Branch Code', u'Branch Name', u'No of accounts', u'Portfolio Outstanding', u'Region']], 
      labels=[[0, 0, 0, 1, 1], [0, 1, 4, 2, 3]]) 

Эта колонка имеет два уровня. Первый уровень имеет значения [u'Area', u'Auto loan'], второй имеет значения [u'Branch Code', u'Branch Name', u'No of accounts', u'Portfolio Outstanding', u'Region'].

Вы можете получить доступ к столбец, задав значение с обоих уровней:

print(df.loc[:, ('Area', 'Branch Name')]) 
# 2 Name1 
# 3 Name2 
# Name: (Area, Branch Name), dtype: object 

print(df.loc[:, ('Auto loan', 'No of accounts')]) 
# 2 0 
# 3 0 
# Name: (Auto loan, No of accounts), dtype: object 

Одно из преимуществ использования мультииндексных является то, что вы можете легко выбрать все столбцы, которые имеют определенное значение уровня. Например, чтобы выбрать подпункт DataFrame, что связано с Auto loans вы можете использовать:

In [279]: df.loc[:, 'Auto loan'] 
Out[279]: 
    No of accounts Portfolio Outstanding 
2    0      0 
3    0      0 

Более подробную информацию о выборе строк и столбцов из мультииндексных см MultiIndexing Using Slicers.

Смежные вопросы