Como converter uma coluna de quadro de dados em tipo numérico?

261

Como você converte uma coluna de quadro de dados em um tipo numérico?

acroa
fonte

Respostas:

267

Como (ainda) ninguém recebeu a marca de seleção, suponho que você tenha algum problema prático em mente, principalmente porque você não especificou em que tipo de vetor deseja converter numeric. Sugiro que você aplique a transformfunção para concluir sua tarefa.

Agora estou prestes a demonstrar certa "anomalia de conversão":

# 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)

Vamos dar uma olhada em 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 vamos correr:

> 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" 

Agora você provavelmente se pergunta "Onde está uma anomalia?" Bem, eu me deparei com coisas bastante peculiares em R, e isso não é a coisa mais confusa, mas pode confundir você, especialmente se você ler isso antes de rolar na cama.

Aqui vai: as duas primeiras colunas são character. Eu deliberadamente chamado 2 nd um fake_char. Descubra a semelhança dessa charactervariável com uma que Dirk criou em sua resposta. Na verdade, é um numericalvetor convertido em character. 3 rd e 4 th coluna são factor, e o último é "puramente" numeric.

Se você utilizar a transformfunção, poderá converter a variável fake_charem numeric, mas não a charprópria variável.

> 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

mas se você fizer o mesmo fake_chare char_factiver sorte, sairá sem 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 você salvar transformado data.framee verificar modee class, obterá:

> 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"

Portanto, a conclusão é: Sim, você pode converter um charactervetor em numericum, mas apenas se os elementos forem "conversíveis" em numeric. Se houver apenas um characterelemento no vetor, você receberá um erro ao tentar converter esse vetor em numericalum.

E apenas para provar meu argumento:

> 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 agora, apenas por diversão (ou prática), tente adivinhar a saída desses comandos:

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

Atenciosamente Patrick Burns! =)

aL3xa
fonte
6
'stringsAsFactors = FALSE' é importante para a leitura de arquivos de dados.
Robert Brisita
4
Eu sei que isso é antigo ... mas ... por que você escolheu transform () sobre df $ fake_char <- as.integer (df $ fake_char)? Existem várias maneiras de fazer a mesma operação no R e fico sem entender a maneira "correta" de fazê-lo. Obrigado.
22416 Ripvlan
Portanto, é absolutamente impossível transformar err <- c (1, "b", 3, 4, "e") em um vetor numérico? No Excel, há um botão que permite "converter para número". tornando qualquer valor da coluna numérico. Estou tentando imitar isso em r.
Flightless13wings
Aviso! = Erro. Você não recebe um erro ao converter numérico / caractere misto em numérico, recebe um aviso e alguns valores de NA.
18718 Gregor Thomas
136

Algo que me ajudou: se você tiver intervalos de variáveis ​​para converter (ou apenas mais de um), poderá usar sapply.

Um pouco absurdo, mas apenas por exemplo:

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

Digamos que as colunas 3, 6 a 15 e 37 de seu dataframe precisem ser convertidas para numéricas.

dat[, c(3,6:15,37)] <- sapply(dat[, c(3,6:15,37)], as.numeric)
Jay
fonte
1
as.factor no código acima faz com que o personagem coluna
MySchizoBuddy
1
sapply é melhor do que transformar, ao manusear vetores de índices em vez de nomes de variáveis
SMCI
@MySchizoBuddy está correto, pelo menos com os meus dados. O df original não assumirá as colunas "convertidas" como fatores; eles permanecerão caráter. Se você encerrar a sapplychamada no as.data.frame()lado direito, como sugerido por @Mehrad Mahmoudian abaixo, ela funcionará.
knowah
Isso funcionará para uma matriz? Eu estou tentando isso com o mesmo código exato, mas quando eu verificar a classe () da coluna depois, ele ainda diz "caráter" e não "numérico"
namore
87

se xé o nome da coluna do quadro de dados date xé do tipo fator, use:

as.numeric(as.character(dat$x))
pangratz
fonte
3
adicionando de as.characterfato é o que eu estava procurando. Caso contrário, a conversão às vezes dá errado. Ao menos em meu caso.
Thieme Hennis
1
Por que o as.character é necessário? Eu estava recebendo um erro: Error: (list) object cannot be coerced to type 'double'embora eu estivesse razoavelmente certo de que meu vetor não tinha caracteres / pontuações. Então eu tentei as.numeric(as.character(dat$x))e funcionou. Agora não tenho certeza se minha coluna é de fato apenas números inteiros ou não!
vagabond
2
Se você fizer como.numérico para um fator, ele converterá os níveis em numéricos e não os valores reais. Daí as.character é necessária para converter o fator a personagem e, em seguida, as.numeric
MySchizoBuddy
Esta é a melhor resposta aqui
mitoRibo 11/11
25

Eu teria adicionado um comentário (não é possível classificar baixa)

Apenas para adicionar user276042 e pangratz

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

Isso substituirá os valores da coluna x existente

Somum
fonte
16

Embora sua pergunta seja estritamente numérica, há muitas conversões difíceis de entender ao iniciar o R. Vou tentar abordar métodos para ajudar. Esta pergunta é semelhante a esta pergunta .

A conversão de tipo pode ser um problema em R porque (1) os fatores não podem ser convertidos diretamente para numéricos, eles precisam ser convertidos para a classe de caracteres primeiro, (2) as datas são um caso especial com o qual você normalmente precisa lidar separadamente e (3) fazer um loop pelas colunas do quadro de dados pode ser complicado. Felizmente, o "arrumado" resolveu a maioria dos problemas.

