Pandas Рекомендации по дизайну для мультииндексированных DataFrames

Целью этого вопроса является дальнейшее изучение данных MultiIndex dataframes и задание вопросов наилучшего подхода к различным задачам.

Создайте DataFrame

import pandas as pd

df = pd.DataFrame({'index_date' : ['12/07/2016','12/07/2016','12/07/2016','12/07/2016','12/07/2016'], 
               'portfolio' : ['A','B','C','D','E'], 
               'reporting_ccy' : ['GBP','GBP','GBP','GBP','GBP'],
               'portfolio_ccy' : ['JPY','USD','USD','EUR','EUR'],
               'amount' : [100,200,300,400,500],
               'injection' : [1,2,3,4,5],
               'to_usd' : [1.3167,1.3167,1.3167,1.3167,1.3167],
               'to_ccy' : [0.009564,1,1,1.1093,1.1093],
               'm5' : [2,4,6,8,10],
               'm6' : [1,3,5,7,9]}); 

Развернуть DataFrame

df_pivot = df.pivot_table(index='index_date',columns=['portfolio','portfolio_ccy','reporting_ccy']).swaplevel(0, 1, axis=1).sortlevel(axis=1)

Переименовать столбцы

df_pivot.columns.names = ['portfolio','measures', 'portfolio_ccy', 'reporting_ccy']

Это дает поворотное представление данных таким образом, что:

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

I условия 4. Какой наилучший подход для реализации, учитывая, что у нас есть xRates для валют?

Таким образом, мы создаем тактику данных, например, полученную здесь:

Создать DataFrame

df1 = pd.DataFrame({'index_date' : ['12/07/2016','12/07/2016','12/07/2016','12/07/2016','12/07/2016'], 
           'portfolio' : ['A','B','C','D','E'], 
           'reporting_ccy' : ['JPY','USD','USD','EUR','EUR'],
           'portfolio_ccy' : ['JPY','USD','USD','EUR','EUR'],
           'amount' : [13767.2522, 263.34, 395.01, 474.785901, 593.4823763],
           'injection' : [1,2,3,4,5],
           'to_usd' : [0.009564, 1, 1, 1.1093, 1.1093],
           'to_ccy' : [1.3167, 1.3167, 1.3167, 1.3167, 1.3167],
           'm5' : [2,4,6,8,10],
           'm6' : [1,3,5,7,9]}); 

Конкатенация и поворот DataFrames

df_concat = pd.concat([df,df1])
df_pivot1 = df_concat.pivot_table(index='index_date',columns=['portfolio','portfolio_ccy','reporting_ccy']).swaplevel(0, 1, axis=1).sortlevel(axis=1)
df_pivot1.columns.names = ['portfolio','measures', 'portfolio_ccy', 'reporting_ccy']

Теперь это показывает 1 меру, имеющую много валют.

df_pivot1.xs(('amount', 'A'), level=('measures','portfolio'), drop_level=False, axis=1)

Вопрос

Есть ли лучший способ, например, добавлять данные непосредственно в мультииндексированный фрейм данных на уровне 3 df_pivot1.columns.get_level_values(3).unique()?

Я хотел бы иметь возможность выполнять итерацию каждого уровня и добавлять новые меры, полученные из других мер, используя df.assign() или другие методы.

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

Ответы

Ответ 1

Вы можете добавить строку df1 по строкам на df_pivot вместо того, чтобы перестроить опорную точку с обоими кадрами concat вместе.

Добавление к концу DataFrame было бы менее дорогостоящим, чем конкатенация и перестроение шарниров с нуля каждый раз, когда будут получены новые данные.

import pandas as pd

df = pd.DataFrame({'index_date' : ['12/07/2016','12/07/2016','12/07/2016','12/07/2016','12/07/2016'], 
               'portfolio' : ['A','B','C','D','E'], 
               'reporting_ccy' : ['GBP','GBP','GBP','GBP','GBP'],
               'portfolio_ccy' : ['JPY','USD','USD','EUR','EUR'],
               'amount' : [100,200,300,400,500],
               'injection' : [1,2,3,4,5],
               'to_usd' : [1.3167,1.3167,1.3167,1.3167,1.3167],
               'to_ccy' : [0.009564,1,1,1.1093,1.1093],
               'm5' : [2,4,6,8,10],
               'm6' : [1,3,5,7,9]}); 

# %%
df_pivot = df.pivot_table(index='index_date',columns=['portfolio','portfolio_ccy','reporting_ccy']).swaplevel(0, 1, axis=1).sortlevel(axis=1)
df1 = pd.DataFrame({'index_date' : ['12/07/2016','12/07/2016','12/07/2016','12/07/2016','12/07/2016'], 
           'portfolio' : ['A','B','C','D','E'], 
           'reporting_ccy' : ['JPY','USD','USD','EUR','EUR'],
           'portfolio_ccy' : ['JPY','USD','USD','EUR','EUR'],
           'amount' : [13767.2522, 263.34, 395.01, 474.785901, 593.4823763],
           'injection' : [1,2,3,4,5],
           'to_usd' : [0.009564, 1, 1, 1.1093, 1.1093],
           'to_ccy' : [1.3167, 1.3167, 1.3167, 1.3167, 1.3167],
           'm5' : [2,4,6,8,10],
           'm6' : [1,3,5,7,9]}); 

df_pivot.columns.names = ['portfolio','measures', 'portfolio_ccy', 'reporting_ccy']
# instead of joining the 2 df add df1 to df_pivot 1 row at a time. 
for i in range(len(df1)):
    row = df1.iloc[i]
    for measure in 'amount injection m5 m6 to_ccy to_usd'.split():
        df_pivot.ix[row.index_date, (row.portfolio,measure,row.portfolio_ccy, row.reporting_ccy)] = row[measure]

#%% check the end result
print(df_pivot.xs(('amount', 'A'), 
      level=('measures','portfolio'), drop_level=False, axis=1))   

Ответ 2

Я очень смущен информационной перегрузкой.
Однако, если я правильно понимаю:

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


рассмотрим df

df = pd.DataFrame(np.arange(64).reshape(-1, 8), list('abcdefgh'), list('ABCDEFGH'))
df

введите описание изображения здесь


мы можем легко добавить уровень к внутреннему уровню индекса

df.index = [df.index, list('XY') * 4]
df

введите описание изображения здесь