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


Réponses:


267

Puisque (encore) personne n'a de coche, je suppose que vous avez un problème pratique à l'esprit, principalement parce que vous n'avez pas spécifié le type de vecteur que vous souhaitez convertir numeric. Je suggère que vous appliquiez la transformfonction afin de terminer 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 à 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 chose la plus déroutante, mais cela peut vous dérouter, surtout si vous lisez ceci avant de vous coucher.

Voilà: les deux premières colonnes sont character. J'ai délibérément appelé 2 e un fake_char. Repérez la similitude de cette charactervariable avec celle créée par Dirk dans sa réponse. C'est en fait un numericalvecteur converti en character. 3 ème et 4 ème colonne sont factor, et le dernier est « purement » numeric.

Si vous utilisez la transformfonction, vous pouvez convertir la fake_charen numeric, mais pas la charvariable 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 fake_charet que char_facvous aurez de la chance et que 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 transformé data.frameet vérifiez modeet 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 un charactervecteur en un numeric, mais seulement si ses éléments sont "convertibles" en numeric. S'il n'y a qu'un seul characterélément dans le vecteur, vous obtiendrez une erreur lorsque vous tenterez de convertir ce vecteur en numericalun.

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 la sortie de ces commandes:

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

Cordialement à Patrick Burns! =)


6
'stringsAsFactors = FALSE' est important pour la lecture de fichiers de données.
Robert Brisita

4
Je sais que c'est vieux ... mais ... pourquoi avez-vous choisi transform () plutôt que df $ fake_char <- as.integer (df $ fake_char)? Il existe plusieurs façons de faire la même opération dans R et je suis coincé à comprendre la façon "correcte" de le faire. Je vous remercie.
ripvlan

Il est donc absolument impossible de transformer err <- c (1, "b", 3, 4, "e") en un vecteur numérique? Dans Excel, il y a un bouton qui vous permet de "convertir en nombre". faire de la valeur de la colonne une valeur numérique. J'essaie d'imiter cela dans r.
flightless13wings

Attention! = Erreur. Vous n'obtenez pas d'erreur lors de la conversion d'un mélange numérique / caractère en numérique, vous obtenez un avertissement et certaines valeurs NA.
Gregor Thomas

136

Quelque chose qui m'a aidé: si vous avez des plages de variables à convertir (ou juste plus d'un), 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 trame de données doivent être converties en numérique, on pourrait:

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

1
as.factor dans le code ci-dessus fait le caractère de colonne
MySchizoBuddy

1
sapply vaut mieux que transformer, lors de la manipulation de vecteurs d'indices plutôt que de noms de variables
smci

@MySchizoBuddy est correct, au moins avec mes données. Le df d'origine ne prendra pas les colonnes "converties" comme facteurs; ils resteront du caractère. Si vous encapsulez l' sapplyappel as.data.frame()sur le côté droit, comme @Mehrad Mahmoudian l'a suggéré ci-dessous, cela fonctionnera.
knowah

Est-ce que cela fonctionnera pour une matrice? J'essaie avec le même code exact, mais quand je vérifie la classe () d'une colonne après, il dit toujours "caractère" et non "numérique"
namore

87

si xest le nom de colonne de la trame de données datet xest de type facteur, utilisez:

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

3
en as.charactereffet, c'est ce que je cherchais. Sinon, la conversion se passe parfois mal. Du moins dans mon cas.
Thieme Hennis

1
Pourquoi le caractère as.character est-il nécessaire? J'obtenais une erreur: Error: (list) object cannot be coerced to type 'double'même si j'étais raisonnablement sûr que mon vecteur n'avait pas de caractères / signes de ponctuation. Ensuite, j'ai essayé as.numeric(as.character(dat$x))et cela a fonctionné. Maintenant, je ne sais pas si ma colonne est en fait uniquement des entiers ou non!
vagabond

2
Si vous faites as.numeric à un facteur, il convertira les niveaux en numérique et non en valeurs réelles. Par conséquent, as.character est nécessaire pour convertir d'abord le facteur en caractère, puis as.numeric
MySchizoBuddy

C'est la meilleure réponse ici
mitoRibo

25

J'aurais ajouté un commentaire (faible note)

Juste pour ajouter user276042 et pangratz

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

Cela remplacera les valeurs de la colonne existante x


16

Bien que votre question soit strictement numérique, il existe de nombreuses conversions difficiles à comprendre au début de R. Je vais essayer de trouver des méthodes pour vous aider. Cette question est similaire à cette question .

