2016-07-19 181 views
6

Ho un dataframe panda che sto leggendo da uno defaultdict in Python, ma alcune delle colonne hanno lunghezze diverse. Ecco ciò che i dati potrebbero assomigliare:Prepending invece di accodare NaNs in panda usando from_dict

Date  col1 col2 col3 col4 col5 
01-01-15 5  12  1  -15  10 
01-02-15 7  0  9  11  7 
01-03-15   6  1  2  18 
01-04-15   9  8  10 
01-05-15   -4    7 
01-06-15   -11    -1 
01-07-15   6    

E io sono in grado di pad gli spazi vuoti con NaN s in questo modo:

pd.DataFrame.from_dict(pred_dict, orient='index').T 

che dà:

Date  col1 col2 col3 col4 col5 
01-01-15 5  12  1  -15  10 
01-02-15 7  0  9  11  7 
01-03-15 NaN  6  1  2  18 
01-04-15 NaN  9  8  10  NaN 
01-05-15 NaN -4  NaN  7  NaN 
01-06-15 NaN -11  NaN -1  NaN 
01-07-15 NaN  6  NaN  NaN  NaN 

Tuttavia, ciò che Sto davvero cercando è un modo per anteporre NaN s invece di aggiungerli alla fine, in modo che i dati siano come questo:

Date  col1 col2 col3 col4 col5 
01-01-15 NaN  12  NaN  NaN  NaN 
01-02-15 NaN  0  NaN -15  NaN 
01-03-15 NaN  6  NaN  11  NaN 
01-04-15 NaN  9  1  2  NaN 
01-05-15 NaN -4  9  10  10 
01-06-15 5  -11  1  7  7 
01-07-15 7  6  8  -1  18 

C'è un modo semplice per farlo?

è possibile ricreare il dizionario con questo codice:

import pandas as pd 
from collections import defaultdict 

d = defaultdict(list) 
d["Date"].extend([ 
    "01-01-15", 
    "01-02-15", 
    "01-03-15", 
    "01-04-15", 
    "01-05-15", 
    "01-06-15", 
    "01-07-15" 
]) 
d["col1"].extend([5, 7]) 
d["col2"].extend([12, 0, 6, 9, -4, -11, 6]) 
d["col3"].extend([1, 9, 1, 8]) 
d["col4"].extend([-15, 11, 2, 10, 7, -1]) 
d["col5"].extend([10, 7, 18]) 

risposta

4

una piccola modifica sulla soluzione itertools al earlier question:

pd.DataFrame(list(itertools.zip_longest(*[reversed(i) for i in d.values()]))[::-1], columns=d.keys()).sort_index(axis=1) 
Out[143]: 
     Date col1 col2 col3 col4 col5 
0 01-01-15 NaN 12 NaN NaN NaN 
1 01-02-15 NaN  0 NaN -15.0 NaN 
2 01-03-15 NaN  6 NaN 11.0 NaN 
3 01-04-15 NaN  9 1.0 2.0 NaN 
4 01-05-15 NaN -4 9.0 10.0 10.0 
5 01-06-15 5.0 -11 1.0 7.0 7.0 
6 01-07-15 7.0  6 8.0 -1.0 18.0 
+1

Mi piace questo +1 – piRSquared

+0

Sì, difficile da leggere ma questo ha fatto il lavoro. Speravo in una risposta più vicina a quella che ho accettato, ma non sembra che sia così. – weskpga

+0

A me personalmente non piaceva molto. Non so quante volte iterare su quel dizionario. :) – ayhan

4

È possibile utilizzare Series.shift per indurre la serie/dataframe. Purtroppo non è possibile passare in serie di periodi: è necessario spostare ogni colonna di un valore intero.

s = df.isnull().sum() 
for col, periods in s.iteritems(): 
    df[col] = df[col].shift(periods) 
2

Reverse ogni lista nel dizionario:

for k, v in d.iteritems(): 
    d[k] = v[::-1] 

df = pd.DataFrame.from_dict(d, orient='index').T.set_index('Date').sort_index(1).sort_index().astype(float) 

enter image description here

+0

Perché i dtypes diventano oggetto con questo? – ayhan

+0

Nessuna idea! Interessante. – piRSquared

+0

@ayhan 'df = df.astype (float)' risolve il problema. Forse sta cercando di preservare il 'int'? – piRSquared

0

Ecco un approccio vectorized che utilizza pd.DataFrame.from_dict per ottenere il dataframe per t lui caso normale. Una volta che abbiamo a disposizione i dati regolari 2D, diventa abbastanza semplice capovolgere e mascherare e raggiungere il nostro dataframe di output desiderato in un modo vettorializzato.

L'implementazione è elencato di seguito -

# Get the normal case output 
df = pd.DataFrame.from_dict(d, orient='index').T 

# Use masking to flip and select flipped elements to re-create expected df 
colmask = df.columns!='Date' 
arr = np.array(df.ix[:,colmask].values, dtype=np.float).T 
mask = ~np.isnan(arr) 
out_arr = np.full(mask.shape,np.nan) 
out_arr[mask[:,::-1]] = arr[mask] 
df.ix[:,colmask] = out_arr.T 

Campione run -

In [209]: d.values() 
Out[209]: 
[[-15, 11, 2, 10, 7, -1], 
[10, 7, 18], 
[12, 0, 6, 9, -4, -11, 6], 
[1, 9, 1, 8], 
[5, 7], 
['01-01-15', 
    '01-02-15', 
    '01-03-15', 
    '01-04-15', 
    '01-05-15', 
    '01-06-15', 
    '01-07-15']] 

In [210]: df 
Out[210]: 
    col4 col5 col2 col3 col1  Date 
0 NaN NaN 12 NaN NaN 01-01-15 
1 -15 NaN 0 NaN NaN 01-02-15 
2 11 NaN 6 NaN NaN 01-03-15 
3 2 NaN 9 1 NaN 01-04-15 
4 10 10 -4 9 NaN 01-05-15 
5 7 7 -11 1 5 01-06-15 
6 -1 18 6 8 7 01-07-15 
Problemi correlati