web-dev-qa-db-fra.com

Convertir toutes les colonnes de caractères du cadre de données en facteurs

Étant donné un bloc de données (préexistant) comportant des colonnes de différents types, quel est le moyen le plus simple de convertir toutes ses colonnes de caractères en facteurs, sans affecter les colonnes d'autres types?

Voici un exemple data.frame:

df <- data.frame(A = factor(LETTERS[1:5]),
                 B = 1:5, C = as.logical(c(1, 1, 0, 0, 1)),
                 D = letters[1:5],
                 E = paste(LETTERS[1:5], letters[1:5]),
                 stringsAsFactors = FALSE)
df
#   A B     C D   E
# 1 A 1  TRUE a A a
# 2 B 2  TRUE b B b
# 3 C 3 FALSE c C c
# 4 D 4 FALSE d D d
# 5 E 5  TRUE e E e
str(df)
# 'data.frame':  5 obs. of  5 variables:
#  $ A: Factor w/ 5 levels "A","B","C","D",..: 1 2 3 4 5
#  $ B: int  1 2 3 4 5
#  $ C: logi  TRUE TRUE FALSE FALSE TRUE
#  $ D: chr  "a" "b" "c" "d" ...
#  $ E: chr  "A a" "B b" "C c" "D d" ...

Je sais que je peux faire:

df$D <- as.factor(df$D)
df$E <- as.factor(df$E)

Est-il possible d'automatiser un peu plus ce processus?

44
Museful
DF <- data.frame(x=letters[1:5], y=1:5, stringsAsFactors=FALSE)

str(DF)
#'data.frame':  5 obs. of  2 variables:
# $ x: chr  "a" "b" "c" "d" ...
# $ y: int  1 2 3 4 5

Le défaut (ennuyeux) de as.data.frame consiste à transformer toutes les colonnes de caractères en colonnes de facteurs. Vous pouvez l'utiliser ici:

DF <- as.data.frame(unclass(DF))
str(DF)
#'data.frame':  5 obs. of  2 variables:
# $ x: Factor w/ 5 levels "a","b","c","d",..: 1 2 3 4 5
# $ y: int  1 2 3 4 5
56
Roland

La réponse de Roland est excellente pour ce problème spécifique, mais je pensais partager une approche plus générale.

DF <- data.frame(x = letters[1:5], y = 1:5, z = LETTERS[1:5], 
                 stringsAsFactors=FALSE)
str(DF)
# 'data.frame':  5 obs. of  3 variables:
#  $ x: chr  "a" "b" "c" "d" ...
#  $ y: int  1 2 3 4 5
#  $ z: chr  "A" "B" "C" "D" ...

## The conversion
DF[sapply(DF, is.character)] <- lapply(DF[sapply(DF, is.character)], 
                                       as.factor)
str(DF)
# 'data.frame':  5 obs. of  3 variables:
#  $ x: Factor w/ 5 levels "a","b","c","d",..: 1 2 3 4 5
#  $ y: int  1 2 3 4 5
#  $ z: Factor w/ 5 levels "A","B","C","D",..: 1 2 3 4 5

Pour la conversion, le côté gauche de l'attribut (DF[sapply(DF, is.character)]) sous-définit les colonnes qui sont des caractères. Dans la partie droite, pour ce sous-ensemble, vous utilisez lapply pour effectuer toutes les conversions nécessaires. R est suffisamment intelligent pour remplacer les colonnes d'origine par les résultats.

La chose pratique à propos de cela est que si vous vouliez faire l'inverse ou effectuer d'autres conversions, il vous suffit de changer ce que vous cherchez à gauche et de spécifier ce que vous voulez changer à droite.

83

Comme @Raf Z a commenté cette question , dplyr a maintenant mutate_if. Super utile, simple et lisible.

> str(df)
'data.frame':   5 obs. of  5 variables:
 $ A: Factor w/ 5 levels "A","B","C","D",..: 1 2 3 4 5
 $ B: int  1 2 3 4 5
 $ C: logi  TRUE TRUE FALSE FALSE TRUE
 $ D: chr  "a" "b" "c" "d" ...
 $ E: chr  "A a" "B b" "C c" "D d" ...

> df <- df %>% mutate_if(is.character,as.factor)

> str(df)
'data.frame':   5 obs. of  5 variables:
 $ A: Factor w/ 5 levels "A","B","C","D",..: 1 2 3 4 5
 $ B: int  1 2 3 4 5
 $ C: logi  TRUE TRUE FALSE FALSE TRUE
 $ D: Factor w/ 5 levels "a","b","c","d",..: 1 2 3 4 5
 $ E: Factor w/ 5 levels "A a","B b","C c",..: 1 2 3 4 5
25
Tedward

Le moyen le plus simple serait d'utiliser le code donné ci-dessous. Cela automatiserait tout le processus de conversion de toutes les variables en tant que facteurs dans un cadre de données en R. Cela fonctionnait parfaitement pour moi. food_cat est ici l'ensemble de données que j'utilise. Changez-le pour celui sur lequel vous travaillez.

    for(i in 1:ncol(food_cat)){

food_cat[,i] <- as.factor(food_cat[,i])

}
2
SHREYANSHU SNEH

J'avais l'habitude de faire une simple boucle for. Comme @ A5C1D2H2I1M1N2O1R2T1 answer, lapply est une solution intéressante. Mais si vous convertissez toutes les colonnes, vous aurez besoin d'un data.frame avant, sinon vous obtiendrez une list. Petites différences de temps d'exécution. 

 mm2N=mm2New[,10:18]
 str(mm2N)
