2013-07-11 19 views
6

Sto lavorando in R e ho un dataframe, dd_2006, con vettori numerici. Quando ho importato i dati per la prima volta, dovevo rimuovere $, i punti decimali e alcuni spazi vuoti da 3 delle mie variabili: SumOfCost, SumOfCases e SumOfUnits. Per fare ciò, ho usato str_replace_all. Tuttavia, una volta utilizzato str_replace_all, i vettori sono stati convertiti in caratteri. Quindi ho usato as.numeric (var) per convertire i vettori in numerico, ma sono stati introdotti gli AN, anche se quando ho eseguito il codice qui sotto PRIMA ho eseguito il codice as.numeric, non c'erano NA nei vettori.Conversione di caratteri in numerici senza NA Coercizione in R

sum(is.na(dd_2006$SumOfCost)) 
[1] 0 
sum(is.na(dd_2006$SumOfCases)) 
[1] 0 
sum(is.na(dd_2006$SumOfUnits)) 
[1] 0 

Ecco il mio codice da dopo l'importazione, che inizia con la rimozione del $ dal vettore. Nell'output str(dd_2006), ho eliminato alcune variabili per motivi di spazio, quindi la colonna #s nel codice str_replace_all riportato di seguito non corrisponde all'output che ho postato qui (ma lo fanno nel codice originale):

library("stringr") 
dd_2006$SumOfCost <- str_sub(dd_2006$SumOfCost, 2,) #2=the first # after the $ 

#Removes decimal pt, zero's after, and commas 
dd_2006[ ,9] <- str_replace_all(dd_2006[ ,9], ".00", "") 
dd_2006[,9] <- str_replace_all(dd_2006[,9], ",", "") 

dd_2006[ ,10] <- str_replace_all(dd_2006[ ,10], ".00", "") 
dd_2006[ ,10] <- str_replace_all(dd_2006[,10], ",", "") 

dd_2006[ ,11] <- str_replace_all(dd_2006[ ,11], ".00", "") 
dd_2006[,11] <- str_replace_all(dd_2006[,11], ",", "") 

str(dd_2006) 
'data.frame': 12604 obs. of 14 variables: 
$ CMHSP      : Factor w/ 46 levels "Allegan","AuSable Valley",..: 1 1 1 
$ FY      : Factor w/ 1 level "2006": 1 1 1 1 1 1 1 1 1 1 ... 
$ Population    : Factor w/ 1 level "DD": 1 1 1 1 1 1 1 1 1 1 ... 
$ SumOfCases    : chr "0" "1" "0" "0" ... 
$ SumOfUnits    : chr "0" "365" "0" "0" ... 
$ SumOfCost     : chr "0" "96416" "0" "0" ... 

ho trovato una risposta a una domanda simile alla mia here, utilizzando il seguente codice:

# create dummy data.frame 
d <- data.frame(char = letters[1:5], 
       fake_char = as.character(1:5), 
       fac = factor(1:5), 
       char_fac = factor(letters[1:5]), 
       num = 1:5, stringsAsFactors = FALSE) 

Diamo uno sguardo alla data.frame

> d 
    char fake_char fac char_fac num 
1 a   1 1  a 1 
2 b   2 2  b 2 
3 c   3 3  c 3 
4 d   4 4  d 4 
5 e   5 5  e 5 

corriamo:

> sapply(d, mode) 
     char fake_char   fac char_fac   num 
"character" "character" "numeric" "numeric" "numeric" 
> sapply(d, class) 
     char fake_char   fac char_fac   num 
"character" "character" "factor" "factor" "integer" 

Ora è probabilmente chiedi "Dove è un'anomalia?" Beh, mi sono imbattuto in cose piuttosto strane in R, e questa non è la cosa più confusa, ma può confondervi, specialmente se leggete questo prima di andare a letto.

Ecco le prime due colonne: carattere. Ho deliberatamente chiamato il secondo uno fake_char. Trova la somiglianza di questa variabile di carattere con quella che Dirk ha creato nella sua risposta. In realtà è un vettore numerico convertito in carattere. La 3a e la 4a colonna sono fattori, e l'ultimo è "puramente" numerico.

Se si utilizza la funzione di trasformazione, è possibile convertire il file fake_char in numerico, ma non la variabile char stessa.

> transform(d, char = as.numeric(char)) 
    char fake_char fac char_fac num 
1 NA   1 1  a 1 
2 NA   2 2  b 2 
3 NA   3 3  c 3 
4 NA   4 4  d 4 
5 NA   5 5  e 5 
Warning message: 
In eval(expr, envir, enclos) : NAs introduced by coercion 
but if you do same thing on fake_char and char_fac, you'll be lucky, and get away with no NA's: 

