Come convertire una colonna di frame di dati in tipo numerico?


Risposte:


267

Dato che (ancora) nessuno ha ottenuto il segno di spunta, presumo che tu abbia qualche problema pratico in mente, soprattutto perché non hai specificato in quale tipo di vettore vuoi convertire numeric. Ti suggerisco di applicare la transformfunzione per completare il tuo compito.

Ora sto per dimostrare una certa "anomalia di conversione":

# 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 un'occhiata 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

e 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 ti chiedi "Dov'è un'anomalia?" Bene, mi sono imbattuto in cose abbastanza peculiari in R, e questa non è la cosa più confusa, ma può confonderti, specialmente se leggi questo prima di rotolare nel letto.

Ecco qui: le prime due colonne sono character. Ho volutamente chiamato 2 ° uno fake_char. Trova la somiglianza di questa charactervariabile con quella creata da Dirk nella sua risposta. In realtà è un numericalvettore convertito in character. La terza e la quarta colonna sono factor, e l'ultima è "puramente" numeric.

Se si utilizza la transformfunzione, è possibile convertire fake_charin numeric, ma non nella charvariabile 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

ma se fai la stessa cosa su fake_chare char_fac, sarai fortunato e scapperai senza NA:

> transform(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

Se salvi trasformato data.framee controlli per modee class, otterrai:

> D <- transform(d, fake_char = as.numeric(fake_char), 
                    char_fac = as.numeric(char_fac))

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

Quindi, la conclusione è: Sì, puoi convertire il charactervettore in numericuno, ma solo se i suoi elementi sono "convertibili" in numeric. Se c'è solo un characterelemento nel vettore, otterrai un errore quando provi a convertire quel vettore in numericaluno.

E solo per dimostrare il mio punto:

> err <- c(1, "b", 3, 4, "e")
> mode(err)
[1] "character"
> class(err)
[1] "character"
> char <- as.numeric(err)
Warning message:
NAs introduced by coercion 
> char
[1]  1 NA  3  4 NA

E ora, solo per divertimento (o pratica), prova a indovinare l'output di questi comandi:

> fac <- as.factor(err)
> fac
???
> num <- as.numeric(fac)
> num
???

Cordiali saluti a Patrick Burns! =)


6
'stringsAsFactors = FALSE' è importante per la lettura di file di dati.
Robert Brisita,

4
So che questo è vecchio ... ma ... perché hai scelto transform () su df $ fake_char <- as.integer (df $ fake_char)? Ci sono molti modi per fare la stessa operazione in R e mi sono bloccato a capire il modo "corretto" di farlo. Grazie.
ripvlan,

Quindi è assolutamente impossibile trasformare err <- c (1, "b", 3, 4, "e") in un vettore numerico? In Excel, c'è un pulsante che ti permette di "convertire in numero". rendendo qualsiasi valore la colonna un numero. Sto cercando di imitare quello in r.
flightless13wings

Attenzione! = Errore. Non si verifica un errore durante la conversione di valori numerici / caratteri misti in valori numerici, viene visualizzato un avviso e alcuni valori NA.
Gregor Thomas,

136

Qualcosa che mi ha aiutato: se hai gamme di variabili da convertire (o solo più di una), puoi usare sapply.

Un po 'senza senso ma solo per esempio:

data(cars)
cars[, 1:2] <- sapply(cars[, 1:2], as.factor)

Supponiamo che le colonne 3, 6-15 e 37 di te, il frame di dati debba essere convertito in uno numerico, possano:

dat[, c(3,6:15,37)] <- sapply(dat[, c(3,6:15,37)], as.numeric)

1
as.factor nel codice sopra rende il carattere di colonna
MySchizoBuddy

1
sapply è meglio che trasformare, quando si maneggiano vettori di indici piuttosto che nomi di variabili
smci

@MySchizoBuddy ha ragione, almeno con i miei dati. Il df originale non assumerà le colonne "convertite" come fattori; rimarranno personaggio. Se avvolgi la sapplychiamata as.data.frame()sul lato destro, come suggerito da @Mehrad Mahmoudian di seguito, funzionerà.
knowah

Funzionerà per una matrice? Sto provando con lo stesso identico codice, ma quando controllo la classe () di una colonna dopo, dice ancora "carattere" e non "numerico"
namore

87

se xè il nome della colonna del frame di dati dated xè di tipo fattore, utilizzare:

as.numeric(as.character(dat$x))

3
l'aggiunta as.characterè davvero quello che stavo cercando. Altrimenti la conversione a volte va storto. Almeno nel mio caso.
Thieme Hennis,

