2016-07-13 39 views
14

Lo scopo di questa domanda è esplorare ulteriormente MultiIndex dataframes e porre domande sull'approccio migliore per varie attività.Considerazioni sulla progettazione di panda per i datafondi MultiIndex

Creare il 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]}); 

Ruotare il dataframe

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

Rinominare le colonne

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

Questo produce una rappresentazione imperniato dei dati in modo tale che:

  1. un portafoglio possono avere 1 o più misure
  2. mostra la valuta di portafoglio di default
  3. mostra il portafoglio moneta di
  4. una misura può avere 1 o molte valute di segnalazione.

I termini di 4. qual è l'approccio migliore per l'implementazione dato che abbiamo le x rate per le valute?

Tale che creiamo un dataframe come quella derivata qui:

Creare 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]}); 

Concatenate & Pivot le 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'] 

Questo dimostra ora 1 misura avendo molte valute.

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

Domanda

Esiste un modo migliore, come l'aggiunta di dati direttamente ad un dataframe multiIndexed al livello 3 df_pivot1.columns.get_level_values(3).unique()?

Mi piacerebbe essere in grado di scorrere ogni livello e aggiungere nuove misure derivate da altre misure usando df.assign() o altri metodi.

Il caso d'uso qui è di aggiungere altre valute alle misure, ove applicabile. La concatenazione e il re-pivot come sopra non sembrano ottimali.

+1

Questo è anche esplorato ulteriormente [qui] (http://stackoverflow.com/questions/38491990/adding-and-renaming-a-column-in-a-multiindex-dataframe/38493363) – toasteez

+0

Anche se questa è una domanda ben formata, sono confuso riguardo alle tue esigenze. Potrebbe essere completamente fuori, ma stai cercando di usare df_pivot e aggiungere tutte le valute di segnalazione o qualcosa del genere? Puoi usare df (prima di pivot) per farlo? –

+0

Quello che sto insinuando è che non esiste un modo semplice per aggiungere a un livello inferiore in un frame di dati con più indici. Ho risolto questo e penso che altre domande pubblicate da me lo esplorino. Questo è dopo pivot. Il motivo è che potresti avere un MultiIndex e vuoi aggiungere altre misure derivate dai dati nel frame Multi-Index esistente o da altre fonti di dati, ecc. – toasteez

risposta

2

È possibile aggiungere df1 riga per riga a df_pivot invece di ricostruire il pivot con entrambi i frame concatenati.

L'accodamento alla fine di DataFrame comporterebbe un risparmio di memoria inferiore rispetto alla concatenazione e alla ricostruzione dei pivot da zero ogni volta che vengono ricevuti nuovi dati.

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's 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)) 
+0

Mentre date la stessa risposta data nella domanda sopra, non avete risposto alla domanda. La domanda è alla ricerca di un modo più ottimale per aggiungere dati a un dataframe con più indici. Per favore guarda questo [link] (http://stackoverflow.com/questions/38491990/adding-and-renaming-a-column-in-a-multiindex-dataframe/38493363) dove ho esplorato ulteriormente. Non sono sicuro che l'introduzione di un ciclo sarà più ottimale di 'pd.concat'. Questo è un piccolo esempio, consideralo su larga scala e facendo anche calcoli attraverso le misure per fornire misure derivate. – toasteez

+0

L'aggiunta riga per riga del primo pivot può essere meno costosa sulla memoria rispetto alla concatenazione di tutti i dati e al ricalcolo di tutti i pivot con ogni nuovo aggiornamento ai dati. Poiché è necessario elaborare solo i nuovi dati in entrata e non i dati esistenti più e più volte. – PabTorre

+0

Ulteriori efficienze potrebbero essere ottenute divergendo dal deepindex df verso HDF5 o SQL, ma credo che questo non rientri nell'ambito della domanda – PabTorre

2

Sono molto confuso dal sovraccarico di informazioni.
Tuttavia, se ho capito bene:

Quello che sto dicendo è che non v'è un modo semplice di aggiungere a un livello più basso in un frame di dati Multi-Index.


considerano df

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

enter image description here


possiamo facilmente aggiungere un livello per il livello all'interno dell'indice

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

enter image description here

+0

che hai aiutato con la risposta nel [collegamento] (http://stackoverflow.com/ questions/38491990/adding-and-renaming-a-column-in-a-multiindex-dataframe/38493363) sopra. Questo è qualcosa che ritiene che gli sviluppatori principali di Pandas dovrebbero aiutare ad affrontare. – toasteez

+0

Ha! Ho un breve ricordo ;-) – piRSquared