2012-03-15 1 views
9

Ho appena messo le mani sui panda e sto cercando di capire come posso leggere un file. Il file proviene dal database WRDS e gli elenchi dei componenti SP500 risalgono agli anni '60. Ho controllato il file e non importa cosa faccio per importarlo usando 'read_csv', non riesco ancora a visualizzare correttamente i dati.Come faccio a leggere un file di testo in formato larghezza fisso nei panda

df = read_csv('sp500-sb.txt') 

df 

<class 'pandas.core.frame.DataFrame'> 
Int64Index: 1231 entries, 0 to 1230 
Data columns: gvkeyx      from      thru     conm 
                                        gvkey      co_conm 
...(the column names) 
dtypes: object(1) 

Che cosa significa il suddetto pezzo di output? Qualunque cosa sarebbe utile

+2

che i panda può aver mangiato i dati ? – hochl

+1

Puoi mostrare le prime righe del file? –

risposta

7

Wes mi ha risposto in un'email. Saluti.

Questo è un file in formato a larghezza fissa (non delimitato da virgole o tabulazioni come al solito ). Mi rendo conto che i panda non hanno un lettore a larghezza fissa come lo R, sebbene uno possa essere modellato molto facilmente. Vedrò cosa posso fare do. Nel frattempo se riesci ad esportare i dati in un altro formato (come csv - veramente separati da virgola) sarai in grado di leggerlo con read_csv. I sospetto con qualche magia unix è possibile trasformare un file FWF in un file CSV .

vi consiglio a seguito dell'emissione su github il tuo indirizzo e-mail è in procinto di scomparire dalla mia casella di posta :)

https://github.com/pydata/pandas/issues/920

migliore, Wes

+6

Seguito alla risposta. La lettura del formato della larghezza della correzione è ora implementata da read_fwf(). Vedi http://pandas.pydata.org/pandas-docs/dev/io.html#files-with-fixed-width-columns –

0

Cosa intendi per display? df['gvkey'] non fornisce i dati nella colonna gvkey?

Se ciò che si fa è stampare l'intero frame di dati sulla console, quindi dare un'occhiata a df.to_string(), ma sarà difficile da leggere se si dispone di troppe colonne. Pandas non stamperà il tutto per impostazione predefinita se hai troppe colonne:

import pandas 
import numpy 

df1 = pandas.DataFrame(numpy.random.randn(10, 3), columns=['col%d' % d for d in range(3)]) 
df2 = pandas.DataFrame(numpy.random.randn(10, 30), columns=['col%d' % d for d in range(30)]) 

print df1 # <--- substitute by df2 to see the difference 
print 
print df1['col1'] 
print 
print df1.to_string() 
+0

grazie TR. Il mio file di dati è un formato a larghezza fissa ... attualmente non supportato. Wes è stato gentilmente aggiunto alla lista delle edizioni dei panda forgiatori. – user1234440

+0

Hai ancora accesso a WRDS?Dovresti avere un'opzione per l'output del file in formato csv. –

0

utente, se è necessario affrontare con il formato fisso in questo momento, è possibile utilizzare qualcosa di simile al seguente:

def fixed_width_to_items(filename, fields, first_column_is_index=False, ignore_first_rows=0): 
    reader = open(filename, 'r') 
    # skip first rows 
    for i in xrange(ignore_first_rows): 
     reader.next() 
    if first_column_is_index: 
     index = slice(0, fields[1]) 
     fields = [slice(*x) for x in zip(fields[1:-1], fields[2:])] 
     return ((line[index], [line[x].strip() for x in fields]) for line in reader) 
    else: 
     fields = [slice(*x) for x in zip(fields[:-1], fields[1:])] 
     return ((i, [line[x].strip() for x in fields]) for i,line in enumerate(reader)) 

Ecco a programma est:

import pandas 
import numpy 
import tempfile 

# create a data frame 
df = pandas.DataFrame(numpy.random.randn(100, 5)) 
file_ = tempfile.NamedTemporaryFile(delete=True) 
file_.write(df.to_string()) 
file_.flush() 

# specify fields 
fields = [0, 3, 12, 22, 32, 42, 52] 
df2 = pandas.DataFrame.from_items(fixed_width_to_items(file_.name, fields, first_column_is_index=True, ignore_first_rows=1)).T 

# need to specify the datatypes, otherwise everything is a string 
df2 = pandas.DataFrame(df2, dtype=float) 
df2.index = [int(x) for x in df2.index] 

# check 
assert (df - df2).abs().max().max() < 1E-6 

Questo dovrebbe fare il trucco se ne avete bisogno in questo momento, ma tenere a mente che la funzione di cui sopra è molto semplice, in particolare, non fa nulla sui tipi di dati.