La conversion de type peut être pénible dans R car (1) les facteurs ne peuvent pas être convertis directement en numérique, ils doivent d'abord être convertis en classe de caractères, (2) les dates sont un cas spécial que vous devez généralement traiter séparément, et (3) le bouclage entre les colonnes de trame de données peut être délicat. 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 voulons appliquer la type.convert()fonction, qui convertit les chaînes en numérique où cela est possible. Parce que R aime les facteurs (je ne sais pas pourquoi) les colonnes de caractères qui devraient rester en caractère sont transformées en facteur. Pour résoudre ce problème, la mutate_if()fonction est utilisée pour détecter les colonnes qui sont des facteurs et passer au caractère. Enfin, je voulais montrer comment lubridate peut être utilisé pour changer un horodatage dans une classe de caractères en date-heure car c'est aussi souvent un blocage 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

Notez que si vous utilisez mutate_all(type.convert, as.is=TRUE)au lieu de mutate_all(type.convert), vous pouvez supprimer / éviter mutate_if(is.factor, as.character)pour raccourcir la commande. as.isest un argument type.convert()qui indique s'il doit convertir des chaînes en caractères ou en facteurs. Par défaut, as.is=FALSEdans type.convert()(c'est- à -dire, convertit les chaînes en classe de facteurs au lieu de classe de caractères).
LC-datascientist

15

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 a data.framemaintenant un résumé de la colonne des facteurs (nombre) et des résumés numériques du as.numeric()--- ce qui est faux car il a obtenu les niveaux des facteurs numériques --- et le résumé (correct) du as.numeric(as.character()).


1
Mon plaisir. C'est l'un des coins les plus stupides de la langue, et je pense qu'il figurait dans l'ancienne question «R Gotchas» ici.
Dirk Eddelbuettel

14

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

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

et pour convertir la matrice entière en numérique, vous avez deux façons: Soit:

mode(X) <- "numeric"

ou:

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

Alternativement, vous pouvez utiliser la data.matrixfonction pour tout convertir en numérique, mais sachez que les facteurs peuvent ne pas être convertis correctement, il est donc plus sûr de tout convertir en characterpremier:

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

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


12

Si vous rencontrez des problèmes avec:

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

Jetez un œil à vos décimales. S'ils 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 c'est assez courant dans certains pays non anglophones.


8

Manière universelle en 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"

3
Ceci est la solution la plus flexible - mérite quelques votes positifs!
Richard Border

Devrait être une bonne réponse. Supprimez simplement as.is = TRUEsi vous souhaitez convertir votre personnage en chiffres ou en facteurs
qfazille

essayer de changer un tas de colonnes dans un data.frame qui a du type matrixà des modifications numériques classes=matrixerroné le premier argument doit être de caractère mode
add-semi-colons

1
C'est la meilleure réponse dans le sujet.
yuk

3

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

facteur en numérique: -

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

Encore une fois, cette réponse n'ajoute rien à l'ensemble actuel de réponses. De plus, ce n'est pas le moyen préféré de convertir un facteur en numérique. Voir stackoverflow.com/q/3418128 pour la méthode préférée.
BenBarnes

Une meilleure réponse était:sapply(data_frame,function(x) as.numeric(as.character(x)))
data-frame-gg

2

Bien que d'autres aient assez bien couvert le sujet, je voudrais ajouter cette pensée / astuce rapide supplémentaire. Vous pouvez utiliser regexp pour vérifier à l'avance si les caractères ne sont potentiellement composés que de chiffres.

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 raison d'apprendre / expérimenter leur puissance, consultez ce site Web vraiment sympa: http://regexr.com/


1

Étant donné qu'il peut exister des colonnes de caractères, celles-ci sont basées sur @Abdou dans Obtenir les types de colonnes de la feuille Excel, répondre automatiquement :

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

Dans mon PC (R v.3.2.3), applyou sapplydonnez une erreur. lapplyfonctionne bien.

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

0

Si la trame de données a plusieurs types de colonnes, certains caractères, certains numériques, essayez ce qui suit pour convertir uniquement les colonnes qui contiennent des valeurs numériques en 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

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

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, cela donne l'erreur ci-dessous

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 numérique avec succès


0

dfist votre trame de données. xest une colonne que dfvous souhaitez convertir

as.numeric(factor(df$x))

0

Si vous ne vous souciez pas de préserver les facteurs et que vous souhaitez l'appliquer à n'importe quelle colonne pouvant être convertie en numérique, j'ai utilisé le script ci-dessous. si df est votre trame de données d'origine, vous pouvez utiliser le script ci-dessous.

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

J'ai référencé la solution de Shane et Joran entre autres

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.