1
Perché è necessario as.character? Stavo ottenendo un errore: Error: (list) object cannot be coerced to type 'double'anche se ero ragionevolmente sicuro che il mio vettore non avesse caratteri / punteggiatura. Poi ho provato as.numeric(as.character(dat$x))e ha funzionato. Ora non sono sicuro che la mia colonna sia in realtà solo numeri interi o no!
vagabondo,

2
Se si fa as.numeric in un fattore, convertirà i livelli in valori numerici e non i valori effettivi. Quindi è necessario as.character per convertire prima il fattore in carattere e poi as.numeric
MySchizoBuddy

Questa è la migliore risposta qui
mitoRibo

25

Avrei aggiunto un commento (non posso votare in basso)

Solo per aggiungere su user276042 e pangratz

dat$x = as.numeric(as.character(dat$x))

Ciò sovrascriverà i valori della colonna esistente x


16

Mentre la tua domanda è strettamente numerica, ci sono molte conversioni che sono difficili da capire quando inizi R. Cercherò di indirizzare i metodi per aiutare. Questa domanda è simile a questa domanda .

La conversione del tipo può essere una seccatura in R perché (1) i fattori non possono essere convertiti direttamente in valori numerici, devono prima essere convertiti in classe di caratteri, (2) le date sono un caso speciale che in genere è necessario affrontare separatamente e (3) eseguire il ciclo tra le colonne del frame di dati può essere complicato. Fortunatamente, il "tidyverse" ha risolto la maggior parte dei problemi.

Questa soluzione utilizza mutate_each()per applicare una funzione a tutte le colonne in un frame di dati. In questo caso, vogliamo applicare la type.convert()funzione, che converte le stringhe in valori numerici laddove possibile. Perché R ama i fattori (non so perché) le colonne di caratteri che dovrebbero rimanere personaggi vengono cambiate in fattore. Per risolvere questo problema, la mutate_if()funzione viene utilizzata per rilevare colonne che sono fattori e cambiano carattere. Infine, volevo mostrare come lubridate può essere usato per cambiare un timestamp nella classe di caratteri in data-ora perché questo è spesso anche un blocco per principianti.


library(tidyverse) 
library(lubridate)

# Recreate data that needs converted to numeric, date-time, etc
data_df
#> # A tibble: 5 × 9
#>             TIMESTAMP SYMBOL    EX  PRICE  SIZE  COND   BID BIDSIZ   OFR
#>                 <chr>  <chr> <chr>  <chr> <chr> <chr> <chr>  <chr> <chr>
#> 1 2012-05-04 09:30:00    BAC     T 7.8900 38538     F  7.89    523  7.90
#> 2 2012-05-04 09:30:01    BAC     Z 7.8850   288     @  7.88  61033  7.90
#> 3 2012-05-04 09:30:03    BAC     X 7.8900  1000     @  7.88   1974  7.89
#> 4 2012-05-04 09:30:07    BAC     T 7.8900 19052     F  7.88   1058  7.89
#> 5 2012-05-04 09:30:08    BAC     Y 7.8900 85053     F  7.88 108101  7.90

# Converting columns to numeric using "tidyverse"
data_df %>%
    mutate_all(type.convert) %>%
    mutate_if(is.factor, as.character) %>%
    mutate(TIMESTAMP = as_datetime(TIMESTAMP, tz = Sys.timezone()))
#> # A tibble: 5 × 9
#>             TIMESTAMP SYMBOL    EX PRICE  SIZE  COND   BID BIDSIZ   OFR
#>                <dttm>  <chr> <chr> <dbl> <int> <chr> <dbl>  <int> <dbl>
#> 1 2012-05-04 09:30:00    BAC     T 7.890 38538     F  7.89    523  7.90
#> 2 2012-05-04 09:30:01    BAC     Z 7.885   288     @  7.88  61033  7.90
#> 3 2012-05-04 09:30:03    BAC     X 7.890  1000     @  7.88   1974  7.89
#> 4 2012-05-04 09:30:07    BAC     T 7.890 19052     F  7.88   1058  7.89
#> 5 2012-05-04 09:30:08    BAC     Y 7.890 85053     F  7.88 108101  7.90

Si noti che se si utilizza mutate_all(type.convert, as.is=TRUE)invece di mutate_all(type.convert), è possibile rimuovere / evitare mutate_if(is.factor, as.character)di abbreviare il comando. as.isè un argomento type.convert()che indica se deve convertire le stringhe come caratteri o come fattori. Per impostazione predefinita, as.is=FALSEin type.convert()(ovvero, converte le stringhe in classe di fattori anziché in classe di caratteri).
LC-datascientist il

