2017-08-29 3 views
0

Je travaille sur une trame de données composée de plusieurs types de données différents (numériques, caractères, horodatages), mais malheureusement toutes sont reçues en tant que caractères. Par conséquent, j'ai besoin de les contraindre dans leur format "approprié" dynamiquement et aussi efficacement que possible.Coercition de variables dans la trame de données au format approprié

Prenons l'exemple suivant:

df <- data.frame("val1" = c("1","2","3","4"), "val2" = c("A", "B", "C", "D"), stringsAsFactors = FALSE) 

Je veux évidemment val1 être numériques et val2 de rester comme un personnage. Par conséquent, mon résultat devrait ressembler à ceci:

'data.frame': 4 obs. of 2 variables: 
$ val1: num 1 2 3 4 
$ val2: chr "A" "B" "C" "D" 

En ce moment je suis en train d'accomplir ceci en vérifiant si la contrainte entraînerait NULL et procédant si cela est contraindre pas le cas:

res <- as.data.frame(lapply(df, function(x){ 

    x <- sapply(x, function(y) { 
    if (is.na(as.numeric(y))) { 
     return(y) 
    } else { 
     y <- as.numeric(y) 
     return(y) 
    }  
    }) 

    return(x) 

}), stringsAsFactors = FALSE) 

Cependant, cela ne me paraît pas la bonne solution en raison de multiples problèmes:

  1. je soupçonne qu'il ya un moyen plus rapide d'y parvenir
  2. Pour une raison quelconque, je reçois l'avertissement In FUN(X[[i]], ...) : NAs introduced by coercion, bien que ce n'est pas le cas (voir le résultat)
  3. Cela semble inappropriée lors de la manipulation d'autres types de données, à savoir dates

Y at-il une approche générale, heuristique ceci, ou une autre solution plus durable? Merci

+0

'data.frame (lapply (df, type.convert)) bibliothèque' '** ou ** (readr); data.frame (lapply (df, fonction (x) parse_guess (x))) 'peut fonctionner mais je ne suis pas sûr –

Répondre

2

Les lecteurs de fichiers récents comme data.table::fread ou le package readr font un travail assez décent dans l'identification et la conversion des colonnes au type approprié. Donc, ma première réaction a été de suggérer d'écrire les données dans un fichier et de les relire, par ex.,

library(data.table) 
fwrite(df, "dummy.csv") 
df_new <- fread("dummy.csv") 
str(df_new) 
Classes ‘data.table’ and 'data.frame': 4 obs. of 2 variables: 
$ val1: int 1 2 3 4 
$ val2: chr "A" "B" "C" "D" 
- attr(*, ".internal.selfref")=<externalptr> 

ou sans écrire sur le disque:

df_new <- fread(paste(capture.output(fwrite(df, "")), collapse = "\n")) 

Cependant, d.b's suggestions sont beaucoup plus intelligents, mais besoin de polissage pour éviter la contrainte au facteur:

df[] <- lapply(df, type.convert, as.is = TRUE) 
str(df) 
'data.frame': 4 obs. of 2 variables: 
$ val1: int 1 2 3 4 
$ val2: chr "A" "B" "C" "D" 

ou

df[] <- lapply(df, readr::parse_guess) 
+0

merci, cela semble être une solution valide pour mon exemple, bien qu'il semble que cela ne fonctionne pas sur mon jeu de données réel. Je suspecte en raison de niveaux plus profonds de nidification. –

0

Vous devriez vérifier le paquet dataPreparation. Vous trouverez la fonction findAndTransformNumerics fonction qui fera exactement ce que vous voulez.

require(dataPreparation) 
data("messy_adult") 
sapply(messy_adult[, .(num1, num2, mail)], class) 
    num1  num2  mail 
"character" "character" "factor" 

messy_adult est un ensemble de données moche pour illustrer les fonctions de ce package. Ici num1 et num2 sont des chaînes:/

messy_adult <- findAndTransformNumerics(messy_adult) 
[1] "findAndTransformNumerics: It took me 0.18s to identify 3 numerics column(s), i will set them as numerics" 
[1] "setColAsNumeric: I will set some columns as numeric" 
[1] "setColAsNumeric: I am doing the columnnum1" 
[1] "setColAsNumeric: 0 NA have been created due to transformation to numeric." 
[1] "setColAsNumeric: I will set some columns as numeric" 
[1] "setColAsNumeric: I am doing the columnnum2" 
[1] "setColAsNumeric: 0 NA have been created due to transformation to numeric." 
[1] "setColAsNumeric: I am doing the columnnum3" 
[1] "setColAsNumeric: 0 NA have been created due to transformation to numeric." 
[1] "findAndTransformNumerics: It took me 0.09s to transform 3 column(s) to a numeric format." 

nous avons effectué ici la recherche et connecté ce qu'il a trouvé

Et savoir:

sapply(messy_adult[, .(num1, num2, mail)], class) 
    num1  num2  mail 
"numeric" "numeric" "factor" 

Hope it helps!

Disclamer: Je suis l'auteur de ce paquet.