2014-06-26 12 views
5

Confrontare la conversione di una stringa di caratteri con as.numeric in modo che possa essere eseguito con read.fwf.Incoerenza possibile nella conversione da testo a numerico

as.numeric("457") # 457 
as.numeric("4 57") # NA with warning message 

Ora da un file "fwf.txt" contenente esattamente "5 7 12 4".

foo<-read.fwf('fwf.txt',widths=c(5,5),colClasses='numeric',header=FALSE) 
    V1 V2 
1 57 124 

foo<-read.fwf('fwf.txt',widths=c(5,5),colClasses='character',header=FALSE) 
    V1 V2 
1 5 7 12 4 

Ora, ti faccio notare che nella versione "numerico", read.fwf fa concatenazione allo stesso modo Fortran fa. Ero solo un po 'sorpreso dal fatto che non generava un errore o NA nello stesso modo di as.numeric. Qualcuno sa perché?

+1

'read.fwf' chiama' read.table', che è la funzione che si occupa di 'colClasses'. Puoi ottenere lo stesso comportamento usando 'read.table' invece di' read.fwf'. Ad esempio, se si modifica il contenuto del file in "5 7 | 12 4" e lo si legge con 'read.table (" fwf.txt ", header = FALSE, sep =" | ", colClasses =" numerico ") ', ottieni lo stesso risultato. Ho capito che read.table deve liberarsi degli spazi intermedi tra i caratteri numerici quando sa che la classe dovrebbe essere numerica, ma guardando il codice della funzione non potrei dire con certezza se è quello che sta succedendo. – eipi10

risposta

5

Come sottolineato da @ eipi10, il comportamento di eliminazione degli spazi non è esclusivo di read.fwf. In realtà viene dalla funzione scan() (utilizzata da read.table utilizzata da read.fwf). In realtà la funzione scan() rimuoverà gli spazi (o le schede se non sono specificati come delimitatore) da qualsiasi valore che non sia un carattere mentre elabora il flusso di input. Una volta che ha "pulito" il valore degli spazi, utilizza la stessa funzione di as.numeric per trasformare quel valore in un numero. Con i valori dei caratteri non elimina nessuno spazio bianco a meno che non si imposti lo strip.white=TRUE che rimuoverà solo lo spazio dall'inizio e dalla fine del valore.

Rispettare questi esempi

scan(text="TRU E", what=logical(), sep="x") 
# [1] TRUE 
scan(text="0 . 0 0 7", what=numeric(), sep="x") 
# [1] 0.007 
scan(text=" text ", what=character(), sep="~") 
# [1] " text " 
scan(text=" text book ", what=character(), sep="~", strip.white=T) 
# [1] "text book" 
scan(text="F\tALS\tE", what=logical(), sep=" ") 
# [1] FALSE 

È possibile trovare la fonte per scan() in /src/main/scan.c e la parte specifica responsabile di questo comportamento è around this line.

Se si voleva as.numeric a comportarsi come, si potrebbe creare una nuova funzione come

As.Numeric<-function(x) as.numeric(gsub(" ", "", x, fixed=T)) 

al fine di ottenere

As.Numeric("4 57") 
# [1] 457