15

Tim ha ragione e Shane ha un'omissione. Ecco altri esempi:

R> df <- data.frame(a = as.character(10:15))
R> df <- data.frame(df, num = as.numeric(df$a), 
                        numchr = as.numeric(as.character(df$a)))
R> df
   a num numchr
1 10   1     10
2 11   2     11
3 12   3     12
4 13   4     13
5 14   5     14
6 15   6     15
R> summary(df)
  a          num           numchr    
 10:1   Min.   :1.00   Min.   :10.0  
 11:1   1st Qu.:2.25   1st Qu.:11.2  
 12:1   Median :3.50   Median :12.5  
 13:1   Mean   :3.50   Mean   :12.5  
 14:1   3rd Qu.:4.75   3rd Qu.:13.8  
 15:1   Max.   :6.00   Max.   :15.0  
R> 

Il nostro data.frameora ha un riepilogo della colonna del fattore (conteggi) e dei riassunti numerici del as.numeric()--- che è sbagliato in quanto ha ottenuto i livelli del fattore numerico --- e il riassunto (corretto) del as.numeric(as.character()).


1
Il piacere è tutto mio. Questo è uno degli angoli più sciocchi della lingua, e penso che sia stato inserito nella vecchia domanda "R Gotchas" qui.
Dirk Eddelbuettel,

14

Con il seguente codice è possibile convertire tutte le colonne del frame di dati in numeriche (X è il frame di dati che vogliamo convertire sono le colonne):

as.data.frame(lapply(X, as.numeric))

e per convertire l'intera matrice in valori numerici hai due modi:

mode(X) <- "numeric"

o:

X <- apply(X, 2, as.numeric)

In alternativa puoi usare la data.matrixfunzione per convertire tutto in valori numerici, sebbene tieni presente che i fattori potrebbero non essere convertiti correttamente, quindi è più sicuro convertire tutto in characterprimo:

X <- sapply(X, as.character)
X <- data.matrix(X)

Di solito uso quest'ultimo se voglio convertire simultaneamente in matrice e numerico


12

Se riscontri problemi con:

as.numeric(as.character(dat$x))

Dai un'occhiata ai segni decimali. Se sono "," anziché "." (es. "5,3") quanto sopra non funzionerà.

Una potenziale soluzione è:

as.numeric(gsub(",", ".", dat$x))

Credo che questo sia abbastanza comune in alcuni paesi non di lingua inglese.


8

Modo universale usando type.convert()e rapply():

convert_types <- function(x) {
    stopifnot(is.list(x))
    x[] <- rapply(x, utils::type.convert, classes = "character",
                  how = "replace", as.is = TRUE)
    return(x)
}
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)
sapply(d, class)
#>        char   fake_char         fac    char_fac         num 
#> "character" "character"    "factor"    "factor"   "integer"
sapply(convert_types(d), class)
#>        char   fake_char         fac    char_fac         num 
#> "character"   "integer"    "factor"    "factor"   "integer"

3
Questa è la soluzione più flessibile: merita alcuni voti!
Richard Border,

Dovrebbe essere la risposta migliore. Rimuovi semplicemente as.is = TRUEse vuoi convertire il tuo personaggio in numerico o in fattori
qfazille,

il tentativo di cambiare un gruppo di colonne in un data.frame che ha il tipo matrixdi modifiche numeriche classes=matrixerrate, il primo argomento deve essere di tipo mode
add-semi-colons

1
Questa è la migliore risposta nell'argomento.
yuk,

3

Per convertire una colonna di frame di dati in valori numerici devi solo fare: -

fattore numerico: -

data_frame$column <- as.numeric(as.character(data_frame$column))

Ancora una volta, questa risposta non aggiunge nulla all'attuale set di risposte. Inoltre, non è il modo preferito per convertire un fattore in numerico. Vedere stackoverflow.com/q/3418128 per il modo preferito.
BenBarnes,

Una risposta migliore fu:sapply(data_frame,function(x) as.numeric(as.character(x)))
data-frame-gg

2

Sebbene altri abbiano trattato abbastanza bene l'argomento, vorrei aggiungere questo breve suggerimento / suggerimento aggiuntivo. È possibile utilizzare regexp per verificare in anticipo se i caratteri sono potenzialmente costituiti solo da numeri.

