2014-10-15 20 views
8

Ho un dataframe di classe mista (numerico e fattore) in cui sto cercando di convertire l'intero frame di dati in numerico. Quanto segue illustra il tipo di dati sto lavorando con così come il problema che sto incontrando:Come convertire l'intero dataframe in numerico preservando i decimali?

> a = as.factor(c(0.01,0.02,0.03,0.04)) 
> b = c(2,4,5,7) 
> df1 = data.frame(a,b) 
> class(df1$a) 
[1] "factor" 
> class(df1$b) 
[1] "numeric" 

Quando provo e convertire l'intero frame di dati a numerico, altera i valori numerici. Per esempio:

> df2 = as.data.frame(sapply(df1, as.numeric)) 
> class(df2$a) 
[1] "numeric" 
> df2 
    a b 
1 1 2 
2 2 4 
3 3 5 
4 4 7 

precedenti messaggi su questo sito suggeriscono utilizzando as.numeric(as.character(df1$a)), che funziona alla grande per una colonna. Tuttavia, ho bisogno di applicare questo approccio a un dataframe che può contenere centinaia di colonne.

Quali sono le opzioni per la conversione di un intero dataframe da fattore a numerico, mantenendo i valori decimali numerici?

che segue è l'uscita desidero produrre dove a e b sono numerica:

 a b 
1 0.01 2 
2 0.02 4 
3 0.03 5 
4 0.04 7 

Ho letto i seguenti messaggi relativi, anche se nessuno di essi applicano direttamente a questo caso:

  1. How to convert a factor variable to numeric while preserving the numbers in R Ciò fa riferimento a una singola colonna in un dataframe.
  2. converting from a character to a numeric data frame. Questo post non tiene conto dei valori decimali.
  3. How can i convert a factor column that contains decimal numbers to numeric?. Questo si applica a una sola colonna in un frame di dati.
+3

Ottimo modo per fare una domanda. [Questa domanda] (http://stackoverflow.com/questions/23206700/sum-on-a-factor-column-returns-incorrect-result) potrebbe essere utile. Questa è una fonte comune di frustrazione per le variabili di 'fattore'. – ilir

risposta

7

Potrebbe essere necessario fare qualche controllo. Non è possibile convertire i fattori direttamente in numerici. as.character deve essere applicato per primo. Altrimenti i fattori verranno convertiti nei loro valori di memoria numerica. Vorrei controllare ogni colonna con is.factor quindi forzare a numerico secondo necessità.

df1[] <- lapply(df1, function(x) { 
    if(is.factor(x)) as.numeric(as.character(x)) else x 
}) 
sapply(df1, class) 
#   a   b 
# "numeric" "numeric" 
+0

O farlo fuori dal ciclo: 'is_factor <- vapply (df1, is.factor, logical (1)); df1 [is_factor] <- ...' – hadley

+0

@hadley - Mi sono chiesto questo. È più efficiente controllare prima e quindi eseguire la modifica sul sottoinsieme? Piuttosto che controllare all'interno del ciclo 'lapply'? –

+0

Data la dimensione del set di dati tipico, dubito che farebbe molta differenza – hadley

1
> df2 <- data.frame(sapply(df1, function(x) as.numeric(as.character(x)))) 
> df2 
    a b 
1 0.01 2 
2 0.02 4 
3 0.03 5 
4 0.04 7 
> sapply(df2, class) 
     a   b 
"numeric" "numeric" 
+1

Potrei sbagliarmi, ma questo non convertirà una colonna numerica in carattere e poi tornerà in numerica? –

+0

@RichardScriven pensa che sia giusto. Penso che la mia risposta soffra dello stesso problema, anche se non penso che sia particolarmente problematico. – n8sty

+0

@ n8sty No, non è affatto problematico, ma sembra un po 'dispendioso. –

1
df2 <- data.frame(apply(df1, 2, function(x) as.numeric(as.character(x)))) 
1

Utilizzando dplyr (un po 'come sapply ..)

df2 <- mutate_all(df1, function(x) as.numeric(as.character(x))) 

che dà:

glimpse(df2) 
Observations: 4 
Variables: 2 
$ a <dbl> 0.01, 0.02, 0.03, 0.04 
$ b <dbl> 2, 4, 5, 7 

dal df1 che era:

glimpse(df1) 
Observations: 4 
Variables: 2 
$ a <fctr> 0.01, 0.02, 0.03, 0.04 
$ b <dbl> 2, 4, 5, 7 
Problemi correlati