Selecionando apenas colunas numéricas de um quadro de dados


189

Suponha que você tenha um data.frame assim:

x <- data.frame(v1=1:20,v2=1:20,v3=1:20,v4=letters[1:20])

Como você selecionaria apenas as colunas em x que são numéricas?

Respostas:


288

EDIT: atualizado para evitar o uso de imprudentes sapply.

Como um quadro de dados é uma lista, podemos usar as funções de aplicação de lista:

nums <- unlist(lapply(x, is.numeric))  

Subconjunto padrão

x[ , nums]

## don't use sapply, even though it's less code
## nums <- sapply(x, is.numeric)

Para um R moderno mais idiomático, eu recomendaria agora

x[ , purrr::map_lgl(x, is.numeric)]

Menos codey, menos refletindo as peculiaridades particulares de R, e mais direto e robusto para usar em rabiscos de banco de dados:

dplyr::select_if(x, is.numeric)

10
x[nums]ou x[sapply(x,is.numeric)]funciona também. E eles sempre retornam data.frame. Compare x[1]vs x[,1]- primeiro é data.frame, o segundo é um vetor. Se alguém quiser impedir a conversão, deve usar x[, 1, drop=FALSE].
Marek

Alguma maneira de selecionar apenas dados contínuos? Este método retorna contínuo e também inteiro.
Abandonado abandonado

Quando não há coluna numérica, o seguinte erro ocorre undefined columns selected. Como você evita isso?
Yohan Obadia

Os dados contínuos do @SoilSciGuy devem ser as.numeric. Talvez você tenha dados de fator que estão na forma numérica? Você deve abrir uma nova pergunta.
Brandon Bertelsen 02/09

1
@YohanObadia Você pode usar um tryCatch()para lidar com isso. Por favor, considere abrir uma nova pergunta.
Brandon Bertelsen

79

A função do pacote dplyr select_if() é uma solução elegante:

library("dplyr")
select_if(x, is.numeric)

44

Filter() do pacote base é a função perfeita para esse caso de uso: você simplesmente precisa codificar:

Filter(is.numeric, x)

Também é muito mais rápido que select_if():

library(microbenchmark)
microbenchmark(
    dplyr::select_if(mtcars, is.numeric),
    Filter(is.numeric, mtcars)
)

retorna (no meu computador) uma mediana de 60 microssegundos por Filtere 21 000 microssegundos por select_if(350x mais rápido).


Esta solução não falha quando não há colunas numéricas. Existem desvantagens em usá-lo?
bli

O filtro se aplica apenas a linhas de um quadro de dados em vez de colunas. Como tal, esta solução não daria o resultado correto.
Michael

4
@ Michael não confunda Filtro do pacote base e filtro do pacote dplyr!
21715 Kevin Kevin Zarca

1
@bli Não vejo nenhuma desvantagem em usar o Filter. Sua entrada é um objeto data.frame e retornar um data.frame
Kevin Zarca

Basta colocar aqui uma referência: o Filter()que não funciona aqui é substituir, por exemplo Filter(is.numeric,iris) <- 0.5*Filter(is.numeric,iris), não funciona.
Mobeus Zoom

8

caso você esteja interessado apenas nos nomes das colunas, use o seguinte:

names(dplyr::select_if(train,is.numeric))

5

Este é um código alternativo para outras respostas:

x[, sapply(x, class) == "numeric"]

com um data.table

x[, lapply(x, is.numeric) == TRUE, with = FALSE]

3
Isso é mais um comentário para a resposta selecionada, em vez de uma resposta única.
precisa

2
As colunas podem ter mais de uma classe.
Rich Scriven


2

A biblioteca PCAmixdata possui functon splitmix que divide quantitativos (dados numéricos) e qualitativos (dados categóricos) de um determinado quadro de dados "YourDataframe", como mostrado abaixo:

install.packages("PCAmixdata")
library(PCAmixdata)
split <- splitmix(YourDataframe)
X1 <- split$X.quanti(Gives numerical columns in the dataset) 
X2 <- split$X.quali (Gives categorical columns in the dataset)

2

Outra maneira poderia ser a seguinte:

#extracting numeric columns from iris datset
(iris[sapply(iris, is.numeric)])

1
Oi Ayushi, isso provavelmente foi diminuído porque é uma repetição da primeira resposta, mas esse método tem alguns problemas que foram identificados. Dê uma olhada nos comentários na primeira resposta, você verá o que quero dizer.
Brandon Bertelsen

1

Se você tiver muitas variáveis ​​de fator, poderá usar a select_iffunção instale os pacotes dplyr. Existem muitas funções que separam dados satisfazendo uma condição. Você pode definir as condições.

Use assim.

categorical<-select_if(df,is.factor)
str(categorical)

2
Parece uma duplicata da resposta anterior stackoverflow.com/a/40808873/170352
Brandon Bertelsen

0

Isso não responde diretamente à pergunta, mas pode ser muito útil, especialmente se você deseja algo como todas as colunas numéricas, exceto a coluna id e a variável dependente.

numeric_cols <- sapply(dataframe, is.numeric) %>% which %>% 
                   names %>% setdiff(., c("id_variable", "dep_var"))

dataframe %<>% dplyr::mutate_at(numeric_cols, function(x) your_function(x))
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.