2015-04-07 15 views
13

C'è un modo per fread per simulare il comportamento del read.table cui il class della variabile viene impostato dai dati che viene letta in.Prevenire colonna classe inferenza in fread()

Ho dati numerici con pochi commenti sotto i dati principali. Quando uso fread per leggere nei dati, le colonne vengono convertite in caratteri. Tuttavia, impostando nrow in read.table` posso fermare questo comportamento. È possibile in frotte. (Preferirei non modificare i dati grezzi o fare una copia modificata). Grazie

Un esempio

d <- data.frame(x=c(1:100, NA, NA, "fff"), y=c(1:100, NA,NA,NA)) 
write.csv(d, "test.csv", row.names=F) 

in_d <- read.csv("test.csv", nrow=100, header=T) 
in_dt <- data.table::fread("test.csv", nrow=100) 

che produce

> str(in_d) 
'data.frame': 100 obs. of 2 variables: 
$ x: int 1 2 3 4 5 6 7 8 9 10 ... 
$ y: int 1 2 3 4 5 6 7 8 9 10 ... 
> str(in_dt) 
Classes ‘data.table’ and 'data.frame': 100 obs. of 2 variables: 
$ x: chr "1" "2" "3" "4" ... 
$ y: int 1 2 3 4 5 6 7 8 9 10 ... 
- attr(*, ".internal.selfref")=<externalptr> 

Come soluzione alternativa ho pensato di essere in grado di utilizzare read.table per leggere in una sola riga, ottenere la classe e impostare il colClasses, ma sto fraintendendo.

cl <- read.csv("test.csv", nrow=1, header=T) 
cols <- unname(sapply(cl, class)) 
in_dt <- data.table::fread("test.csv", nrow=100, colClasses=cols) 
str(in_dt) 

Utilizzando Windows8.1 versione R 3.1.2 (2014/10/31) Piattaforma: x86_64-W64-mingw32/x64 (64-bit)

+3

Sembrava un piano ragionevole, ma in realtà ho letto la pagina di aiuto: "fread promuoverà una colonna solo a un tipo più alto se colClasses lo richiede. Non effettuerà il downgrade di una colonna a un tipo inferiore dal risultato di NA. costretti a forzare tali colonne in seguito, se hai davvero bisogno di una perdita di dati. " Sembra che anche la limitazione della lettura a 5 righe fallisca. Penso di ricordare che il meccanismo di colClasses era un'aggiunta abbastanza recente, quindi forse dovresti inviare una richiesta di funzionalità. Matthew e Arun sono spesso molto accomodanti. –

+2

Sicuramente ci deve essere una strategia DT per forzare tutte le colonne a numeriche? Imposta '.SDcols' su un vettore appropriato e qualcosa del genere:' DT [, .SD: = lapply (.SDcols, as.numeric), .SDcols = vec] '. Non sono un utente di DT, ma sono sicuro che ci sia un approccio di tipo minimale e sospetto che tu possa trovarlo illustrato nelle risposte SO. –

+0

@BondedDust; Anche io non sono un utente DT, solo che read.table sta avendo (più gravi) problemi con i miei dati di quanto lo sia. Devo dare un'occhiata a SO. grazie – user2957945

risposta

17

Opzione 1: Utilizzo di un comando di sistema

fread() consente l'utilizzo di un comando di sistema nel suo primo argomento. Possiamo usarlo per rimuovere le virgolette nella prima colonna del file.

indt <- data.table::fread("cat test.csv | tr -d '\"'", nrows = 100) 
str(indt) 
# Classes ‘data.table’ and 'data.frame': 100 obs. of 2 variables: 
# $ x: int 1 2 3 4 5 6 7 8 9 10 ... 
# $ y: int 1 2 3 4 5 6 7 8 9 10 ... 
# - attr(*, ".internal.selfref")=<externalptr> 

Il comando di sistemacat test.csv | tr -d '\"'spiegato:

  • cat test.csv legge il file di uscita standard
  • | è un tubo, utilizzando l'uscita del comando precedente come input per il prossimo comando
  • tr -d '\"' cancella (-d) tutte le occorrenze di doppi apici ('\"') dalla corrente di ingresso

Opzione 2: coercizione dopo aver letto

Dal opzione 1 non sembra essere al lavoro sul vostro sistema, un altro è possibile leggere il file come hai fatto, ma convertire la colonna x con type.convert().

library(data.table) 
indt2 <- fread("test.csv", nrows = 100)[, x := type.convert(x)] 
str(indt2) 
# Classes ‘data.table’ and 'data.frame': 100 obs. of 2 variables: 
# $ x: int 1 2 3 4 5 6 7 8 9 10 ... 
# $ y: int 1 2 3 4 5 6 7 8 9 10 ... 
# - attr(*, ".internal.selfref")=<externalptr> 

Nota a margine: Io di solito preferiscono usare type.convert() sopra as.numeric() per evitare il "AN introdotta con la coercizione" allarme entra in funzione in alcuni casi.Ad esempio,

x <- c("1", "4", "NA", "6") 
as.numeric(x) 
# [1] 1 4 NA 6 
# Warning message: 
# NAs introduced by coercion 
type.convert(x) 
# [1] 1 4 NA 6 

Ma naturalmente è possibile utilizzare as.numeric() pure.


Nota: Questa risposta presuppone data.table dev v1.9.5

+0

Grazie Richard, tuttavia, questo genera un errore sul mio sistema. Sto usando Windows 8.1 – user2957945

+0

Grazie per le informazioni extra. Ho installato la versione di sviluppo ma lo stesso errore su Windows (funziona, con un avvertimento utile su linux). Potresti spiegare il comando di chiamata di sistema per favore. – user2957945

+1

@ user2957945 - Va bene sapere. Ho aggiunto una seconda opzione che dovrebbe essere sufficientemente efficiente –

-2

Ok, il cliente è abusing CSV format scrivere intenzionalmente fuori trascinamento righe stringhe ad una colonna integer, ma senza le righe che iniziano con un comment.char (#) .

Quindi ci si aspetta in qualche modo che si possa sovrascrivere l'inferenza di tipo di fread() per leggerli come numeri interi, utilizzando il comando nrow per provare a limitarlo per visualizzare solo le righe intere. read.csv(..., nrow) accetterà ciò, tuttavia fread() utilizza sempre tutte le righe per l'inferenza del tipo (non solo quelle specificate da nrow, skip, header) e anche se iniziano con comment.char (che è un bug).

  1. Sembra un abuso di CSV. Le righe dei commenti devono essere anteposte con #
  2. Sì, fread() ha bisogno di una correzione/miglioramento per ignorare le righe di commento per l'inferenza di tipo.
  3. Per il momento, è possibile risolvere con fread() da post-elaborazione dei dati-tavolo letta in
  4. E 'discutibile se fread() dovrebbe essere cambiata per supportare il comportamento desiderato:. Usando nrows per limitare ciò che viene esposto a digitare-inferenza . Potrebbe risolvere il tuo caso (piuttosto unico) e rompere altri.

Non vedo il motivo per cui: non (EDIT cliente) potete scrivere i vostri commenti a un/file separato .txt/README dati-dizionario per accompagnare il .csv. La pratica dell'utilizzo di un file di dizionario dati separato è abbastanza consolidata. Non ho mai visto qualcuno farlo in un file CSV. Almeno sposta i commenti nell'intestazione, non in un piè di pagina.

+0

Il csv non ha un'intestazione multi-riga. Ha elementi indesiderati nella parte inferiore del file –

+0

Ok, quindi le righe di commento finali (stringa), senza alcun '#' iniziale. Perché non li hai semplicemente aggiunti manualmente a write.csv? – smci

+0

Non è una mia domanda, ma suppongo che OP abbia già il file e abbia usato 'write.csv()' per creare un esempio. –