Eu tenho um quadro de dados. Vamos chamá-lo bob
:
> head(bob)
phenotype exclusion
GSM399350 3- 4- 8- 25- 44+ 11b- 11c- 19- NK1.1- Gr1- TER119-
GSM399351 3- 4- 8- 25- 44+ 11b- 11c- 19- NK1.1- Gr1- TER119-
GSM399352 3- 4- 8- 25- 44+ 11b- 11c- 19- NK1.1- Gr1- TER119-
GSM399353 3- 4- 8- 25+ 44+ 11b- 11c- 19- NK1.1- Gr1- TER119-
GSM399354 3- 4- 8- 25+ 44+ 11b- 11c- 19- NK1.1- Gr1- TER119-
GSM399355 3- 4- 8- 25+ 44+ 11b- 11c- 19- NK1.1- Gr1- TER119-
Eu gostaria de concatenar as linhas desse quadro de dados (essa será outra pergunta). Mas olhe:
> class(bob$phenotype)
[1] "factor"
Bob
As colunas de são fatores. Então, por exemplo:
> as.character(head(bob))
[1] "c(3, 3, 3, 6, 6, 6)" "c(3, 3, 3, 3, 3, 3)"
[3] "c(29, 29, 29, 30, 30, 30)"
Não começo a entender isso, mas acho que esses são índices nos níveis dos fatores das colunas (da corte do rei caractacus) de bob
? Não é o que eu preciso.
Estranhamente, posso passar pelas colunas bob
à mão e fazer
bob$phenotype <- as.character(bob$phenotype)
o que funciona bem E, depois de digitar, posso obter um data.frame cujas colunas são caracteres e não fatores. Então, minha pergunta é: como posso fazer isso automaticamente? Como converter um data.frame com colunas de fator em um data.frame com colunas de caracteres sem ter que passar manualmente por cada coluna?
Pergunta de bônus: por que a abordagem manual funciona?
bob
.Respostas:
Apenas seguindo Matt e Dirk. Se você deseja recriar seu quadro de dados existente sem alterar a opção global, é possível recriá-lo com uma instrução apply:
Isso converterá todas as variáveis na classe "caractere"; se você quiser converter apenas fatores, consulte a solução de Marek abaixo .
Como @hadley aponta, o seguinte é mais conciso.
Nos dois casos,
lapply
gera uma lista; no entanto, devido às propriedades mágicas de R, a utilização de[]
, no segundo caso mantém a classe data.frame dobob
objeto, eliminando assim a necessidade de converter de novo em data.frame usandoas.data.frame
com o argumentostringsAsFactors = FALSE
.fonte
type.convert
após a fundição de tudo paracharacter
, em seguida, reformulaçãofactors
de volta paracharacter
novamente.bob[] <-
no exemplo oubob <-
?; o primeiro mantém o data.frame; o segundo altera o data.frame para uma lista, eliminando os nomes de usuário. Atualizarei a resposta #iris[] <- lapply(iris, function(x) if (is.factor(x)) as.character(x) else {x})
Para substituir apenas fatores:
No pacote dplyr na versão 0.5.0,
mutate_if
foi introduzida uma nova função :O pacote purrr do RStudio oferece outra alternativa:
fonte
purrr
linha retorna uma lista, não adata.frame
!i
um vetor decolnames()
.A opção global
pode ser algo que você deseja definir
FALSE
nos arquivos de inicialização (por exemplo, ~ / .Rprofile). Por favor vejahelp(options)
.fonte
Se você entender como os fatores são armazenados, poderá evitar o uso de funções baseadas em aplicação para fazer isso. O que não significa que as soluções de aplicação não funcionem bem.
Os fatores são estruturados como índices numéricos vinculados a uma lista de 'níveis'. Isso pode ser visto se você converter um fator para numérico. Assim:
Os números retornados na última linha correspondem aos níveis do fator.
Observe que
levels()
retorna uma matriz de caracteres. Você pode usar esse fato para converter de maneira fácil e compacta fatores em cadeias ou números como este:Isso também funciona para valores numéricos, desde que você envolva sua expressão
as.numeric()
.fonte
as.character(f)
, é melhor em legibilidade e eficiência paralevels(f)[as.numeric(f)]
. Se você quisesse ser esperto, poderia usarlevels(f)[f]
. Observe que, ao converter um fator com valores numéricos, você obtém alguns benefícios deas.numeric(levels(f))[f]
mais, por exemploas.numeric(as.character(f))
, mas isso ocorre porque você só precisa converter os níveis em numérico e subconjunto.as.character(f)
está bem como está.Se você deseja um novo quadro de dados em
bobc
que todos os vetores de fatoresbobf
sejam convertidos em um vetor de caracteres, tente o seguinte:Se você desejar convertê-lo novamente, poderá criar um vetor lógico cujas colunas são fatores e usá-lo para aplicar seletivamente o fator
fonte
Normalmente, faço essa função para além de todos os meus projetos. Rápido e fácil.
fonte
Outra maneira é convertê-lo usando o aplicativo
E uma melhor (a anterior é da classe 'matriz')
fonte
as.data.frame(lapply(...
Atualização: Aqui está um exemplo de algo que não funciona. Eu pensei que sim, mas acho que a opção stringsAsFactors funciona apenas em cadeias de caracteres - deixa os fatores em paz.
Tente o seguinte:
De um modo geral, sempre que você estiver tendo problemas com fatores que deveriam ser caracteres, há uma
stringsAsFactors
configuração em algum lugar para ajudá-lo (incluindo uma configuração global).fonte
bob
para começar (mas não depois do fato).Ou você pode tentar
transform
:Apenas certifique-se de colocar todos os fatores que você deseja converter em caracteres.
Ou você pode fazer algo assim e matar todas as pragas com um golpe:
Não é uma boa ideia colocar os dados em um código como este, eu poderia fazer o
sapply
parte separadamente (na verdade, é muito mais fácil fazê-lo assim), mas você entendeu o ponto ... Eu não verifiquei o código, porque Não estou em casa, então espero que funcione! =)Essa abordagem, no entanto, tem uma desvantagem ... você deve reorganizar as colunas posteriormente, enquanto
transform
você pode fazer o que quiser, mas com o custo de "redação de código no estilo de pedestre" ...Então aí ... =)
fonte
No início do seu quadro de dados,
stringsAsFactors = FALSE
ignore todos os mal-entendidos.fonte
Se você usasse o
data.table
pacote para as operações no data.frame, o problema não está presente.Se você já possui um fator de colunas no conjunto de dados e deseja convertê-las em caracteres, pode fazer o seguinte.
fonte
In [<-.data.table(*tmp*, sapply(bob, is.factor), : Coerced 'character' RHS to 'double' to match the column's type. Either change the target column to 'character' first (by creating a new 'character' vector length 1234 (nrows of entire table) and assign that; i.e. 'replace' column), or coerce RHS to 'double' (e.g. 1L, NA_[real|integer]_, as.*, etc) to make your intent clear and for speed. Or, set the column type correctly up front when you create the table and stick to it, please.
É mais fácil corrigir o DF e recriar o DT.Isso funciona para mim - eu finalmente imaginei um forro
fonte
Esta função faz o truque
fonte
Talvez uma opção mais nova?
fonte
Você deve usar
convert
nohablar
que dá sintaxe legível compatível comtidyverse
tubos:o que lhe dá:
fonte
Com o
dplyr
pacote carregado, usese você quiser alterar a
phenotype
coluna-especificamente.fonte
Isso funciona transformando tudo em caractere e, em seguida, numérico em numérico:
Adaptado de: obtenha tipos de colunas da folha do Excel automaticamente
fonte