Convertir toutes les colonnes de caractères de bloc 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 des autres types?

Voici un exemple de 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 # ABCDE # 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?

 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 

La valeur par défaut (agaçante) 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 

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'affectation ( DF[sapply(DF, is.character)] ) DF[sapply(DF, is.character)] les colonnes qui sont des caractères. Dans la partie droite, pour ce sous-ensemble, vous utilisez lapply pour effectuer les conversions nécessaires. R est assez intelligent pour remplacer les colonnes d'origine par les résultats.

Ce qui est pratique à ce sujet, c'est que si vous voulez aller dans l'autre sens ou effectuer d'autres conversions, il vous suffit de changer ce que vous recherchez à gauche et de spécifier ce que vous voulez changer à droite.

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 

J’avais l’habitude de faire une simple boucle. Comme @ A5C1D2H2I1M1N2O1R2T1, la réponse est une bonne solution. Mais si vous convertissez toutes les colonnes, vous aurez besoin d’un data.frame , sinon vous vous retrouverez avec une list . Peu de 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 ... 

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

  for(i in 1:ncol(food_cat)){ food_cat[,i] <- as.factor(food_cat[,i]) }