web-dev-qa-db-fra.com

Comment convertir une colonne de trame de données en type numérique?

Comment convertir une colonne de trame de données en un type numérique?

223
acroa

Puisque (toujours) personne n’a coché, je suppose que vous avez un problème pratique en tête, principalement parce que vous n’avez pas spécifié le type de vecteur que vous voulez convertir en numeric. Je suggère que vous devriez appliquer la fonction transform afin de compléter votre tâche.

Maintenant, je suis sur le point de démontrer certaines "anomalies de conversion":

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

Jetons un coup d'œil sur 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

et laissez-nous courir:

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

Maintenant, vous vous demandez probablement "Où est une anomalie?" Eh bien, je suis tombé sur des choses assez particulières dans R, et ce n'est pas la Ce qui est le plus déroutant, mais cela peut vous dérouter, surtout si vous lisez ceci avant de vous coucher.

Voici: les deux premières colonnes sont character. J'ai délibérément appelé 2dakota du Nord un fake_char. Repérez la similarité de cette variable character avec celle que Dirk a créée dans sa réponse. C'est en fait un vecteur numerical converti en character. 3rd et 4th les colonnes sont factor, et le dernier est "purement" numeric.

Si vous utilisez la fonction transform, vous pouvez convertir le fake_char en numeric, mais pas la variable char elle-même.

> 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

mais si vous faites la même chose avec fake_char et char_fac, vous aurez de la chance et vous vous en sortirez sans 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

Si vous enregistrez le data.frame transformé et recherchez les variables mode et class, vous obtiendrez:

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

Donc, la conclusion est: Oui, vous pouvez convertir le vecteur character en un numeric, mais uniquement si ses éléments sont "convertibles" en numeric.</ i> S'il n'y a qu'un seul élément character dans le vecteur, vous obtiendrez une erreur en essayant de convertir ce vecteur en numerical un.

Et juste pour prouver mon point:

> 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

Et maintenant, juste pour le plaisir (ou la pratique), essayez de deviner le résultat de ces commandes:

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

Cordialement à Patrick Burns! =)

238
aL3xa

Quelque chose m'a aidé: si vous avez des plages de variables à convertir (ou juste plus d'une), vous pouvez utiliser sapply.

Un peu absurde mais juste par exemple:

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

Supposons que les colonnes 3, 6-15 et 37 de votre structure de données doivent être converties en une unité numérique:

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

si x est le nom de la colonne de dataframe dat et que x est de type facteur, utilisez

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

J'aurais ajouté un commentaire (faible note)

Juste pour ajouter sur user276042 et pangratz

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

Cela remplacera les valeurs de la colonne existante x

19
Somum

Tim a raison et Shane a une omission. Voici des exemples supplémentaires:

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> 

Notre data.frame a maintenant un résumé de la colonne de facteur (comptes) et des résumés numériques de as.numeric() --- qui est faux car il a obtenu les niveaux de facteur numériques --- et le résumé (correct) de as.numeric(as.character()).

14
Dirk Eddelbuettel

Avec le code suivant, vous pouvez convertir toutes les colonnes du cadre de données en numérique (X est le cadre de données que nous voulons convertir en colonnes):

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

et pour convertir une matrice entière en numérique, vous avez deux possibilités: Soit:

mode(X) <- "numeric"

ou:

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

Sinon, vous pouvez utiliser la fonction data.matrix pour tout convertir en numérique, bien que les facteurs puissent ne pas être convertis correctement. Il est donc plus sûr de tout convertir en character en premier:

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

J'utilise habituellement ce dernier si je veux pour convertir simultanément en matrice et en numérique

13
Mehrad Mahmoudian

Bien que votre question porte strictement sur les chiffres, il existe de nombreuses conversions difficiles à comprendre au début de R. Je vais essayer de vous aider. Cette question est similaire à Cette question

La conversion de type peut être un problème pour R parce que (1) les facteurs ne peuvent pas être convertis directement en chiffres, ils doivent d'abord être convertis en classe de caractères, (2) les dates constituent un cas spécial qu'il convient généralement de traiter séparément, et (3) La boucle entre les colonnes du cadre de données peut être délicate. Heureusement, le "tidyverse" a résolu la plupart des problèmes. 

Cette solution utilise mutate_each() pour appliquer une fonction à toutes les colonnes d'un bloc de données. Dans ce cas, nous souhaitons appliquer la fonction type.convert(), qui convertit les chaînes en valeurs numériques autant que possible. Parce que R aime les facteurs (je ne sais pas pourquoi), les colonnes de caractères qui doivent rester sont changées en facteur. Pour résoudre ce problème, la fonction mutate_if() est utilisée pour détecter les colonnes qui sont des facteurs et changer de caractère. Enfin, je voulais montrer comment lubrifier peut être utilisé pour changer l’horodatage de la classe de caractères en date-heure, car c’est aussi un bloc bloquant pour les débutants. 


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
11
Matt Dancho

Si vous rencontrez des problèmes avec:

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

Jetez un oeil à vos marques décimales. Si elles sont "," au lieu de "." (par exemple "5,3"), ce qui précède ne fonctionnera pas.

Une solution potentielle est:

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

Je pense que cela est assez courant dans certains pays non anglophones.

11
Gorka

Méthode universelle utilisant type.convert() et 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"
6
Artem Klevtsov

Pour convertir une colonne de trame de données en numérique, il suffit de: -

facteur en numérique: - 

data_frame$column <- as.numeric(as.character(data_frame$column))
3
Aayush Agrawal

Bien que d’autres aient assez bien abordé le sujet, je voudrais ajouter cette remarque rapide supplémentaire. Vous pouvez utiliser regexp pour vérifier à l'avance si les caractères sont uniquement constitués de nombres. 

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)

Pour des expressions régulières plus sophistiquées et une bonne idée pourquoi apprendre/expérimenter leur puissance, voyez ce site vraiment sympa: http://regexr.com/

2
Matt Bannert

Si la structure de données comporte plusieurs types de colonnes, certains caractères, certains numériques, tentent ce qui suit pour convertir uniquement les colonnes contenant des valeurs numériques:

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
Philipp

Considérant qu'il peut exister des colonnes de caractères, ceci est basé sur @Abdou dans Obtenir les types de colonne de la feuille Excel automatiquement answer:

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
Ferroao

avec hablar :: convert

Pour convertir facilement plusieurs colonnes en différents types de données, vous pouvez utiliser hablar::convert. Syntaxe simple: df %>% convert(num(a)) convertit la colonne a de df en numérique.

Exemple détaillé  

Permet de convertir toutes les colonnes de mtcars en caractère.

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    

Avec hablar::convert:

library(hablar)

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

résulte en:

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

Dans mon PC (R v.3.2.3), apply ou sapply donne une erreur. lapply fonctionne bien.

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

Pour convertir un caractère en numérique, vous devez le convertir en facteur en appliquant 

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

Vous devez créer deux colonnes avec les mêmes données, car une colonne ne peut pas être convertie en numérique. Si vous effectuez une conversion, l'erreur ci-dessous apparaît 

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

donc, après avoir fait deux colonnes des mêmes données s'appliquent

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

il transformera le caractère en numérique avec succès

0
jadhav suraj