Esta solução usa mutate_each()para aplicar uma função a todas as colunas em um quadro de dados. Nesse caso, queremos aplicar a type.convert()função, que converte seqüências de caracteres em numérico, sempre que possível. Como R ama fatores (não sei por que) as colunas de caracteres que devem permanecer são alteradas para fator. Para corrigir isso, a mutate_if()função é usada para detectar colunas que são fatores e mudar para caractere. Por fim, eu queria mostrar como o lubridato pode ser usado para alterar um carimbo de data / hora na classe de caracteres para data e hora, porque esse também é um obstáculo para iniciantes.


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
Matt Dancho
fonte
Observe que se você usar em mutate_all(type.convert, as.is=TRUE)vez de mutate_all(type.convert), poderá remover / evitar mutate_if(is.factor, as.character)encurtar o comando. as.isé um argumento type.convert()que indica se deve converter cadeias de caracteres como caracteres ou como fatores. Por padrão, as.is=FALSEem type.convert()(ou seja, converte seqüências de caracteres em classe de fator em vez de classe de caractere).
LC-datascientist
15

Tim está correto e Shane tem uma omissão. Aqui estão alguns exemplos adicionais:

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> 

Nosso data.frameagora tem um resumo da coluna fator (contagens) e resumos numéricos do as.numeric()--- que é errado , uma vez que tem os níveis de fator numéricos --- e o resumo (correta) da as.numeric(as.character()).

Dirk Eddelbuettel
fonte
1
O prazer é meu. Este é um dos cantos mais bobos da linguagem, e acho que apareceu na pergunta mais antiga de 'R Gotchas' aqui.
Dirk Eddelbuettel
14

Com o código a seguir, você pode converter todas as colunas do quadro de dados em numérico (X é o quadro de dados que queremos converter nas colunas):

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

e para converter a matriz inteira em numérica, você tem duas maneiras:

mode(X) <- "numeric"

ou:

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

Como alternativa, você pode usar a data.matrixfunção para converter tudo em numérico, embora esteja ciente de que os fatores podem não ser convertidos corretamente, portanto, é mais seguro converter tudo em characterprimeiro:

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

Eu costumo usar este último se quiser converter para matriz e numérico simultaneamente

Mehrad Mahmoudian
fonte
12

Se você tiver problemas com:

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

Dê uma olhada nas suas marcas decimais. Se eles são "," em vez de "." (por exemplo, "5,3") o acima não funcionará.

Uma solução potencial é:

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

Eu acredito que isso é bastante comum em alguns países que não falam inglês.

Gorka
fonte
8

Maneira universal 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"
Artem Klevtsov
fonte
3
Esta é a solução mais flexível - merece alguns votos positivos!
Richard Border
Deve ser a melhor resposta. Basta remover as.is = TRUEse você deseja converter o seu personagem para numérico ou fatores
qfazille
Tentando mudar monte de colunas em uma data.frame que tem o tipo matrixde mudanças numéricos classes=matrixerrados fora primeiro argumento deve ser de caráter modo
add-ponto e vírgula
1
Esta é a melhor resposta no tópico.
yuk
3

Para converter uma coluna de quadro de dados em numérico, basta fazer o seguinte: -

fator para numérico: -

data_frame$column <- as.numeric(as.character(data_frame$column))
Aayush Agrawal
fonte
Novamente, esta resposta não adiciona nada ao conjunto atual de respostas. Além disso, não é a maneira preferida de converter um fator para numérico. Consulte stackoverflow.com/q/3418128 para a maneira preferida.
Ben Barnes
Uma resposta melhor foi:sapply(data_frame,function(x) as.numeric(as.character(x)))
data-frame-gg
2

Embora outros tenham abordado o tópico muito bem, eu gostaria de adicionar esse pensamento / sugestão rápida adicional. Você pode usar o regexp para verificar antecipadamente se os caracteres potencialmente consistem apenas em números.

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)

Para expressões regulares mais sofisticadas e um porquê de aprender / experimentar seu poder, consulte este site realmente agradável: http://regexr.com/

Matt Bannert
fonte
1

Considerando que podem existir colunas char, isso se baseia em @Abdou na resposta Obter tipos de colunas da planilha do Excel 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)
Ferroao
fonte
0

No meu PC (R v.3.2.3), applyou sapplydê erro. lapplyfunciona bem.

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

Se o quadro de dados tiver vários tipos de colunas, alguns caracteres e alguns numéricos, tente o seguinte para converter apenas as colunas que contêm valores numéricos em numérico:

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])
  }
}
Philipp
fonte
0

com hablar :: convert

Para converter facilmente várias colunas em diferentes tipos de dados, você pode usar hablar::convert. Sintaxe simples: df %>% convert(num(a))converte a coluna a de df em numérico.

Exemplo detalhado

Permite converter todas as colunas de mtcarspara caractere.

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    

Com hablar::convert:

library(hablar)

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

resulta em:

# 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   
davsjob
fonte
0

Para converter caractere em numérico, você deve convertê-lo em fator aplicando

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

Você precisa criar duas colunas com os mesmos dados, porque uma coluna não pode ser convertida em numérica. Se você fizer uma conversão, ocorrerá o erro abaixo

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

então, depois de fazer duas colunas dos mesmos dados, aplique

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

ele transformará o caractere em numérico com êxito

jadhav suraj
fonte
0

dfé o seu quadro de dados. xé uma coluna que dfvocê deseja converter

as.numeric(factor(df$x))
Justin Lange
fonte
0

Se você não se preocupa em preservar os fatores e deseja aplicá-lo a qualquer coluna que possa ser convertida para numérica, usei o script abaixo. se df é o seu dataframe original, você pode usar o script abaixo.

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

Referenciei a solução de Shane e Joran entre

Michael Kassa
fonte