2013-06-13 11 views
15

Ho un pandas.DataFrame che desidero esportare in un file CSV. Tuttavia, i panda sembrano scrivere alcuni dei valori come float invece dei tipi int. Non potrei non trovare come cambiare questo comportamento.Python panda: output dataframe a csv con numeri interi

Costruire un frame di dati:

df = pandas.DataFrame(columns=['a','b','c','d'], index=['x','y','z'], dtype=int) 
x = pandas.Series([10,10,10], index=['a','b','d'], dtype=int) 
y = pandas.Series([1,5,2,3], index=['a','b','c','d'], dtype=int) 
z = pandas.Series([1,2,3,4], index=['a','b','c','d'], dtype=int) 
df.loc['x']=x; df.loc['y']=y; df.loc['z']=z 

vederlo:

>>> df 
    a b c d 
x 10 10 NaN 10 
y 1 5 2 3 
z 1 2 3 4 

esportarlo:

>>> df.to_csv('test.csv', sep='\t', na_rep='0', dtype=int) 
>>> for l in open('test.csv'): print l.strip('\n') 
     a  b  c  d 
x  10.0 10.0 0  10.0 
y  1  5  2  3 
z  1  2  3  4 

Perché le decine hanno una virgola zero?

Certo, ho potuto solo bastone questa funzione nella mia condotta di riconvertire l'intero file CSV, ma sembra inutile:

def lines_as_integer(path): 
    handle = open(path) 
    yield handle.next() 
    for line in handle: 
     line = line.split() 
     label = line[0] 
     values = map(float, line[1:]) 
     values = map(int, values) 
     yield label + '\t' + '\t'.join(map(str,values)) + '\n' 
handle = open(path_table_int, 'w') 
handle.writelines(lines_as_integer(path_table_float)) 
handle.close() 
+2

si dovrebbe 'panda importazione come pd' :) –

+3

@Andy Perché dovrei farlo? I namespace sono un'ottima idea ... fino a quando non li abbrevi tutti e diventa illeggibile. – xApple

+0

Questo è lo standard, analogamente numpy è np (e disponibile come pd.np). panda è significativamente più lungo di pd, scrivendolo ogni volta renderebbe il codice * meno * leggibile IMO. –

risposta

8

La risposta che cercavo era una leggera variazione di cosa ha proposto @Jeff nella sua risposta. Il merito va a lui. Questo è ciò che ha risolto il mio problema, alla fine, per riferimento:

import pandas 
    df = pandas.DataFrame(data, columns=['a','b','c','d'], index=['x','y','z']) 
    df = df.fillna(0) 
    df = df.astype(int) 
    df.to_csv('test.csv', sep='\t') 
+2

Questo aggira i float ma perdete le informazioni NaN. Forse riempire NA con -9999 o qualche valore che sai non è "reale" nel tuo set di dati. – Cyrille

8

Questo è un "gotcha" in pandas (Support for integer NA), dove le colonne interi con NaNs vengono convertiti in float.

Questo trade-off viene fatto in gran parte per motivi di memoria e prestazioni, e anche perché la Serie risultante continui ad essere "numerica". Una possibilità è quella di utilizzare gli array dtype=object.

+0

Quindi non c'è modo di ottenerli come numeri interi senza riorganizzare l'intero file? Che ne dici se io uso 'df.fillna()'? – xApple

+2

Usa 'dtype = object' (piuttosto che' int') quando crei 'x' e' df'. –

7

Il problema è che dal momento che si sta assegnando le cose per righe, ma dtypes sono raggruppati per colonne, quindi le cose si gettano a object DTYPE, che non è una buona cosa, si perde ogni efficacia. Quindi, un modo è quello di convertire che costringerà a float/int dtype secondo necessità.

Come abbiamo risposto a un'altra domanda, se si costruisce il telaio tutti in una volta (o costruire colonna per colonna) non sarà necessario questo passaggio

In [23]: def convert(x): 
    ....:  try: 
    ....:   return x.astype(int) 
    ....:  except: 
    ....:   return x 
    ....:  

In [24]: df.apply(convert) 
Out[24]: 
    a b c d 
x 10 10 NaN 10 
y 1 5 2 3 
z 1 2 3 4 

In [25]: df.apply(convert).dtypes 
Out[25]: 
a  int64 
b  int64 
c float64 
d  int64 
dtype: object 

In [26]: df.apply(convert).to_csv('test.csv') 

In [27]: !cat test.csv 
,a,b,c,d 
x,10,10,,10 
y,1,5,2.0,3 
z,1,2,3.0,4 
+2

Ma poi c'è '.0's nelle colonne' c' ...: s –

+1

perché è un float! nessuna scelta (beh, puoi passare '' float_format = '%. 0f''' a '' to_csv'', ma questo potrebbe portare a una perdita di precisione - – Jeff

+1

Ma ma ..., se usi dtype = object (es. in xe df tramite la costruzione di OP, che sono d'accordo non è il modo migliore) quindi 2, 3 e 10 sono tutti ints ...quasi sempre non vale la pena preoccuparsi comunque. Questo sembra proprio la trasposizione dello sforzo dell'OP: s –

Problemi correlati