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

261

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

acroa
la source

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! =)

aL3xa
la source
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)
Geai
la source
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))
pangratz
la source
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

Somum
la source
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
Matt Dancho
la source
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()).

Dirk Eddelbuettel
la source
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

Mehrad Mahmoudian
la source
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.

Gorka
la source
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"
Artem Klevtsov
la source
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))
Aayush Agrawal
la source
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/

Matt Bannert
la source
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)
Ferroao
la source
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)))
JKim
la source
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])
  }
}
Philipp
la source
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   
davsjob
la source
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

jadhav suraj
la source
0

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

as.numeric(factor(df$x))
Justin Lange
la source
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

Michael Kassa
la source