Trasforma (d, fake_char = as.numeric (fake_char), char_fac = as.numeric (char_fac))

char fake_char fac char_fac num 
1 a   1 1  1 1 
2 b   2 2  2 2 
3 c   3 3  3 3 
4 d   4 4  4 4 
5 e   5 5  5 5 

così ho provato il codice di cui sopra nel mio script , ma è ancora arrivato con NA (senza un messaggio di avvertimento sulla coercizione).

#changing sumofcases, cost, and units to numeric 
dd_2006_1 <- transform(dd_2006, SumOfCases = as.numeric(SumOfCases), SumOfUnits = as.numeric(SumOfUnits), SumOfCost = as.numeric(SumOfCost)) 

> sum(is.na(dd_2006_1$SumOfCost)) 
[1] 12 
> sum(is.na(dd_2006_1$SumOfCases)) 
[1] 7 
> sum(is.na(dd_2006_1$SumOfUnits)) 
[1] 11 

Ho anche usato table(dd_2006$SumOfCases) ecc a guardare le osservazioni per vedere se ci sono dei personaggi che ho perso nelle osservazioni, ma non ce n'erano. Qualche idea sul perché gli AN stanno spuntando e su come liberarsene?

+2

Siamo spiacenti, ma qual è la domanda? La risposta collegata sembra riassumere tutto abbastanza bene, e senza un esempio riproducibile del problema * tu * stai effettivamente affrontando, non sono sicuro di come gli altri possano aiutare .... – A5C1D2H2I1M1N2O1R2T1

+0

Immagino che questi dati provengano da Excel o un altro foglio di calcolo. La prossima volta, cancella tutta la formattazione prima di esportarla. –

risposta

10

Come ha sottolineato Anando, il problema è da qualche parte nei tuoi dati e non possiamo davvero aiutarti molto senza un esempio riproducibile.Detto questo, ecco un frammento di codice per aiutare a definire con precisione i record i dati che si stanno causando problemi:

test = as.character(c(1,2,3,4,'M')) 
v = as.numeric(test) # NAs intorduced by coercion 
ix.na = is.na(v) 
which(ix.na) # row index of our problem = 5 
test[ix.na] # shows the problematic record, "M" 

Invece di indovinare il motivo per cui si stanno introducendo AN, estrarre i record che causano il problema e indirizzarli direttamente/individualmente fino a quando le AN non si allontanano.

AGGIORNAMENTO: Sembra che il problema sia nella chiamata a str_replace_all. Non so la biblioteca stringr, ma penso che si può ottenere la stessa cosa con gsub come questo:

v2 = c("1.00","2.00","3.00") 
gsub("\\.00", "", v2) 

[1] "1" "2" "3" 

io non sono del tutto sicuro di cosa si compie però:

sum(as.numeric(v2)!=as.numeric(gsub("\\.00", "", v2))) # Illustrate that vectors are equivalent. 

[1] 0 

A meno che questo Ottiene qualche scopo specifico per te, ti suggerirei di abbandonare completamente questo passaggio dalla pre-elaborazione, in quanto non sembra necessario e sembra darti dei problemi.

+0

Quando eseguo quel codice per SumOfUnits, ottengo '> quale indice (ix.na) #row del problema NAs [1] 1098 2297 4728 5559 5592 5702 6955 8191 10517 10881 10955 > test [ix.na] # [ 1] "" "" "" "" "" "" " Ma quando guardo quelle file nel set di dati originale, assomiglia a questo: ' SumOfUnits 800,00 0,00 100,00 100,00 100,00 300,00 400,00 200,00 200,00 600,00 100.00' Così come è che un pro blem con i dati invece succede qualcosa quando eseguo il codice 'str_replace_all'? – idemanalyst

+0

Sembra che tu abbia bloccato il problema. Non so davvero quale sia il pre-processamento di quelle stringhe poiché è possibile trasmettere quei valori ai numeri con o senza decimali, ma illustrerò una soluzione alternativa usando 'gsub' nella mia risposta aggiornata. –

+0

questo è tutto, grazie! – idemanalyst

4

Se si desidera convertire il carattere in un valore numerico, quindi prima convertirlo in un fattore (utilizzando as.factor) e salvare/sovrascrivere la variabile esistente. Successivamente converti questa variabile fattore in numerica (usando as.numeric). In questo modo non creerai NA e sarai in grado di convertire il set di dati che hai in numerico.

+0

as.numeric (come.factor (df $ x)) sostituisce semplicemente i valori con 1 e 2, indici –