'data.frame':   35487 obs. of  9 variables:
 $ bb    : int  4 6 2 3 3 2 5 2 1 2 ...
 $ vabb  : int  -3 -3 -2 -2 -3 -1 0 0 3 3 ...
 $ bb55  : int  7 6 3 4 4 4 9 2 5 4 ...
 $ vabb55: int  -3 -1 0 -1 -2 -2 -3 0 -1 3 ...
 $ zr    : num  0 -2 -1 1 -1 -1 -1 1 1 0 ...
 $ z55r  : num  -2 -2 0 1 -2 -2 -2 1 -1 1 ...
 $ fechar: num  0 -1 1 0 1 1 0 0 1 0 ...
 $ varr  : num  3 3 1 1 1 1 4 1 1 3 ...
 $ minmax: int  3 0 4 6 6 6 0 6 6 1 ...

 # For solution
 t1=Sys.time()
 for(i in 1:ncol(mm2N)) mm2N[,i]=as.factor(mm2N[,i])
 Sys.time()-t1
Time difference of 0.2020121 secs
 str(mm2N)
'data.frame':   35487 obs. of  9 variables:
 $ bb    : Factor w/ 6 levels "1","2","3","4",..: 4 6 2 3 3 2 5 2 1 2 ...
 $ vabb  : Factor w/ 7 levels "-3","-2","-1",..: 1 1 2 2 1 3 4 4 7 7 ...
 $ bb55  : Factor w/ 8 levels "2","3","4","5",..: 6 5 2 3 3 3 8 1 4 3 ...
 $ vabb55: Factor w/ 7 levels "-3","-2","-1",..: 1 3 4 3 2 2 1 4 3 7 ...
 $ zr    : Factor w/ 5 levels "-2","-1","0",..: 3 1 2 4 2 2 2 4 4 3 ...
 $ z55r  : Factor w/ 5 levels "-2","-1","0",..: 1 1 3 4 1 1 1 4 2 4 ...
 $ fechar: Factor w/ 3 levels "-1","0","1": 2 1 3 2 3 3 2 2 3 2 ...
 $ varr  : Factor w/ 5 levels "1","2","3","4",..: 3 3 1 1 1 1 4 1 1 3 ...
 $ minmax: Factor w/ 7 levels "0","1","2","3",..: 4 1 5 7 7 7 1 7 7 2 ...

 #lapply solution
 mm2N=mm2New[,10:18]
 t1=Sys.time()
 mm2N <- lapply(mm2N, as.factor)
 Sys.time()-t1
Time difference of 0.209012 secs
 str(mm2N)
List of 9
 $ bb    : Factor w/ 6 levels "1","2","3","4",..: 4 6 2 3 3 2 5 2 1 2 ...
 $ vabb  : Factor w/ 7 levels "-3","-2","-1",..: 1 1 2 2 1 3 4 4 7 7 ...
 $ bb55  : Factor w/ 8 levels "2","3","4","5",..: 6 5 2 3 3 3 8 1 4 3 ...
 $ vabb55: Factor w/ 7 levels "-3","-2","-1",..: 1 3 4 3 2 2 1 4 3 7 ...
 $ zr    : Factor w/ 5 levels "-2","-1","0",..: 3 1 2 4 2 2 2 4 4 3 ...
 $ z55r  : Factor w/ 5 levels "-2","-1","0",..: 1 1 3 4 1 1 1 4 2 4 ...
 $ fechar: Factor w/ 3 levels "-1","0","1": 2 1 3 2 3 3 2 2 3 2 ...
 $ varr  : Factor w/ 5 levels "1","2","3","4",..: 3 3 1 1 1 1 4 1 1 3 ...
 $ minmax: Factor w/ 7 levels "0","1","2","3",..: 4 1 5 7 7 7 1 7 7 2 ...

 #data.frame lapply solution
 mm2N=mm2New[,10:18]
 t1=Sys.time()
 mm2N <- data.frame(lapply(mm2N, as.factor))
 Sys.time()-t1
Time difference of 0.2010119 secs
 str(mm2N)
'data.frame':   35487 obs. of  9 variables:
 $ bb    : Factor w/ 6 levels "1","2","3","4",..: 4 6 2 3 3 2 5 2 1 2 ...
 $ vabb  : Factor w/ 7 levels "-3","-2","-1",..: 1 1 2 2 1 3 4 4 7 7 ...
 $ bb55  : Factor w/ 8 levels "2","3","4","5",..: 6 5 2 3 3 3 8 1 4 3 ...
 $ vabb55: Factor w/ 7 levels "-3","-2","-1",..: 1 3 4 3 2 2 1 4 3 7 ...
 $ zr    : Factor w/ 5 levels "-2","-1","0",..: 3 1 2 4 2 2 2 4 4 3 ...
 $ z55r  : Factor w/ 5 levels "-2","-1","0",..: 1 1 3 4 1 1 1 4 2 4 ...
 $ fechar: Factor w/ 3 levels "-1","0","1": 2 1 3 2 3 3 2 2 3 2 ...
 $ varr  : Factor w/ 5 levels "1","2","3","4",..: 3 3 1 1 1 1 4 1 1 3 ...
 $ minmax: Factor w/ 7 levels "0","1","2","3",..: 4 1 5 7 7 7 1 7 7 2 ...
1
xm1