web-dev-qa-db-fra.com

dplyr change beaucoup de types de données

pour changer les types de données, je peux utiliser quelque chose comme

l1 <- c("fac1","fac2","fac3")
l2 <- c("dbl1","dbl2","dbl3")
dat[,l1] <- lapply(dat[,l1], factor)
dat[,l2] <- lapply(dat[,l2], as.numeric)

avec dplyr

dat <- dat %>% mutate(
    fac1 = factor(fac1), fac2 = factor(fac2), fac3 = factor(fac3),
    dbl1 = as.numeric(dbl1), dbl2 = as.numeric(dbl2), dbl3 = as.numeric(dbl3)
)

existe-t-il un moyen plus élégant (plus court) dans Dplyr?

merci Christof

49
ckluss

Vous pouvez utiliser la version d'évaluation standard de mutate_each (lequel est mutate_each_) pour changer les classes de colonnes:

dat %>% mutate_each_(funs(factor), l1) %>% mutate_each_(funs(as.numeric), l2)
46
docendo discimus

Au bas du ?mutate_each (Au moins dans dplyr 0.5), il semble que cette fonction, comme dans la réponse de @docendo discimus, soit déconseillée et remplacée par des alternatives plus souples mutate_if, mutate_all Et mutate_at. Celui qui ressemble le plus à ce que @hadley mentionne dans son commentaire utilise probablement mutate_at. Notez que l'ordre des arguments est inversé, comparé à mutate_each, Et vars() utilise select() comme une sémantique, ce que j'interprète comme signifiant les fonctions ?select_helpers .

dat %>% mutate_at(vars(starts_with("fac")),funs(factor)) %>%   
  mutate_at(vars(starts_with("dbl")),funs(as.numeric))

Mais mutate_at Peut prendre des numéros de colonne au lieu d'un argument vars(), et après avoir lu cette page et examiné les alternatives, j'ai fini par utiliser mutate_at Mais avec grep pour capturer plusieurs types de noms de colonnes différents à la fois (sauf si vous avez toujours des noms de colonnes aussi évidents!)

dat %>% mutate_at(grep("^(fac|fctr|fckr)",colnames(.)),funs(factor)) %>%
  mutate_at(grep("^(dbl|num|qty)",colnames(.)),funs(as.numeric))

J'étais très enthousiaste à l'idée de trouver mutate_at + grep, car maintenant une ligne peut fonctionner sur beaucoup de colonnes.

EDIT - maintenant je vois matches() parmi les select_helpers, qui gère les expressions rationnelles, alors maintenant, j'aime ça.

dat %>% mutate_at(vars(matches("fac|fctr|fckr")),funs(factor)) %>%
  mutate_at(vars(matches("dbl|num|qty")),funs(as.numeric))

Autre commentaire généralement lié: si vous avez toutes vos colonnes de date avec des noms compatibles et des formats cohérents, ceci est puissant. Dans mon cas, toutes mes colonnes AAAAMMJJ, lues sous forme de nombres, sont transformées en dates.

  mutate_at(vars(matches("_DT$")),funs(as.Date(as.character(.),format="%Y%m%d")))
42
Rafael Zayas

Puisque la réponse de Nick est obsolète et que le commentaire de Rafael est vraiment utile, je veux ajouter ceci comme réponse. Si vous voulez changer toutfactor colonnes en character, utilisez mutate_if:

dat %>% mutate_if(is.factor, as.character)

De plus, d'autres fonctions sont autorisées. Par exemple, j’ai utilisé iconv pour modifier l’encodage de toutes les colonnes character:

dat %>% mutate_if(is.character, function(x){iconv(x, to = "ASCII//TRANSLIT")})

ou pour substituer tout NA par 0 dans les colonnes numériques:

dat %>% mutate_if(is.numeric, function(x){ifelse(is.na(x), 0, x)})
22
loki

Une manière plus générale d’atteindre une transformation de type de colonne est la suivante:

Si vous souhaitez transformer toutes vos colonnes factor en caractère, par exemple, vous pouvez le faire en utilisant un canal:

df %>%  mutate_each_( funs(as.character(.)), names( .[,sapply(., is.factor)] ))
4
Nick

C'est un one-liner avec mutate_at:

dat %>% mutate_at("l1", factor) %>% mutate_at("l2", as.numeric)
1
nexonvantec

Ou peut-être encore plus simple avec convert de hablar:

library(hablar)

dat %>% 
  convert(fct(fac1, fac2, fac3),
          num(dbl1, dbl2, dbl3))

ou se combine avec tidyselect:

dat %>% 
  convert(fct(contains("fac")),
          num(contains("dbl")))
0
davsjob