for(i in seq_along(names(df)){
     potential_numcol[i] <- all(!grepl("[a-zA-Z]",d[,i]))
}
# and now just convert only the numeric ones
d <- sapply(d[,potential_numcol],as.numeric)

Per espressioni regolari più sofisticate e un chiaro motivo per imparare / sperimentare il loro potere, visita questo sito Web davvero carino: http://regexr.com/


1

Considerando che potrebbero esistere colonne di caratteri, questo si basa su @Abdou in Ottieni tipi di colonne di foglio Excel che rispondono automaticamente :

makenumcols<-function(df){
  df<-as.data.frame(df)
  df[] <- lapply(df, as.character)
  cond <- apply(df, 2, function(x) {
    x <- x[!is.na(x)]
    all(suppressWarnings(!is.na(as.numeric(x))))
  })
  numeric_cols <- names(df)[cond]
  df[,numeric_cols] <- sapply(df[,numeric_cols], as.numeric)
  return(df)
}
df<-makenumcols(df)

0

Nel mio PC (R v.3.2.3), applyo sapplydare errore. lapplyfunziona bene.

dt[,2:4] <- lapply(dt[,2:4], function (x) as.factor(as.numeric(x)))

0

Se il frame di dati ha più tipi di colonne, alcuni caratteri, alcuni numerici provano quanto segue per convertire solo le colonne che contengono valori numerici in numerici:

for (i in 1:length(data[1,])){
  if(length(as.numeric(data[,i][!is.na(data[,i])])[!is.na(as.numeric(data[,i][!is.na(data[,i])]))])==0){}
  else {
    data[,i]<-as.numeric(data[,i])
  }
}

0

con hablar :: convert

Per convertire facilmente più colonne in diversi tipi di dati è possibile utilizzare hablar::convert. Sintassi semplice:df %>% convert(num(a)) converte la colonna a da df in numerico.

Esempio dettagliato

Consente di convertire tutte le colonne mtcarsin carattere.

df <- mtcars %>% mutate_all(as.character) %>% as_tibble()

> df
# A tibble: 32 x 11
   mpg   cyl   disp  hp    drat  wt    qsec  vs    am    gear  carb 
   <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr>
 1 21    6     160   110   3.9   2.62  16.46 0     1     4     4    
 2 21    6     160   110   3.9   2.875 17.02 0     1     4     4    
 3 22.8  4     108   93    3.85  2.32  18.61 1     1     4     1    

Con hablar::convert:

library(hablar)

# Convert columns to integer, numeric and factor
df %>% 
  convert(int(cyl, vs),
          num(disp:wt),
          fct(gear))

risulta in:

# A tibble: 32 x 11
   mpg     cyl  disp    hp  drat    wt qsec     vs am    gear  carb 
   <chr> <int> <dbl> <dbl> <dbl> <dbl> <chr> <int> <chr> <fct> <chr>
 1 21        6  160    110  3.9   2.62 16.46     0 1     4     4    
 2 21        6  160    110  3.9   2.88 17.02     0 1     4     4    
 3 22.8      4  108     93  3.85  2.32 18.61     1 1     4     1    
 4 21.4      6  258    110  3.08  3.22 19.44     1 0     3     1   

0

Per convertire il carattere in numerico devi convertirlo in fattore applicandolo

BankFinal1 <- transform(BankLoan,   LoanApproval=as.factor(LoanApproval))
BankFinal1 <- transform(BankFinal1, LoanApp=as.factor(LoanApproval))

Devi creare due colonne con gli stessi dati, perché una colonna non può essere convertita in numerico. Se si esegue una conversione, viene visualizzato l'errore seguente

transform(BankData, LoanApp=as.numeric(LoanApproval))
Warning message:
  In eval(substitute(list(...)), `_data`, parent.frame()) :
  NAs introduced by coercion

quindi, dopo aver fatto due colonne degli stessi dati si applicano

BankFinal1 <- transform(BankFinal1, LoanApp      = as.numeric(LoanApp), 
                                    LoanApproval = as.numeric(LoanApproval))

trasformerà il carattere in numerico correttamente


0

dfè il tuo dataframe. xè una colonna dfche vuoi convertire

as.numeric(factor(df$x))

0

Se non ti interessa conservare i fattori e vuoi applicarlo a qualsiasi colonna che può essere convertita in numerico, ho usato lo script qui sotto. se df è il tuo frame di dati originale, puoi utilizzare lo script seguente.

df[] <- lapply(df, as.character)
df <- data.frame(lapply(df, function(x) ifelse(!is.na(as.numeric(x)), as.numeric(x),  x)))

Ho fatto riferimento alla soluzione di Shane e Joran tra l'altro

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.