Выбор только числовых столбцов из фрейма данных


192

Предположим, у вас есть такой data.frame:

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

Как бы вы выбрали только те столбцы в x, которые являются числовыми?

Ответы:


297

РЕДАКТИРОВАТЬ: обновлено, чтобы избежать использования опрометчивого sapply.

Поскольку фрейм данных представляет собой список, мы можем использовать функции применения списка:

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

Тогда стандартное подмножество

x[ , nums]

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

Для более идиоматичного современного R я бы теперь рекомендовал

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

Менее запутанный, менее отражающий особенности R, более простой и надежный для использования в таблицах с базой данных:

dplyr::select_if(x, is.numeric)

11
x[nums]или x[sapply(x,is.numeric)]тоже работает. И они всегда возвращаются data.frame. Сравнить x[1]vs x[,1]- первое data.frame, второе - вектор. Если кто-то хочет предотвратить преобразование, необходимо использовать x[, 1, drop=FALSE].
Марек

Есть ли способ выбрать только непрерывные данные? Этот метод возвращает как непрерывное, так и целое число.
Заброшенный

Когда числовой столбец отсутствует, возникает следующая ошибка undefined columns selected. Как этого избежать?
Йохан Обадиа,

Непрерывные данные @SoilSciGuy должны быть как числовые. Возможно, у вас есть факторные данные в числовой форме? Вам следует открыть новый вопрос.
Брэндон Бертельсен

1
@YohanObadia Вы можете использовать, tryCatch()чтобы справиться с этим. Пожалуйста, подумайте об открытии нового вопроса.
Брэндон Бертельсен

81

Функция) пакета dplyr select_if(представляет собой элегантное решение:

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

46

Filter() из базового пакета - идеальная функция для этого варианта использования: вам просто нужно написать код:

Filter(is.numeric, x)

Это также намного быстрее, чем select_if():

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

возвращает (на моем компьютере) среднее значение 60 микросекунд для Filterи 21 000 микросекунд для select_if(в 350 раз быстрее).


Это решение не сработает, если нет числовых столбцов. Есть ли недостатки в его использовании?
bli

Фильтр применяется только к строкам фрейма данных, а не к столбцам. Таким образом, это решение не даст правильного результата.
Майкл

4
@Michael не путайте фильтр из базового пакета и фильтр из пакета dplyr!
Кевин Зарка 01

1
@bli Я не вижу недостатков в использовании фильтра. Его вход - объект data.frame, и он возвращает data.frame
Кевин Зарка, 01

Просто позвоните сюда для справки: то, что Filter()здесь не работает, - это замена, например Filter(is.numeric,iris) <- 0.5*Filter(is.numeric,iris), не будет работать.
Mobeus Zoom,

9

если вас интересуют только имена столбцов, используйте это:

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



2

Библиотека PCAmixdata имеет функцию splitmix, которая разделяет количественные (числовые данные) и качественные (категориальные данные) заданного фрейма данных YourDataframe, как показано ниже:

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

Другой способ мог быть следующим: -

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

1
Привет, Аюши, это, вероятно, было отклонено, потому что это повторение первого ответа, но у этого метода есть некоторые проблемы, которые были выявлены. Взгляните на комментарии в первом ответе, вы поймете, что я имею в виду.
Брэндон Бертельсен

1

Если у вас много факторных переменных, вы можете использовать select_ifфункцию. установить пакеты dplyr. Есть много функций, которые разделяют данные, удовлетворяя условию. вы можете установить условия.

Используйте вот так.

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

2
Похоже на дубликат этого более раннего ответа stackoverflow.com/a/40808873/170352
Брэндон Бертельсен

0

Это не дает прямого ответа на вопрос, но может быть очень полезным, особенно если вам нужно что-то вроде всех числовых столбцов, кроме столбца идентификатора и зависимой переменной.

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))

0
Numerical_variables <- which(sapply(df, is.numeric))
# then extract column names 
Names <- names(Numerical_variables)

Привет, Мо! Я рекомендую вам попробовать это в консоли, потому что я не думаю, что это даст вам то, что вы думаете.
Брэндон Бертельсен

0
iris %>% dplyr::select(where(is.numeric)) #as per most recent updates

Другой вариант purrr- отрицать discardфункцию:

iris %>% purrr::discard(~!is.numeric(.))

Если вам нужны имена числовых столбцов, вы можете добавить namesили colnames:

iris %>% purrr::discard(~!is.numeric(.)) %>% names
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.