134 votes

Convertir les classes de colonnes dans data.table

J'ai un problème avec data.table : Comment convertir les classes de colonnes ? Voici un exemple simple : Avec data.frame je n'ai pas de problème de conversion, avec data.table je ne sais pas comment faire :

df <- data.frame(ID=c(rep("A", 5), rep("B",5)), Quarter=c(1:5, 1:5), value=rnorm(10))
#One way: http://stackoverflow.com/questions/2851015/r-convert-data-frame-columns-from-factors-to-characters
df <- data.frame(lapply(df, as.character), stringsAsFactors=FALSE)
#Another way
df[, "value"] <- as.numeric(df[, "value"])

library(data.table)
dt <- data.table(ID=c(rep("A", 5), rep("B",5)), Quarter=c(1:5, 1:5), value=rnorm(10))
dt <- data.table(lapply(dt, as.character), stringsAsFactors=FALSE) 
#Error in rep("", ncol(xi)) : invalid 'times' argument
#Produces error, does data.table not have the option stringsAsFactors?
dt[, "ID", with=FALSE] <- as.character(dt[, "ID", with=FALSE]) 
#Produces error: Error in `[<-.data.table`(`*tmp*`, , "ID", with = FALSE, value = "c(1, 1, 1, 1, 1, 2, 2, 2, 2, 2)") : 
#unused argument(s) (with = FALSE)

Ai-je raté quelque chose d'évident ?

Mise à jour suite au post de Matthew : J'utilisais une version plus ancienne, mais même après la mise à jour vers la version 1.6.6 (la version que j'utilise maintenant), j'obtiens toujours une erreur.

Mise à jour 2 : Supposons que je veuille convertir chaque colonne de la classe "facteur" en une colonne "caractère", mais que je ne sache pas à l'avance quelle colonne appartient à quelle classe. Avec un data.frame, je peux faire ce qui suit :

classes <- as.character(sapply(df, class))
colClasses <- which(classes=="factor")
df[, colClasses] <- sapply(df[, colClasses], as.character)

Puis-je faire quelque chose de similaire avec data.table ?

Mise à jour 3 :

s R version 2.13.1 (2011-07-08) Plateforme : x86_64-pc-mingw32/x64 (64-bit)

locale:
[1] C

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
[1] data.table_1.6.6

loaded via a namespace (and not attached):
[1] tools_2.13.1

0voto

uribo Points 37

J'ai essayé plusieurs approches.

# BY {dplyr}
data.table(ID      = c(rep("A", 5), rep("B",5)), 
           Quarter = c(1:5, 1:5), 
           value   = rnorm(10)) -> df1
df1 %<>% dplyr::mutate(ID      = as.factor(ID),
                       Quarter = as.character(Quarter))
# check classes
dplyr::glimpse(df1)
# Observations: 10
# Variables: 3
# $ ID      (fctr) A, A, A, A, A, B, B, B, B, B
# $ Quarter (chr) "1", "2", "3", "4", "5", "1", "2", "3", "4", "5"
# $ value   (dbl) -0.07676732, 0.25376110, 2.47192852, 0.84929175, -0.13567312,  -0.94224435, 0.80213218, -0.89652819...

ou autre

# from list to data.table using data.table::setDT
list(ID      = as.factor(c(rep("A", 5), rep("B",5))), 
     Quarter = as.character(c(1:5, 1:5)), 
     value   = rnorm(10)) %>% setDT(list.df) -> df2
class(df2)
# [1] "data.table" "data.frame"

0voto

liqg3 Points 23

Je propose un moyen plus général et plus sûr de faire ce genre de choses,

".." <- function (x) 
{
  stopifnot(inherits(x, "character"))
  stopifnot(length(x) == 1)
  get(x, parent.frame(4))
}

set_colclass <- function(x, class){
  stopifnot(all(class %in% c("integer", "numeric", "double","factor","character")))
  for(i in intersect(names(class), names(x))){
    f <- get(paste0("as.", class[i]))
    x[, (..("i")):=..("f")(get(..("i")))]
  }
  invisible(x)
}

La fonction .. s'assure que nous obtenons une variable hors de la portée de data.table ; set_colclass définit les classes de vos colonnes. Vous pouvez l'utiliser comme suit :

dt <- data.table(i=1:3,f=3:1)
set_colclass(dt, c(i="character"))
class(dt$i)

0voto

yuskam Points 87

Voici la même méthode que celle suggérée par @Nera pour vérifier d'abord la classe, mais au lieu d'utiliser .SD est d'utiliser la boucle rapide de data.table avec set comme la solution de @Matt Dowle avec un contrôle de classe supplémentaire.

for (j in seq_len(ncol(DT))){
  if(class(DT[[j]]) == 'factor')
    set(DT, j = j, value = as.character(DT[[j]]))
}

0voto

asepsiswu Points 11
columnID = c(1,2) # or
columnID = c('column1','column2')

for(i in columnID) class(dt[[i]]) <- 'character'

for loop change l'attribut du vecteur colonne en classe de caractères. Il traite en fait le data.table comme un type de liste.

-2voto

user151444 Points 11

Essayer :

dt <- data.table(A = c(1:5), 
                 B= c(11:15))

x <- ncol(dt)

for(i in 1:x) 
{
     dt[[i]] <- as.character(dt[[i]])
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X