Comment convertir une colonne de trame de données en un type numérique?
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! =)
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)
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))
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
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())
.
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
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
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.
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"
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))
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/
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])
}
}
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)
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
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)))
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