R dplyr: удаление нескольких столбцов


97

У меня есть фрейм данных и список столбцов в этом фреймворке, который я хотел бы удалить. Давайте использовать irisнабор данных в качестве примера. Я хотел бы бросить Sepal.Lengthи Sepal.Widthи использовать только оставшиеся столбцы. Как это сделать с помощью пакета selectили select_из dplyrпакета?

Вот что я пробовал до сих пор:

drop.cols <- c('Sepal.Length', 'Sepal.Width')
iris %>% select(-drop.cols)

Ошибка в -drop.cols: недопустимый аргумент унарного оператора

iris %>% select_(.dots = -drop.cols)

Ошибка в -drop.cols: недопустимый аргумент унарного оператора

iris %>% select(!drop.cols)

Ошибка в! Drop.cols: недопустимый тип аргумента

iris %>% select_(.dots = !drop.cols)

Ошибка в! Drop.cols: недопустимый тип аргумента

Я чувствую, что упускаю что-то очевидное, потому что это кажется довольно полезной операцией, которая уже должна существовать. На Github кто-то опубликовал аналогичную проблему , и Хэдли сказал использовать «отрицательную индексацию». Вот что (я думаю) я пробовал, но безуспешно. Какие-либо предложения?

Ответы:


128

Проверьте справку по select_vars. Это дает вам дополнительные идеи о том, как с этим работать.

В твоем случае:

iris %>% select(-one_of(drop.cols))

Спасибо. По какой-то причине это работает iris, но не на моем фактическом фрейме данных ( irisбыл игрушечным примером). Мой фрейм данных содержит 4558 строк и 147 столбцов. Я получил сообщение об ошибке Error in eval(x$expr, data, x$env) : variable names are limited to 10000 bytes. Есть идеи, почему это может происходить?
Navaneethan Santhanam

1
Ах, похоже, я ошибся. Случайно использовал select_varsвместо select. Теперь работает отлично!
Navaneethan Santhanam

6
Где мы должны узнать о встроенных функциях вроде one_of? Если я чего-то не упускаю, этого нет в документации пакета ( help(package='dplyr')).
geotheory 05

4
@geotheory, на самом деле one_of задокументирован. см help(one_of, package = "dplyr"). По крайней мере, это версия пакета 0.5.0. Но когда есть обновления одного из его пакетов, полезно читать блоги, которые публикует Хэдли. А некоторые функции задокументированы внутри других функций. К сожалению, для этого необходимо прочитать всю документацию, что я обычно делаю, когда хочу что-то, что не сразу очевидно или невозможно с функцией.
phiver 06

11
Спасибо. Как вы вообще узнали об этих функциях, с точки зрения документации?
geotheory 06


37

Кроме того, select(-one_of(drop.cols))существует пара других вариантов удаления столбцов с использованием, select()которые не включают определение всех конкретных имен столбцов (с использованием образцов данных dplyr starwars для большего разнообразия имен столбцов):

starwars %>% 
  select(-(name:mass)) %>%        # the range of columns from 'name' to 'mass'
  select(-contains('color')) %>%  # any column name that contains 'color'
  select(-starts_with('bi')) %>%  # any column name that starts with 'bi'
  select(-ends_with('er')) %>%    # any column name that ends with 'er'
  select(-matches('^f.+s$')) %>%  # any column name matching the regex pattern
  select_if(~!is.list(.)) %>%     # not by column name but by data type
  head(2)

# A tibble: 2 x 2
homeworld species
  <chr>     <chr>  
1 Tatooine  Human  
2 Tatooine  Droid 

Есть select_if(~!is.list(.))эквивалент select_if(is.list(.))?
Яша

3
В данном случае ~это сокращенное обозначение purrr для определения анонимной функции, это не еще один символ для not. Например, эти два значения означают одно function(x) {!is.list(x)}и то же и ~!is.list(.). Считайте ~это сокращением для function(.).
SlyFox

8

Будьте осторожны с этой select()функцией, потому что она используется как в пакетах dplyr, так и в MASS, поэтому, если MASS загружен, select () может работать некорректно. Чтобы узнать, какие пакеты загружены, введите sessionInfo()и найдите его в разделе «другие прикрепленные пакеты:». Если он загружен, введите detach( "package:MASS", unload = TRUE ), и ваша select()функция должна снова заработать.


12
в качестве альтернативы вы можете получить доступ к функции непосредственно в пространстве имен пакета dplyr::select().
Triamus

2
Я слишком часто сталкиваюсь с этой проблемой. Теперь я обычно определяю новую функцию в верхней части скрипта dselect <- dplyr::select().
filups21 04

5

Мы можем попробовать

iris %>% 
      select_(.dots= setdiff(names(.),drop.cols))

Спасибо @akrun, это сработало отлично. Однако, учитывая шумиху вокруг dplyrспособности сделать базовые задачи анализа легкими для чтения и записи, я разочарован тем, что реальное решение выглядит как обходной путь.
Navaneethan Santhanam

@NavaneethanSanthanam На самом деле, one_ofдругое решение - это то, что нужно. Я забыл об этом.
Akrun 07

3

Другой способ - изменить нежелательные столбцы, чтобы NULLизбежать использования встроенных круглых скобок:

head(iris,2) %>% mutate_at(drop.cols, ~NULL)
#   Petal.Length Petal.Width Species
# 1          1.4         0.2  setosa
# 2          1.4         0.2  setosa

Это также не дает предупреждения, если столбец отсутствует.
skoz

3

Если у вас есть специальный символ в именах столбцов, либо selectили select_не может работать , как ожидалось. Это свойство dplyrиспользования ".". Чтобы обратиться к набору данных в вопросе, для решения этой проблемы можно использовать следующую строку:

drop.cols <- c('Sepal.Length', 'Sepal.Width')
  iris %>% .[,setdiff(names(.),drop.cols)]

Ответы только на код не приветствуются. Пожалуйста, объясните, как работает ответ и чем он отличается от уже представленных ответов.
Ральф Стубнер

Спасибо!! Ни одно из вышеперечисленных решений не помогло именно по этой причине.
Marty999 09

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.