Tenho um problema ao usar data.table: Como converter classes de colunas? Aqui está um exemplo simples: Com data.frame não tenho problemas para convertê-lo, com data.table, só não sei como:
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)
Eu sinto falta de algo óbvio aqui?
Atualização devido ao post de Matthew: Eu usei uma versão mais antiga antes, mas mesmo depois de atualizar para 1.6.6 (a versão que uso agora) ainda recebo um erro.
Atualização 2: digamos que eu queira converter todas as colunas da classe "fator" em uma coluna "caractere", mas não sei com antecedência qual coluna pertence a qual classe. Com um data.frame, posso fazer o seguinte:
classes <- as.character(sapply(df, class))
colClasses <- which(classes=="factor")
df[, colClasses] <- sapply(df[, colClasses], as.character)
Posso fazer algo semelhante com data.table?
Atualização 3:
sessionInfo () R versão 2.13.1 (2011-07-08) Plataforma: x86_64-pc-mingw32 / x64 (64 bits)
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
fonte
data.table
métodos são diferentes do que são paradata.frame
#Produces error
. 1 de qualquer maneira. Não recebo nenhum erro, qual versão você tem? Porém, há um problema nessa área, já mencionado antes. FR # 1224 e FR # 1493 são de alta prioridade para resolver. A resposta de Andrie é a melhor maneira, no entanto.invalid times argument
erro? Funciona bem para mim. Qual versão você tem?Respostas:
Para uma única coluna:
Usando
lapply
eas.character
:fonte
convcols
de caracteres de colunas.dt[,lapply(.SD,as.numeric),.SDcols=convcols]
é quase instantâneo enquantodt[,convcols:=lapply(.SD,as.numeric),.SDcols=convcols]
quase congela R, então estou supondo que estou fazendo errado. Obrigadoset()
por exemplo,for (col in names_factors) set(dt, j=col, value=as.factor(dt[[col]]))
[citação final]Tente isto
fonte
Filter
função para identificar as colunas, por exemplo:changeCols<- names(Filter(is.character, DT))
changeCols <- names(DT)[sapply(DT, is.character)]
.Levantando o comentário de Matt Dowle à resposta de Geneorama ( https://stackoverflow.com/a/20808945/4241780 ) para torná-lo mais óbvio (conforme recomendado), você pode usar
for(...)set(...)
.Criado em 12/02/2020 pelo pacote reprex (v0.3.0)
Veja outro comentário de Matt em https://stackoverflow.com/a/33000778/4241780 para mais informações.
Editar.
Conforme observado por Espen e em
help(set)
,j
pode ser "Nome (s) de coluna (caractere) ou número (s) (inteiro) a ser atribuído valor quando coluna (s) já existem". Entãonames_factors <- c(1L, 3L)
também funcionará.fonte
names_factors
está aqui. Eu acho que foi tirado de stackoverflow.com/a/20808945/1666063 então énames_factors = c('fac1', 'fac2')
neste caso - que são os nomes das colunas. Mas também podem ser os números das colunas, por exemplo 1; ncol (dt) que converteria todas as colunasEsta é uma maneira RUIM de fazer isso! Só estou deixando esta resposta caso ela resolva outros problemas estranhos. Esses métodos melhores são provavelmente, em parte, o resultado de versões mais novas de data.table ... portanto, vale a pena documentar dessa maneira difícil. Além disso, este é um bom exemplo de
eval
substitute
sintaxe para sintaxe.o que dá a você
fonte
set()
por exemplofor (col in names_factors) set(dt, j=col, value=as.factor(dt[[col]]))
set
é mais apropriado.for(...)set(...)
aqui: stackoverflow.com/a/33000778/403310Tentei várias abordagens.
, ou então
fonte
Eu ofereço uma maneira mais geral e segura de fazer essas coisas,
A função
..
garante que obtenhamos uma variável fora do escopo de data.table; set_colclass irá definir as classes de seus cols. Você pode usá-lo assim:fonte
Se você tiver uma lista de nomes de colunas em data.table, você deseja alterar a classe de do:
fonte
dt[, c(convert_to_character) := lapply(.SD, as.character), .SDcols=convert_to_character]
para atribuir por referência, em vez de usar a atribuição mais lenta de data.frame.experimentar:
fonte